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 submitting PRs. If you are interested in taking over maintenance and have a history of contributions to Kingpin, please let me know.

Current status. Kingpin is largely feature stable. There hasn't been a need to add new features in a while, but there are some bugs that should be fixed.

Why? I no longer use Kingpin personally (I now use kong). Rather than leave the project in a limbo of people filing issues and wondering why they're note being worked on, I believe this notice will more clearly set expectations.

Kingpin - A Go (golang) command line and flag parser

Build Status Gitter chat

Overview

Kingpin is a fluent-style, type-safe command-line parser. It supports flags, nested commands, and positional arguments.

Install it with:

$ go get gopkg.in/alecthomas/kingpin.v2

It looks like this:

var (
  verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
  name    = kingpin.Arg("name", "Name of user.").Required().String()
)

func main() {
  kingpin.Parse()
  fmt.Printf("%v, %s\n", *verbose, *name)
}

More examples are available.

Second to parsing, providing the user with useful help is probably the most important thing a command-line parser does. Kingpin tries to provide detailed contextual help if --help is encountered at any point in the command line (excluding after --).

Features

  • Help output that isn't as ugly as sin.
  • Fully customisable help, via Go templates.
  • Parsed, type-safe flags (kingpin.Flag("f", "help").Int())
  • Parsed, type-safe positional arguments (kingpin.Arg("a", "help").Int()).
  • Parsed, type-safe, arbitrarily deep commands (kingpin.Command("c", "help")).
  • Support for required flags and required positional arguments (kingpin.Flag("f", "").Required().Int()).
  • Support for arbitrarily nested default commands (command.Default()).
  • Callbacks per command, flag and argument (kingpin.Command("c", "").Action(myAction)).
  • POSIX-style short flag combining (-a -b -> -ab).
  • Short-flag+parameter combining (-a parm -> -aparm).
  • Read command-line from files (@<file>).
  • Automatically generate man pages (--help-man).

User-visible changes between v1 and v2

Flags can be used at any point after their definition.

Flags can be specified at any point after their definition, not just immediately after their associated command. From the chat example below, the following used to be required:

$ chat --server=chat.server.com:8080 post --image=~/Downloads/owls.jpg pics

But the following will now work:

$ chat post --server=chat.server.com:8080 --image=~/Downloads/owls.jpg pics

Short flags can be combined with their parameters

Previously, if a short flag was used, any argument to that flag would have to be separated by a space. That is no longer the case.

API changes between v1 and v2

  • ParseWithFileExpansion() is gone. The new parser directly supports expanding @<file>.
  • Added FatalUsage() and FatalUsageContext() for displaying an error + usage and terminating.
  • Dispatch() renamed to Action().
  • Added ParseContext() for parsing a command line into its intermediate context form without executing.
  • Added Terminate() function to override the termination function.
  • Added UsageForContextWithTemplate() for printing usage via a custom template.
  • Added UsageTemplate() for overriding the default template to use. Two templates are included:
    1. DefaultUsageTemplate - default template.
    2. CompactUsageTemplate - compact command template for larger applications.

Versions

Kingpin uses gopkg.in for versioning.

The current stable version is gopkg.in/alecthomas/kingpin.v2. The previous version, gopkg.in/alecthomas/kingpin.v1, is deprecated and in maintenance mode.

V2 is the current stable version

Installation:

$ go get gopkg.in/alecthomas/kingpin.v2

V1 is the OLD stable version

Installation:

$ go get gopkg.in/alecthomas/kingpin.v1

Change History

  • 2015-09-19 -- Stable v2.1.0 release.

    • Added command.Default() to specify a default command to use if no other command matches. This allows for convenient user shortcuts.
    • Exposed HelpFlag and VersionFlag for further customisation.
    • Action() and PreAction() added and both now support an arbitrary number of callbacks.
    • kingpin.SeparateOptionalFlagsUsageTemplate.
    • --help-long and --help-man (hidden by default) flags.
    • Flags are "interspersed" by default, but can be disabled with app.Interspersed(false).
    • Added flags for all simple builtin types (int8, uint16, etc.) and slice variants.
    • Use app.Writer(os.Writer) to specify the default writer for all output functions.
    • Dropped os.Writer prefix from all printf-like functions.
  • 2015-05-22 -- Stable v2.0.0 release.

    • Initial stable release of v2.0.0.
    • Fully supports interspersed flags, commands and arguments.
    • Flags can be present at any point after their logical definition.
    • Application.Parse() terminates if commands are present and a command is not parsed.
    • Dispatch() -> Action().
    • Actions are dispatched after all values are populated.
    • Override termination function (defaults to os.Exit).
    • Override output stream (defaults to os.Stderr).
    • Templatised usage help, with default and compact templates.
    • Make error/usage functions more consistent.
    • Support argument expansion from files by default (with @).
    • Fully public data model is available via .Model().
    • Parser has been completely refactored.
    • Parsing and execution has been split into distinct stages.
    • Use go generate to generate repeated flags.
    • Support combined short-flag+argument: -fARG.
  • 2015-01-23 -- Stable v1.3.4 release.

    • Support "--" for separating flags from positional arguments.
    • Support loading flags from files (ParseWithFileExpansion()). Use @FILE as an argument.
    • Add post-app and post-cmd validation hooks. This allows arbitrary validation to be added.
    • A bunch of improvements to help usage and formatting.
    • Support arbitrarily nested sub-commands.
  • 2014-07-08 -- Stable v1.2.0 release.

    • Pass any value through to Strings() when final argument. Allows for values that look like flags to be processed.
    • Allow --help to be used with commands.
    • Support Hidden() flags.
    • Parser for units.Base2Bytes type. Allows for flags like --ram=512MB or --ram=1GB.
    • Add an Enum() value, allowing only one of a set of values to be selected. eg. Flag(...).Enum("debug", "info", "warning").
  • 2014-06-27 -- Stable v1.1.0 release.

    • Bug fixes.
    • Always return an error (rather than panicing) when misconfigured.
    • OpenFile(flag, perm) value type added, for finer control over opening files.
    • Significantly improved usage formatting.
  • 2014-06-19 -- Stable v1.0.0 release.

    • Support cumulative positional arguments.
    • Return error rather than panic when there are fatal errors not caught by the type system. eg. when a default value is invalid.
    • Use gokpg.in.
  • 2014-06-10 -- Place-holder streamlining.

    • Renamed MetaVar to PlaceHolder.
    • Removed MetaVarFromDefault. Kingpin now uses heuristics to determine what to display.

Examples

Simple Example

Kingpin can be used for simple flag+arg applications like so:

$ ping --help
usage: ping [<flags>] <ip> [<count>]

Flags:
  --debug            Enable debug mode.
  --help             Show help.
  -t, --timeout=5s   Timeout waiting for ping.

Args:
  <ip>        IP address to ping.
  [<count>]   Number of packets to send
$ ping 1.2.3.4 5
Would ping: 1.2.3.4 with timeout 5s and count 5

From the following source:

package main

import (
  "fmt"

  "gopkg.in/alecthomas/kingpin.v2"
)

var (
  debug   = kingpin.Flag("debug", "Enable debug mode.").Bool()
  timeout = kingpin.Flag("timeout", "Timeout waiting for ping.").Default("5s").OverrideDefaultFromEnvar("PING_TIMEOUT").Short('t').Duration()
  ip      = kingpin.Arg("ip", "IP address to ping.").Required().IP()
  count   = kingpin.Arg("count", "Number of packets to send").Int()
)

func main() {
  kingpin.Version("0.0.1")
  kingpin.Parse()
  fmt.Printf("Would ping: %s with timeout %s and count %d\n", *ip, *timeout, *count)
}

Reading arguments from a file

Kingpin supports reading arguments from a file. Creat a file with the corresponding arguments:

echo -t=5\n > args

And now supply it:

$ ping @args

Complex Example

Kingpin can also produce complex command-line applications with global flags, subcommands, and per-subcommand flags, like this:

$ chat --help
usage: chat [<flags>] <command> [<flags>] [<args> ...]

A command-line chat application.

Flags:
  --help              Show help.
  --debug             Enable debug mode.
  --server=127.0.0.1  Server address.

Commands:
  help [<command>]
    Show help for a command.

  register <nick> <name>
    Register a new user.

  post [<flags>] <channel> [<text>]
    Post a message to a channel.

$ chat help post
usage: chat [<flags>] post [<flags>] <channel> [<text>]

Post a message to a channel.

Flags:
  --image=IMAGE  Image to post.

Args:
  <channel>  Channel to post to.
  [<text>]   Text to post.

$ chat post --image=~/Downloads/owls.jpg pics
...

From this code:

package main

import (
  "os"
  "strings"
  "gopkg.in/alecthomas/kingpin.v2"
)

var (
  app      = kingpin.New("chat", "A command-line chat application.")
  debug    = app.Flag("debug", "Enable debug mode.").Bool()
  serverIP = app.Flag("server", "Server address.").Default("127.0.0.1").IP()

  register     = app.Command("register", "Register a new user.")
  registerNick = register.Arg("nick", "Nickname for user.").Required().String()
  registerName = register.Arg("name", "Name of user.").Required().String()

  post        = app.Command("post", "Post a message to a channel.")
  postImage   = post.Flag("image", "Image to post.").File()
  postChannel = post.Arg("channel", "Channel to post to.").Required().String()
  postText    = post.Arg("text", "Text to post.").Strings()
)

func main() {
  switch kingpin.MustParse(app.Parse(os.Args[1:])) {
  // Register user
  case register.FullCommand():
    println(*registerNick)

  // Post message
  case post.FullCommand():
    if *postImage != nil {
    }
    text := strings.Join(*postText, " ")
    println("Post:", text)
  }
}

Reference Documentation

Displaying errors and usage information

Kingpin exports a set of functions to provide consistent errors and usage information to the user.

Error messages look something like this:

<app>: error: <message>

The functions on Application are:

Function Purpose
Errorf(format, args) Display a printf formatted error to the user.
Fatalf(format, args) As with Errorf, but also call the termination handler.
FatalUsage(format, args) As with Fatalf, but also print contextual usage information.
FatalUsageContext(context, format, args) As with Fatalf, but also print contextual usage information from a ParseContext.
FatalIfError(err, format, args) Conditionally print an error prefixed with format+args, then call the termination handler

There are equivalent global functions in the kingpin namespace for the default kingpin.CommandLine instance.

Sub-commands

Kingpin supports nested sub-commands, with separate flag and positional arguments per sub-command. Note that positional arguments may only occur after sub-commands.

For example:

var (
  deleteCommand     = kingpin.Command("delete", "Delete an object.")
  deleteUserCommand = deleteCommand.Command("user", "Delete a user.")
  deleteUserUIDFlag = deleteUserCommand.Flag("uid", "Delete user by UID rather than username.")
  deleteUserUsername = deleteUserCommand.Arg("username", "Username to delete.")
  deletePostCommand = deleteCommand.Command("post", "Delete a post.")
)

func main() {
  switch kingpin.Parse() {
  case deleteUserCommand.FullCommand():
  case deletePostCommand.FullCommand():
  }
}

Custom Parsers

Kingpin supports both flag and positional argument parsers for converting to Go types. For example, some included parsers are Int(), Float(), Duration() and ExistingFile() (see parsers.go for a complete list of included parsers).

Parsers conform to Go's flag.Value interface, so any existing implementations will work.

For example, a parser for accumulating HTTP header values might look like this:

type HTTPHeaderValue http.Header

func (h *HTTPHeaderValue) Set(value string) error {
  parts := strings.SplitN(value, ":", 2)
  if len(parts) != 2 {
    return fmt.Errorf("expected HEADER:VALUE got '%s'", value)
  }
  (*http.Header)(h).Add(parts[0], parts[1])
  return nil
}

func (h *HTTPHeaderValue) String() string {
  return ""
}

As a convenience, I would recommend something like this:

func HTTPHeader(s Settings) (target *http.Header) {
  target = &http.Header{}
  s.SetValue((*HTTPHeaderValue)(target))
  return
}

You would use it like so:

headers = HTTPHeader(kingpin.Flag("header", "Add a HTTP header to the request.").Short('H'))

Repeatable flags

Depending on the Value they hold, some flags may be repeated. The IsCumulative() bool function on Value tells if it's safe to call Set() multiple times or if an error should be raised if several values are passed.

The built-in Values returning slices and maps, as well as Counter are examples of Values that make a flag repeatable.

Boolean values

Boolean values are uniquely managed by Kingpin. Each boolean flag will have a negative complement: --<name> and --no-<name>.

Default Values

The default value is the zero value for a type. This can be overridden with the Default(value...) function on flags and arguments. This function accepts one or several strings, which are parsed by the value itself, so they must be compliant with the format expected.

Place-holders in Help

The place-holder value for a flag is the value used in the help to describe the value of a non-boolean flag.

The value provided to PlaceHolder() is used if provided, then the value provided by Default() if provided, then finally the capitalised flag name is used.

Here are some examples of flags with various permutations:

--name=NAME           // Flag(...).String()
--name="Harry"        // Flag(...).Default("Harry").String()
--name=FULL-NAME      // Flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()

Consuming all remaining arguments

A common command-line idiom is to use all remaining arguments for some purpose. eg. The following command accepts an arbitrary number of IP addresses as positional arguments:

./cmd ping 10.1.1.1 192.168.1.1

Such arguments are similar to repeatable flags, but for arguments. Therefore they use the same IsCumulative() bool function on the underlying Value, so the built-in Values for which the Set() function can be called several times will consume multiple arguments.

To implement the above example with a custom Value, we might do something like this:

type ipList []net.IP

func (i *ipList) Set(value string) error {
  if ip := net.ParseIP(value); ip == nil {
    return fmt.Errorf("'%s' is not an IP address", value)
  } else {
    *i = append(*i, ip)
    return nil
  }
}

func (i *ipList) String() string {
  return ""
}

func (i *ipList) IsCumulative() bool {
  return true
}

func IPList(s Settings) (target *[]net.IP) {
  target = new([]net.IP)
  s.SetValue((*ipList)(target))
  return
}

And use it like so:

ips := IPList(kingpin.Arg("ips", "IP addresses to ping."))

Bash/ZSH Shell Completion

By default, all flags and commands/subcommands generate completions internally.

Out of the box, CLI tools using kingpin should be able to take advantage of completion hinting for flags and commands. By specifying --completion-bash as the first argument, your CLI tool will show possible subcommands. By ending your argv with --, hints for flags will be shown.

To allow your end users to take advantage you must package a /etc/bash_completion.d script with your distribution (or the equivalent for your target platform/shell). An alternative is to instruct your end user to source a script from their bash_profile (or equivalent).

Fortunately Kingpin makes it easy to generate or source a script for use with end users shells. ./yourtool --completion-script-bash and ./yourtool --completion-script-zsh will generate these scripts for you.

Installation by Package

For the best user experience, you should bundle your pre-created completion script with your CLI tool and install it inside /etc/bash_completion.d (or equivalent). A good suggestion is to add this as an automated step to your build pipeline, in the implementation is improved for bug fixed.

Installation by bash_profile

Alternatively, instruct your users to add an additional statement to their bash_profile (or equivalent):

eval "$(your-cli-tool --completion-script-bash)"

Or for ZSH

eval "$(your-cli-tool --completion-script-zsh)"

Additional API

To provide more flexibility, a completion option API has been exposed for flags to allow user defined completion options, to extend completions further than just EnumVar/Enum.

Provide Static Options

When using an Enum or EnumVar, users are limited to only the options given. Maybe we wish to hint possible options to the user, but also allow them to provide their own custom option. HintOptions gives this functionality to flags.

app := kingpin.New("completion", "My application with bash completion.")
app.Flag("port", "Provide a port to connect to").
    Required().
    HintOptions("80", "443", "8080").
    IntVar(&c.port)

Provide Dynamic Options Consider the case that you needed to read a local database or a file to provide suggestions. You can dynamically generate the options

func listHosts() []string {
  // Provide a dynamic list of hosts from a hosts file or otherwise
  // for bash completion. In this example we simply return static slice.

  // You could use this functionality to reach into a hosts file to provide
  // completion for a list of known hosts.
  return []string{"sshhost.example", "webhost.example", "ftphost.example"}
}

app := kingpin.New("completion", "My application with bash completion.")
app.Flag("flag-1", "").HintAction(listHosts).String()

EnumVar/Enum When using Enum or EnumVar, any provided options will be automatically used for bash autocompletion. However, if you wish to provide a subset or different options, you can use HintOptions or HintAction which will override the default completion options for Enum/EnumVar.

Examples You can see an in depth example of the completion API within examples/completion/main.go

Supporting -h for help

kingpin.CommandLine.HelpFlag.Short('h')

Short help is also available when creating a more complicated app:

var (
	app = kingpin.New("chat", "A command-line chat application.")
  // ...
)

func main() {
	app.HelpFlag.Short('h')
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
  // ...
  }
}

Custom help

Kingpin v2 supports templatised help using the text/template library (actually, a fork).

You can specify the template to use with the Application.UsageTemplate() function.

There are four included templates: kingpin.DefaultUsageTemplate is the default, kingpin.CompactUsageTemplate provides a more compact representation for more complex command-line structures, kingpin.SeparateOptionalFlagsUsageTemplate looks like the default template, but splits required and optional command flags into separate lists, and kingpin.ManPageTemplate is used to generate man pages.

See the above templates for examples of usage, and the the function UsageForContextWithTemplate() method for details on the context.

Default help template

$ go run ./examples/curl/curl.go --help
usage: curl [<flags>] <command> [<args> ...]

An example implementation of curl.

Flags:
  --help            Show help.
  -t, --timeout=5s  Set connection timeout.
  -H, --headers=HEADER=VALUE
                    Add HTTP headers to the request.

Commands:
  help [<command>...]
    Show help.

  get url <url>
    Retrieve a URL.

  get file <file>
    Retrieve a file.

  post [<flags>] <url>
    POST a resource.

Compact help template

$ go run ./examples/curl/curl.go --help
usage: curl [<flags>] <command> [<args> ...]

An example implementation of curl.

Flags:
  --help            Show help.
  -t, --timeout=5s  Set connection timeout.
  -H, --headers=HEADER=VALUE
                    Add HTTP headers to the request.

Commands:
  help [<command>...]
  get [<flags>]
    url <url>
    file <file>
  post [<flags>] <url>
Comments
  • Add Bash Completion Support

    Add Bash Completion Support

    I've implemented deep bash completion integration within the library. Work towards #75. A bash completion script can call into any tool using Kingpin by using a new flag --help-bash-completion as the first argument, followed by subsequent user-entered arguments.

    Opening this PR to get some eyes on it, and see how it can be improved. Happy to add docs once we're happy with the overall structure of it (Since this does bring some new API):

    • type HintAction func(args []string) []string A new type HintAction, a function that returns a list of options for completions.
    • func (a *ArgClause) HintAction(action HintAction) *ArgClause to register a HintAction to call when completions are requested for an argument.
    • func (a *ArgClause) HintOptions(options ...string) *ArgClause to register a static slice of strings to provide as completions when requested. Internally registers a HintAction that returns this slice.
    • func (a *FlagClause) HintAction(action HintAction) *FlagClause - Same as described for ArgClause
    • func (a *FlagClause) HintOptions(options ...string) *FlagClause - Same as described for ArgClause

    Additionally, FlagClause EnumVar will register all available EnumVar options as completion options too.

    Users will be presented with completion options for:

    • sub-commands
    • flags for a command (when - was the last user-entered argument)
    • options for a flag (when the second last argument was a flag)

    There's a bit of re-shuffling in this PR, including a new mixin (cmdMixin), due to some shared logic between the Application type and the CmdClause type for autocompletion

    Additionally, a lot of logic from Application.execute has been moved to Application.Parse to allow different code paths for bash completion / normal execution.

    An additional argument has been added to Application.applyPreActions to change whether or not sub commands should have preActions dispatched, since this causes issues with functionality such as help, and --version

    Included are two scripts support/bash_completion and support/zsh_completion which should be modified and then sourced/installed by end users within their shells to enable bash completion.

  • Pattern for having flags override config file

    Pattern for having flags override config file

    I'm converting a viper/cobra app to use Kingpin. That app uses the viper functionality of having configuration from both command line flags and a config file, with flags taking priority.

    Are there any recommended ways of implementing this pattern with Kingpin? I've experimented with simply reading the file before the flag parsing and assigning values read from the file to the flag vars, but I worry about this possibly not playing nice with Kingpin features such as required flags/override from envars, etc.

  • Multi-language support

    Multi-language support

    Is there a way to display different language according to system locale?

    Though I can change the template in order to print help information in another language, I can't change some of the messages like error: required flag xxx not provided....

    So can you add multiple language support or allow us to change such error message.

  • Ability to make a subcommand the default if none specified

    Ability to make a subcommand the default if none specified

    Right now, if you have a Command added to your kingpin.New() app, and no sub-command is specified at runtime, usage is printed and the program aborts.

    My attempt to achieve this with the below failed:

    var (
        appCommand          = kingpin.New("myapp", "Yum yum yum.")
        mySubcommand = appCommand.Command("mysubcommand", "Frob the bars")
    )
    
    func main() {
        switch kingpin.MustParse(appCommand.Parse(os.Args[1:])) {
        case mySubcommand():
                    log.Print("my subcommand was selected")
        default:
            // default action - alas, usage is printed and we never make it here
                    log.Print("my default action")
        }
    }
    
  • Flags mimic bool

    Flags mimic bool

    Hi! I have an idea how to add flags similar to Booleans, but taking optional values. I also figured out how to make isSetByUser posible for users. I implemented this idea and use it in my application. But when implementing I did not understand how to set the default value correctly and used a dirty hack :-) If these flags are interesting, I can try to make the proper setting of default values.

  • Help Message with Nested Commands

    Help Message with Nested Commands

    When there are many nested subcommands the Usage information is huge and impossible to understand. I was thinking of a different approach to Usage information and I would like to propose it. I think it Application Usage could be greatly simplified by making Usage print only the first set of available commands. Then, It would be great too if when specifying a correct first command but no subsequent subcommands we could show the Usage for that specific command instead of the whole app. And so on, instead of having the Application print every possible combination of commands, we could just show the next step in the tree of combinations.

    Instead of: app would print:

    app
    Flags:
    Commands:
    delete user [<flags>]
    delete post [<flags>]
    

    For example: app would print:

    app
    Flags:
    Commands:
    delete <command>
    

    app delete would print:

    app delete
    Flags:
    
    Commands:
    user [<flags>]
    post [<flags>]
    

    I dont know if i make myself clear. Hope you like my proposal Cheers!

  • Provide a list of environment variables to use as fallback (feature request)

    Provide a list of environment variables to use as fallback (feature request)

    I'd like to be able to define a flag that gets its default value from a list of Environment variables (using the first one that's set)

    codegangsta/cli uses a comma separated string for this.

    Would you be open to a pull request that makes the following work?:

    app :=  kingpin.New("app","")
    workdir := app.Flag("workdir","").Envar("APP_WORKDIR,TMPDIR").String()
    

    (this makes the app use APP_WORKDIR when it is set, TMPDIR otherwise)

  • When using Bool flag '--no' is not shown in help.

    When using Bool flag '--no' is not shown in help.

    When using a Bool flag the --no option is not shown in the help text. This could be a bit confusing to end users since there is no indication on how to use it.

    If the flag is set to required it shows in the usage but not under flags.

    Example:

    ./bin/deli region update --help
    usage: deli region update --[no-]schedulable <region ID>
    
    Flags:
          --help         Show context-sensitive help (also try --help-long and
                         --help-man).
      -d, --debug        Debug logging.
          --api-server="http://localhost:8080"
                         Sandwich Cloud API Server [Env: DELI_API_SERVER]
          --raw          Show raw json output
          --schedulable  Enable or disable the ability to schedule workloads in the
                         region
    
    Args:
      <region ID>  The region ID
    
  • Fix conflict with standard flag package on testing

    Fix conflict with standard flag package on testing

    This fixes https://github.com/alecthomas/kingpin/issues/167 and https://github.com/alecthomas/kingpin/issues/187.

    How it works

    If it's a test (binary name ends with .test), keep flags that doesn't start with -test. and remove them from os.Args (as we have no control over flag.Parse).

    Like that, for a command like go test -timeout 5s -args --flagforkingpin, we keep -test.timeout=5s for flag.Parse and --flagforkingpin for kingpin.Parse.


    I also tried defusing flag.Parse by replacing flag.CommandLine with a new flag.FlagSet using PanicOnError instead of ExitOnError and recover if panic error is flag provided but not defined.
    But we loose -test. flags.

  • Positional arguments can't be before flags

    Positional arguments can't be before flags

    I want to be able to have:

    executable build myproject:123 <flags>

    right now, the myproject:123 is registered as an Arg() and is always placed at the end of the flags. It makes no sense for the users of my CLI tool to put the project name at the end of the flags. I need to at least support it at the beginning, if not anywhere when considered as a positional argument.

    Is that possible, how complex would it be to implement ? I was thinking at an option on the Command() to mark it as not having any sub-commands, so it can handle positional arguments before the flags. What do you think ?

  • github.com/spf13/viper integration

    github.com/spf13/viper integration

    Has any thought been given to integrating kingpin with https://github.com/spf13/viper ? This would allow kingpin to be layered on top of viper configuration loading much like the defacto https://github.com/spf13/cobra cli library does.

    I find kingpin far more powerful for my uses than cobra, and want to discuss possible integration patterns. There are bind functions into viper that may be a good starting point:

    https://godoc.org/github.com/spf13/viper

    func (v *Viper) BindEnv(input ...string) error
    func (v *Viper) BindFlagValue(key string, flag FlagValue) error
    func (v *Viper) BindFlagValues(flags FlagValueSet) (err error)
    func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error
    func (v *Viper) BindPFlags(flags *pflag.FlagSet) error
    

    And a FlagValue interface (no native arg support) that could be implemented:

    https://godoc.org/github.com/spf13/viper#FlagValue

    I would be willing to hack at a poc bridge, but figured I would open this for discussion first.

  • HintAction can break the argument order

    HintAction can break the argument order

    go version go1.13.5 darwin/amd64 kingpn version v2.2.6

    I came across a strange issue where the introduction of a HintAction broke the order of the arguments. I managed to come up with a small example, which you can find here: https://github.com/OliverGoetz/kingpin-hintaction/blob/master/kingpin-hintaction.go

    The gist of it is that under certain circumstances the HintAction implementation can break the order in which the arguments for a command are expected. This is also reflected in the help output as you can see here"

    usage: kingpin-hintaction [<flags>] <command> [<args> ...]
    
    demo how hintaction breaks arg order
    
    Flags:
      -h, --help        Show context-sensitive help (also try --help-long and --help-man).
          --argset="x"  set of arguments to use
          --version     Show application version.
    
    Commands:
      help [<command>...]
        Show help.
    
      correctorder <arg1> <arg2>
        Command with correct arg order
    
      brokenorder <barg2> <barg1>
        Command with broken arg order
    

    For both commands the argument with number 1 should be first.

    I don't understand this behaviour, but I cannot imagine that this is as intended. It's also a mystery to me why the implementation of the HintAction should have any influence over this, as my understanding is that the HintAction methods are not even invoked when just a help message is printed out.

  • Documentation of public methods on private structs is hidden

    Documentation of public methods on private structs is hidden

    It seems like a lot of the API documentation is not visible on go.dev or godoc.org because of the fact that these methods belong to private structs used as mixins into public structs.

    So for example the *Application returned by kingpin.New has a Flag method provided by its embedded cmdMixin, which in turn embeds a *flagGroup. But this method is entirely missing from the API docs because flagGroup is private.

    I don't know that this is easily fixable in v2 but it'd be really nice to fix this in v3.

  • Unexpected

    Unexpected "doubling" behavior when trying to test output

    I am trying to write some unit tests for my kingpin.Application, to test things like help output. To do that, I build the application the same as I would in my real program, and redirect output to a buffer. I also apparently have to tell the app not to terminate the program (the test) whenever it encounters an error. But when I do all of these things, I notice that the Terminate callback is called multiple times (though only when I have a subcommand) and the expected output is duplicated.

    Here is a small reproducible test case.

    package main
    
    import (
    	"bytes"
    	"fmt"
    
    	"gopkg.in/alecthomas/kingpin.v2"
    )
    
    func main() {
    	app := kingpin.New("test", "Test application.")
    	_ = app.Command("subcommand", "A subcommand.")
    	var buf bytes.Buffer
    	app.Writer(&buf)
    	app.Terminate(func(exitcode int) { fmt.Printf("terminate(%d)\n", exitcode) })
    	_, err := app.Parse([]string{"--help"})
    	fmt.Printf("Parse error: %v\n", err)
    	fmt.Printf("%s\n", buf.String())
    }
    

    Expected output:

    terminate(0)
    Parse error: command not specified
    usage: test [<flags>] <command> [<args> ...]
    
    Test application.
    
    Flags:
      --help  Show context-sensitive help (also try --help-long and --help-man).
    
    Commands:
      help [<command>...]
        Show help.
    
      subcommand
        A subcommand.
    

    Actual output:

    terminate(0)
    terminate(0)
    Parse error: command not specified
    usage: test [<flags>] <command> [<args> ...]
    
    Test application.
    
    Flags:
      --help  Show context-sensitive help (also try --help-long and --help-man).
    
    Commands:
      help [<command>...]
        Show help.
    
      subcommand
        A subcommand.
    
    
    usage: test [<flags>] <command> [<args> ...]
    
    Test application.
    
    Flags:
      --help  Show context-sensitive help (also try --help-long and --help-man).
    
    Commands:
      help [<command>...]
        Show help.
    
      subcommand
        A subcommand.
    

    If there is a better way to do what I want to do, I'm all ears. But for now, this looks like a bug.

  • Actions should have a way to determine the what triggered them

    Actions should have a way to determine the what triggered them

    AFAICT there is currently no way to determine which flag triggered an action from within the action function itself. This makes it difficult to re-use an action function between multiple flags. It would be nice if either the context contained the particular flag that called the action, or if there was a second parameter which contained this information.

  • ExistingDir() still checked when program run with --version

    ExistingDir() still checked when program run with --version

    When using kingpin.Version("..."), passing --version means .Required() arguments do not have to be provided. I have an argument with a .Default() that must be an .ExistingDir(). The default path does not exist on the system. When passing only --version, I get an error that the default directory doesn't exist, rather than the version. Passing --version --help means the version is printed correctly.

    It would be very useful if kingpin did not check that .ExistingDir()s actually existed if the program is run with only the --version flag.

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
Flag is a simple but powerful command line option parsing library for Go support infinite level subcommand

Flag Flag is a simple but powerful commandline flag parsing library for Go. Documentation Documentation can be found at Godoc Supported features bool

Sep 26, 2022
Go Micro examples. Contributions welcome!

Examples This is a repository for go-micro examples. Feel free to contribute. Contents broker - A example of using Broker for Publish and Subscribing.

Dec 26, 2022
Go binding configuration and command flag made easy✨✨
Go binding configuration and command flag made easy✨✨

✨ Binding configuration and command flag made easy! ✨ You can use multiple keys tag to simplify the look like this (supported feature**): // single ta

Sep 18, 2022
A youtube library for retrieving metadata, and obtaining direct links to video-only/audio-only/mixed versions of videos on YouTube in Go.

A youtube library for retrieving metadata, and obtaining direct links to video-only/audio-only/mixed versions of videos on YouTube in Go. Install go g

Dec 10, 2022
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
Argparse for golang. Just because `flag` sucks

Golang argparse Let's be honest -- Go's standard command line arguments parser flag terribly sucks. It cannot come anywhere close to the Python's argp

Dec 28, 2022
An open-source GitLab command line tool bringing GitLab's cool features to your command line
An open-source GitLab command line tool bringing GitLab's cool features to your command line

GLab is an open source GitLab CLI tool bringing GitLab to your terminal next to where you are already working with git and your code without switching

Dec 30, 2022
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
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
The standard library flag package with its missing features

cmd Package cmd is a minimalistic library that enables easy sub commands with the standard flag library. This library extends the standard library fla

Oct 4, 2022
A collection of CLI argument types for the Go `flag` package.

flagvar A collection of CLI argument types for the flag package. import "github.com/sgreben/flagvar" Or just copy & paste what you need. It's public d

Sep 26, 2022
Drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags.

Description pflag is a drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags. pflag is compatible with the GNU extensions to

Dec 30, 2022
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 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
Kong is a command-line parser for Go
Kong is a command-line parser for Go

Kong is a command-line parser for Go Introduction Help Help as a user of a Kong application Defining help in Kong Command handling Switch on the comma

Dec 27, 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
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
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