// Package getopt implements a command-line argument parser.//// It tries to cover all common styles of option syntaxes, and provides context// information when given a partial input. It is mainly useful for writing// completion engines and wrapper programs.//// If you are looking for an option parser for your go program, consider using// the flag package in the standard library instead.
package getopt//go:generate stringer -type=Config,HasArg,ContextType -output=string.goimport// Getopt specifies the syntax of command-line arguments.typeGetoptstruct {Options []*OptionConfigConfig}// Config configurates the parsing behavior.typeConfiguintconst (// DoubleDashTerminatesOptions indicates that all elements after an argument // "--" are treated as arguments.DoubleDashTerminatesOptionsConfig = 1 << iota// FirstArgTerminatesOptions indicates that all elements after the first // argument are treated as arguments.FirstArgTerminatesOptions// LongOnly indicates that long options may be started by either one or two // dashes, and short options are not allowed. Should replicate the behavior // of getopt_long_only and the // flag package of the Go standard library.LongOnly// GNUGetoptLong is a configuration that should replicate the behavior of // GNU getopt_long.GNUGetoptLong = DoubleDashTerminatesOptions// POSIXGetopt is a configuration that should replicate the behavior of // POSIX getopt.POSIXGetopt = DoubleDashTerminatesOptions | FirstArgTerminatesOptions)// HasAll tests whether a configuration has all specified flags set.func ( Config) ( Config) bool {return ( & ) == }// Option is a command-line option.typeOptionstruct {// Short option. Set to 0 for long-only.Shortrune// Long option. Set to "" for short-only.Longstring// Whether the option takes an argument, and whether it is required.HasArgHasArg}// HasArg indicates whether an option takes an argument, and whether it is// required.typeHasArguintconst (// NoArgument indicates that an option takes no argument.NoArgumentHasArg = iota// RequiredArgument indicates that an option must take an argument. The // argument can come either directly after a short option (-oarg), after a // long option followed by an equal sign (--long=arg), or as a subsequent // argument after the option (-o arg, --long arg).RequiredArgument// OptionalArgument indicates that an option takes an optional argument. // The argument can come either directly after a short option (-oarg) or // after a long option followed by an equal sign (--long=arg).OptionalArgument)// ParsedOption represents a parsed option.typeParsedOptionstruct {Option *OptionLongboolArgumentstring}// Context indicates what may come after the supplied argument list.typeContextstruct {// The nature of the context.TypeContextType// Current option, with a likely incomplete Argument. Non-nil when Type is // OptionArgument.Option *ParsedOption// Current partial long option name or argument. Non-empty when Type is // LongOption or Argument.Textstring}// ContextType encodes what may be appended to the last element of the argument// list.typeContextTypeuintconst (// NewOptionOrArgument indicates that the last element may be either a new // option or a new argument. Returned when it is an empty string.NewOptionOrArgumentContextType = iota// NewOption indicates that the last element must be new option, short or // long. Returned when it is "-".NewOption// NewLongOption indicates that the last element must be a new long option. // Returned when it is "--".NewLongOption// LongOption indicates that the last element is a long option, but not its // argument. The partial name of the long option is stored in Context.Text.LongOption// ChainShortOption indicates that a new short option may be chained. // Returned when the last element consists of a chain of options that take // no arguments.ChainShortOption// OptionArgument indicates that the last element list must be an argument // to an option. The option in question is stored in Context.Option.OptionArgument// Argument indicates that the last element is an argument. The partial // argument is stored in Context.Text.Argument)func ( *Getopt) ( rune) *Option {for , := range .Options {if == .Short {return } }returnnil}// parseShort parse short options, without the leading dash. It returns the// parsed options and whether an argument is still to be seen.func ( *Getopt) ( string) ([]*ParsedOption, bool) {var []*ParsedOptionvarboolfor , := range { := .findShort()if != nil {if .HasArg == NoArgument { = append(, &ParsedOption{, false, ""})continue } else { := &ParsedOption{, false, [+len(string()):]} = append(, ) = .Argument == "" && .HasArg == RequiredArgumentbreak } }// Unknown option, treat as taking an optional argument := &ParsedOption{ &Option{, "", OptionalArgument}, false, [+len(string()):]} = append(, )break }return , }// parseLong parse a long option, without the leading dashes. It returns the// parsed option and whether an argument is still to be seen.func ( *Getopt) ( string) (*ParsedOption, bool) { := strings.IndexRune(, '=')for , := range .Options {if == .Long {return &ParsedOption{, true, ""}, .HasArg == RequiredArgument } elseif != -1 && [:] == .Long {return &ParsedOption{, true, [+1:]}, false } }// Unknown option, treat as taking an optional argumentif == -1 {return &ParsedOption{&Option{0, , OptionalArgument}, true, ""}, false }return &ParsedOption{&Option{0, [:], OptionalArgument}, true, [+1:]}, false}// Parse parses an argument list.func ( *Getopt) ( []string) ([]*ParsedOption, []string, *Context) {var ( []*ParsedOption []string// Non-nil only when the last element was an option with required // argument, but the argument has not been seen. *ParsedOption// True if an option terminator has been seen. The criteria of option // terminators is determined by the configuration.bool )varstring := func( string) bool { returnstrings.HasPrefix(, ) }for _, = range [:len()-1] {if != nil { .Argument = = append(, ) = nil } elseif { = append(, ) } elseif .Config.HasAll(DoubleDashTerminatesOptions) && == "--" { = true } elseif ("--") { , := .parseLong([2:])if { = } else { = append(, ) } } elseif ("-") {if .Config.HasAll(LongOnly) { , := .parseLong([1:])if { = } else { = append(, ) } } else { , := .parseShort([1:])if { = append(, [:len()-1]...) = [len()-1] } else { = append(, ...) } } } else { = append(, )if .Config.HasAll(FirstArgTerminatesOptions) { = true } } } = [len()-1] := &Context{}if != nil { .Argument = .Type, .Option = OptionArgument, } elseif { .Type, .Text = Argument, } elseif == "" { .Type = NewOptionOrArgument } elseif == "-" { .Type = NewOption } elseif == "--" { .Type = NewLongOption } elseif ("--") {if !strings.ContainsRune(, '=') { .Type, .Text = LongOption, [2:] } else { , := .parseLong([2:]) .Type, .Option = OptionArgument, } } elseif ("-") {if .Config.HasAll(LongOnly) {if !strings.ContainsRune(, '=') { .Type, .Text = LongOption, [1:] } else { , := .parseLong([1:]) .Type, .Option = OptionArgument, } } else { , := .parseShort([1:])if [len()-1].Option.HasArg == NoArgument { = append(, ...) .Type = ChainShortOption } else { = append(, [:len()-1]...) .Type, .Option = OptionArgument, [len()-1] } } } else { .Type, .Text = Argument, }return , , }
The pages are generated with Goldsv0.2.8-preview. (GOOS=darwin GOARCH=arm64)