This is pretty specific to my setup but the idea can be adapted to work with pretty much anything.
Go has a flag package which makes parsing command line arguments really easy.
package main
import "flag"
import "fmt"
var param1 = flag.String("param1", "default-value", "a description for param1")
var param2 = flag.Int64("param2", 123, "a description for param2")
func init() {
flag.Parse()
}
func main() {
fmt.Printf("param1: %s, param2 %d", *param1, *param2)
}
Zsh lets you define custom tab completion scripts. Here's one for the example program above.
foo
is what triggers the completion. So the program would have to be called foo
and be somewhere in your PATH.
#compdef foo
_arguments -s \
'-param1[a description for param1]' \
'-param2[a description for param2]'
This is cool, but typing these out is a pain so let's automate it! The flag package has a VisitAll method which lets you iterate over all defined flags. Using that we can easily create the completion script.
func PrintCompletions(name string) {
var cmpl []string
flag.VisitAll(func(f *flag.Flag) {
cmpl = append(
cmpl, fmt.Sprintf("\t'-%s[%s]' \\\n", f.Name, f.Usage))
})
fmt.Printf("#compdef %s\n\n_arguments -s \\\n%s\n\n",
name, strings.Join(cmpl, " "))
}
Here's a complete example go playground
package main
import (
"flag"
"fmt"
"strings"
)
var (
param1 = flag.String("param1", "foo", "this is param1, it's useless")
param2 = flag.String("param2", "foo", "this is param2, even more useless")
complete = flag.Bool("complete", true, "output zsh completions")
)
func init() {
flag.Parse()
}
func PrintCompletions(name string) {
var cmpl []string
flag.VisitAll(func(f *flag.Flag) {
cmpl = append(
cmpl, fmt.Sprintf("\t'-%s[%s]' \\\n", f.Name, f.Usage))
})
fmt.Print(
fmt.Sprintf("#compdef %s\n\n_arguments -s \\\n%s\n\n",
name, strings.Join(cmpl, " ")),
)
}
func main() {
if *complete {
PrintCompletions("main")
return
}
}
To use it, just pipe the output into a new completion script
$ myapp -complete > ~/.zsh/completion/_myapp
If you need more info about zsh completion scripts, check out this article.
Since --help also works for programs using the flag package, this is superflous: