Kong is a command-line parser for Go

Kong is a command-line parser for Go

CircleCI Go Report Card Slack chat

Introduction

Kong aims to support arbitrarily complex command-line structures with as little developer effort as possible.

To achieve that, command-lines are expressed as Go types, with the structure and tags directing how the command line is mapped onto the struct.

For example, the following command-line:

shell rm [-f] [-r] <paths> ...
shell ls [<paths> ...]

Can be represented by the following command-line structure:

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())
  }
}

Help

Help as a user of a Kong application

Every Kong application includes a --help flag that will display auto-generated help.

eg.

$ shell --help
usage: shell <command>

A shell-like example app.

Flags:
  --help   Show context-sensitive help.
  --debug  Debug mode.

Commands:
  rm <path> ...
    Remove files.

  ls [<path> ...]
    List paths.

If a command is provided, the help will show full detail on the command including all available flags.

eg.

$ shell --help rm
usage: shell rm <paths> ...

Remove files.

Arguments:
  <paths> ...  Paths to remove.

Flags:
      --debug        Debug mode.

  -f, --force        Force removal.
  -r, --recursive    Recursively remove files.

Defining help in Kong

Help is automatically generated from the command-line structure itself, including help:"" and other tags. Variables will also be interpolated into the help string.

Finally, any command, argument, or flag type implementing the interface Help() string will have this function called to retrieve the help string. This allows for much more descriptive text than can fit in Go tags.

Command handling

There are two ways to handle commands in Kong.

Switch on the command string

When you call kong.Parse() it will return a unique string representation of the command. Each command branch in the hierarchy will be a bare word and each branching argument or required positional argument will be the name surrounded by angle brackets. Here's an example:

There's an example of this pattern here.

eg.

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())
  }
}

This has the advantage that it is convenient, but the downside that if you modify your CLI structure, the strings may change. This can be fragile.

Attach a Run(...) error method to each command

A more robust approach is to break each command out into their own structs:

  1. Break leaf commands out into separate structs.
  2. Attach a Run(...) error method to all leaf commands.
  3. Call kong.Kong.Parse() to obtain a kong.Context.
  4. Call kong.Context.Run(bindings...) to call the selected parsed command.

Once a command node is selected by Kong it will search from that node back to the root. Each encountered command node with a Run(...) error will be called in reverse order. This allows sub-trees to be re-used fairly conveniently.

In addition to values bound with the kong.Bind(...) option, any values passed through to kong.Context.Run(...) are also bindable to the target's Run() arguments.

Finally, hooks can also contribute bindings via kong.Context.Bind() and kong.Context.BindTo().

There's a full example emulating part of the Docker CLI here.

eg.

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)
}

Hooks: BeforeResolve(), BeforeApply(), AfterApply() and the Bind() option

If a node in the grammar has a BeforeResolve(...), BeforeApply(...) error and/or AfterApply(...) error method, those methods will be called before validation/assignment and after validation/assignment, respectively.

The --help flag is implemented with a BeforeApply hook.

Arguments to hooks are provided via the Run(...) method or Bind(...) option. *Kong, *Context and *Path are also bound and finally, hooks can also contribute bindings via kong.Context.Bind() and kong.Context.BindTo().

eg.

// A flag with a hook that, if triggered, will set the debug loggers output to stdout.
type debugFlag bool

func (d debugFlag) BeforeApply(logger *log.Logger) error {
  logger.SetOutput(os.Stdout)
  return nil
}

var cli struct {
  Debug debugFlag `help:"Enable debug logging."`
}

func main() {
  // Debug logger going to discard.
  logger := log.New(ioutil.Discard, "", log.LstdFlags)

  ctx := kong.Parse(&cli, kong.Bind(logger))

  // ...
}

Flags

Any mapped field in the command structure not tagged with cmd or arg will be a flag. Flags are optional by default.

eg. The command-line app [--flag="foo"] can be represented by the following.

type CLI struct {
  Flag string
}

Commands and sub-commands

Sub-commands are specified by tagging a struct field with cmd. Kong supports arbitrarily nested commands.

eg. The following struct represents the CLI structure command [--flag="str"] sub-command.

type CLI struct {
  Command struct {
    Flag string

    SubCommand struct {
    } `cmd`
  } `cmd`
}

If a sub-command is tagged with default:"1" it will be selected if there are no further arguments.

Branching positional arguments

In addition to sub-commands, structs can also be configured as branching positional arguments.

This is achieved by tagging an unmapped nested struct field with arg, then including a positional argument field inside that struct with the same name. For example, the following command structure:

app rename <name> to <name>

Can be represented with the following:

var CLI struct {
  Rename struct {
    Name struct {
      Name string `arg` // <-- NOTE: identical name to enclosing struct field.
      To struct {
        Name struct {
          Name string `arg`
        } `arg`
      } `cmd`
    } `arg`
  } `cmd`
}

This looks a little verbose in this contrived example, but typically this will not be the case.

Terminating positional arguments

If a mapped type is tagged with arg it will be treated as the final positional values to be parsed on the command line.

If a positional argument is a slice, all remaining arguments will be appended to that slice.

Slices

Slice values are treated specially. First the input is split on the sep:"<rune>" tag (defaults to ,), then each element is parsed by the slice element type and appended to the slice. If the same value is encountered multiple times, elements continue to be appended.

To represent the following command-line:

cmd ls <file> <file> ...

You would use the following:

var CLI struct {
  Ls struct {
    Files []string `arg type:"existingfile"`
  } `cmd`
}

Maps

Maps are similar to slices except that only one key/value pair can be assigned per value, and the sep tag denotes the assignment character and defaults to =.

To represent the following command-line:

cmd config set <key>=<value> <key>=<value> ...

You would use the following:

var CLI struct {
  Config struct {
    Set struct {
      Config map[string]float64 `arg type:"file:"`
    } `cmd`
  } `cmd`
}

For flags, multiple key+value pairs should be separated by mapsep:"rune" tag (defaults to ;) eg. --set="key1=value1;key2=value2".

Custom named decoders

Kong includes a number of builtin custom type mappers. These can be used by specifying the tag type:"<type>". They are registered with the option function NamedMapper(name, mapper).

Name Description
path A path. ~ expansion is applied. - is accepted for stdout, and will be passed unaltered.
existingfile An existing file. ~ expansion is applied. - is accepted for stdin, and will be passed unaltered.
existingdir An existing directory. ~ expansion is applied.
counter Increment a numeric field. Useful for -vvv. Can accept -s, --long or --long=N.

Slices and maps treat type tags specially. For slices, the type:"" tag specifies the element type. For maps, the tag has the format tag:"[<key>]:[<value>]" where either may be omitted.

Supported field types

Custom decoders (mappers)

Any field implementing encoding.TextUnmarshaler or json.Unmarshaler will use those interfaces for decoding values. Kong also includes builtin support for many common Go types:

Type Description
time.Duration Populated using time.ParseDuration().
time.Time Populated using time.Parse(). Format defaults to RFC3339 but can be overridden with the format:"X" tag.
*os.File Path to a file that will be opened, or - for os.Stdin. File must be closed by the user.
*url.URL Populated with url.Parse().

For more fine-grained control, if a field implements the MapperValue interface it will be used to decode arguments into the field.

Supported tags

Tags can be in two forms:

  1. Standard Go syntax, eg. kong:"required,name='foo'".
  2. Bare tags, eg. required name:"foo"

Both can coexist with standard Tag parsing.

Tag Description
cmd If present, struct is a command.
arg If present, field is an argument.
env:"X" Specify envar to use for default value.
name:"X" Long name, for overriding field name.
help:"X" Help text.
type:"X" Specify named types to use.
placeholder:"X" Placeholder text.
default:"X" Default value.
default:"1" On a command, make it the default.
short:"X" Short name, if flag.
aliases:"X,Y" One or more aliases (for cmd).
required If present, flag/arg is required.
optional If present, flag/arg is optional.
hidden If present, command or flag is hidden.
negatable If present on a bool field, supports prefixing a flag with --no- to invert the default value
format:"X" Format for parsing input, if supported.
sep:"X" Separator for sequences (defaults to ","). May be none to disable splitting.
mapsep:"X" Separator for maps (defaults to ";"). May be none to disable splitting.
enum:"X,Y,..." Set of valid values allowed for this flag.
group:"X" Logical group for a flag or command.
xor:"X" Exclusive OR group for flags. Only one flag in the group can be used which is restricted within the same command.
prefix:"X" Prefix for all sub-flags.
set:"K=V" Set a variable for expansion by child elements. Multiples can occur.
embed If present, this field's children will be embedded in the parent. Useful for composition.
- Ignore the field. Useful for adding non-CLI fields to a configuration struct.

Plugins

Kong CLI's can be extended by embedding the kong.Plugin type and populating it with pointers to Kong annotated structs. For example:

var pluginOne struct {
  PluginOneFlag string
}
var pluginTwo struct {
  PluginTwoFlag string
}
var cli struct {
  BaseFlag string
  kong.Plugins
}
cli.Plugins = kong.Plugins{&pluginOne, &pluginTwo}

Additionally if an interface type is embedded, it can also be populated with a Kong annotated struct.

Variable interpolation

Kong supports limited variable interpolation into help strings, enum lists and default values.

Variables are in the form:

${<name>}
${<name>=<default>}

Variables are set with the Vars{"key": "value", ...} option. Undefined variable references in the grammar without a default will result in an error at construction time.

Variables can also be set via the set:"K=V" tag. In this case, those variables will be available for that node and all children. This is useful for composition by allowing the same struct to be reused.

When interpolating into flag or argument help strings, some extra variables are defined from the value itself:

${default}
${enum}

For flags with associated environment variables, the variable ${env} can be interpolated into the help string. In the absence of this variable in the help string, Kong will append ($$${env}) to the help string.

eg.

type cli struct {
  Config string `type:"path" default:"${config_file}"`
}

func main() {
  kong.Parse(&cli,
    kong.Vars{
      "config_file": "~/.app.conf",
    })
}

Validation

Kong does validation on the structure of a command-line, but also supports extensible validation. Any node in the tree may implement the following interface:

type Validatable interface {
    Validate() error
 }

+If one of these nodes is in the active command-line it will be called during +normal validation.

Modifying Kong's behaviour

Each Kong parser can be configured via functional options passed to New(cli interface{}, options...Option).

The full set of options can be found here.

Name(help) and Description(help) - set the application name description

Set the application name and/or description.

The name of the application will default to the binary name, but can be overridden with Name(name).

As with all help in Kong, text will be wrapped to the terminal.

Configuration(loader, paths...) - load defaults from configuration files

This option provides Kong with support for loading defaults from a set of configuration files. Each file is opened, if possible, and the loader called to create a resolver for that file.

eg.

kong.Parse(&cli, kong.Configuration(kong.JSON, "/etc/myapp.json", "~/.myapp.json"))

See the tests for an example of how the JSON file is structured.

Resolver(...) - support for default values from external sources

Resolvers are Kong's extension point for providing default values from external sources. As an example, support for environment variables via the env tag is provided by a resolver. There's also a builtin resolver for JSON configuration files.

Example resolvers can be found in resolver.go.

*Mapper(...) - customising how the command-line is mapped to Go values

Command-line arguments are mapped to Go values via the Mapper interface:

// A Mapper knows how to map command-line input to Go.
type Mapper interface {
  // Decode scan into target.
  //
  // "ctx" contains context about the value being decoded that may be useful
  // to some mappers.
  Decode(ctx *MapperContext, scan *Scanner, target reflect.Value) error
}

All builtin Go types (as well as a bunch of useful stdlib types like time.Time) have mappers registered by default. Mappers for custom types can be added using kong.??Mapper(...) options. Mappers are applied to fields in four ways:

  1. NamedMapper(string, Mapper) and using the tag key type:"<name>".
  2. KindMapper(reflect.Kind, Mapper).
  3. TypeMapper(reflect.Type, Mapper).
  4. ValueMapper(interface{}, Mapper), passing in a pointer to a field of the grammar.

ConfigureHelp(HelpOptions) and Help(HelpFunc) - customising help

The default help output is usually sufficient, but if not there are two solutions.

  1. Use ConfigureHelp(HelpOptions) to configure how help is formatted (see HelpOptions for details).
  2. Custom help can be wired into Kong via the Help(HelpFunc) option. The HelpFunc is passed a Context, which contains the parsed context for the current command-line. See the implementation of PrintHelp for an example.
  3. Use HelpFormatter(HelpValueFormatter) if you want to just customize the help text that is accompanied by flags and arguments.
  4. Use Groups([]Group) if you want to customize group titles or add a header.

Bind(...) - bind values for callback hooks and Run() methods

See the section on hooks for details.

Other options

The full set of options can be found here.

Comments
  • env interpolation does not seem to work

    env interpolation does not seem to work

    I have the following structure:

    type Config struct {
    	Project   string `short:"p" env:"CI_PROJECT_ID" help:"Environment variable: ${env}"`
    }
    

    When I try to use it, I get:

    panic: help for --project=STRING: undefined variable ${env}
    

    I am using kong v0.2.18.

  • Unable to fully capture the rest of arguments and pass it through to another command

    Unable to fully capture the rest of arguments and pass it through to another command

    So I am trying to implement exec pattern, where I have a subtool I want to execute and pass all other arguments to it. Trying passthrough:"" does not fully work with --help flag. I have something like:

    type Commands struct {
    	Exec ExecCommand `cmd:"" help:"Run the sub-tool.`
    }
    
    type ExecCommand struct {
            Arg []string `arg:"" optional:"" passthrough:"" help:"Arguments passed on to the sub-tool."`
    }
    

    Inside ExecCommand's Run I do: subtool.Main(append([]string{"subtool"}, c.Arg...)) to pass all args to the subtool's CLI parsing.

    And this does not work. So if I do:

    tool exec foobar
    

    it works well, and sub-tool gets foobar as an argument.

    But:

    tool exec --help
    

    returns help of tool and not of the sub-tool.

    A workaround is:

    tool exec -- --help
    

    which does work. But how can I make it work without --? I think this might be related to https://github.com/alecthomas/kong/discussions/216 and in general that I would prefer that global flags do not get inherited by the subcommands. So in general tool --help subcommand should work and tool subcommand --help should not, unless subcommand explicitly defines --help flag.

    I tried to move passthrough:"" to Exec itself, but I got panic passthrough only makes sense for positional arguments.

  • Add support for negatable boolean flags

    Add support for negatable boolean flags

    Adds support for a new negatable struct tag, which will automatically set a boolean Struct flag value to false if the flag's name starts with --no-, even when the default is true. This idea is shamelessly stolen from the commander npm library

    For example:

    type Cmd struct {
      Sort bool `default:"true",negatable`
    }
    

    Calling

    command
    # or
    command --sort
    

    Will set Sort to true, but

    command --no-sort
    

    Will set Sort to false.

    Why do this?

    It avoids the situation of having to do:

    type Cmd struct {
      NoSort bool
    }
    
    func (c *Cmd) Run() error {
      if !c.NoSort {
        // Double negations are hard to read!
      }
      return nil
    }
    
  • `-x` in an `arg` string slice confuses kong

    `-x` in an `arg` string slice confuses kong

    I'm writing a program that takes a bunch of arguments, as well as a shell command as input (interpreted by kong as an arg) and exec's that command after doing a little processing. Unfortunately, kong doesn't deal well with the presence of short arguments given to the command-as-argument confuse kong and it errors. Here's an example:

    package main
    
    import (
    	"fmt"
    
    	"github.com/alecthomas/kong"
    )
    
    var CLI struct {
    	Run struct {
    		Cmd []string `arg name:"command" help:"Command to run."`
    	} `cmd help:"Run command."`
    }
    
    func main() {
    	ctx := kong.Parse(&CLI)
    	switch ctx.Command() {
    	case "run <command>":
    		fmt.Println(CLI)
    	default:
    		panic(ctx.Command())
    	}
    }
    

    Results

    A plain command works:

    $ go run main.go run ls
    {{[ls]}}
    

    A command with flags works after a --:

    $ go run main.go run -- ls -la
    {{[ls -la]}}
    

    A command with flags is interpreted by kong and errors:

    $ go run main.go run ls -la
    main: error: unknown flag -l
    exit status 1
    

    Expected result

    I would have expected kong to stop parsing further arguments once it finds things fitting the terminating argument string slice & treat the command line given above like it does it in the "works after a --" example.

    Workaround

    Have users pass in the -- flag, but that they can pass the un----escaped command line means if they start out without the escape and then add flags later, the command may fail without them realizing (or expecting) it.

  • Example of custom validation?

    Example of custom validation?

    I had a look around the README and the examples and couldn't see an example of the canonical way to do custom validation for a flag. Apologies the issue question!

    I assume I need a custom type and then to use BeforeApply to validate it, but I can't figure out what to bind in there, I tried kong.Value, but no luck (e.g couldn't find binding of type kong.Value...)

    Am Iooking at this wrong? Does Validation occur elseswhere?

    For context, the problem I am trying to solve is a complex relationship between flags (more than what xor can handle).

  • Is there a way to validate a flag which is set via an ENV variable?

    Is there a way to validate a flag which is set via an ENV variable?

    So if i have a flag as follows, can i validate this is set without adding required?

    The rational is I just want to know if it was defaulted from an ENV or set via a command flag.

    Stage      stageFlag  `help:"The stage this is deployed." env:"STAGE"`
    

    Cheers

  • Allow single dash as argument value

    Allow single dash as argument value

    Some CLI tools traditionally use the single dash to mean "stdin".

    Examples are tar tvfz - or cat -

    Kong however chokes when encountering a - not followed with a letter with error: expected short flag.

  • Discussion about Help

    Discussion about Help

    While I was working on custom HelpPrinter implementation I realized that I had to copy a lot of code from the DefaultHelpPrinter function. And with the newly added interpolation of the $env variable, the current HelpPrinter function is very close to what I was looking for. To close the gap I would like propose the following changes:

    1) Better representation of enum values as placeholder

    For the following Tags:

    StringFlag string `enum:"a,b,c" help:"Help."`
    

    I would like to see the following placeholder:

    Flags:
          --string-flag=a|b|c        Help.
    

    And if there is a default tag:

    StringFlag string `enum:"a,b,c" help:"Help." default:"b"`
    

    Maybe something like this:

    Flags:
          --string-flag=a|(b)|c        Help.
    

    Or maybe even make the selected value bold with github.com/fatih/color.

    2) AutomaticEnv option

    Add a new Option AutomaticEnv which would do the following:

    Visit all flags and args and sets the empty env field tags with the following:

    strings.ToUpper(app.Model.Name+"_"+strings.ReplaceAll(flag.Name,"-","_"))
    

    So a flag-name would correspond to APPNAME_FLAG_NAME

    Let me know what you think. I am willing to do the implementation if you want.

  • "existingfile"/"existingdir" always checks default value

    When type:"existingfile" is given, kong checks if the default value exists as a file even the config value is explicitly set to something else.

  • Backslash characters removed from Windows paths using []string and existingFile

    Backslash characters removed from Windows paths using []string and existingFile

    This code:

    package main
    
    import (
    	"fmt"
    
    	"github.com/alecthomas/kong"
    )
    
    type arg struct {
    	InputFile  string   `short:"i"  type:"existingFile"`
    	InputPath  string   `short:"p"  type:"path"`
    	InputFiles []string `short:"f" type:"existingFile"`
    	InputPaths []string `short:"t"  type:"path"`
    }
    
    var Arg arg
    
    func main() {
    	kong.Parse(&Arg)
    	fmt.Println("InputFile:", Arg.InputFile)
    	fmt.Println("InputPath", Arg.InputPath)
    	fmt.Println("InputFiles:", Arg.InputFiles)
    	fmt.Println("InputPaths", Arg.InputPaths)
    }
    

    With this command line:

    
    kt.exe -i c:\temp\foo.json -p c:\myfolderpath\subfolder -f c:\temp\foo.resjson -t c:\somefolder\subfolder
    
    

    Prints this. Notice InputFiles value is missing all the \ and InputPaths is missing the last one

    InputFile: c:\temp\foo.json
    InputPath c:\myfolderpath\subfolder
    InputFiles: [c:tempfoo.resjson]
    InputPaths [C:\temp\somefoldersubfolder]
    
  • Panic on building sub-commands that are pointers.

    Panic on building sub-commands that are pointers.

    Hi Alec - thank you for writing the library!

    Last we spoke, we discussed the possibility of generating CLI flags from protobuf schemas (that when compiled, inject kong struct tags).

    I've decided to give this approach a whirl but am getting stuck on kong panic'ing when I attempt to .Parse(opts).

    My generated opts struct looks as follows:

    type CLIOptions struct {
    	// @gotags: kong:"embed"
    	Global *GlobalCLIOptions `protobuf:"bytes,1,opt,name=global,proto3" json:"global,omitempty" kong:"embed"`
    	// @gotags: kong:"cmd"
    	Server               *ServerConfig `protobuf:"bytes,5,opt,name=server,proto3" json:"server,omitempty" kong:"cmd"`
    	//XXX_NoUnkeyedLiteral struct{}      `json:"-"`
    	//XXX_unrecognized     []byte        `json:"-"`
    	//XXX_sizecache        int32         `json:"-"`
    }
    

    GlobalCLIOptions looks like this:

    type GlobalCLIOptions struct {
    	Debug                  bool     `protobuf:"varint,1,opt,name=debug,proto3" json:"debug,omitempty"`
    	Quiet                  bool     `protobuf:"varint,2,opt,name=quiet,proto3" json:"quiet,omitempty"`
    	StatsEnable            bool     `protobuf:"varint,3,opt,name=stats_enable,json=statsEnable,proto3" json:"stats_enable,omitempty"`
    	StatsReportIntervalSec int32    `protobuf:"varint,4,opt,name=stats_report_interval_sec,json=statsReportIntervalSec,proto3" json:"stats_report_interval_sec,omitempty"`
    

    and ServerConfig looks like this:

    	// Unique ID that identifies this plumber node
    	NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
    ... cut rest of the fields - they're all primitives and the XXX fields are commented
    

    After CLIOptions is instantiated fully and I attempt to do a kong.Parse(opts), I get the following:

    panic: unsupported field type protos.CLIOptions.ServerConfig (of type *protos.ServerConfig), perhaps missing a cmd:"" tag?
    
    goroutine 1 [running]:
    github.com/alecthomas/kong.Parse(0x1539d80, 0xc00006e960, 0x0, 0x0, 0x0, 0xc000000180)
    	/Users/dselans/Code/batch/cli-test/vendor/github.com/alecthomas/kong/global.go:11 +0x145
    main.main()
    	/Users/dselans/Code/batch/cli-test/kong-latest.go:295 +0xc6
    exit status 2
    

    Additional (potentially helpful?) context:

    • protos is the vendored lib containing the compiled/generated pb's.
    • If I comment out Server from CLIOptions - the parse does not panic
    • If I leave only Server - still panics
    • I've tried dumbing down Server to just a string - still panics
    • Kong version: v0.2.17

    Appreciate any help!

  • `filecontent` argument fields appear to accept multiple arguments

    `filecontent` argument fields appear to accept multiple arguments

    I just updated to the latest commit (919e70103f7a7068ebccb991e24836f2933529fd) because I wanted to use the new type:"filecontent" feature (thank you!). It works as expected, but I notice in the help output the argument is followed by ..., which I believe implies multiple arguments could be supplied. Is this an artifact of the field type being []byte?

    See <function-io> in the help output below.

    $ _output/bin/linux_arm64/xfn run negz/xfn-nop:latest ~/fnio.yaml moo
    Usage: crossplane run <image> <function-io> ...
    
    Run a Composition Function.
    
    Arguments:
      <image>              OCI image to run.
      <function-io> ...    YAML encoded FunctionIO to pass to the function.
    
    Flags:
      -h, --help                   Show context-sensitive help.
      -d, --debug                  Print verbose logging statements.
      -v, --version                Print version and quit.
    
      -c, --cache-dir="/xfn"       Directory used for caching function images and containers.
          --timeout=30s            Maximum time for which the function may run before being killed.
          --map-root-uid=100000    UID that will map to 0 in the function's user namespace. The following 65336 UIDs must be available. Ignored if xfn does not have CAP_SETUID and CAP_SETGID.
          --map-root-gid=100000    GID that will map to 0 in the function's user namespace. The following 65336 GIDs must be available. Ignored if xfn does not have CAP_SETUID and CAP_SETGID.
    
    // Command runs a Composition function.
    type Command struct {
    	CacheDir   string        `short:"c" help:"Directory used for caching function images and containers." default:"/xfn"`
    	Timeout    time.Duration `help:"Maximum time for which the function may run before being killed." default:"30s"`
    	MapRootUID int           `help:"UID that will map to 0 in the function's user namespace. The following 65336 UIDs must be available. Ignored if xfn does not have CAP_SETUID and CAP_SETGID." default:"100000"`
    	MapRootGID int           `help:"GID that will map to 0 in the function's user namespace. The following 65336 GIDs must be available. Ignored if xfn does not have CAP_SETUID and CAP_SETGID." default:"100000"`
    
    	Image      string `arg:"" help:"OCI image to run."`
    	FunctionIO []byte `arg:"" help:"YAML encoded FunctionIO to pass to the function." type:"filecontent"`
    }
    
  • Ignore required field if struct already has a default value

    Ignore required field if struct already has a default value

    Hello, Does kong support autoignore errors if struct field has required flag and already has a value?

    type Config struct {
      AppName        string `kong:"required"`
    }
    
    func main() {
    cfg := Config{}
    cfg.AppName = "test"
    
    kong.Parse(&cfg) will result into error -app-name flag is not set
    }
    
    

    Thanks

  • "prefix" doesn't prefix xor names

    type DBConfig struct {
    	Password         string         `help:"Password" xor:"password" optional:""`
    	PasswordFile     string         `help:"File which content will be used for a password" xor:"password" optional:""`
    	PasswordCommand  string         `help:"Command to run to retrieve password" xor:"password" optional:""`
    }
    
    type SourceTargetConfig struct {
    	Source DBConfig `help:"Database config of source to be copied from" prefix:"source-" embed:""`
    	Target DBConfig `help:"Database config of source to be copied from" prefix:"target-" embed:""`
    }
    

    I get error:

    --source-password --target-password can't be used together
    
  • In command's Validate I cannot access top-level configuration/flags

    In command's Validate I cannot access top-level configuration/flags

    I have a bit of a chicken and egg problem. In top-level Validate I cannot know which command user has selected. And if I put Validate on the command struct, then I cannot access top-level configuration/flags. Maybe Validate should get kong.Context as a parameter?

  • `${default}` not interpolated into `help` if using vars

    `${default}` not interpolated into `help` if using vars

    type cli struct {
      Config string `type:"path" default:"${config_file}" help:"Default: ${default}"`
    }
    
    func main() {
      kong.Parse(&cli,
        kong.Vars{
          "config_file": "~/.app.conf",
        })
    }
    

    This prints in help Default: ${config_file} and not Default: ~/.app.conf.

A command line tool that builds and (re)starts your web application everytime you save a Go or template fileA command line tool that builds and (re)starts your web application everytime you save a Go or template file

# Fresh Fresh is a command line tool that builds and (re)starts your web application everytime you save a Go or template file. If the web framework yo

Nov 22, 2021
A command line tool to prompt for a value to be included in another command line.

readval is a command line tool which is designed for one specific purpose—to prompt for a value to be included in another command line. readval prints

Dec 22, 2021
go command line option parser

go-flags: a go library for parsing command line arguments This library provides similar functionality to the builtin flag library of go, but provides

Jan 4, 2023
Fully featured Go (golang) command line option parser with built-in auto-completion support.

go-getoptions Go option parser inspired on the flexibility of Perl’s GetOpt::Long. Table of Contents Quick overview Examples Simple script Program wit

Dec 14, 2022
CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser

CONTRIBUTIONS ONLY What does this mean? I do not have time to fix issues myself. The only way fixes or new features will be added is by people submitt

Dec 29, 2022
A simple command line time description parser

Zeit Zeit is an extremely simple command line application to read a natural language time description and output it as a timestamp. The main usecase f

Aug 21, 2021
Brigodier is a command parser & dispatcher, designed and developed for command lines such as for Discord bots or Minecraft chat commands. It is a complete port from Mojang's "brigadier" into Go.

brigodier Brigodier is a command parser & dispatcher, designed and developed to provide a simple and flexible command framework. It can be used in man

Dec 15, 2022
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.

asciigraph Go package to make lightweight ASCII line graphs ╭┈╯. Installation go get github.com/guptarohit/asciigraph Usage Basic graph package main

Jan 8, 2023
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.

Table of contents Introduction Reference Contributing Introduction Overview git-xargs is a command-line tool (CLI) for making updates across multiple

Dec 31, 2022
git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command
git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command

git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command. You give git-xargs:

Feb 5, 2022
Package command provide simple API to create modern command-line interface

Package command Package command provide simple API to create modern command-line interface, mainly for lightweight usage, inspired by cobra Usage pack

Jan 16, 2022
A command line tool for simplified docker volume command built with go

dockervol A command line tool for simplified docker volume command built with go. Features: Remove anonymous volume (beta) Remove volume by matching n

Dec 18, 2021
Watcher - A simple command line app to watch files in a directory for changes and run a command when files change!

Watcher - Develop your programs easily Watcher watches all the files present in the directory it is run from of the directory that is specified while

Mar 27, 2022
minigli is a tiny command argument parser for Go.

minigli is a tiny command argument parser for Go.

Jan 29, 2022
LINE account link: Sample code for LINE account link
LINE account link: Sample code for LINE account link

LINE account link: Sample code for LINE account link This is sample code to demostration LINE chatbot account link, refer to document https://develope

Dec 11, 2021
argv - Go library to split command line string as arguments array using the bash syntax.

Argv Argv is a library for Go to split command line string into arguments array. Documentation Documentation can be found at Godoc Example func TestAr

Nov 19, 2022
CLI - A package for building command line app with go
CLI - A package for building command line app with go

Command line interface Screenshot Key features Lightweight and easy to use. Defines flag by tag, e.g. flag name(short or/and long), description, defau

Dec 23, 2022
Simple and complete API for building command line applications in Go

Simple and complete API for building command line applications in Go Module cli provides a simple, fast and complete API for building command line app

Nov 23, 2022
Golang library with POSIX-compliant command-line UI (CLI) and Hierarchical-configuration. Better substitute for stdlib flag.
Golang library with POSIX-compliant command-line UI (CLI) and Hierarchical-configuration. Better substitute for stdlib flag.

cmdr cmdr is a POSIX-compliant, command-line UI (CLI) library in Golang. It is a getopt-like parser of command-line options, be compatible with the ge

Oct 28, 2022