|
152 | 152 | // Unless an option type explicitly prohibits it, an option may appear more than |
153 | 153 | // once in the arguments. The last value provided to the option is the value. |
154 | 154 | // |
| 155 | +// MANDATORY OPTIONS |
| 156 | +// |
| 157 | +// An option marked as mandatory and not seen when parsing will cause an error |
| 158 | +// to be reported such as: "program: --name is a mandatory option". An option |
| 159 | +// is marked mandatory by using the Mandatory method: |
| 160 | +// |
| 161 | +// getopt.FlagLong(&fileName, "path", 0, "the path").Mandatory() |
| 162 | +// |
| 163 | +// Mandatory options have (required) appended to their help message: |
| 164 | +// |
| 165 | +// --path=value the path (required) |
| 166 | +// |
| 167 | +// MUTUALLY EXCLUSIVE OPTIONS |
| 168 | +// |
| 169 | +// Options can be marked as part of a mutually exclusive group. When two or |
| 170 | +// more options in a mutually exclusive group are both seen while parsing then |
| 171 | +// an error such as "program: options -a and -b are mutually exclusive" will be |
| 172 | +// reported. Mutually exclusive groups are declared using the SetGroup method: |
| 173 | +// |
| 174 | +// getopt.Flag(&a, 'a', "use method A").SetGroup("method") |
| 175 | +// getopt.Flag(&a, 'b', "use method B").SetGroup("method") |
| 176 | +// |
| 177 | +// A set can have multiple mutually exclusive groups. Mutually exclusive groups |
| 178 | +// are identified with their group name in {}'s appeneded to their help message: |
| 179 | +// |
| 180 | +// -a use method A {method} |
| 181 | +// -b use method B {method} |
| 182 | +// |
155 | 183 | // BUILTIN TYPES |
156 | 184 | // |
157 | 185 | // The Flag and FlagLong functions support most standard Go types. For the |
@@ -318,7 +346,7 @@ func (s *Set) PrintOptions(w io.Writer) { |
318 | 346 | for _, opt := range s.options { |
319 | 347 | if opt.uname != "" { |
320 | 348 | opt.help = strings.TrimSpace(opt.help) |
321 | | - if len(opt.help) == 0 { |
| 349 | + if len(opt.help) == 0 && !opt.mandatory && opt.group == "" { |
322 | 350 | fmt.Fprintf(w, " %s\n", opt.uname) |
323 | 351 | continue |
324 | 352 | } |
@@ -350,6 +378,12 @@ func (s *Set) PrintOptions(w io.Writer) { |
350 | 378 | if def != "" { |
351 | 379 | helpMsg += " [" + def + "]" |
352 | 380 | } |
| 381 | + if opt.group != "" { |
| 382 | + helpMsg += " {" + opt.group + "}" |
| 383 | + } |
| 384 | + if opt.mandatory { |
| 385 | + helpMsg += " (required)" |
| 386 | + } |
353 | 387 |
|
354 | 388 | help := strings.Split(helpMsg, "\n") |
355 | 389 | // If they did not put in newlines then we will insert |
@@ -444,6 +478,12 @@ func (s *Set) Getopt(args []string, fn func(Option) bool) (err error) { |
444 | 478 | } |
445 | 479 | } |
446 | 480 | }() |
| 481 | + |
| 482 | + defer func() { |
| 483 | + if err == nil { |
| 484 | + err = s.checkOptions() |
| 485 | + } |
| 486 | + }() |
447 | 487 | if fn == nil { |
448 | 488 | fn = func(Option) bool { return true } |
449 | 489 | } |
@@ -562,3 +602,35 @@ Parsing: |
562 | 602 | s.args = []string{} |
563 | 603 | return nil |
564 | 604 | } |
| 605 | + |
| 606 | +func (s *Set) checkOptions() error { |
| 607 | + groups := map[string]Option{} |
| 608 | + for _, opt := range s.options { |
| 609 | + if !opt.Seen() { |
| 610 | + if opt.mandatory { |
| 611 | + return fmt.Errorf("option %s is mandatory", opt.Name()) |
| 612 | + } |
| 613 | + continue |
| 614 | + } |
| 615 | + if opt.group == "" { |
| 616 | + continue |
| 617 | + } |
| 618 | + if opt2 := groups[opt.group]; opt2 != nil { |
| 619 | + return fmt.Errorf("options %s and %s are mutually exclusive", opt2.Name(), opt.Name()) |
| 620 | + } |
| 621 | + groups[opt.group] = opt |
| 622 | + } |
| 623 | + for _, group := range s.requiredGroups { |
| 624 | + if groups[group] != nil { |
| 625 | + continue |
| 626 | + } |
| 627 | + var flags []string |
| 628 | + for _, opt := range s.options { |
| 629 | + if opt.group == group { |
| 630 | + flags = append(flags, opt.Name()) |
| 631 | + } |
| 632 | + } |
| 633 | + return fmt.Errorf("exactly one of the following options must be specified: %s", strings.Join(flags, ", ")) |
| 634 | + } |
| 635 | + return nil |
| 636 | +} |
0 commit comments