Documentation
¶
Overview ¶
Package optargs provides a collection of CLI parsing utilities in order to aid in the development of command line applications.
POSIX/GNU GetOpt ¶
At the heart of the optargs package is a Go implementation of the GNU glibc versions the getopt(3), getopt_long(3), and getopt_long_only(3) functions.
Leveraging GNU/POSIX conventions as the backend parser option means that the parser has a very large degree of flexibility without restricting application design choices.
For example, POSIX/GNU allows for the following:
- short-only options.
- long-only options.
- long and short options that do not require a value. I.e. it should be possible to pass `--foo` and specify that it never takes a value, and any attempt to pass it a value should be ignored or or result in an error.
- short-options of any character that is a valid `isgraph()` character; with the exception of `-`, `:` and `;`. This means that the following options are valid: -=, -+, -{, -}, -^, -!, -@, etc.
- short-option compaction: `-abc` is the equivalent of `-a -b -c`
- short-option compaction with optional args: `-abarg` is the equivalent of `-a -b arg`
- arguments to short options that begin with `-`: `-a -1` should pass `-1` as an argument to `-a`
- long-arguments that include any `isgraph()` character in the name, this includes allowing `=` in the name of the argument. For example, `--foo=bar=boo` should map `foo=bar` as the Flag, and `boo` as the value to the flag. This potentially also allows for curious long-arg syntax such as: `--command:arg=value`.
- many-to-one flag mappings. For example, the GNU `ls` command supports `--format=<format>` where each possible `<format>` options is also supported by a unique short-option. For example: `--format=across` = `-x`, `--format=commas` = `-m`, `--format=horizontal` = `-x`, `--format=long` = `-l`, etc.
- The GNU `-W` flag which allows short-options to behave like an undefined long-option. E.g. `-W foo` should be interpreted as if `--foo` was passed to the application.
- long-options that may look similar, but behave differently, from short options. E.g. `-c` and `--c` are allowed to behave differently.
It is always possible to implement a Flag handler which imposes opinionated rules atop a non-opinionated parser, but it is not possible to write a less opinionated Flag handler atop an opinionated parser. To that end, the [optarg] parsers do not make any judgements outside of strictly adhering to the POSIX/GNU conventions. Applications are free to implement their own argument handler to best-fit their application's needs.
Flags() ¶
Optargs supports traditional Go style flags which act as convenience methods around GetOpt, GetOptLong, and GetOptLongOnly with the aim of fully supporting drop-in replacements commonly used CLI tooling, such as:
While these packages are quite useful, they have some fundamental limitations and quirks that come from their design choices which aim to be overcome by optargs and in the case of spf13/pflag, those quirks ultimately percolate up to the user, such as spf13/pflag's boolean flags. Or putting arbitrary restrictions on applications, such as supporting long-only options, but not allowing short-only options. Or not supporting true non-option flags. I.e. many (all?) of the existing Go flag packages only allow an argument to a flag to be optional or required and are not capable of handling flags that never require an argument.
Index ¶
- type ArgType
- type CommandRegistry
- func (cr CommandRegistry) AddAlias(alias, existingCommand string) error
- func (cr CommandRegistry) AddCmd(name string, parser *Parser) *Parser
- func (cr CommandRegistry) ExecuteCommand(name string, args []string) (*Parser, error)
- func (cr CommandRegistry) ExecuteCommandCaseInsensitive(name string, args []string, caseIgnore bool) (*Parser, error)
- func (cr CommandRegistry) GetAliases(targetParser *Parser) []string
- func (cr CommandRegistry) GetCommand(name string) (*Parser, bool)
- func (cr CommandRegistry) HasCommands() bool
- func (cr CommandRegistry) ListCommands() map[string]*Parser
- type Flag
- type Option
- type ParseMode
- type Parser
- func GetOpt(args []string, optstring string) (*Parser, error)
- func GetOptLong(args []string, optstring string, longopts []Flag) (*Parser, error)
- func GetOptLongOnly(args []string, optstring string, longopts []Flag) (*Parser, error)
- func NewParser(config ParserConfig, shortOpts map[byte]*Flag, longOpts map[string]*Flag, ...) (*Parser, error)
- func NewParserWithCaseInsensitiveCommands(shortOpts map[byte]*Flag, longOpts map[string]*Flag, args []string) (*Parser, error)
- func (p *Parser) AddAlias(alias, existingCommand string) error
- func (p *Parser) AddCmd(name string, parser *Parser) *Parser
- func (p *Parser) ExecuteCommand(name string, args []string) (*Parser, error)
- func (p *Parser) GetAliases(targetParser *Parser) []string
- func (p *Parser) GetCommand(name string) (*Parser, bool)
- func (p *Parser) HasCommands() bool
- func (p *Parser) ListCommands() map[string]*Parser
- func (p *Parser) Options() iter.Seq2[Option, error]
- func (p *Parser) SetHandler(name string, handler func(string, string) error) error
- func (p *Parser) SetLongHandler(name string, handler func(string, string) error) error
- func (p *Parser) SetShortHandler(c byte, handler func(string, string) error) error
- type ParserConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ArgType ¶
type ArgType int
ArgType specifies whether a flag takes no argument, a required argument, or an optional argument.
type CommandRegistry ¶
CommandRegistry manages subcommands for a parser using a simple map
func NewCommandRegistry ¶
func NewCommandRegistry() CommandRegistry
NewCommandRegistry creates a new command registry
func (CommandRegistry) AddAlias ¶
func (cr CommandRegistry) AddAlias(alias, existingCommand string) error
AddAlias creates an alias for an existing command
func (CommandRegistry) AddCmd ¶
func (cr CommandRegistry) AddCmd(name string, parser *Parser) *Parser
AddCmd registers a new subcommand with the parser Returns the registered parser for chaining
func (CommandRegistry) ExecuteCommand ¶
func (cr CommandRegistry) ExecuteCommand(name string, args []string) (*Parser, error)
ExecuteCommand finds and prepares a command for execution.
func (CommandRegistry) ExecuteCommandCaseInsensitive ¶
func (cr CommandRegistry) ExecuteCommandCaseInsensitive(name string, args []string, caseIgnore bool) (*Parser, error)
ExecuteCommandCaseInsensitive finds and prepares a command for execution with optional case-insensitive matching.
func (CommandRegistry) GetAliases ¶
func (cr CommandRegistry) GetAliases(targetParser *Parser) []string
GetAliases returns all aliases for a given parser
func (CommandRegistry) GetCommand ¶
func (cr CommandRegistry) GetCommand(name string) (*Parser, bool)
GetCommand retrieves a parser by command name (exact match).
func (CommandRegistry) HasCommands ¶
func (cr CommandRegistry) HasCommands() bool
HasCommands returns true if any commands are registered
func (CommandRegistry) ListCommands ¶
func (cr CommandRegistry) ListCommands() map[string]*Parser
ListCommands returns all command mappings
type Flag ¶
Flag describes a single option definition for long option parsing. Name is the option name (without leading dashes) and HasArg specifies the argument requirement. Handle, when non-nil, is invoked instead of yielding an Option through the iterator.
type Option ¶
Option represents a parsed option yielded by the iterator. Name is the option name, HasArg indicates whether an argument was consumed, and Arg holds the argument value if present.
type ParseMode ¶
type ParseMode int
ParseMode controls how non-option arguments are handled during parsing.
const ( // ParseDefault permutes arguments so that non-options are moved to the end. ParseDefault ParseMode = iota // ParseNonOpts treats each non-option argument as an argument to a // synthetic option with character code 1. ParseNonOpts // ParsePosixlyCorrect stops option processing at the first non-option argument. ParsePosixlyCorrect )
type Parser ¶
type Parser struct {
Args []string
// Command support - simple map of command name to parser
Commands CommandRegistry
// contains filtered or unexported fields
}
Parser is the core argument parser. It processes command-line arguments according to POSIX getopt(3) and GNU getopt_long(3) conventions.
Args holds the remaining unprocessed arguments. After iteration completes, Args contains non-option arguments (and any arguments after "--").
Commands holds registered subcommands. Use Parser.AddCmd to register subcommands; do not manipulate Commands directly.
func GetOpt ¶
GetOpt creates a parser implementing POSIX getopt(3) behavior. It parses args according to the optstring specification.
func GetOptLong ¶
GetOptLong creates a parser implementing GNU getopt_long(3) behavior. It supports both short options via optstring and long options via longopts.
func GetOptLongOnly ¶
GetOptLongOnly creates a parser implementing GNU getopt_long_only(3) behavior. Single-dash options are first tried as long options; on failure, the parser falls back to short option parsing via the optstring.
func NewParser ¶
func NewParser(config ParserConfig, shortOpts map[byte]*Flag, longOpts map[string]*Flag, args []string) (*Parser, error)
NewParser creates a Parser from pre-built configuration, short option map, long option map, and argument list. Most callers should use GetOpt, GetOptLong, or GetOptLongOnly instead.
Flag structs in shortOpts and longOpts may include a non-nil Handle field for per-option handler dispatch. When a flag with a non-nil Handle is resolved during parsing, the handler is invoked instead of yielding an Option through the iterator. This is the construction-time path for attaching handlers:
verbose := &optargs.Flag{Name: "verbose", HasArg: optargs.NoArgument}
debug := &optargs.Flag{
Name: "debug",
HasArg: optargs.NoArgument,
Handle: func(name, arg string) error {
log.Println("debug mode enabled")
return nil
},
}
p, err := optargs.NewParser(config,
map[byte]*optargs.Flag{'v': verbose, 'd': debug},
map[string]*optargs.Flag{"verbose": verbose, "debug": debug},
os.Args[1:],
)
For parsers created via GetOpt, GetOptLong, or GetOptLongOnly, handlers can be attached after construction using Parser.SetHandler, Parser.SetShortHandler, or Parser.SetLongHandler. The two paths are complementary: NewParser for construction-time setup, SetHandler variants for post-construction attachment.
func NewParserWithCaseInsensitiveCommands ¶
func NewParserWithCaseInsensitiveCommands(shortOpts map[byte]*Flag, longOpts map[string]*Flag, args []string) (*Parser, error)
NewParserWithCaseInsensitiveCommands creates a new parser with case insensitive command matching enabled
func (*Parser) ExecuteCommand ¶
ExecuteCommand finds and executes a command
func (*Parser) GetAliases ¶
GetAliases returns all aliases for a given parser
func (*Parser) GetCommand ¶
GetCommand retrieves a parser by command name
func (*Parser) HasCommands ¶
HasCommands returns true if any commands are registered
func (*Parser) ListCommands ¶
ListCommands returns all command mappings
func (*Parser) Options ¶
Options returns an iterator over parsed options. Each iteration yields an Option and an error. When a subcommand is encountered, the iterator dispatches to the child parser automatically.
func (*Parser) SetHandler ¶ added in v0.2.0
SetHandler is a convenience method that attaches a handler to a matching option using command-line prefix syntax. Pass "--name" for long options or "-c" for short options. Returns an error if the prefix is missing or no matching option is found.
Examples:
parser.SetHandler("--verbose", handler) // calls SetLongHandler("verbose", handler)
parser.SetHandler("-v", handler) // calls SetShortHandler('v', handler)
parser.SetHandler("--v", handler) // calls SetLongHandler("v", handler)
SetHandler only modifies options on this parser — it does not walk the parent chain.
func (*Parser) SetLongHandler ¶ added in v0.2.0
SetLongHandler attaches a handler to a long option registered on this parser. Returns an error if no matching long option is found.
Long option names may be single characters (e.g., "v" for --v). Use SetLongHandler for long options and SetShortHandler for short options — the two namespaces are independent.
SetLongHandler only modifies options on this parser — it does not walk the parent chain.
func (*Parser) SetShortHandler ¶ added in v0.2.0
SetShortHandler attaches a handler to a short option registered on this parser. Returns an error if no matching short option is found.
SetShortHandler only modifies options on this parser — it does not walk the parent chain.
type ParserConfig ¶
type ParserConfig struct {
// contains filtered or unexported fields
}
ParserConfig holds configuration for a Parser instance. All fields are unexported; configuration is set via optstring prefix flags and constructor parameters.