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} 50 51// New returns a newly created option set. 52func New() *Set { 53 s := &Set{ 54 shortOptions: make(map[rune]*option), 55 longOptions: make(map[string]*option), 56 parameters: "[parameters ...]", 57 } 58 59 s.usage = func() { 60 s.PrintUsage(stderr) 61 } 62 return s 63} 64 65func (s *Set) setState(state State) { 66 s.stateMu.Lock() 67 s.state = state 68 s.stateMu.Unlock() 69} 70 71// State returns the current state of the Set s. The state is normally the 72// reason the most recent call to Getopt returned. 73func (s *Set) State() State { 74 s.stateMu.Lock() 75 defer s.stateMu.Unlock() 76 return s.state 77} 78 79// The default set of command-line options. 80var CommandLine = New() 81 82// PrintUsage calls PrintUsage in the default option set. 83func PrintUsage(w io.Writer) { CommandLine.PrintUsage(w) } 84 85// Usage calls the usage function in the default option set. 86func Usage() { CommandLine.usage() } 87 88// Parse calls Parse in the default option set with the command line arguments 89// found in os.Args. 90func Parse() { CommandLine.Parse(os.Args) } 91 92// Getops returns the result of calling Getop in the default option set with the 93// command line arguments found in os.Args. The fn function, which may be nil, 94// is passed to Getopt. 95func Getopt(fn func(Option) bool) error { return CommandLine.Getopt(os.Args, fn) } 96 97// Arg returns the n'th command-line argument. Arg(0) is the first remaining 98// argument after options have been processed. 99func Arg(n int) string { 100 if n >= 0 && n < len(CommandLine.args) { 101 return CommandLine.args[n] 102 } 103 return "" 104} 105 106// Arg returns the n'th argument. Arg(0) is the first remaining 107// argument after options have been processed. 108func (s *Set) Arg(n int) string { 109 if n >= 0 && n < len(s.args) { 110 return s.args[n] 111 } 112 return "" 113} 114 115// Args returns the non-option command line arguments. 116func Args() []string { 117 return CommandLine.args 118} 119 120// Args returns the non-option arguments. 121func (s *Set) Args() []string { 122 return s.args 123} 124 125// NArgs returns the number of non-option command line arguments. 126func NArgs() int { 127 return len(CommandLine.args) 128} 129 130// NArgs returns the number of non-option arguments. 131func (s *Set) NArgs() int { 132 return len(s.args) 133} 134 135// SetParameters sets the parameters string for printing the command line 136// usage. It defaults to "[parameters ...]" 137func SetParameters(parameters string) { 138 CommandLine.parameters = parameters 139} 140 141// SetParameters sets the parameters string for printing the s's usage. 142// It defaults to "[parameters ...]" 143func (s *Set) SetParameters(parameters string) { 144 s.parameters = parameters 145} 146 147// SetProgram sets the program name to program. Normally it is determined 148// from the zeroth command line argument (see os.Args). 149func SetProgram(program string) { 150 CommandLine.program = program 151} 152 153// SetProgram sets s's program name to program. Normally it is determined 154// from the zeroth argument passed to Getopt or Parse. 155func (s *Set) SetProgram(program string) { 156 s.program = program 157} 158 159// SetUsage sets the function used by Parse to display the commands usage 160// on error. It defaults to calling PrintUsage(os.Stderr). 161func SetUsage(usage func()) { 162 CommandLine.usage = usage 163} 164 165// SetUsage sets the function used by Parse to display usage on error. It 166// defaults to calling f.PrintUsage(os.Stderr). 167func (s *Set) SetUsage(usage func()) { 168 s.usage = usage 169} 170 171// Lookup returns the Option associated with name. Name should either be 172// a rune (the short name) or a string (the long name). 173func Lookup(name interface{}) Option { 174 return CommandLine.Lookup(name) 175} 176 177// Lookup returns the Option associated with name in s. Name should either be 178// a rune (the short name) or a string (the long name). 179func (s *Set) Lookup(name interface{}) Option { 180 switch v := name.(type) { 181 case rune: 182 return s.shortOptions[v] 183 case int: 184 return s.shortOptions[rune(v)] 185 case string: 186 return s.longOptions[v] 187 } 188 return nil 189} 190 191// IsSet returns true if the Option associated with name was seen while 192// parsing the command line arguments. Name should either be a rune (the 193// short name) or a string (the long name). 194func IsSet(name interface{}) bool { 195 return CommandLine.IsSet(name) 196} 197 198// IsSet returns true if the Option associated with name was seen while 199// parsing s. Name should either be a rune (the short name) or a string (the 200// long name). 201func (s *Set) IsSet(name interface{}) bool { 202 if opt := s.Lookup(name); opt != nil { 203 return opt.Seen() 204 } 205 return false 206} 207 208// GetCount returns the number of times the Option associated with name has been 209// seen while parsing the command line arguments. Name should either be a rune 210// (the short name) or a string (the long name). 211func GetCount(name interface{}) int { 212 return CommandLine.GetCount(name) 213} 214 215// GetCount returns the number of times the Option associated with name has been 216// seen while parsing s's arguments. Name should either be a rune (the short 217// name) or a string (the long name). 218func (s *Set) GetCount(name interface{}) int { 219 if opt := s.Lookup(name); opt != nil { 220 return opt.Count() 221 } 222 return 0 223} 224 225// GetValue returns the final value set to the command-line Option with name. 226// If the option has not been seen while parsing s then the default value is 227// returned. Name should either be a rune (the short name) or a string (the 228// long name). 229func GetValue(name interface{}) string { 230 return CommandLine.GetValue(name) 231} 232 233// GetValue returns the final value set to the Option in s associated with name. 234// If the option has not been seen while parsing s then the default value is 235// returned. Name should either be a rune (the short name) or a string (the 236// long name). 237func (s *Set) GetValue(name interface{}) string { 238 if opt := s.Lookup(name); opt != nil { 239 return opt.String() 240 } 241 return "" 242} 243 244// Visit visits the command-line options in lexicographical order, calling fn 245// for each. It visits only those options that have been set. 246func Visit(fn func(Option)) { CommandLine.Visit(fn) } 247 248// Visit visits the options in s in lexicographical order, calling fn 249// for each. It visits only those options that have been set. 250func (s *Set) Visit(fn func(Option)) { 251 sort.Sort(s.options) 252 for _, opt := range s.options { 253 if opt.count > 0 { 254 fn(opt) 255 } 256 } 257} 258 259// VisitAll visits the options in s in lexicographical order, calling fn 260// for each. It visits all options, even those not set. 261func VisitAll(fn func(Option)) { CommandLine.VisitAll(fn) } 262 263// VisitAll visits the command-line flags in lexicographical order, calling fn 264// for each. It visits all flags, even those not set. 265func (s *Set) VisitAll(fn func(Option)) { 266 sort.Sort(s.options) 267 for _, opt := range s.options { 268 fn(opt) 269 } 270} 271 272// Reset resets all the command line options to the initial state so it 273// appears none of them have been seen. 274func Reset() { 275 CommandLine.Reset() 276} 277 278// Reset resets all the options in s to the initial state so it 279// appears none of them have been seen. 280func (s *Set) Reset() { 281 for _, opt := range s.options { 282 opt.Reset() 283 } 284} 285