1
2
3
4
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
60 package flag
61
62 import (
63 "fmt"
64 "os"
65 "sort"
66 "strconv"
67 )
68
69
70 var ErrHelp = os.NewError("flag: help requested")
71
72
73 type boolValue bool
74
75 func newBoolValue(val bool, p *bool) *boolValue {
76 *p = val
77 return (*boolValue)(p)
78 }
79
80 func (b *boolValue) Set(s string) bool {
81 v, err := strconv.Atob(s)
82 *b = boolValue(v)
83 return err == nil
84 }
85
86 func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
87
88
89 type intValue int
90
91 func newIntValue(val int, p *int) *intValue {
92 *p = val
93 return (*intValue)(p)
94 }
95
96 func (i *intValue) Set(s string) bool {
97 v, err := strconv.Btoi64(s, 0)
98 *i = intValue(v)
99 return err == nil
100 }
101
102 func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
103
104
105 type int64Value int64
106
107 func newInt64Value(val int64, p *int64) *int64Value {
108 *p = val
109 return (*int64Value)(p)
110 }
111
112 func (i *int64Value) Set(s string) bool {
113 v, err := strconv.Btoi64(s, 0)
114 *i = int64Value(v)
115 return err == nil
116 }
117
118 func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
119
120
121 type uintValue uint
122
123 func newUintValue(val uint, p *uint) *uintValue {
124 *p = val
125 return (*uintValue)(p)
126 }
127
128 func (i *uintValue) Set(s string) bool {
129 v, err := strconv.Btoui64(s, 0)
130 *i = uintValue(v)
131 return err == nil
132 }
133
134 func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
135
136
137 type uint64Value uint64
138
139 func newUint64Value(val uint64, p *uint64) *uint64Value {
140 *p = val
141 return (*uint64Value)(p)
142 }
143
144 func (i *uint64Value) Set(s string) bool {
145 v, err := strconv.Btoui64(s, 0)
146 *i = uint64Value(v)
147 return err == nil
148 }
149
150 func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
151
152
153 type stringValue string
154
155 func newStringValue(val string, p *string) *stringValue {
156 *p = val
157 return (*stringValue)(p)
158 }
159
160 func (s *stringValue) Set(val string) bool {
161 *s = stringValue(val)
162 return true
163 }
164
165 func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
166
167
168 type float64Value float64
169
170 func newFloat64Value(val float64, p *float64) *float64Value {
171 *p = val
172 return (*float64Value)(p)
173 }
174
175 func (f *float64Value) Set(s string) bool {
176 v, err := strconv.Atof64(s)
177 *f = float64Value(v)
178 return err == nil
179 }
180
181 func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
182
183
184
185 type Value interface {
186 String() string
187 Set(string) bool
188 }
189
190
191 type ErrorHandling int
192
193 const (
194 ContinueOnError ErrorHandling = iota
195 ExitOnError
196 PanicOnError
197 )
198
199
200 type FlagSet struct {
201
202
203
204 Usage func()
205
206 name string
207 actual map[string]*Flag
208 formal map[string]*Flag
209 args []string
210 exitOnError bool
211 errorHandling ErrorHandling
212 }
213
214
215 type Flag struct {
216 Name string
217 Usage string
218 Value Value
219 DefValue string
220 }
221
222
223 func sortFlags(flags map[string]*Flag) []*Flag {
224 list := make(sort.StringSlice, len(flags))
225 i := 0
226 for _, f := range flags {
227 list[i] = f.Name
228 i++
229 }
230 list.Sort()
231 result := make([]*Flag, len(list))
232 for i, name := range list {
233 result[i] = flags[name]
234 }
235 return result
236 }
237
238
239
240 func (f *FlagSet) VisitAll(fn func(*Flag)) {
241 for _, flag := range sortFlags(f.formal) {
242 fn(flag)
243 }
244 }
245
246
247
248 func VisitAll(fn func(*Flag)) {
249 commandLine.VisitAll(fn)
250 }
251
252
253
254 func (f *FlagSet) Visit(fn func(*Flag)) {
255 for _, flag := range sortFlags(f.actual) {
256 fn(flag)
257 }
258 }
259
260
261
262 func Visit(fn func(*Flag)) {
263 commandLine.Visit(fn)
264 }
265
266
267 func (f *FlagSet) Lookup(name string) *Flag {
268 return f.formal[name]
269 }
270
271
272
273 func Lookup(name string) *Flag {
274 return commandLine.formal[name]
275 }
276
277
278
279 func (f *FlagSet) Set(name, value string) bool {
280 flag, ok := f.formal[name]
281 if !ok {
282 return false
283 }
284 ok = flag.Value.Set(value)
285 if !ok {
286 return false
287 }
288 f.actual[name] = flag
289 return true
290 }
291
292
293
294 func Set(name, value string) bool {
295 return commandLine.Set(name, value)
296 }
297
298
299 func (f *FlagSet) PrintDefaults() {
300 f.VisitAll(func(f *Flag) {
301 format := " -%s=%s: %s\n"
302 if _, ok := f.Value.(*stringValue); ok {
303
304 format = " -%s=%q: %s\n"
305 }
306 fmt.Fprintf(os.Stderr, format, f.Name, f.DefValue, f.Usage)
307 })
308 }
309
310
311 func PrintDefaults() {
312 commandLine.PrintDefaults()
313 }
314
315
316 func defaultUsage(f *FlagSet) {
317 fmt.Fprintf(os.Stderr, "Usage of %s:\n", f.name)
318 f.PrintDefaults()
319 }
320
321
322
323 var Usage = func() {
324 defaultUsage(commandLine)
325 }
326
327
328 func (f *FlagSet) NFlag() int { return len(f.actual) }
329
330
331 func NFlag() int { return len(commandLine.actual) }
332
333
334
335 func (f *FlagSet) Arg(i int) string {
336 if i < 0 || i >= len(f.args) {
337 return ""
338 }
339 return f.args[i]
340 }
341
342
343
344 func Arg(i int) string {
345 return commandLine.Arg(i)
346 }
347
348
349 func (f *FlagSet) NArg() int { return len(f.args) }
350
351
352 func NArg() int { return len(commandLine.args) }
353
354
355 func (f *FlagSet) Args() []string { return f.args }
356
357
358 func Args() []string { return commandLine.args }
359
360
361
362 func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
363 f.Var(newBoolValue(value, p), name, usage)
364 }
365
366
367
368 func BoolVar(p *bool, name string, value bool, usage string) {
369 commandLine.Var(newBoolValue(value, p), name, usage)
370 }
371
372
373
374 func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
375 p := new(bool)
376 f.BoolVar(p, name, value, usage)
377 return p
378 }
379
380
381
382 func Bool(name string, value bool, usage string) *bool {
383 return commandLine.Bool(name, value, usage)
384 }
385
386
387
388 func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
389 f.Var(newIntValue(value, p), name, usage)
390 }
391
392
393
394 func IntVar(p *int, name string, value int, usage string) {
395 commandLine.Var(newIntValue(value, p), name, usage)
396 }
397
398
399
400 func (f *FlagSet) Int(name string, value int, usage string) *int {
401 p := new(int)
402 f.IntVar(p, name, value, usage)
403 return p
404 }
405
406
407
408 func Int(name string, value int, usage string) *int {
409 return commandLine.Int(name, value, usage)
410 }
411
412
413
414 func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
415 f.Var(newInt64Value(value, p), name, usage)
416 }
417
418
419
420 func Int64Var(p *int64, name string, value int64, usage string) {
421 commandLine.Var(newInt64Value(value, p), name, usage)
422 }
423
424
425
426 func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
427 p := new(int64)
428 f.Int64Var(p, name, value, usage)
429 return p
430 }
431
432
433
434 func Int64(name string, value int64, usage string) *int64 {
435 return commandLine.Int64(name, value, usage)
436 }
437
438
439
440 func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
441 f.Var(newUintValue(value, p), name, usage)
442 }
443
444
445
446 func UintVar(p *uint, name string, value uint, usage string) {
447 commandLine.Var(newUintValue(value, p), name, usage)
448 }
449
450
451
452 func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
453 p := new(uint)
454 f.UintVar(p, name, value, usage)
455 return p
456 }
457
458
459
460 func Uint(name string, value uint, usage string) *uint {
461 return commandLine.Uint(name, value, usage)
462 }
463
464
465
466 func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
467 f.Var(newUint64Value(value, p), name, usage)
468 }
469
470
471
472 func Uint64Var(p *uint64, name string, value uint64, usage string) {
473 commandLine.Var(newUint64Value(value, p), name, usage)
474 }
475
476
477
478 func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
479 p := new(uint64)
480 f.Uint64Var(p, name, value, usage)
481 return p
482 }
483
484
485
486 func Uint64(name string, value uint64, usage string) *uint64 {
487 return commandLine.Uint64(name, value, usage)
488 }
489
490
491
492 func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
493 f.Var(newStringValue(value, p), name, usage)
494 }
495
496
497
498 func StringVar(p *string, name string, value string, usage string) {
499 commandLine.Var(newStringValue(value, p), name, usage)
500 }
501
502
503
504 func (f *FlagSet) String(name string, value string, usage string) *string {
505 p := new(string)
506 f.StringVar(p, name, value, usage)
507 return p
508 }
509
510
511
512 func String(name string, value string, usage string) *string {
513 return commandLine.String(name, value, usage)
514 }
515
516
517
518 func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
519 f.Var(newFloat64Value(value, p), name, usage)
520 }
521
522
523
524 func Float64Var(p *float64, name string, value float64, usage string) {
525 commandLine.Var(newFloat64Value(value, p), name, usage)
526 }
527
528
529
530 func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
531 p := new(float64)
532 f.Float64Var(p, name, value, usage)
533 return p
534 }
535
536
537
538 func Float64(name string, value float64, usage string) *float64 {
539 return commandLine.Float64(name, value, usage)
540 }
541
542
543
544
545
546
547
548 func (f *FlagSet) Var(value Value, name string, usage string) {
549
550 flag := &Flag{name, usage, value, value.String()}
551 _, alreadythere := f.formal[name]
552 if alreadythere {
553 fmt.Fprintf(os.Stderr, "%s flag redefined: %s\n", f.name, name)
554 panic("flag redefinition")
555 }
556 f.formal[name] = flag
557 }
558
559
560
561
562
563
564
565 func Var(value Value, name string, usage string) {
566 commandLine.Var(value, name, usage)
567 }
568
569
570
571 func (f *FlagSet) failf(format string, a ...interface{}) os.Error {
572 err := fmt.Errorf(format, a...)
573 fmt.Fprintln(os.Stderr, err)
574 f.usage()
575 return err
576 }
577
578
579
580 func (f *FlagSet) usage() {
581 if f == commandLine {
582 Usage()
583 } else {
584 f.Usage()
585 }
586 }
587
588
589 func (f *FlagSet) parseOne() (bool, os.Error) {
590 if len(f.args) == 0 {
591 return false, nil
592 }
593 s := f.args[0]
594 if len(s) == 0 || s[0] != '-' || len(s) == 1 {
595 return false, nil
596 }
597 num_minuses := 1
598 if s[1] == '-' {
599 num_minuses++
600 if len(s) == 2 {
601 f.args = f.args[1:]
602 return false, nil
603 }
604 }
605 name := s[num_minuses:]
606 if len(name) == 0 || name[0] == '-' || name[0] == '=' {
607 return false, f.failf("bad flag syntax: %s", s)
608 }
609
610
611 f.args = f.args[1:]
612 has_value := false
613 value := ""
614 for i := 1; i < len(name); i++ {
615 if name[i] == '=' {
616 value = name[i+1:]
617 has_value = true
618 name = name[0:i]
619 break
620 }
621 }
622 m := f.formal
623 flag, alreadythere := m[name]
624 if !alreadythere {
625 if name == "help" || name == "h" {
626 f.usage()
627 return false, ErrHelp
628 }
629 return false, f.failf("flag provided but not defined: -%s", name)
630 }
631 if fv, ok := flag.Value.(*boolValue); ok {
632 if has_value {
633 if !fv.Set(value) {
634 f.failf("invalid boolean value %q for flag: -%s", value, name)
635 }
636 } else {
637 fv.Set("true")
638 }
639 } else {
640
641 if !has_value && len(f.args) > 0 {
642
643 has_value = true
644 value, f.args = f.args[0], f.args[1:]
645 }
646 if !has_value {
647 return false, f.failf("flag needs an argument: -%s", name)
648 }
649 ok = flag.Value.Set(value)
650 if !ok {
651 return false, f.failf("invalid value %q for flag: -%s", value, name)
652 }
653 }
654 f.actual[name] = flag
655 return true, nil
656 }
657
658
659
660
661
662 func (f *FlagSet) Parse(arguments []string) os.Error {
663 f.args = arguments
664 for {
665 seen, err := f.parseOne()
666 if seen {
667 continue
668 }
669 if err == nil {
670 break
671 }
672 switch f.errorHandling {
673 case ContinueOnError:
674 return err
675 case ExitOnError:
676 os.Exit(2)
677 case PanicOnError:
678 panic(err)
679 }
680 }
681 return nil
682 }
683
684
685
686 func Parse() {
687
688 commandLine.Parse(os.Args[1:])
689 }
690
691
692 var commandLine = NewFlagSet(os.Args[0], ExitOnError)
693
694
695
696 func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
697 f := &FlagSet{
698 name: name,
699 actual: make(map[string]*Flag),
700 formal: make(map[string]*Flag),
701 errorHandling: errorHandling,
702 }
703 f.Usage = func() { defaultUsage(f) }
704 return f
705 }