go-flags

repository·main·Indexed 25 days ago

https://github.com/jessevdk/go-flags

An extensive command line option parser for Go that uses reflection and struct tags to define CLI interfaces. It supports short and long flags, required options, choice restrictions, environment variable integration, and nested subcommands. The library provides interfaces for custom flag unmarshaling, marshaling, validation, and shell completion, as well as the ability to define positional arguments using the Arg type.

Tokens
6.4K
Snippets
11
Records
49
Agent score
82%

What's inside go-flags

  1. Define command line options using struct tags

    main

    The go-flags library uses Go structs and reflection to define command line options. You specify options by adding struct fields with specific tags. Supported tags include:

    • short: Single character short name (e.g., short:"v" for -v).
    • long: Long name (e.g., long:"verbose" for --verbose).
    • description: Help text for the option.
    • required: Set to "true" to make the flag mandatory.
    • choice: Restricts the input to a pre-defined set of strings (e.g., choice:"cat" choice:"dog").
    • value-name: The name used for the argument in the help message (e.g., value-name:"FILE").
    • default: The default value for the option.
    • env: The environment variable name to use if the flag is not provided.
    • env-delim: The delimiter used for environment variable values (e.g., env-delim:",").

    Supported types include all primitive Go types, slices (for multiple occurrences), maps, pointers, and function callbacks.

    type Options struct {
    	Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` 
    	Name    string `short:"n" long:"name" description:"A name" required:"true"` 
    	Animal  string `long:"animal" choice:"cat" choice:"dog"` 
    }
  2. Enable Bash completion for go-flags applications

    main

    go-flags provides built-in support for bash completion. To enable it, your application must be invoked with the environment variable GO_FLAGS_COMPLETION=1.

    Usage: GO_FLAGS_COMPLETION=1 ./your-app arg1 arg2 arg3 (where arg3 is the argument currently being completed).

    Bash Integration Example:

    _completion_example() {
        # All arguments except the first one
        args=("${COMP_WORDS[@]:1:$COMP_CWORD})"
    
        # Only split on newlines
        local IFS=$'\n'
    
        # Call completion
        COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}"))
        return 0
    }
    
    complete -F _completion_example completion-example

    Notes:

    • Completion requires the parser option PassDoubleDash.
    • Setting GO_FLAGS_COMPLETION=verbose will show descriptions of possible completion items if there are more than one.
    • You can customize completion for argument values by implementing the flags.Completer interface.
  3. Implement commands in go-flags

    main

    Commands allow you to separate different functions of your application (similar to git).

    There are two ways to define them:

    1. Use AddCommand on an existing parser.
    2. Add a struct field to your options struct annotated with the command:"command-name" tag.

    Execution Flow: When parsing ends, if an active command implements the Commander interface, its Execute method will be run with the remaining command line arguments.

    Idiomatic Pattern: Define a global parser instance and implement each command in a separate file. Use a go init() function in the command file to call AddCommand on the global parser.

  4. Parse command line options from an INI file

    main

    Use flags.IniParse to quickly load configuration from an INI file into a struct. This function uses default settings and expects the struct to represent the 'Application Options' group.

    For more granular control, create an IniParser using flags.NewIniParser(parser) and use its Parse or ParseFile methods.

  5. Implement option groups

    main

    Option groups semantically separate options in the help output. You can specify them in three ways:

    1. Use NewNamedParser specifying various option groups.
    2. Use AddGroup to add a group to an existing parser.
    3. Add a struct field to the top-level options annotated with the group:"group-name" tag.
  6. Complete usage example of go-flags

    main

    This example demonstrates various features: boolean slices for repeated flags, automatic type marshalling, function callbacks, required flags, choice restrictions, pointers, slices, maps, and environment variable integration.

    var opts struct {
    	Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
    	Offset uint `long:"offset" description:"Offset"`
    	Call func(string) `short:"c" description:"Call phone number"`
    	Name string `short:"n" long:"name" description:"A name" required:"true"`
    	Animal string `long:"animal" choice:"cat" choice:"dog"`
    	File string `short:"f" long:"file" description:"A file" value-name:"FILE"`
    	Ptr *int `short:"p" description:"A pointer to an integer"`
    	StringSlice []string `short:"s" description:"A slice of strings"`
    	PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"`
    	IntMap map[string]int `long:"intmap" description:"A map from string to int"`
    	Thresholds  []int     `long:"thresholds" default:"1" default:"2" env:"THRESHOLD_VALUES"  env-delim:"\","`
    }
    
    opts.Call = func(num string) {
    	cmd := exec.Command("open", "callto:"+num)
    	cmd.Start()
    	cmd.Process.Release()
    }
    
    args := []string{
    	"-vv",
    	"--offset=5",
    	"-n", "Me",
    	"--animal", "dog",
    	"-p", "3",
    	"-s", "hello",
    	"-s", "world",
    	"--ptrslice", "hello",
    	"--ptrslice", "world",
    	"--intmap", "a:1",
    	"--intmap", "b:5",
    	"arg1",
    	"arg2",
    	"arg3",
    }
    
    args, err := flags.ParseArgs(&opts, args)
    if err != nil {
    	panic(err)
    }
    
    fmt.Printf("Verbosity: %v\n", opts.Verbose)
    fmt.Printf("Offset: %d\n", opts.Offset)
    fmt.Printf("Name: %s\n", opts.Name)
    fmt.Printf("Animal: %s\n", opts.Animal)
    fmt.Printf("Ptr: %d\n", *opts.Ptr)
    fmt.Printf("StringSlice: %v\n", opts.StringSlice)
    fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
    fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"])
    fmt.Printf("Remaining args: %s\n", strings.Join(args, " "))
  7. Parse command line arguments with go-flags

    main
    To parse arguments, you can use flags.Parse(&opts) to parse the standard os.Args, or flags.ParseArgs(&opts, args) to parse a specific slice of strings. The latter returns the remaining non-flag arguments and an error if parsing fails.
  8. Retrieve groups and options from a Group

    main

    A Group provides methods to inspect its contents:

    • Groups() []*Group: Returns the list of subgroups embedded in this group.
    • Options() []*Option: Returns the list of options in this group.
  9. Organize CLI flags using Group

    main
    The Group type allows you to logically group options together under a description. Groups can be nested to provide structure to your CLI, which is reflected in the generated help messages and man pages. You can add subgroups or individual options to an existing group.
  10. Check if an error was caused by a help request

    main
    When calling ParseArgs(), an error might be returned if the user requested help (e.g., via -h or --help). Use the WroteHelp helper function to determine if the error returned is specifically a help request. This allows you to distinguish between actual parsing errors and the intentional triggering of the help message.
  11. Handle command execution with `CommandHandler`

    main

    By default, when a command is parsed, the parser calls the command's Execute method (if the command implements the Commander interface). You can override this behavior by setting the CommandHandler field on the Parser.

    The handler receives:

    • command: The Commander instance that was matched.
    • args: The remaining non-option arguments.

    Note: If you override the handler, you are responsible for calling command.Execute within your handler if you want the command to actually run.

  12. Configure CLI options using the Option struct

    main
    The Option struct is used to define the metadata and behavior for command-line flags. You can configure short names, long names, default values, environment variable defaults, requirement constraints, and allowed choices. This struct is typically populated via struct tags when using the go-flags parser, but its fields define the available configuration surface.