kingpin

repository·master·Indexed 25 days ago

https://github.com/alecthomas/kingpin

A fluent-style, type-safe command-line and flag parser for Go. Kingpin supports complex CLI requirements including nested commands, required arguments, POSIX-style flags, and customizable help output via Go templates. It provides built-in support for shell completion scripts (Bash, ZSH, Fish), environment variable defaults, and file expansion using the @<file> syntax.

Tokens
9.7K
Snippets
14
Records
90
Agent score
86%

What's inside kingpin

  1. Overview of Kingpin Features

    master

    Kingpin provides several advanced CLI capabilities:

    • Type-safe parsing: Supports Int(), String(), Bool(), and more for both flags and positional arguments.
    • Nested Commands: Create arbitrarily deep command hierarchies using kingpin.Command().
    • Required Inputs: Enforce presence of flags or arguments using .Required().
    • Callbacks: Execute logic via .Action(myAction) on commands, flags, or arguments.
    • POSIX-style flags: Supports combining short flags (e.g., -ab) and combining short flags with parameters (e.g., -aparm).
    • File Expansion: Read command-line arguments from files using the @<file> syntax.
    • Help Generation: Automatically generates man pages via --help-man and provides customizable help via Go templates.
  2. Migrating from v1 to v2

    master

    If you are upgrading from v1 to v2, note the following changes:

    Behavior Changes

    • Interspersed Flags: Flags can now be used at any point after their definition, not just immediately after their associated command.
    • Short Flag Combining: Short flags can be combined with their parameters without a space (e.g., -fARG).

    API Changes

    • File Expansion: ParseWithFileExpansion() is removed; the parser now supports @<file> directly.
    • Action Renaming: Dispatch() has been renamed to Action().
    • New Error Handling: Added FatalUsage() and FatalUsageContext() for displaying errors and usage before terminating.
    • New Parsing Mode: Added ParseContext() to parse a command line into an intermediate context without executing actions.
    • Termination Control: Added Terminate() to override the default termination function (which defaults to os.Exit).
    • Custom Templates: Added UsageTemplate() to override the default template. Available templates include DefaultUsageTemplate and CompactUsageTemplate.
  3. Create custom flag and argument parsers

    master

    Parsers convert command-line strings into Go types. They must implement the Go flag.Value interface (Set(string) error and String() string). You can use the Settings.SetValue() helper to simplify creating parser functions.

    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 ""
    }
    
    // Helper function for convenience
    func HTTPHeader(s Settings) (target *http.Header) {
      target = &http.Header{}
      s.SetValue((*HTTPHeaderValue)(target))
      return
    }
    
    // Usage
    headers = HTTPHeader(kingpin.Flag("header", "Add a HTTP header to the request.").Short('H'))
  4. Generate shell completion scripts

    master

    Kingpin can generate completion scripts for Bash, ZSH, and Fish.

    Installation via shell profile

    Bash

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

    ZSH

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

    Fish

    your-cli-tool --completion-script-fish | source
    # Or permanently:
    your-cli-tool --completion-script-fish > ~/.config/fish/completions/your-cli-tool.fish

    Built-in completion behavior

    Users can trigger completions directly from your CLI:

    • Use --completion-bash as the first argument to show subcommands.
    • End the argument list with -- to show flag hints.
  5. Quickstart: Basic Flag and Argument Parsing

    master

    Kingpin is a fluent-style, type-safe command-line parser. You define flags and arguments as global variables and then call kingpin.Parse() to populate them. The variables are pointers to the parsed values.

    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)
    }
  6. Create a simple flag and argument application

    master

    For basic CLI tools, you can define flags and arguments as package-level variables using kingpin.Flag and kingpin.Arg. Use .Bool(), .Duration(), .Int(), or .IP() to specify the expected type. Call kingpin.Parse() in your main function to process the command-line arguments.

    package main
    
    import (
      "fmt"
    
      "github.com/alecthomas/kingpin/v2"
    )
    
    var (
      debug   = kingpin.Flag("debug", "Enable debug mode.").Bool()
      timeout = kingpin.Flag("timeout", "Timeout waiting for ping.").Default("5s").Envar("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)
    }
  7. Create a complex application with subcommands

    master

    For advanced CLI tools, use kingpin.New() to create a new application instance. This allows you to define global flags, subcommands via .Command(), and per-subcommand flags and arguments. Use app.Parse(os.Args[1:]) and check the result against command.FullCommand() in a switch statement to handle different subcommands.

    package main
    
    import (
      "os"
      "strings"
      "github.com/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)
      }
    }
  8. Implement nested sub-commands

    master

    Kingpin supports nested sub-commands, allowing separate flags and positional arguments for each level. Note that positional arguments may only occur after sub-commands have been defined.

    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():
      }
    }
  9. Set default values and help placeholders

    master

    By default, the value for a type is its zero value. You can override this using .Default(value...).

    Placeholders in help text are determined in this order of precedence:

    1. The value provided via .PlaceHolder(string).
    2. The value provided via .Default(string...).
    3. The capitalized flag name.
    // Examples of flag permutations
    --name=NAME           // Flag(...).String()
    --name="Harry"        // Flag(...).Default("Harry").String()
    --name=FULL-NAME      // Flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
  10. Customize help templates

    master

    Kingpin supports custom help layouts using the text/template library via Application.UsageTemplate().

    Included templates:

    • kingpin.DefaultUsageTemplate: The standard layout.
    • kingpin.CompactUsageTemplate: A condensed version for complex command structures.
    • kingpin.SeparateOptionalFlagsUsageTemplate: Splits required and optional flags into distinct lists.
    • kingpin.ManPageTemplate: Formatted for man pages.