github.com/jmigpin/editor@v1.6.0/util/flagutil/parsedargs.go (about) 1 package flagutil 2 3 import "strings" 4 5 // NOTE: alternative to flag.flagset (more premitive, lacks documentation utility) 6 7 func ParseParsedArgs(args []string, isBool map[string]bool) ParsedArgs { 8 pa := ParsedArgs{} 9 for i := 0; i < len(args); i++ { 10 name, value, k := parseArg(args, i, isBool) 11 arg := &Arg{Name: name, Value: value} 12 i = k 13 pa = append(pa, arg) 14 } 15 return pa 16 } 17 18 //---------- 19 20 type ParsedArgs []*Arg 21 22 func (pa ParsedArgs) Get(name string) (*Arg, bool) { 23 for _, a := range pa { 24 if a.Name == name { 25 return a, true 26 } 27 } 28 return nil, false 29 } 30 31 func (pa *ParsedArgs) Remove(arg *Arg) { 32 for i, a := range *pa { 33 if a == arg { 34 *pa = append((*pa)[:i], (*pa)[i+1:]...) 35 break 36 } 37 } 38 } 39 40 func (pa ParsedArgs) Join() []string { 41 u := []string{} 42 for _, a := range pa { 43 u = append(u, a.String()) 44 } 45 return u 46 } 47 48 //---------- 49 50 func (pa ParsedArgs) CommonSplit() (ParsedArgs, ParsedArgs, ParsedArgs) { 51 pa, binaryPa := pa.SplitAtDoubleDashExclude() 52 pa, unnamedPa := pa.SplitAtFirstUnnamed() 53 unnamedPa, namedPa := unnamedPa.SplitAtFirstNamed() 54 binaryPa = append(namedPa, binaryPa...) 55 return pa, unnamedPa, binaryPa 56 } 57 58 func (pa ParsedArgs) SplitAtFirstUnnamed() (ParsedArgs, ParsedArgs) { 59 for i, a := range pa { 60 if a.Name == "" { // name is empty if no dash was used 61 return pa[:i], pa[i:] 62 } 63 } 64 return pa, nil 65 } 66 67 func (pa ParsedArgs) SplitAtFirstNamed() (ParsedArgs, ParsedArgs) { 68 for i, a := range pa { 69 if a.Name != "" { // name is not empty if a dash was used 70 return pa[:i], pa[i:] 71 } 72 } 73 return pa, nil 74 } 75 76 func (pa ParsedArgs) SplitAtDoubleDashExclude() (ParsedArgs, ParsedArgs) { 77 return pa.SplitAtNameExclude("--") 78 } 79 80 func (pa ParsedArgs) SplitAtNameExclude(name string) (ParsedArgs, ParsedArgs) { 81 for i, a := range pa { 82 if a.Name == name { 83 return pa[:i], pa[i+1:] 84 } 85 } 86 return pa, nil 87 } 88 89 //---------- 90 91 type Arg struct { 92 Name string // can be empty if just a value 93 Value string // can be empty if just a name 94 } 95 96 func (a *Arg) String() string { 97 s := "" 98 if a.Name != "" { 99 s += "-" + a.Name 100 } 101 if a.Value != "" { 102 if a.Name != "" { 103 s += "=" 104 } 105 s += a.Value 106 } 107 return s 108 } 109 110 //---------- 111 112 func parseArg(args []string, i int, isBool map[string]bool) (name string, value string, curI int) { 113 curI = i 114 arg := args[curI] 115 116 dash := "-" 117 dashed := strings.HasPrefix(arg, dash) 118 if !dashed { 119 value = arg 120 return 121 } 122 123 // TODO: cut only 2? 124 noDashArg := strings.TrimLeft(arg, dash) 125 126 // an arg full of dashes (ex: "--") 127 if noDashArg == "" { 128 name = arg 129 return 130 } 131 132 name = noDashArg 133 if k := strings.Index(noDashArg, "="); k >= 0 { 134 name = noDashArg[:k] 135 value = noDashArg[k+1:] 136 137 // simplify bool values 138 if isBool != nil && isBool[name] { 139 if s, ok := simplifyBoolValue(value); ok { 140 value = s 141 } 142 } 143 144 return 145 } 146 147 // value after a space from here 148 149 if isBool != nil && isBool[name] { 150 return // no spaced value 151 } 152 153 if i+1 >= len(args) { 154 return // missing spaced value 155 } 156 157 // take next arg as value 158 curI = i + 1 159 arg = args[curI] 160 value = arg 161 return 162 }