package hook import ( "fmt" "os" "path/filepath" ) // ZshCompletionScript replaces Cobra's generated zsh completion. Cobra's script // spawns a subshell per candidate and passes every host through _describe, // which takes tens of seconds for thousands of hosts. This script splits the // candidates with parameter expansion only: entries with a description // (subcommands, flags) go through _describe, plain hostnames through compadd. // // The file works both from fpath (autoloaded as _netssh) and when sourced. const ZshCompletionScript = `#compdef netssh compdef _netssh netssh # netssh zsh completion — generated by netssh, do not edit. _netssh() { local -a lines described plain local out directive=0 entry ret=1 local -a nospace out=$(netssh __complete "${(@)words[2,CURRENT]}" 2>/dev/null) || return 1 lines=("${(@f)out}") if [[ ${lines[-1]} == :<-> ]]; then directive=${lines[-1]#:} lines[-1]=() fi # Directive 1: error. (( directive & 1 )) && return 1 lines=(${lines:#_activeHelp_*}) lines=(${lines:#}) # Directive 2: no trailing space. (( directive & 2 )) && nospace=(-S '') # Directive 8: the lines are file extensions to filter by. if (( directive & 8 )); then local -a globs for entry in $lines; do globs+=("*.${entry}"); done _files -g "(${(j:|:)globs})" return fi # Directive 16: complete directories only. if (( directive & 16 )); then _files -/ return fi described=(${(M)lines:#*$'\t'*}) plain=(${lines:#*$'\t'*}) if (( $#described )); then local -a items for entry in $described; do items+=("${${entry%%$'\t'*}//:/\\:}:${entry#*$'\t'}") done _describe -t commands 'netssh command' items $nospace && ret=0 fi if (( $#plain )); then # netssh already filtered the hosts, also by the name after an instance # prefix: "fsn1" offers "prod/fsn1-…". 'l:|=*' lets zsh accept text # before the typed word instead of discarding these matches. local -a group=(-J hosts) # Directive 32: keep the order supplied by netssh. (( directive & 32 )) && group=(-V hosts) compadd $group -X '%Bhosts%b' -M 'l:|=*' $nospace -- $plain && ret=0 fi # Directive 4: no file completion as a fallback. if (( ! $#lines && ! (directive & 4) )); then _files && ret=0 fi return ret } if [ "$funcstack[1]" = "_netssh" ]; then _netssh "$@" fi ` // ZshCompletionNote tells the user how zsh picks up a completion file in dir. func ZshCompletionNote(dir string) string { dump := filepath.Join(zshDir(), ".zcompdump") return fmt.Sprintf(`zsh loads it from fpath. The netssh block in your .zshrc adds %s (netssh hook install). Otherwise add this before compinit: fpath=(%s $fpath) Then refresh the completion cache: rm -f %s* && exec zsh`, dir, dir, dump) } func zshDir() string { if dir := os.Getenv("ZDOTDIR"); dir != "" { return dir } return os.Getenv("HOME") } // ZshFuncDir is the user directory netssh installs zsh completion files into. func ZshFuncDir() string { return filepath.Join(os.Getenv("HOME"), ".zfunc") }