Kong Command-Line Parser for Go
repository·master·Indexed 25 days ago
https://github.com/alecthomas/kongA command-line parser for Go that maps complex CLI structures to Go types using struct tags. It supports nested commands, positional arguments, flags, and automatic help generation. Key features include lifecycle hooks, custom help providers via the HelpProvider interface, and the ability to serve a CLI interactively over SSH.
What's inside kong
- Kong is a command-line parser for Go that allows you to express complex command-line structures using Go types. The structure and struct tags direct how the command line is mapped onto your Go structs.
Understand the Hermit environment
masterThis directory is managed by Hermit. The symlinks within this directory are used to automatically download and install Hermit and its associated packages. These packages are scoped locally to this specific environment.Inject Values into Run() Methods
masterWhen implementing command execution via
Run(...) errormethods, you can inject dependencies using several patterns:Bind(value): Bind a value directly.BindTo(interface): Bind a value to an interface type.BindToProvider(func): Bind a value to a provider function.Provide<Type>() error: Implement a provider method on the command structure itself.
Use Variable Interpolation in Help and Defaults
masterKong supports limited variable interpolation in help strings, placeholder strings, enum lists, and default values using the syntax
${<name>}or${<name>=<default>}.Variables can be provided in two ways:
- Via
kong.Vars: Pass a map of variables tokong.Parse. - Via
settag: Use theset:"K=V"tag on a struct field. These variables are available to that node and all its children.
Special variables available during interpolation:
${default}: The default value.${enum}: The list of enum values.${env}: The name of the associated environment variable. If${env}is used in a help string, Kong will automatically append($${env})to the help text.
type cli struct { Config string `type:"path" default:"${config_file}"` } func main() { kong.Parse(&cli, kong.Vars{ "config_file": "~/.app.conf", }) }- Via
Handle commands by attaching a Run() method
masterA robust way to handle commands is to define a
Run(... error)method on your command structs.- Define leaf commands as separate structs.
- Attach a
Run(... error)method to these structs. - Call
ctx.Run(bindings...)to execute the selected command.
Kong will traverse from the selected node back to the root, calling any
Run()methods it encounters in reverse order. This allows for reusable sub-trees.type Context struct { Debug bool } type RmCmd struct { Force bool `help:"Force removal."` Recursive bool `help:"Recursively remove files."` Paths []string `arg:"" name:"path" help:"Paths to remove." type:"path"` } func (r *RmCmd) Run(ctx *Context) error { fmt.Println("rm", r.Paths) return nil } type LsCmd struct { Paths []string `arg:"" optional:"" name:"path" help:"Paths to list." type:"path"` } func (l *LsCmd) Run(ctx *Context) error { fmt.Println("ls", l.Paths) return nil } var cli struct { Debug bool `help:"Enable debug mode."` Rm RmCmd `cmd:"" help:"Remove files."` Ls LsCmd `cmd:"" help:"List paths."` } func main() { ctx := kong.Parse(&cli) // Call the Run() method of the selected parsed command. err := ctx.Run(&Context{Debug: cli.Debug}) ctx.FatalIfErrorf(err) }Generate help documentation in Kong
masterKong automatically generates
--helpdocumentation based on your struct tags (help:"").- Top-level help: Displays available commands and global flags.
- Contextual help: If a command is provided (e.g.,
app --help <command>), Kong shows detailed help for that specific command, including its flags and arguments. - Custom help: Any command or argument type implementing the
Help() stringinterface can provide additional descriptive text that augments the standard help tags.
Implement custom help providers using the HelpProvider interface
masterYou can augment the help text generated by Kong'shelp:""tagged annotations by implementing theHelpProviderinterface. To do this, add aHelp() stringmethod to your command structs, argument structs, or flag types. Kong will call this method to retrieve additional help information for that specific component.Run an interactive Kong server over SSH
masterKong can be used to serve a command-line interface interactively over an SSH connection. This allows users to interact with your application's commands via an SSH client rather than a standard local terminal.Configure CLI definitions using struct tags
masterKong uses Go struct tags to define CLI commands, flags, and arguments. You can use the
kong:tag to specify various properties likename,help,default,required, and more. If a field is marked withkong:"-", it will be ignored by Kong.Properties can be defined directly on the field or via a
Signatureinterface on the type to provide defaults that can be overridden by the field itself.Embed nested data structures
masterUse the
embed:""tag to include nested data structures. You can combine this withprefix:""to create prefixed flags. For example,prefix:"logging."with a fieldLevelwill result in the flag--logging.level.var CLI struct { Logging struct { Level string `enum:"debug,info,warn,error" default:"info"` Type string `enum:"json,console" default:"console"` } `embed:"" prefix:"logging."` }Define a command-line structure with Kong
masterTo use Kong, define a Go struct where fields represent flags, arguments, or sub-commands. Use struct tags like
help:"..."for documentation,cmd:""to define a command, andarg:""for positional arguments.package main import "github.com/alecthomas/kong" var CLI struct { Rm struct { Force bool `help:"Force removal."` Recursive bool `help:"Recursively remove files."` Paths []string `arg:"" name:"path" help:"Paths to remove." type:"path"` } `cmd:"" help:"Remove files."` Ls struct { Paths []string `arg:"" optional:"" name:"path" help:"Paths to list." type:"path"` } `cmd:"" help:"List paths."` } func main() { ctx := kong.Parse(&CLI) switch ctx.Command() { case "rm <path>": case "ls": default: panic(ctx.Command()) } }Define branching positional arguments
masterYou can configure structs as branching positional arguments by tagging an unmapped nested struct field with
arg, and then including a positional argument field inside that struct with the same name as the enclosing field.var CLI struct { Rename struct { Name struct { Name string `arg` // <-- NOTE: identical name to enclosing struct field. To struct { Name struct { Name string `arg` } `cmd` } `cmd` } `arg` } `cmd` }