Skip to content

Commit c5000d0

Browse files
committed
chore: upgrade goNixArgParser
- refactor(optionSetParse): Lift Option.AcceptValue check - feat(flag): add `prefixMatchLen` - feat(option): extract shortcut funcs to create Option
1 parent 07e845e commit c5000d0

File tree

9 files changed

+245
-82
lines changed

9 files changed

+245
-82
lines changed

src/goNixArgParser/flag.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package goNixArgParser
22

3-
func NewFlag(name string, canMerge, canFollowAssign, canConcatAssign bool, assignSigns []string) *Flag {
3+
func NewFlag(name string, prefixMatchLen int, canMerge, canFollowAssign, canConcatAssign bool, assignSigns []string) *Flag {
44
return &Flag{
55
Name: name,
6+
prefixMatchLen: prefixMatchLen,
67
canMerge: canMerge,
78
canFollowAssign: canFollowAssign,
89
canConcatAssign: canConcatAssign,
@@ -21,7 +22,7 @@ func NewSimpleFlag(name string) *Flag {
2122
assignSigns = append(assignSigns, "=")
2223
}
2324

24-
return NewFlag(name, canMerge, true, canConcatAssign, assignSigns)
25+
return NewFlag(name, 0, canMerge, true, canConcatAssign, assignSigns)
2526
}
2627

2728
func NewSimpleFlags(names []string) []*Flag {

src/goNixArgParser/option.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,71 @@ func (opt *Option) GetHelp() []byte {
8888

8989
return buffer.Bytes()
9090
}
91+
92+
func NewFlagOption(key, flag, envVar, summary string) Option {
93+
return Option{
94+
Key: key,
95+
Flags: []*Flag{NewSimpleFlag(flag)},
96+
EnvVars: StringToSlice(envVar),
97+
Summary: summary,
98+
}
99+
}
100+
101+
func NewFlagsOption(key string, flags []string, envVar, summary string) Option {
102+
return Option{
103+
Key: key,
104+
Flags: NewSimpleFlags(flags),
105+
EnvVars: StringToSlice(envVar),
106+
Summary: summary,
107+
}
108+
}
109+
110+
func NewFlagValueOption(key, flag, envVar, defaultValue, summary string) Option {
111+
return Option{
112+
Key: key,
113+
Flags: []*Flag{NewSimpleFlag(flag)},
114+
AcceptValue: true,
115+
OverridePrev: true,
116+
EnvVars: StringToSlice(envVar),
117+
DefaultValues: StringToSlice(defaultValue),
118+
Summary: summary,
119+
}
120+
}
121+
122+
func NewFlagValuesOption(key, flag, envVar string, defaultValues []string, summary string) Option {
123+
return Option{
124+
Key: key,
125+
Flags: []*Flag{NewSimpleFlag(flag)},
126+
AcceptValue: true,
127+
MultiValues: true,
128+
UniqueValues: true,
129+
EnvVars: StringToSlice(envVar),
130+
DefaultValues: defaultValues,
131+
Summary: summary,
132+
}
133+
}
134+
135+
func NewFlagsValueOption(key string, flags []string, envVar, defaultValue, summary string) Option {
136+
return Option{
137+
Key: key,
138+
Flags: NewSimpleFlags(flags),
139+
AcceptValue: true,
140+
OverridePrev: true,
141+
EnvVars: StringToSlice(envVar),
142+
DefaultValues: StringToSlice(defaultValue),
143+
Summary: summary,
144+
}
145+
}
146+
147+
func NewFlagsValuesOption(key string, flags []string, envVar string, defaultValues []string, summary string) Option {
148+
return Option{
149+
Key: key,
150+
Flags: NewSimpleFlags(flags),
151+
AcceptValue: true,
152+
MultiValues: true,
153+
UniqueValues: true,
154+
EnvVars: StringToSlice(envVar),
155+
DefaultValues: defaultValues,
156+
Summary: summary,
157+
}
158+
}

src/goNixArgParser/optionSet.go

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,33 @@ func (s *OptionSet) isUdefFlag(input string) bool {
8888
return false
8989
}
9090

91-
func (s *OptionSet) Append(opt Option) error {
91+
func (s *OptionSet) findFlagByPrefix(prefix string) (flag *Flag, ambiguous bool) {
92+
if !s.hasPrefixMatch {
93+
return
94+
}
95+
96+
prefixLen := len(prefix)
97+
if prefixLen == 0 {
98+
return
99+
}
100+
101+
var matched *Flag
102+
103+
for _, opt := range s.options {
104+
for _, flag := range opt.Flags {
105+
if prefixLen >= flag.prefixMatchLen && strings.HasPrefix(flag.Name, prefix) {
106+
if matched != nil { // found more than 1 match, not unique match
107+
return nil, true
108+
}
109+
matched = flag
110+
}
111+
}
112+
}
113+
114+
return matched, false
115+
}
116+
117+
func (s *OptionSet) Add(opt Option) error {
92118
// verify
93119
if len(opt.Key) == 0 {
94120
return errors.New("key is empty")
@@ -124,6 +150,9 @@ func (s *OptionSet) Append(opt Option) error {
124150
if len(flag.assignSigns) > 0 {
125151
s.hasAssignSigns = true
126152
}
153+
if flag.prefixMatchLen > 0 {
154+
s.hasPrefixMatch = true
155+
}
127156

128157
flagName := flag.Name
129158
s.flagOptionMap[flagName] = option
@@ -157,71 +186,27 @@ func (s *OptionSet) Append(opt Option) error {
157186
}
158187

159188
func (s *OptionSet) AddFlag(key, flag, envVar, summary string) error {
160-
return s.Append(Option{
161-
Key: key,
162-
Flags: []*Flag{NewSimpleFlag(flag)},
163-
EnvVars: StringToSlice(envVar),
164-
Summary: summary,
165-
})
189+
return s.Add(NewFlagOption(key, flag, envVar, summary))
166190
}
167191

168192
func (s *OptionSet) AddFlags(key string, flags []string, envVar, summary string) error {
169-
return s.Append(Option{
170-
Key: key,
171-
Flags: NewSimpleFlags(flags),
172-
EnvVars: StringToSlice(envVar),
173-
Summary: summary,
174-
})
193+
return s.Add(NewFlagsOption(key, flags, envVar, summary))
175194
}
176195

177196
func (s *OptionSet) AddFlagValue(key, flag, envVar, defaultValue, summary string) error {
178-
return s.Append(Option{
179-
Key: key,
180-
Flags: []*Flag{NewSimpleFlag(flag)},
181-
AcceptValue: true,
182-
OverridePrev: true,
183-
EnvVars: StringToSlice(envVar),
184-
DefaultValues: StringToSlice(defaultValue),
185-
Summary: summary,
186-
})
197+
return s.Add(NewFlagValueOption(key, flag, envVar, defaultValue, summary))
187198
}
188199

189200
func (s *OptionSet) AddFlagValues(key, flag, envVar string, defaultValues []string, summary string) error {
190-
return s.Append(Option{
191-
Key: key,
192-
Flags: []*Flag{NewSimpleFlag(flag)},
193-
AcceptValue: true,
194-
MultiValues: true,
195-
UniqueValues: true,
196-
EnvVars: StringToSlice(envVar),
197-
DefaultValues: defaultValues,
198-
Summary: summary,
199-
})
201+
return s.Add(NewFlagValuesOption(key, flag, envVar, defaultValues, summary))
200202
}
201203

202204
func (s *OptionSet) AddFlagsValue(key string, flags []string, envVar, defaultValue, summary string) error {
203-
return s.Append(Option{
204-
Key: key,
205-
Flags: NewSimpleFlags(flags),
206-
AcceptValue: true,
207-
OverridePrev: true,
208-
EnvVars: StringToSlice(envVar),
209-
DefaultValues: StringToSlice(defaultValue),
210-
Summary: summary,
211-
})
205+
return s.Add(NewFlagsValueOption(key, flags, envVar, defaultValue, summary))
212206
}
213207

214208
func (s *OptionSet) AddFlagsValues(key string, flags []string, envVar string, defaultValues []string, summary string) error {
215-
return s.Append(Option{
216-
Key: key,
217-
Flags: NewSimpleFlags(flags),
218-
AcceptValue: true,
219-
MultiValues: true,
220-
UniqueValues: true,
221-
EnvVars: StringToSlice(envVar),
222-
DefaultValues: defaultValues,
223-
Summary: summary,
224-
})
209+
return s.Add(NewFlagsValuesOption(key, flags, envVar, defaultValues, summary))
225210
}
226211

227212
func (s *OptionSet) GetHelp() []byte {

src/goNixArgParser/optionSetParse.go

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,22 +79,32 @@ func (s *OptionSet) splitAssignSignArg(arg *Arg) (args []*Arg) {
7979

8080
argText := arg.Text
8181
for _, flag := range s.flagMap {
82+
flagName := flag.Name
83+
if !s.flagOptionMap[flagName].AcceptValue {
84+
continue
85+
}
8286
for _, assignSign := range flag.assignSigns {
83-
flagName := flag.Name
84-
85-
if len(assignSign) == 0 || !s.flagOptionMap[flagName].AcceptValue {
87+
if len(assignSign) == 0 {
8688
continue
8789
}
8890

8991
prefix := flagName + assignSign
90-
if !strings.HasPrefix(argText, prefix) {
91-
continue
92+
if strings.HasPrefix(argText, prefix) {
93+
args = append(args, NewArg(flagName, FlagArg))
94+
args = append(args, NewArg(argText[len(prefix):], ValueArg))
95+
return
9296
}
93-
flagValue := argText[len(prefix):]
9497

95-
args = append(args, NewArg(flagName, FlagArg))
96-
args = append(args, NewArg(flagValue, ValueArg))
97-
return
98+
assignIndex := strings.Index(argText, assignSign)
99+
if assignIndex <= 0 {
100+
continue
101+
}
102+
prefix = argText[0:assignIndex]
103+
if foundFlag, _ := s.findFlagByPrefix(prefix); foundFlag == flag {
104+
args = append(args, NewArg(flagName, FlagArg))
105+
args = append(args, NewArg(argText[assignIndex+len(assignSign):], ValueArg))
106+
return
107+
}
98108
}
99109
}
100110

@@ -149,6 +159,27 @@ func (s *OptionSet) splitConcatAssignArgs(initArgs []*Arg) []*Arg {
149159
return args
150160
}
151161

162+
func (s *OptionSet) markAmbiguPrefixArgsValues(args []*Arg) {
163+
foundAmbiguFlag := false
164+
for _, arg := range args {
165+
if arg.Type != UndetermArg {
166+
foundAmbiguFlag = false
167+
continue
168+
}
169+
actualFlag, ambiguous := s.findFlagByPrefix(arg.Text)
170+
if ambiguous {
171+
arg.Type = AmbiguousFlagArg
172+
foundAmbiguFlag = true
173+
} else if actualFlag != nil {
174+
arg.Type = FlagArg
175+
arg.Text = actualFlag.Name
176+
foundAmbiguFlag = false
177+
} else if foundAmbiguFlag {
178+
arg.Type = AmbiguousFlagValueArg
179+
}
180+
}
181+
}
182+
152183
func (s *OptionSet) markUndefArgsValues(args []*Arg) {
153184
foundUndefFlag := false
154185
for _, arg := range args {
@@ -176,9 +207,10 @@ func isValueArg(flag *Flag, arg *Arg) bool {
176207
}
177208
}
178209

179-
func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string, rests, undefs []string) {
210+
func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string, rests, ambigus, undefs []string) {
180211
args = map[string][]string{}
181212
rests = []string{}
213+
ambigus = []string{}
182214
undefs = []string{}
183215

184216
flagOptionMap := s.flagOptionMap
@@ -194,6 +226,7 @@ func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string,
194226
argObjs = s.splitConcatAssignArgs(argObjs)
195227
}
196228

229+
s.markAmbiguPrefixArgsValues(argObjs)
197230
s.markUndefArgsValues(argObjs)
198231

199232
// walk
@@ -213,6 +246,16 @@ func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string,
213246
continue
214247
}
215248

249+
// ambigus
250+
if arg.Type == AmbiguousFlagValueArg {
251+
continue
252+
}
253+
254+
if arg.Type == AmbiguousFlagArg {
255+
ambigus = append(ambigus, arg.Text)
256+
continue
257+
}
258+
216259
// undefs
217260
if arg.Type == UndefFlagValueArg {
218261
continue
@@ -284,15 +327,15 @@ func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string,
284327
}
285328
}
286329

287-
return args, rests, undefs
330+
return args, rests, ambigus, undefs
288331
}
289332

290333
func (s *OptionSet) parseInGroup(argObjs, configObjs []*Arg) *ParseResult {
291334
keyOptionMap := s.keyOptionMap
292335

293-
args, argRests, argUndefs := s.parseArgsInGroup(argObjs)
336+
args, argRests, argAmbigus, argUndefs := s.parseArgsInGroup(argObjs)
294337
envs := s.keyEnvMap
295-
configs, configRests, configUndefs := s.parseArgsInGroup(configObjs)
338+
configs, configRests, configAmbigus, configUndefs := s.parseArgsInGroup(configObjs)
296339
defaults := s.keyDefaultMap
297340

298341
return &ParseResult{
@@ -306,6 +349,9 @@ func (s *OptionSet) parseInGroup(argObjs, configObjs []*Arg) *ParseResult {
306349
argRests: argRests,
307350
configRests: configRests,
308351

352+
argAmbigus: argAmbigus,
353+
configAmbigus: configAmbigus,
354+
309355
argUndefs: argUndefs,
310356
configUndefs: configUndefs,
311357
}

0 commit comments

Comments
 (0)