- Go 96.6%
- Shell 2.3%
- Makefile 1.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
Add three missing API surface items that cobra depends on: - Flag.NoOptDefVal: default value used when a flag appears on the command line without an explicit value (e.g. --flag without =value). - ErrHelp: sentinel error returned when -help is invoked, matching the upstream pflag and stdlib flag convention. - FlagSet.ParseErrorsWhitelist: deprecated field mirroring ParseErrorsAllowlist, needed because cobra accesses it by field name. The parser now checks both fields. |
||
| .github | ||
| docs | ||
| example | ||
| goarg | ||
| pflag | ||
| posix | ||
| scripts | ||
| .coveragerc | ||
| .editorconfig | ||
| .gitignore | ||
| .golangci.yml | ||
| .markdownlint-cli2.yaml | ||
| .pre-commit-config.yaml | ||
| .secrets.baseline | ||
| abbreviation_property_test.go | ||
| benchmark_test.go | ||
| bytes_property_test.go | ||
| command.go | ||
| command_test.go | ||
| CONTRIBUTING.md | ||
| convert.go | ||
| convert_test.go | ||
| COVERAGE.md | ||
| errors.go | ||
| errors_test.go | ||
| getopt.go | ||
| getopt_test.go | ||
| go.mod | ||
| handler_test.go | ||
| helpers_test.go | ||
| LICENSE | ||
| Makefile | ||
| misc.go | ||
| misc_test.go | ||
| NOTES.md | ||
| optargs_test.go | ||
| parser.go | ||
| parser_test.go | ||
| README.md | ||
| round_trip_test.go | ||
| slice_value_property_test.go | ||
| strict_subcommands_test.go | ||
| typed_integration_test.go | ||
| typed_maps.go | ||
| typed_maps_test.go | ||
| typed_property_test.go | ||
| typed_scalars.go | ||
| typed_scalars_test.go | ||
| typed_slices.go | ||
| typed_slices_test.go | ||
| typed_special.go | ||
| typed_special_test.go | ||
| typed_values.go | ||
| typed_values_test.go | ||
OptArgs
A Go implementation of POSIX getopt(3), GNU getopt_long(3), and getopt_long_only(3) with native subcommand support.
OptArgs Core is the foundation for API-compatible wrapper modules that serve as drop-in replacements for popular Go argument parsing libraries.
Design
OptArgs is a general-purpose, unopinionated parser that faithfully implements GNU/POSIX getopt(3), getopt_long(3), and getopt_long_only(3) behavior. It exposes the full API surface needed to construct opinionated parsers on top — goarg and pflag are two such compatibility layers, each matching the API conventions of their upstream counterparts while gaining the correctness and features of the core engine.
Features
- Full POSIX getopt(3) compliance: short options, compaction,
--termination,POSIXLY_CORRECT - GNU getopt_long(3):
--option=value,--option value, abbreviation matching, case-insensitive - GNU getopt_long_only(3): single-dash long options with short option fallback
- Advanced handling:
-Wextension, option redefinition, negative arguments - Native subcommand dispatch via
AddCmd()with option inheritance through the parent chain - Iterator-based processing (
Options()returnsiter.Seq2[Option, error]) - Verbose and silent error modes, both working through subcommand chains
- Zero dependencies
Compatibility Modules
| Module | Upstream | Description |
|---|---|---|
| goarg | alexflint/go-arg | API-compatible drop-in replacement using struct tags |
| pflag | spf13/pflag | API-compatible drop-in replacement using flag methods |
Install
go get github.com/major0/optargs
Requires Go 1.23+.
Usage
GetOpt (POSIX short options)
package main
import (
"fmt"
"github.com/major0/optargs"
)
func main() {
p, _ := optargs.GetOpt(os.Args[1:], "vf:o::")
for opt, err := range p.Options() {
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
continue
}
switch opt.Name {
case "v":
fmt.Println("verbose")
case "f":
fmt.Println("file:", opt.Arg)
case "o":
fmt.Println("output:", opt.Arg)
}
}
}
GetOptLong (GNU long options)
p, _ := optargs.GetOptLong(os.Args[1:], "vf:", []optargs.Flag{
{Name: "verbose", HasArg: optargs.NoArgument},
{Name: "file", HasArg: optargs.RequiredArgument},
{Name: "output", HasArg: optargs.OptionalArgument},
})
for opt, err := range p.Options() {
// ...
}
GetOptLongOnly (single-dash long options)
p, _ := optargs.GetOptLongOnly(os.Args[1:], "vf:", []optargs.Flag{
{Name: "verbose", HasArg: optargs.NoArgument},
{Name: "file", HasArg: optargs.RequiredArgument},
})
// -verbose tries long match first, falls back to short options via optstring
Subcommands
root, _ := optargs.GetOptLong(os.Args[1:], "v", []optargs.Flag{
{Name: "verbose", HasArg: optargs.NoArgument},
})
serve, _ := optargs.GetOptLong([]string{}, "p:", []optargs.Flag{
{Name: "port", HasArg: optargs.RequiredArgument},
})
root.AddCmd("serve", serve)
// Root iteration dispatches to child when "serve" is encountered.
// Child inherits parent options via parent-chain walk.
for opt, err := range root.Options() { /* root options */ }
for opt, err := range serve.Options() { /* serve options + inherited */ }
Strict Subcommands
By default, child parsers inherit parent options — unknown options in a subcommand are resolved by walking the parent chain. To disable this (POSIX-strict behavior where each command owns its own options):
root.SetStrictSubcommands(true)
root.AddCmd("serve", serve) // serve will NOT inherit root's options
This is automatically enabled when POSIXLY_CORRECT is set or when the
optstring starts with +.
Optstring Syntax
| Prefix | Behavior |
|---|---|
: |
Silent error mode — suppress error logging |
+ |
POSIXLY_CORRECT — stop at first non-option |
- |
Treat non-options as argument to option \x01 |
| Suffix | Meaning |
|---|---|
f |
No argument |
f: |
Required argument |
f:: |
Optional argument |
W; |
GNU -W word extension |
Examples
example/— vanilla GetOpt, GetOptLong, GetOptLongOnly usageposix/— obscure POSIX/GNU patterns: subcommand dispatch, silent error mode, POSIXLY_CORRECT
Contributing
See CONTRIBUTING.md.