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