github.com/wtrep/tgf@v1.18.8/arguments.go (about) 1 package main 2 3 import ( 4 "strings" 5 6 "gopkg.in/alecthomas/kingpin.v2" 7 ) 8 9 // ApplicationArguments allows proper management between managed and non managed arguments provided to kingpin 10 type ApplicationArguments struct { 11 *kingpin.Application 12 longs map[string]bool 13 shorts map[rune]bool 14 } 15 16 func (app ApplicationArguments) add(name, description string, isSwitch bool, shorts ...rune) *kingpin.FlagClause { 17 flag := app.Application.Flag(name, description) 18 switch len(shorts) { 19 case 0: 20 break 21 case 1: 22 flag = flag.Short(shorts[0]) 23 app.shorts[shorts[0]] = isSwitch 24 default: 25 panic("Maximum one short option should be specified") 26 } 27 28 app.longs[name] = isSwitch 29 return flag 30 } 31 32 // Switch adds a switch argument to the application 33 // A switch is a boolean flag that do not require additional value 34 func (app ApplicationArguments) Switch(name, description string, shorts ...rune) *kingpin.FlagClause { 35 return app.add(name, description, true, shorts...) 36 } 37 38 // Argument adds an argument to the application 39 // The argument requires additional argument to be complete 40 func (app ApplicationArguments) Argument(name, description string, shorts ...rune) *kingpin.FlagClause { 41 return app.add(name, description, false, shorts...) 42 } 43 44 // SplitManaged splits the managed by kingpin and unmanaged argument to avoid error 45 func (app ApplicationArguments) SplitManaged(args []string) (managed []string, unmanaged []string) { 46 Arg: 47 for i := 1; i < len(args); i++ { 48 arg := args[i] 49 if arg == "--" { 50 unmanaged = append(unmanaged, args[i+1:]...) 51 break 52 } 53 if strings.HasPrefix(arg, "--") { 54 argSplit := strings.Split(args[i][2:], "=") 55 if isSwitch, ok := app.longs[argSplit[0]]; ok { 56 managed = append(managed, arg) 57 if !isSwitch && len(argSplit) == 1 { 58 // This is not a switch (bool flag) and there is no argument with 59 // the flag, so the argument must be after and we add it to 60 // the managed args if there is. 61 i++ 62 if i < len(args) { 63 managed = append(managed, args[i]) 64 } 65 } 66 } else { 67 unmanaged = append(unmanaged, arg) 68 } 69 } else if strings.HasPrefix(arg, "-") { 70 withArg := false 71 for pos, opt := range arg[1:] { 72 if isSwitch, ok := app.shorts[opt]; ok { 73 if !isSwitch { 74 // This is not a switch (bool flag), so we check if there are characters 75 // following the current flag in the same word. If it is not the case, 76 // then the argument must be after and we add it to the managed args 77 // if there is. If it is the case, then, the argument is included in 78 // the current flag and we consider the whole word as a managed argument. 79 withArg = pos == len(arg[1:])-1 80 break 81 } 82 } else { 83 unmanaged = append(unmanaged, arg) 84 continue Arg 85 } 86 } 87 managed = append(managed, arg) 88 if withArg { 89 // The next argument must be an argument to the current flag 90 i++ 91 if i < len(args) { 92 managed = append(managed, args[i]) 93 } 94 } 95 } else { 96 unmanaged = append(unmanaged, arg) 97 } 98 } 99 return 100 } 101 102 // NewApplication returns an initialized copy of ApplicationArguments 103 func NewApplication(app *kingpin.Application) ApplicationArguments { 104 return ApplicationArguments{ 105 Application: app, 106 longs: map[string]bool{ 107 "help-man": true, 108 "help-long": true, 109 "completion-bash": true, 110 "completion-script-bash": true, 111 "completion-script-zsh": true, 112 }, 113 shorts: map[rune]bool{}, 114 } 115 }