CONTRIBUTIONS ONLY: A Go (golang) command line and flag parser

Related tags

go cli command-line kingpin
Overview

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>
Issues
  • 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.

    opened by nickw444 21
  • 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.

    opened by carlpett 17
  • 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.

    opened by superfashi 14
  • 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")
        }
    }
    
    opened by orospakr 12
  • Bash completion

    Bash completion

    Initial implementation of #75. This only provides the top level commands to an application.

    opened by rgbkrk 11
  • 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.

    opened by sakateka 11
  • 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!

    enhancement 
    opened by sschepens 11
  • Arguments from file example ?

    Arguments from file example ?

    I didn't found about the case. Could somebody bring me one? Thanks

    opened by dreampuf 10
  • 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)

    opened by levinalex 10
  • 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 ?

    opened by abourget 9
  •  There is a problem with flag and kingpin colleagues

    There is a problem with flag and kingpin colleagues

    If flag.parse() and kingpin.parse() exist at the same time, kingpin will override the flag。 image

    opened by caoshitong369 0
  • 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.

    opened by OliverGoetz 1
  • 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.

    opened by autarch 2
  • Readme uses `OverrideDefaultFromEnvar` which is deprecated

    Readme uses `OverrideDefaultFromEnvar` which is deprecated

    ...according to https://godoc.org/gopkg.in/alecthomas/kingpin.v2#FlagClause.OverrideDefaultFromEnvar.

    opened by JensRantil 0
  • 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.

    opened by peterbourgon 0
  • 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.

    opened by pgier 0
  • 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.

    opened by gebn 2
  • Feature Request: Fish completions

    Feature Request: Fish completions

    With a growing number of fish shell users, it would be nice to also have fish completions generated. See: https://fishshell.com/docs/current/index.html#completion-own

    Downstream project issue that this would benefit: https://github.com/Netflix-Skunkworks/go-jira/issues/189

    opened by jerr0328 2
  • Is it possible to set a StringMap() from environment?

    Is it possible to set a StringMap() from environment?

    If I define a StringMap() I can set multiple key/value pairs by repeating the flag:

     --flag foo=bar --flag baz=bar
    

    But this can not work with environment variables because you can only have one variable of the same name:

    APP_FLAG=foo=bar
    

    I could not find a way to set the second parameter with the env var - is this supported? I tried to add a \n to it but it didnt work.

    opened by scudette 1
  • export envVarValuesSeparator

    export envVarValuesSeparator

    I just failed to configure multiple values for .Strings() with an systemd EnvironmentFile= it is not possible to use \n there.

    It would be great if we could change the value of envVarValuesSeparator with a Setter() or by exporting the variable. Another solution would be to introduce a new fluent .EnvSeparator()

    https://github.com/alecthomas/kingpin/blob/master/envar.go#L9

    opened by mschneider82 0
Releases(v1.3.4)
  • v1.3.4(Jan 23, 2015)

    Since v1.2.0:

    • 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.
    Source code(tar.gz)
    Source code(zip)
  • v1.3.2(Nov 21, 2014)

  • v1.2.0(Jul 7, 2014)

    • 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").
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 27, 2014)

    • Fixed a bug (#6) where an invalid default value could prevent the application from starting. Bad.
    • Fixed formatting issue (#5) where very long default values would result in unreadable output.
    • Added OpenFile(flag, perm) for controlling how files are opened.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Jun 18, 2014)

    First stable release. No breaking API changes in this major version.

    • gopkg.in for versioning (import "gopkg.in/alecthomas/kingpin.v1")
    • 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.
    Source code(tar.gz)
    Source code(zip)
  • v0.3.0(Jun 18, 2014)

    • Use OverrideDefaultFromEnvar(envar) to allow flag values to be overridden by environment variables.
    • Support cumulative arg parsing of remaining args "Args[n:]".
    • Add Version(v) function to automatically add a --version flag.
    • Bug fixes.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(Jun 18, 2014)

    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()
    
    Source code(tar.gz)
    Source code(zip)
Owner
Alec Thomas
Alec Thomas
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

Steve Francia 1.6k Sep 20, 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

Alexey Kamenskiy 363 Sep 23, 2021
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

Alec Thomas 3.1k Sep 15, 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

David Gamba 37 Sep 16, 2021
A Commander for modern Go CLI interactions

Cobra is both a library for creating powerful modern CLI applications as well as a program to generate applications and command files. Cobra is used i

Steve Francia 23.2k Sep 17, 2021
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

Alec Thomas 663 Sep 25, 2021
A versatile library for building CLI applications in Go

mow.cli Package cli provides a framework to build command line applications in Go with most of the burden of arguments parsing and validation placed o

Jawher Moussa 748 Sep 5, 2021
Idiomatic Go input parsing with subcommands, positional values, and flags at any position. No required project or package layout and no external dependencies.

Sensible and fast command-line flag parsing with excellent support for subcommands and positional values. Flags can be at any position. Flaggy has no

Eric Greer 733 Sep 6, 2021
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

null 116 Sep 6, 2021
HAProxy configuration parser

HAProxy configuration parser autogenerated code if you change types/types.go you need to run go run generate/go-generate.go $(pwd) Contributing For co

haproxytech 64 Sep 8, 2021
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

Eyal Posener 34 Sep 2, 2021
A modern UNIX ed (line editor) clone written in Go

ed (the awesome UNIX line editor) ed is a clone of the UNIX command-line tool by the same name ed a line editor that was nortorious for being and most

James Mills 45 May 29, 2021
Generate flags by parsing structures

Flags based on structures. The sflags package uses structs, reflection and struct field tags to allow you specify command line options. It supports di

null 129 Sep 13, 2021
Simplistic interactive filtering tool

peco Simplistic interactive filtering tool NOTE: If you are viewing this on GitHub, this document refers to the state of peco in whatever current bran

null 6.5k Sep 18, 2021
textnote is a command line tool for quickly creating and managing daily plain text notes.

textnote is a command line tool for quickly creating and managing daily plain text notes. It is designed for ease of use to encourage the practice of daily, organized note taking. textnote intentionally facilitates only the management (creation, opening, organizing, and consolidated archiving) of notes, following the philosophy that notes are best written in a text editor and not via a CLI.

Daniel Kaslovsky 148 Sep 5, 2021
A rich tool for parsing flags and values in pure Golang

A rich tool for parsing flags and values in pure Golang. No additional library is required and you can use everywhere.

ALi.w 13 Jun 20, 2021
Another CLI framework for Go. It works on my machine.

Command line interface framework Go framework for rapid command line application development

Ulrich Kautz 108 May 24, 2021
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

Gruntwork 489 Sep 24, 2021
:cherry_blossom: A command-line fuzzy finder

fzf is a general-purpose command-line fuzzy finder. It's an interactive Unix filter for command-line that can be used with any list; files, command hi

Junegunn Choi 39.3k Sep 24, 2021