xflags

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 26, 2022 License: MIT Imports: 10 Imported by: 0

README

Expressive flags for Go

Go Reference Build Status

Package xflags implements command-line flag parsing and is a compatible alternative to Go's flag package. This package provides higher-order features such as subcommands, positional arguments, required arguments, validation, support for environment variables and others.

Package xflags aims to make composing large, full-featured command line tools as simple and clean as possible. The Builder pattern is employed with method chaining to configure commands and flags declaratively with error checking.

See the docs for comprehensive examples.

Documentation

Overview

Package xflags implements command-line flag parsing and is a compatible alternative to Go's flag package. This package provides higher-order features such as subcommands, positional arguments, required arguments, validation, support for environment variables and others.

Package xflags aims to make composing large, full-featured command line tools as simple and clean as possible. The Builder pattern is employed with method chaining to configure commands and flags declaratively with error checking.

For compatibility, flag.FlagSets may be imported with CommandBuilder.FlagSet.

Usage

Every xflags program must define a top-level command using xflags.NewCommand:

import (
	"os"

	"github.com/cavaliergopher/xflags"
)

var App = xflags.NewCommand(os.Args[0], "My application")

func main() {
	os.Exit(xflags.Run(App))
}

You can import all global flags defined using Go's flag library with CommandBuilder.FlagSet.

var App = xflags.NewCommand(os.Args[0], "").FlagSet(flag.CommandLine)

You can bind a flag to a variable using the Var functions.

var flagvar int

var App = xflags.NewCommand(os.Args[0], "").
	Flags(
		xflags.Int(
			&flagvar, "flagname", 1234, "help message for flagname",
		),
	)

Or you can create custom flags that satisfy the Value interface (with pointer receivers) and couple them to a flag parsing by

xflags.Var(&flagVal, "name", "help message for flagname")

For such flags, the default value is just the initial value of the variable.

A handler may be defined for your command by

var App = xflags.NewCommand(os.Args[0], "").HandleFunc(MyAppHandler)

func MyAppHandler(args []string) int {
	return 0
}

Flag parsing will stop after "--" only if a command sets WithTerminator. All arguments following the terminator will be passed to the command handler.

You can define subcommands by

var (
	FooCommand = xflags.NewCommand("foo", "Foo command")
	BarCommand = xflags.NewCommand("bar", "Bar command")

	App = xflags.NewCommand(os.Args[0], "Foo bar program").
		Subcommands(FooCommand, BarCommand)
)

After all flags are defined, call

xflags.Run(App)

to parse the command line into the defined flags and call the handler associated with the command or any if its subcommands if specified in os.Args.

Flags may then be used directly.

fmt.Println("ip has value ", ip)
fmt.Println("flagvar has value ", flagvar)

Command line flag syntax

In addition to positional arguments, the following forms are permitted:

-f
-f=x
-f x // non-boolean flags only
--flag
--flag=x
--flag x // non-boolean flags only

The noted forms are not permitted for boolean flags because of the meaning of the command

cmd -x *

where * is a Unix shell wildcard, will change if there is a file called 0, false, etc.

Example
// This example demonstrates a simple "Hello, World!" CLI program.
package main

import (
	"fmt"
	"os"
	"strings"
)

var (
	flagLanguage   string
	flagNoNewLines bool
	flagMessage    []string
)

var translations = map[string]string{
	"en": "Hello, World!",
	"es": "Hola, Mundo!",
	"it": "Ciao, Mondo!",
	"nl": "Hallo, Wereld!",
}

var App = NewCommand("helloworld", "Print \"Hello, World!\"").
	Synopsis(
		"The helloworld utility writes \"Hello, World!\" to the standard\n"+
			" output multiple languages.",
	).
	Flags(
		// Bool flag to turn off newline printing with -n. The flag value is
		// stored in cmd.NoNewLines.
		Bool(
			&flagNoNewLines,
			"n",
			false,
			"Do not print the trailing newline character",
		),

		// String flag to select a desired language. Can be specified with
		// -l, --language or the HW_LANG environment variable.
		String(
			&flagLanguage,
			"language",
			"en",
			"Language (en, es, it or nl)",
		).
			ShortName("l").
			Env("HW_LANG"),

		// StringSlice flag to optionally print multiple positional
		// arguments. Positional arguments are not denoted with "-" or "--".
		Strings(
			&flagMessage,
			"MESSAGE",
			nil,
			"Optional message to print",
		).Positional(),
	).
	HandleFunc(helloWorld)

// helloWorld is the HandlerFunc for the main App command.
func helloWorld(args []string) (exitCode int) {
	s, ok := translations[flagLanguage]
	if !ok {
		fmt.Fprintf(os.Stderr, "Unsupported language: %s", flagLanguage)
		return 1
	}
	if len(flagMessage) > 0 {
		s = strings.Join(flagMessage, " ")
	}
	fmt.Print(s)
	if !flagNoNewLines {
		fmt.Print("\n")
	}
	return
}

func main() {
	fmt.Println("+ helloworld --help")
	RunWithArgs(App, "--help")

	// Most programs will call the following from main:
	//
	//     func main() {
	//         os.Exit(xflags.Run(App))
	//     }
	//
	fmt.Println()
	fmt.Println("+ helloworld --language=es")
	RunWithArgs(App, "--language=es")
}
Output:

+ helloworld --help
Usage: helloworld [OPTIONS] [MESSAGE...]

Print "Hello, World!"

Positional arguments:
  MESSAGE  Optional message to print

Options:
  -n              Do not print the trailing newline character
  -l, --language  Language (en, es, it or nl)

Environment variables:
  HW_LANG  Language (en, es, it or nl)

The helloworld utility writes "Hello, World!" to the standard
 output multiple languages.

+ helloworld --language=es
Hola, Mundo!
Example (CustomTypes)
// This example demonstrates how a custom struct type may be used to encapsulate
// the behavior of a single command.
package main

import (
	"fmt"
)

// exampleCommand implements the Commander interface to define a CLI command and its handler using a
// custom type.
// It collects the value of each flag as a struct field.
// Command types should be very fast to initialize, ideally initialized with their zero-value.
type exampleCommand struct {
	Species    string
	GopherType string
}

// Command implements Commander and returns the CLI configuration of the example command.
func (c *exampleCommand) Command() (*Command, error) {
	return NewCommand("example", "An example CLI program").
		Flags(
			String(&c.Species, "species", "Gopher", "the species we are studying"),
			String(&c.GopherType, "gopher_type", "Pocket", "the variety of gopher"),
		).
		HandleFunc(c.Run).
		Command()
}

// Run handles calls to this command from the command line.
//
// If WithTerminator is specified for the App command, any arguments given after
// the "--" terminator will be passed in as the args parameter without any
// further parsing.
func (c *exampleCommand) Run(args []string) int {
	fmt.Printf("%s is a variety of species %s\n", c.GopherType, c.Species)
	return 0
}

// ExampleCommand is a global instance of the exampleCommand type so that its
// parsed flag values can be accessed from other commands. This is an optional
// alternative to defining flag variables individually in the global scope.
var ExampleCommand = &exampleCommand{}

func main() {
	fmt.Println("+ example --help")
	RunWithArgs(ExampleCommand, "--help")

	// Most programs will call the following from main:
	//
	//     func main() {
	//         os.Exit(xflags.Run(ExampleCommand))
	//     }
	//
	fmt.Println()
	fmt.Println("+ example --gopher_type 'Goldman's pocket gopher'")
	RunWithArgs(ExampleCommand, "--gopher_type", "Goldman's pocket gopher")
}
Output:

+ example --help
Usage: example [OPTIONS]

An example CLI program

Options:
   --species      the species we are studying
   --gopher_type  the variety of gopher

+ example --gopher_type 'Goldman's pocket gopher'
Goldman's pocket gopher is a variety of species Gopher
Example (DependencyInjection)
// This example demonstrates a pattern for injecting dependencies into your command handlers.
package main

import (
	"context"
	"database/sql"
	"fmt"
	"os"
)

// DBClient is our main command with two subcommands.
var DBClient = NewCommand("db-client", "query a database").
	Subcommands(
		GetCommand,
		DeleteCommand,
	)

// GetCommand is a subcommand with dependencies injected into the handler by Wrap.
var GetCommand = NewCommand("get", "Get DB resources").
	HandleFunc(Wrap(Get))

// DeleteCommand is a subcommand with dependecnies injected into the handler by Wrap.
var DeleteCommand = NewCommand("delete", "Delete DB resources").
	HandleFunc(Wrap(Delete))

// Wrap returns a HandlerFunc that initialises common dependencies for command handlers and then
// injects them into fn.
func Wrap(fn func(ctx context.Context, db *sql.DB) error) HandlerFunc {
	return func(args []string) (exitCode int) {
		// build a context
		ctx := context.Background()

		// build a database connection
		var db *sql.DB = nil

		// call the handler with all dependencies
		if err := fn(ctx, db); err != nil {
			fmt.Fprint(os.Stderr, err)
			return 1
		}
		return 0
	}
}

// Get is a custom handler for GetCommand
func Get(ctx context.Context, db *sql.DB) error {
	fmt.Println("Issued a get query")
	return nil
}

// Delete is a custom handler for DeleteCommand
func Delete(ctx context.Context, db *sql.DB) error {
	fmt.Println("Issued a delete query")
	return nil
}

func main() {
	RunWithArgs(DBClient, "get")
}
Output:

Issued a get query

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Format added in v0.3.0

func Format(w io.Writer, cmd *Command) error

Format is the default FormatFunc to print help messages for a commands.

func Run

func Run(cmd Commander) int

Run parses the arguments provided by os.Args and executes the handler for the command or subcommand specified by the arguments.

func main() {
    os.Exit(xflags.Run(cmd))
}

If -h or --help are specified, usage information will be printed to os.Stdout and the exit code will be 0.

If a command is invoked that has no handler, usage information will be printed to os.Stderr and the exit code will be non-zero.

func RunWithArgs added in v0.2.0

func RunWithArgs(cmd Commander, args ...string) int

Run parses the given arguments and executes the handler for the command or subcommand specified by the arguments.

func main() {
    os.Exit(xflags.RunWithArgs(cmd, "--foo", "--bar"))
}

If -h or --help are specified, usage information will be printed to os.Stdout and the exit code will be 0.

If a command is invoked that has no handler, usage information will be printed to os.Stderr and the exit code will be non-zero.

Types

type ArgumentError added in v0.1.9

type ArgumentError struct {
	Text string
	Err  error
	Cmd  *Command
	Flag *Flag
	Arg  string
}

ArgumentError indicates that an argument specified on the command line was incorrect.

func (*ArgumentError) Error added in v0.1.9

func (e *ArgumentError) Error() string

func (*ArgumentError) String added in v0.3.1

func (e *ArgumentError) String() string

func (*ArgumentError) Unwrap added in v0.3.1

func (e *ArgumentError) Unwrap() error

type BoolValue added in v0.1.3

type BoolValue interface {
	Value
	IsBoolFlag() bool
}

BoolValue is an optional interface to indicate boolean flags that can be supplied without a "=value" argument.

type Command

type Command struct {
	Parent         *Command
	Name           string
	Usage          string
	Synopsis       string
	Hidden         bool
	WithTerminator bool
	FlagGroups     []*FlagGroup
	Subcommands    []*Command
	FormatFunc     FormatFunc
	HandlerFunc    HandlerFunc
	Stdout         io.Writer
	Stderr         io.Writer
	// contains filtered or unexported fields
}

Command describes a command that users may invoke from the command line.

Programs should not create Command directly and instead use the Command function to build one with proper error checking.

func (*Command) Arg added in v0.3.0

func (c *Command) Arg(i int) string

Arg returns the i'th argument specified after the "--" terminator if it was enabled. Arg(0) is the first remaining argument after flags the terminator. Arg returns an empty string if the requested element does not exist.

func (*Command) Args added in v0.2.0

func (c *Command) Args() []string

Args returns any command line arguments specified after the "--" terminator if it was enabled. Args is only populated after the command line is successfully parsed.

func (*Command) Command added in v0.2.0

func (c *Command) Command() (*Command, error)

Command implements the Commander interface.

func (*Command) Parse added in v0.2.0

func (c *Command) Parse(args []string) (*Command, error)

Parse parses the given set of command line arguments and stores the value of each argument in each command flag's target. The rules for each flag are checked and any errors are returned.

If -h or --help are specified, a HelpError will be returned containing the subcommand that was specified.

The returned *Command will be this command or one of its subcommands if specified by the command line arguments.

func (*Command) Run added in v0.2.0

func (c *Command) Run(args []string) int

Run parses the given set of command line arguments and calls the handler for the command or subcommand specified by the arguments.

If -h or --help are specified, usage information will be printed to os.Stdout and the return code will be 0.

If a command is invoked that has no handler, usage information will be printed to os.Stderr and the return code will be non-zero.

func (*Command) String added in v0.2.0

func (c *Command) String() string

func (*Command) WriteUsage added in v0.2.0

func (c *Command) WriteUsage(w io.Writer) error

WriteUsage prints a help message to the given Writer using the configured Formatter.

type CommandBuilder

type CommandBuilder struct {
	// contains filtered or unexported fields
}

CommandBuilder builds a Command which defines a command and all of its flags. Create a command builder with NewCommand. All chain methods return a pointer to the same builder.

func NewCommand added in v0.2.0

func NewCommand(name, usage string) *CommandBuilder

NewCommand returns a CommandBuilder which can be used to define a command and all of its flags.

func (*CommandBuilder) Command added in v0.2.0

func (c *CommandBuilder) Command() (*Command, error)

Command implements the Commander interface and produces a new Command.

func (*CommandBuilder) FlagGroup added in v0.1.4

func (c *CommandBuilder) FlagGroup(
	name, usage string,
	flags ...Flagger,
) *CommandBuilder

FlagGroup adds a group of command line flags to this command and shows them under a common heading in help messages.

Example
var n int
var rightToLeft bool
var endcoding string

cmd := NewCommand("helloworld", "").
	// n flag defines how many times to print "Hello, World!".
	Flags(Int(&n, "n", 1, "Print n times")).

	// Create a flag group for language-related flags.
	FlagGroup(
		"language",
		"Language options",
		String(&endcoding, "encoding", "utf-8", "Text encoding"),
		Bool(&rightToLeft, "rtl", false, "Print right-to-left"),
	)

// Print the help page
RunWithArgs(cmd, "--help")
Output:

Usage: helloworld [OPTIONS]

Options:
  -n   Print n times

Language options:
   --encoding  Text encoding
   --rtl       Print right-to-left

func (*CommandBuilder) FlagSet added in v0.1.3

func (c *CommandBuilder) FlagSet(flagSet *flag.FlagSet) *CommandBuilder

FlagSet imports flags from a Flagset created using Go's flag package. All parsing and error handling is still managed by this package.

To import any globally defined flags, import flag.CommandLine.

Example
// create a Go-native flag set
flagSet := flag.NewFlagSet("native", flag.ExitOnError)
message := flagSet.String("m", "Hello, World!", "Message to print")

// import the flagset into an xflags command
cmd := NewCommand("helloworld", "").
	FlagSet(flagSet).
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Println(*message)
		return
	})

// Print the help page
fmt.Println("+ helloworld --help")
RunWithArgs(cmd, "--help")

// Run the command
fmt.Println()
fmt.Println("+ helloworld")
RunWithArgs(cmd)
Output:

+ helloworld --help
Usage: helloworld [OPTIONS]

Options:
  -m   Message to print

+ helloworld
Hello, World!

func (*CommandBuilder) Flags

func (c *CommandBuilder) Flags(flags ...Flagger) *CommandBuilder

Flag adds command line flags to the default FlagGroup for this command.

func (*CommandBuilder) FormatFunc added in v0.3.0

func (c *CommandBuilder) FormatFunc(fn FormatFunc) *CommandBuilder

Formatter specifies a custom Formatter for formatting help messages for this command.

func (*CommandBuilder) HandleFunc added in v0.2.0

func (c *CommandBuilder) HandleFunc(
	handler func(args []string) int,
) *CommandBuilder

HandleFunc registers the handler for the command. If no handler is specified and the command is invoked, it will print usage information to stderr.

func (*CommandBuilder) Hidden

func (c *CommandBuilder) Hidden() *CommandBuilder

Hidden hides the command from all help messages but still allows the command to be invoked on the command line.

func (*CommandBuilder) Must added in v0.1.3

func (c *CommandBuilder) Must() *Command

Must is a helper that calls Command and panics if the error is non-nil.

func (*CommandBuilder) Output added in v0.3.0

func (c *CommandBuilder) Output(stdout, stderr io.Writer) *CommandBuilder

Output sets the destination for usage and error messages.

func (*CommandBuilder) Subcommands

func (c *CommandBuilder) Subcommands(commands ...Commander) *CommandBuilder

Subcommands adds subcommands to this command.

Example
var n int

// configure a "create" subcommand
create := NewCommand("create", "Make new widgets").
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("Created %d widget(s)\n", n)
		return
	})

// configure a "destroy" subcommand
destroy := NewCommand("destroy", "Destroy widgets").
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("Destroyed %d widget(s)\n", n)
		return
	})

// configure the main command with two subcommands and a global "n" flag.
cmd := NewCommand("widgets", "").
	Flags(Int(&n, "n", 1, "Affect n widgets")).
	Subcommands(create, destroy)

// Print the help page
fmt.Println("+ widgets --help")
RunWithArgs(cmd, "--help")

// Invoke the "create" subcommand
fmt.Println()
fmt.Println("+ widgets create -n=3")
RunWithArgs(cmd, "create", "-n=3")
Output:

+ widgets --help
Usage: widgets [OPTIONS] COMMAND

Options:
  -n   Affect n widgets

Commands:
  create   Make new widgets
  destroy  Destroy widgets

+ widgets create -n=3
Created 3 widget(s)

func (*CommandBuilder) Synopsis added in v0.1.9

func (c *CommandBuilder) Synopsis(s string) *CommandBuilder

Synopsis specifies the detailed help message for this command.

Example
var n int
cmd := NewCommand("helloworld", "Say \"Hello, World!\"").
	// Configure a synopsis to print detailed usage information on the help
	// page.
	Synopsis(
		"This utility prints \"Hello, World!\" to the standard output.\n" +
			"Print more than once with -n.",
	).
	Flags(Int(&n, "n", 1, "Print n times"))

// Print the help page
RunWithArgs(cmd, "--help")
Output:

Usage: helloworld [OPTIONS]

Say "Hello, World!"

Options:
  -n   Print n times

This utility prints "Hello, World!" to the standard output.
Print more than once with -n.

func (*CommandBuilder) WithTerminator added in v0.1.3

func (c *CommandBuilder) WithTerminator() *CommandBuilder

WithTerminator specifies that any command line argument after "--" will be passed through to the args parameter of the command's handler without any further processing.

Example
var verbose bool

// create a command that passes arguments to /bin/echo
cmd := NewCommand("echo_wrapper", "calls /bin/echo").
	Flags(
		Bool(&verbose, "v", false, "Print verbose output"),
	).
	WithTerminator(). // enable the "--" terminator
	HandleFunc(func(args []string) (exitCode int) {
		// read verbose argument which was parsed by xflags
		if verbose {
			fmt.Printf("+ /bin/echo %s\n", strings.Join(args, " "))
		}

		// pass unparsed arguments after the "--" terminator to /bin/echo
		output, err := exec.Command("/bin/echo", args...).Output()
		if err != nil {
			fmt.Println(err)
			return 1
		}
		fmt.Println(string(output))
		return
	})

// run in verbose mode and pass ["Hello", "World!"] to /bin/echo.
RunWithArgs(cmd, "-v", "--", "Hello,", "World!")
Output:

+ /bin/echo Hello, World!
Hello, World!

type Commander added in v0.2.0

type Commander interface {
	Command() (*Command, error)
}

Commander is an interface that describes any type that produces a Command.

The interface is implemented by both CommandBuilder and Command so they can often be used interchangeably.

type Flag added in v0.2.0

type Flag struct {
	Name        string
	ShortName   string
	Usage       string
	ShowDefault bool
	Positional  bool
	MinCount    int
	MaxCount    int
	Hidden      bool
	EnvVar      string
	Validate    ValidateFunc
	Value       Value
}

Flag describes a command line flag that may be specified on the command line.

Programs should not create Flag directly and instead use one of the FlagBuilders to build one with proper error checking.

func (*Flag) Flag added in v0.2.0

func (c *Flag) Flag() (*Flag, error)

Flag implements the Flagger interface.

func (*Flag) Set added in v0.2.0

func (c *Flag) Set(s string) error

Set sets the value of the command-line flag.

func (*Flag) String added in v0.2.0

func (c *Flag) String() string

type FlagBuilder

type FlagBuilder struct {
	// contains filtered or unexported fields
}

FlagBuilder builds a Flag which defines a command line flag for a CLI command. All chain methods return a pointer to the same builder.

func BitField added in v0.3.0

func BitField(p *uint64, mask uint64, name string, value bool, usage string) *FlagBuilder

BitField returns a FlagBuilder that can be used to define a uint64 flag with specified name, default value, and usage string. The argument p points to a uint64 variable in which to toggle each of the bits in the mask argument. You can specify multiple BitFieldVars to toggle bits in the same underlying uint64.

Example
const (
	UserRead    uint64 = 0400
	UserWrite   uint64 = 0200
	UserExecute uint64 = 0100
)

var mode uint64 = 0444 // -r--r--r--

cmd := NewCommand("user-allow", "").
	Flags(
		BitField(&mode, UserRead, "r", false, "Enable user read"),
		BitField(&mode, UserWrite, "w", false, "Enable user write"),
		BitField(&mode, UserExecute, "x", false, "Enable user execute"),
	).
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("File mode: %s\n", os.FileMode(mode))
		return
	})

// Enable user read and write
RunWithArgs(cmd, "-r", "-w")
Output:

File mode: -rw-r--r--

func Bool

func Bool(p *bool, name string, value bool, usage string) *FlagBuilder

Bool returns a FlagBuilder that can be used to define a bool flag with specified name, default value, and usage string. The argument p points to a bool variable in which to store the value of the flag.

func Duration

func Duration(p *time.Duration, name string, value time.Duration, usage string) *FlagBuilder

Duration returns a FlagBuilder that can be used to define a time.Duration flag with specified name, default value, and usage string. The argument p points to a time.Duration variable in which to store the value of the flag. The flag accepts a value acceptable to time.ParseDuration.

func Float64

func Float64(p *float64, name string, value float64, usage string) *FlagBuilder

Float64 returns a FlagBuilder that can be used to define a float64 flag with specified name, default value, and usage string. The argument p points to a float64 variable in which to store the value of the flag.

func Func added in v0.3.0

func Func(name, usage string, fn func(s string) error) *FlagBuilder

Func returns a FlagBuilder that can used to define a flag with the specified name and usage string. Each time the flag is seen, fn is called with the value of the flag. If fn returns a non-nil error, it will be treated as a flag value parsing error.

Example
var ip net.IP

cmd := NewCommand("ping", "").
	Output(os.Stdout, os.Stdout). // for tests
	Flags(
		Func("ip", "IP address to ping", func(s string) error {
			ip = net.ParseIP(s)
			if ip == nil {
				return fmt.Errorf("invalid IP: %s", s)
			}
			return nil
		}),
	).
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("ping: %s\n", ip)
		return
	})

RunWithArgs(cmd, "--ip", "127.0.0.1")

// 256 is not a valid IPv4 component
RunWithArgs(cmd, "--ip", "256.0.0.1")
Output:

ping: 127.0.0.1
Argument error: --ip: invalid IP: 256.0.0.1

func Int added in v0.3.0

func Int(p *int, name string, value int, usage string) *FlagBuilder

Int returns a FlagBuilder that can be used to define an int flag with specified name, default value, and usage string. The argument p points to an int variable in which to store the value of the flag.

func Int64

func Int64(p *int64, name string, value int64, usage string) *FlagBuilder

Int64 returns a FlagBuilder that can be used to define an int64 flag with specified name, default value, and usage string. The argument p points to an int64 variable in which to store the value of the flag.

func String

func String(p *string, name, value, usage string) *FlagBuilder

String returns a FlagBuilder that can be used to define a string flag with specified name, default value, and usage string. The argument p points to a string variable in which to store the value of the flag.

func Strings added in v0.3.0

func Strings(p *[]string, name string, value []string, usage string) *FlagBuilder

Strings returns a FlagBuilder that can be used to define a string slice flag with specified name, default value, and usage string. The argument p points to a string slice variable in which each flag value will be stored in command line order.

Example
var widgets []string

cmd := NewCommand("create-widgets", "").
	Flags(
		// Configure a repeatable string slice flag that must be specified
		// at least once.
		Strings(&widgets, "name", nil, "Widget name").NArgs(1, 0),
	).
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("Created new widgets: %s", strings.Join(widgets, ", "))
		return
	})

RunWithArgs(cmd, "--name=foo", "--name=bar")
Output:

Created new widgets: foo, bar

func Uint added in v0.3.0

func Uint(p *uint, name string, value uint, usage string) *FlagBuilder

Uint returns a FlagBuilder that can be used to define an uint flag with specified name, default value, and usage string. The argument p points to an uint variable in which to store the value of the flag.

func Uint64 added in v0.3.0

func Uint64(p *uint64, name string, value uint64, usage string) *FlagBuilder

Uint64 returns a FlagBuilder that can be used to define an uint64 flag with specified name, default value, and usage string. The argument p points to an uint64 variable in which to store the value of the flag.

func Var

func Var(value Value, name, usage string) *FlagBuilder

Var returns a FlagBuilder that can be used to define a command line flag with custom value parsing.

func (*FlagBuilder) Choices added in v0.3.1

func (c *FlagBuilder) Choices(elems ...string) *FlagBuilder

Choices is a convenience method that calls Validate and sets a ValidateFunc that enforces that the flag value must be one of the given choices.

func (*FlagBuilder) Env added in v0.1.3

func (c *FlagBuilder) Env(name string) *FlagBuilder

Env allows the value of the flag to be specified with an environment variable if it is not specified on the command line.

func (*FlagBuilder) Flag added in v0.2.0

func (c *FlagBuilder) Flag() (*Flag, error)

Flag implements the Flagger interface and produces a new Flag.

func (*FlagBuilder) Hidden

func (c *FlagBuilder) Hidden() *FlagBuilder

Hidden hides the command line flag from all help messages but still allows the flag to be specified on the command line.

func (*FlagBuilder) Must added in v0.1.3

func (c *FlagBuilder) Must() *Flag

Must is a helper that calls Build and panics if the error is non-nil.

func (*FlagBuilder) NArgs

func (c *FlagBuilder) NArgs(min, max int) *FlagBuilder

NArgs indicates how many times this flag may be specified on the command line. Value.Set will be called once for each instance of the flag specified in the command arguments.

To disable min or max count checking, set their value to 0.

func (*FlagBuilder) Positional

func (c *FlagBuilder) Positional() *FlagBuilder

Position indicates that this flag is a positional argument, and therefore has no "-" or "--" delimeter. You cannot specify both a positional arguments and subcommands.

func (*FlagBuilder) Required

func (c *FlagBuilder) Required() *FlagBuilder

Required is shorthand for NArgs(1, 1) and indicates that this flag must be specified on the command line once and only once.

func (*FlagBuilder) ShortName

func (c *FlagBuilder) ShortName(name string) *FlagBuilder

ShortName specifies an alternative short name for a command line flag. For example, a command named "foo" can be specified on the command line with "--foo" but may also use a short name of "f" to be specified by "-f".

func (*FlagBuilder) ShowDefault added in v0.1.3

func (c *FlagBuilder) ShowDefault() *FlagBuilder

ShowDefault specifies that the default vlaue of this flag should be show in the help message.

func (*FlagBuilder) Validate added in v0.1.6

func (c *FlagBuilder) Validate(f ValidateFunc) *FlagBuilder

Validate specifies a function to validate an argument for this flag before it is parsed. If the function returns an error, parsing will fail with the same error.

Example
var ip string

cmd := NewCommand("ping", "").
	Output(os.Stdout, os.Stdout). // for tests
	Flags(
		String(&ip, "ip", "127.0.0.1", "IP Address to ping").
			Validate(func(arg string) error {
				if net.ParseIP(arg) == nil {
					return fmt.Errorf("invalid IP: %s", arg)
				}
				return nil
			}),
	).
	HandleFunc(func(args []string) (exitCode int) {
		fmt.Printf("ping: %s\n", ip)
		return
	})

RunWithArgs(cmd, "--ip=127.0.0.1")

// 256 is not a valid IPv4 component
RunWithArgs(cmd, "--ip=256.0.0.1")
Output:

ping: 127.0.0.1
Argument error: --ip: invalid IP: 256.0.0.1

type FlagGroup added in v0.2.0

type FlagGroup struct {
	Name  string
	Usage string
	Flags []*Flag
}

FlagGroup is a nominal grouping of flags which affects how the flags are shown in help messages.

type Flagger added in v0.2.0

type Flagger interface {
	Flag() (*Flag, error)
}

Flagger is an interface that describes any type that produces a Flag.

The interface is implemented by both FlagBuilder and Flag so they can often be used interchangeably.

type FormatFunc added in v0.3.0

type FormatFunc func(w io.Writer, cmd *Command) error

FormatFunc is a function that prints a help message for a command.

type HandlerFunc added in v0.2.0

type HandlerFunc func(args []string) int

A HandlerFunc is a function that handles the invokation a command specified by command line arguments.

Args will receive any arguments ignored by the parser after the "--" terminator if it is enabled.

type HelpError added in v0.1.9

type HelpError struct {
	Cmd *Command // The command that was invoked and produced this error.
}

HelpError is the error returned if the -h or --help argument is specified but no such flag is explicitly defined.

func (*HelpError) Error added in v0.1.9

func (err *HelpError) Error() string

type ValidateFunc added in v0.1.6

type ValidateFunc = func(arg string) error

ValidateFunc is a function that validates an argument before it is parsed.

type Value

type Value interface {
	// String() string
	Set(s string) error
}

Value is the interface to the dynamic value stored in a flag. (The default value is represented as a string.)

Set is called once, in command line order, for each flag present.

Example
package main

import (
	"fmt"
	"net"
)

// ipValue implements the Value interface for net.IP.
type ipValue net.IP

func (p *ipValue) Set(s string) error {
	ip := net.ParseIP(s)
	if ip == nil {
		return fmt.Errorf("invalid IP: %s", s)
	}
	*p = ipValue(ip)
	return nil
}

// IPVar returns a FlagBuilder that can be used to define a net.IP flag with
// specified name, default value, and usage string. The argument p points to a
// net.IP variable in which to store the value of the flag.
func IPVar(p *net.IP, name string, value net.IP, usage string) *FlagBuilder {
	*p = value
	return Var((*ipValue)(p), name, usage)
}

func main() {
	var ip net.IP

	cmd := NewCommand("ping", "").
		Flags(
			// configure a net.IP flag with our custom Value type
			IPVar(&ip, "ip", net.IPv6zero, "IP address to ping"),
		).
		HandleFunc(func(args []string) (exitCode int) {
			fmt.Printf("ping: %s\n", ip)
			return
		})

	RunWithArgs(cmd, "--ip=ff02:0000:0000:0000:0000:0000:0000:0001")
}
Output:

ping: ff02::1

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL