1// Copyright 2017 Google Inc. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package getopt 6 7import ( 8 "io" 9 "os" 10 "sort" 11 "sync" 12) 13 14// A State is why the Getopt returned. 15type State int 16 17const ( 18 InProgress = State(iota) // Getopt is still running 19 Dash // Returned on "-" 20 DashDash // Returned on "--" 21 EndOfOptions // End of options reached 22 EndOfArguments // No more arguments 23 Terminated // Terminated by callback function 24 Failure // Terminated due to error 25 Unknown // Indicates internal error 26) 27 28type Set struct { 29 stateMu sync.Mutex 30 state State 31 32 // args are the parameters remaining after parsing the optoins. 33 args []string 34 35 // program is the name of the program for usage and error messages. 36 // If not set it will automatically be set to the base name of the 37 // first argument passed to parse. 38 program string 39 40 // parameters is what is displayed on the usage line after displaying 41 // the various options. 42 parameters string 43 44 usage func() // usage should print the programs usage and exit. 45 46 shortOptions map[rune]*option 47 longOptions map[string]*option 48 options optionList 49 requiredGroups []string 50} 51 52// New returns a newly created option set. 53func New() *Set { 54 s := &Set{ 55 shortOptions: make(map[rune]*option), 56 longOptions: make(map[string]*option), 57 parameters: "[parameters ...]", 58 } 59 60 s.usage = func() { 61 s.PrintUsage(stderr) 62 } 63 return s 64} 65 66func (s *Set) setState(state State) { 67 s.stateMu.Lock() 68 s.state = state 69 s.stateMu.Unlock() 70} 71 72// State returns the current state of the Set s. The state is normally the 73// reason the most recent call to Getopt returned. 74func (s *Set) State() State { 75 s.stateMu.Lock() 76 defer s.stateMu.Unlock() 77 return s.state 78} 79 80// The default set of command-line options. 81var CommandLine = New() 82 83// PrintUsage calls PrintUsage in the default option set. 84func PrintUsage(w io.Writer) { CommandLine.PrintUsage(w) } 85 86// Usage calls the usage function in the default option set. 87func Usage() { CommandLine.usage() } 88 89// Parse calls Parse in the default option set with the command line arguments 90// found in os.Args. 91func Parse() { CommandLine.Parse(os.Args) } 92 93// Same as parse but not found in version 1 of getopt. 94func ParseV2() { CommandLine.Parse(os.Args) } 95 96// Getops returns the result of calling Getop in the default option set with the 97// command line arguments found in os.Args. The fn function, which may be nil, 98// is passed to Getopt. 99func Getopt(fn func(Option) bool) error { return CommandLine.Getopt(os.Args, fn) } 100 101// Arg returns the n'th command-line argument. Arg(0) is the first remaining 102// argument after options have been processed. 103func Arg(n int) string { 104 if n >= 0 && n < len(CommandLine.args) { 105 return CommandLine.args[n] 106 } 107 return "" 108} 109 110// Arg returns the n'th argument. Arg(0) is the first remaining 111// argument after options have been processed. 112func (s *Set) Arg(n int) string { 113 if n >= 0 && n < len(s.args) { 114 return s.args[n] 115 } 116 return "" 117} 118 119// Args returns the non-option command line arguments. 120func Args() []string { 121 return CommandLine.args 122} 123 124// Args returns the non-option arguments. 125func (s *Set) Args() []string { 126 return s.args 127} 128 129// NArgs returns the number of non-option command line arguments. 130func NArgs() int { 131 return len(CommandLine.args) 132} 133 134// NArgs returns the number of non-option arguments. 135func (s *Set) NArgs() int { 136 return len(s.args) 137} 138 139// SetParameters sets the parameters string for printing the command line 140// usage. It defaults to "[parameters ...]" 141func SetParameters(parameters string) { 142 CommandLine.parameters = parameters 143} 144 145// SetParameters sets the parameters string for printing the s's usage. 146// It defaults to "[parameters ...]" 147func (s *Set) SetParameters(parameters string) { 148 s.parameters = parameters 149} 150 151// Parameters returns the parameters set by SetParameters on s. 152func (s *Set) Parameters() string { return s.parameters } 153 154// SetProgram sets the program name to program. Normally it is determined 155// from the zeroth command line argument (see os.Args). 156func SetProgram(program string) { 157 CommandLine.program = program 158} 159 160// SetProgram sets s's program name to program. Normally it is determined 161// from the zeroth argument passed to Getopt or Parse. 162func (s *Set) SetProgram(program string) { 163 s.program = program 164} 165 166// Program returns the program name associated with Set s. 167func (s *Set) Program() string { return s.program } 168 169// SetUsage sets the function used by Parse to display the commands usage 170// on error. It defaults to calling PrintUsage(os.Stderr). 171func SetUsage(usage func()) { 172 CommandLine.usage = usage 173} 174 175// SetUsage sets the function used by Parse to display usage on error. It 176// defaults to calling f.PrintUsage(os.Stderr). 177func (s *Set) SetUsage(usage func()) { 178 s.usage = usage 179} 180 181// Lookup returns the Option associated with name. Name should either be 182// a rune (the short name) or a string (the long name). 183func Lookup(name interface{}) Option { 184 return CommandLine.Lookup(name) 185} 186 187// Lookup returns the Option associated with name in s. Name should either be 188// a rune (the short name) or a string (the long name). 189func (s *Set) Lookup(name interface{}) Option { 190 switch v := name.(type) { 191 case rune: 192 return s.shortOptions[v] 193 case int: 194 return s.shortOptions[rune(v)] 195 case string: 196 return s.longOptions[v] 197 } 198 return nil 199} 200 201// IsSet returns true if the Option associated with name was seen while 202// parsing the command line arguments. Name should either be a rune (the 203// short name) or a string (the long name). 204func IsSet(name interface{}) bool { 205 return CommandLine.IsSet(name) 206} 207 208// IsSet returns true if the Option associated with name was seen while 209// parsing s. Name should either be a rune (the short name) or a string (the 210// long name). 211func (s *Set) IsSet(name interface{}) bool { 212 if opt := s.Lookup(name); opt != nil { 213 return opt.Seen() 214 } 215 return false 216} 217 218// GetCount returns the number of times the Option associated with name has been 219// seen while parsing the command line arguments. Name should either be a rune 220// (the short name) or a string (the long name). 221func GetCount(name interface{}) int { 222 return CommandLine.GetCount(name) 223} 224 225// GetCount returns the number of times the Option associated with name has been 226// seen while parsing s's arguments. Name should either be a rune (the short 227// name) or a string (the long name). 228func (s *Set) GetCount(name interface{}) int { 229 if opt := s.Lookup(name); opt != nil { 230 return opt.Count() 231 } 232 return 0 233} 234 235// GetValue returns the final value set to the command-line Option with name. 236// If the option has not been seen while parsing s then the default value is 237// returned. Name should either be a rune (the short name) or a string (the 238// long name). 239func GetValue(name interface{}) string { 240 return CommandLine.GetValue(name) 241} 242 243// GetValue returns the final value set to the Option in s associated with name. 244// If the option has not been seen while parsing s then the default value is 245// returned. Name should either be a rune (the short name) or a string (the 246// long name). 247func (s *Set) GetValue(name interface{}) string { 248 if opt := s.Lookup(name); opt != nil { 249 return opt.String() 250 } 251 return "" 252} 253 254// Visit visits the command-line options in lexicographical order, calling fn 255// for each. It visits only those options that have been set. 256func Visit(fn func(Option)) { CommandLine.Visit(fn) } 257 258// Visit visits the options in s in lexicographical order, calling fn 259// for each. It visits only those options that have been set. 260func (s *Set) Visit(fn func(Option)) { 261 sort.Sort(s.options) 262 for _, opt := range s.options { 263 if opt.count > 0 { 264 fn(opt) 265 } 266 } 267} 268 269// VisitAll visits the options in s in lexicographical order, calling fn 270// for each. It visits all options, even those not set. 271func VisitAll(fn func(Option)) { CommandLine.VisitAll(fn) } 272 273// VisitAll visits the command-line flags in lexicographical order, calling fn 274// for each. It visits all flags, even those not set. 275func (s *Set) VisitAll(fn func(Option)) { 276 sort.Sort(s.options) 277 for _, opt := range s.options { 278 fn(opt) 279 } 280} 281 282// Reset resets all the command line options to the initial state so it 283// appears none of them have been seen. 284func Reset() { 285 CommandLine.Reset() 286} 287 288// Reset resets all the options in s to the initial state so it 289// appears none of them have been seen. 290func (s *Set) Reset() { 291 for _, opt := range s.options { 292 opt.Reset() 293 } 294} 295 296// RequiredGroup marks the group set with Option.SetGroup as required. At least 297// one option in the group must be seen by parse. Calling RequiredGroup with a 298// group name that has no options will cause parsing to always fail. 299func (s *Set) RequiredGroup(group string) { 300 s.requiredGroups = append(s.requiredGroups, group) 301} 302 303// RequiredGroup marks the group set with Option.SetGroup as required on the 304// command line. At least one option in the group must be seen by parse. 305// Calling RequiredGroup with a group name that has no options will cause 306// parsing to always fail. 307func RequiredGroup(group string) { 308 CommandLine.requiredGroups = append(CommandLine.requiredGroups, group) 309} 310