Documentation
¶
Overview ¶
Package getoptx implements a command line parser. Under the hood, we use the excellent github.com/pborman/getopt/v2 library.
Index ¶
- Variables
- type CommandParser
- func Command(description string, options interface{}, subcommands ...*CommandParser) *CommandParser
- func LeafSubcommand(name, description string, options interface{}, config ...Config) *CommandParser
- func Subcommand(name, description string, options interface{}, subcommands ...*CommandParser) *CommandParser
- type Config
- type Counter
- type HasPrintedHelp
- type Parser
- type SelectedCommand
Constants ¶
This section is empty.
Variables ¶
var ( // ErrTooManyPositionalArguments indicates that you passed too many // positional arguments to the current parser. ErrTooManyPositionalArguments = errors.New("too many positional arguments") // ErrTooFewPositionalArguments indicates that you passed too few // positional arguments to the current parser. ErrTooFewPositionalArguments = errors.New("too few positional arguments") )
var ErrNoSuchSubcommand = errors.New("no such subcommand")
ErrNoSuchSubcommand indicates that we don't know a subcommand with that name.
Functions ¶
This section is empty.
Types ¶
type CommandParser ¶
type CommandParser struct {
// contains filtered or unexported fields
}
CommandParser is a parser for a command or a subcommand. You construct this type using Command (for a top-level command) or Subcommand.
Once you have constructed a CommandParser you call Getopt or MustGetopt to parse the command line arguments and get the SelectedSubcommand.
See Subcommand for more details on the typical usage.
func Command ¶
func Command( description string, options interface{}, subcommands ...*CommandParser) *CommandParser
Command creates the toplevel command for the whole program with the given description, the given options, and zero or more subcommands. This function also register an internal subcommand implementing the `help` subcommand unless you have already included one such command in subcommands. Apart from that, this function is equivalent to calling Subcommand with os.Args[0] as the first argument followed by the arguments passed to Command. For this reason, please see Subcommand for more information about the usage.
func LeafSubcommand ¶
func LeafSubcommand( name, description string, options interface{}, config ...Config) *CommandParser
LeafSubcommand creates a subcommand that does not take any further subcommand (i.e., a "leaf" subcommand in the commands tree).
You can use Configs such as NoPositionalArguments() to control the leaf subcommand behavior in terms of positional arguments. This function will emit a warning and otherwise ignore any piece of config that does not specifically deal with controlling positional arguments.
See Subcommand's docs for further information.
func Subcommand ¶
func Subcommand(name, description string, options interface{}, subcommands ...*CommandParser) *CommandParser
Subcommand creates a new subcommand with the given name, the given description, the given options, and zero or more subcommands.
The typical usage for Command, Subcommand, and LeafSubcommand calls for creating data structures containing options you'd like to fill and for instantiating a complex command line parser by chaining calls to Command, Subcommand, or LeafSubcommand depending on your needs.
Here's an example:
type GlobalOptions struct {
Batch bool `doc:"emit JSON messages" short:"b"`
Logfile string `doc:"file where to write logs" short:"L"`
Verbose bool `doc:"run in verbose mode" short:"v"`
}
type WebsitesOptions struct {
ForceHTTP3 bool `doc:"forces using HTTP3" short:"3"`
}
type URLGetterOptions struct {
SNI string `doc:"forces using a specific SNI"`
Host string `doc:"forces using a specific host header"`
}
type RunOptions struct {
Input string `doc:"add URL to measure"`
InputFile string `doc:"add file from which to read URLs"`
Websites WebsitesOptions `doc:"-"` // <- (3)
URLGetter URLGetterOptions `doc:"-"`
}
type ListOptions struct {
ID int `doc:"ID of the result to show" short:"I"`
}
type RmOptions struct {
ID int `doc:"ID of the result to remove" short:"I"`
}
type Options struct {
Global GlobalOptions
Run RunOptions
Rm RmOptions
List ListOptions
}
options := &Options{}
cli := getoptx.Command(
"Network measurement tool",
&options.Global,
getoptx.Subcommand(
"run", "Runs network measurements", &options.RunOptions,
getoptx.LeafCommand(
"websites", "Tests websites for censorship", &options.Websites,
getoptx.NoPositionalArguments(),
),
getoptx.LeafCommand(
"urlgetter", "Swiss-knife measurements tool", &options.URLGetter,
getoptx.NoPositionalArguments(),
),
),
getoptx.LeafCommand(
"list", "Lists network measurements", &options.ListOptions,
),
getoptx.LeafCommand(
"rm", "Remove network measurements", &options.RmOptions,
),
)
selected := cli.MustGetopt(os.Args)
switch selected.Options().(type) { // <- (2)
case *WebsitesOptions:
Websites(options)
case *URLGetterOptions:
URLGetter(options)
case *ListOptions:
List(options)
case *RmOptions:
Rm(options)
case *getoptx.HasPrintedHelp: // <- (1)
os.Exit(0)
default:
log.Fatalf("unhandled selected option: %T %+v", selected, selected)
}
This example shows the most complex usage possible. In particular, here you see the following functionality in action:
1. MustGetopt automatically prints contextual help for -h/--help as well as for the `help` subcommand and lets you know when this happens;
2. you know which command has been selected by checking for the type of the leaf option structure that has been filled;
3. you can embed options within other options and mark them as `doc:"-"` to force the underlying parser to skip them (since they can't be parsed).
If you want to write a custom `"help"` command, you just need to pass to the toplevel Command call a subcommand implementing `"help"`. In which case, we will not register our internal interceptor for the `"help"` command.
Likewise, we'll attach to each subparser a -h/--help rule for printing help. But you can avoid this by adding an option that resolves to -h or --help.
func (*CommandParser) Getopt ¶
func (p *CommandParser) Getopt(args []string) (*SelectedCommand, error)
Getopt parses command line arguments for the given command. This function returns either the selected command or subcommand, or an error.
See the documentation of the Subcommand factory for more usage information.
func (*CommandParser) MustGetopt ¶
func (p *CommandParser) MustGetopt(args []string) *SelectedCommand
MustGetopt is exactly like Getopt except that it calls os.Exit(1) in case of error.
type Config ¶
type Config interface {
// contains filtered or unexported methods
}
Config is a piece of configuration for NewParser. You can pass a bunch of configs to NewParser to change its behavior.
func AtLeastOnePositionalArgument ¶
func AtLeastOnePositionalArgument() Config
AtLeastOnePositionalArgument is a bit of config that causes Parse to fail if the user has provided no positional arguments.
func JustOnePositionalArgument ¶
func JustOnePositionalArgument() Config
JustOnePositionalArgument is a bit of config that causes Parse to fail if the user has not provided exactly one positional argument.
func NoPositionalArguments ¶
func NoPositionalArguments() Config
NoPositionalArguments is a bit of config that causes Parse to fail if the user has provided any positional argument.
func SetPositionalArgumentsPlaceholder ¶
SetPositionalArgumentsPlaceholder allows a user to set the name given to the positional arguments in the usage string.
Note that this value will not be printed if the parser does not accept at least a single positional argument.
If the provided name is empty, we will not modify the name that would printed by default for representing positional arguments.
func SetProgramName ¶
SetProgramName sets the program name printed in the usage string.
If the provided name is empty, this option does not modify the program name that would be printed by default.
type Counter ¶
type Counter int
Counter counts the number of times the given flag has been set from the command line.
type HasPrintedHelp ¶
type HasPrintedHelp struct{}
HasPrintedHelp is the fake subcommand returned when CommandParser.Getopt or CommandParser.MustGetopt have printed an help message.
type Parser ¶
type Parser interface {
// Getopt parses the command line options in args, which in the
// common case should be just os.Args.
Getopt(args []string) error
// MustGetopt is like Getopt but prints usage and exits on error.
MustGetopt(args []string)
// PrintUsage prints a detailed usage string on the given writer.
PrintUsage(w io.Writer)
// NArgs returns the number of positional arguments.
NArgs() int
// Args returns the positional arguments.
Args() []string
}
Parser is a command line parser.
func MustNewParser ¶
MustNewParser is like NewParser but print an error on stderr and calls os.Exit(1) if NewParser fails.
func NewParser ¶
NewParser creates a new parser that stores the parsed options into the given `flags` opaque argument. Use `config...` to adjust the parser's behavior.
The `flags“ opaque argument must be a pointer to a struct where each field must be tagged with `doc:"..."`. We will use the value of the doc tag to generate the help message produced by PrintUsage. We will return an error if we find a field that is not documented. You should use `doc:"-"` to force the parser to skip a field.
The name of the structure field is converted to kebab case and used to generate the command line option.
To define a short option, add the `short:"v"` tag, where "v" must be a string containing a single one-byte character. If present, we'll use the value in short to determine the short option name.
The `required:"true"` tag indicates that an option is required.
For example:
type CLI struct {
Help bool `doc:"prints this help message" short:"h"`
Input string `doc:"sets the URL to measure" required:"true"`
Verbose bool `doc:"runs in verbose mode" short:"v"`
}
becomes:
program [-h,--help] --input value [-v,--verbose]
Note that, by default, this parser does not treat `-h` or `--help` specially; you'll need to implement actions for them.
By default, the returned parser accepts any number of positional arguments, as the original getopt does. You can change that by using, e.g., the NoPositionalArguments Config constructor to force the parser to fail if the user has specified one or more positional arguments.
For example:
parser, err := getoptx.NewParser(&cli, getoptx.NoPositionalArguments())
Likewise, you can use SetProgramName and SetPositionalArguments to control exactly how PrintUsage works.
This constructor returns either a valid parser and a nil error, on success, or a nil parser and an error, on failure.
type SelectedCommand ¶
type SelectedCommand struct {
// contains filtered or unexported fields
}
SelectedCommand is the type returned by successful parsing of command line arguments by CommandParser.{Must,}Getopt.
See the documentation of Subcommand for more info on actual usage.
func (*SelectedCommand) Args ¶
func (sc *SelectedCommand) Args() []string
Args returns the selected command's positional arguments.
func (*SelectedCommand) NArgs ¶
func (sc *SelectedCommand) NArgs() int
NArgs returns the number of positional arguments.
func (*SelectedCommand) Options ¶
func (sc *SelectedCommand) Options() interface{}
Options returns the selected command's options. See the documentation of Subcommand for more information on how to use this method.