Skip to content

Commit 1de0b57

Browse files
committed
chore: upgrade goNixArgParser
- feat(flag): use assignSymbols instead of canEqualAssign - feat(flag): let canConcatAssign defaults to true for single char flag - feat(command): add command alias names
1 parent a59a1cb commit 1de0b57

File tree

9 files changed

+137
-65
lines changed

9 files changed

+137
-65
lines changed

src/goNixArgParser/command.go

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,56 +7,79 @@ import (
77
)
88

99
func NewCommand(
10-
name, summary, mergeFlagPrefix string,
10+
names []string,
11+
summary, mergeFlagPrefix string,
1112
restsSigns, groupSeps []string,
1213
) *Command {
1314
return &Command{
14-
name: name,
15+
names: names,
1516
summary: summary,
1617
options: NewOptionSet(mergeFlagPrefix, restsSigns, groupSeps),
1718
subCommands: []*Command{},
1819
}
1920
}
2021

21-
func NewSimpleCommand(name, summary string) *Command {
22+
func NewSimpleCommand(name, summary string, aliasNames ...string) *Command {
23+
names := make([]string, 0, 1+len(aliasNames))
24+
names = append(names, name)
25+
names = append(names, aliasNames...)
26+
2227
return &Command{
23-
name: name,
28+
names: names,
2429
summary: summary,
2530
options: NewSimpleOptionSet(),
2631
subCommands: []*Command{},
2732
}
2833
}
2934

3035
func (c *Command) NewSubCommand(
31-
name, summary, mergeFlagPrefix string,
36+
names []string,
37+
summary, mergeFlagPrefix string,
3238
restsSigns, groupSeps []string,
3339
) *Command {
34-
subCommand := NewCommand(name, summary, mergeFlagPrefix, restsSigns, groupSeps)
40+
subCommand := NewCommand(names, summary, mergeFlagPrefix, restsSigns, groupSeps)
3541
c.subCommands = append(c.subCommands, subCommand)
3642
return subCommand
3743
}
3844

39-
func (c *Command) NewSimpleSubCommand(name, summary string) *Command {
40-
subCommand := NewSimpleCommand(name, summary)
45+
func (c *Command) NewSimpleSubCommand(name, summary string, aliasNames ...string) *Command {
46+
subCommand := NewSimpleCommand(name, summary, aliasNames...)
4147
c.subCommands = append(c.subCommands, subCommand)
4248
return subCommand
4349
}
4450

51+
func (c *Command) hasName(name string) bool {
52+
for _, n := range c.names {
53+
if n == name {
54+
return true
55+
}
56+
}
57+
return false
58+
}
59+
4560
func (c *Command) GetSubCommand(name string) *Command {
4661
if c.subCommands == nil {
4762
return nil
4863
}
4964

5065
for _, cmd := range c.subCommands {
51-
if cmd.name == name {
66+
if cmd.hasName(name) {
5267
return cmd
5368
}
5469
}
5570
return nil
5671
}
5772

58-
func (c *Command) Name() string {
59-
return c.name
73+
func (c *Command) Name() (name string) {
74+
if len(c.names) > 0 {
75+
name = c.names[0]
76+
}
77+
78+
return
79+
}
80+
81+
func (c *Command) Names() []string {
82+
return c.names
6083
}
6184

6285
func (c *Command) Summary() string {
@@ -81,10 +104,10 @@ func (c *Command) getNormalizedArgs(initArgs []string) (*Command, []*Arg) {
81104
args := make([]*Arg, 0, len(initArgs))
82105

83106
for i, arg := range initArgs {
84-
if i == 0 && cmd.name == arg {
85-
args = append(args, NewArg(arg, CommandArg))
107+
if i == 0 && cmd.hasName(arg) {
108+
args = append(args, NewArg(cmd.Name(), CommandArg))
86109
} else if subCmd := cmd.GetSubCommand(arg); subCmd != nil {
87-
args = append(args, NewArg(arg, CommandArg))
110+
args = append(args, NewArg(subCmd.Name(), CommandArg))
88111
cmd = subCmd
89112
} else {
90113
break
@@ -103,9 +126,6 @@ func (c *Command) splitCommandsArgs(initArgs, initConfigs []string) (
103126

104127
commands = []string{}
105128
for _, arg := range argCmds {
106-
if arg.Type != CommandArg {
107-
break
108-
}
109129
commands = append(commands, arg.Text)
110130
}
111131

@@ -148,14 +168,15 @@ func (c *Command) ParseGroups(initArgs, initConfigs []string) (results []*ParseR
148168
func (c *Command) GetHelp() []byte {
149169
buffer := &bytes.Buffer{}
150170

151-
if len(c.name) > 0 {
152-
buffer.WriteString(path.Base(c.name))
171+
name := c.Name()
172+
if len(name) > 0 {
173+
buffer.WriteString(path.Base(name))
153174
buffer.WriteString(": ")
154175
}
155176
if len(c.summary) > 0 {
156177
buffer.WriteString(c.summary)
157178
}
158-
if len(c.name) > 0 || len(c.summary) > 0 {
179+
if buffer.Len() > 0 {
159180
buffer.WriteByte('\n')
160181
} else {
161182
buffer.WriteString("Usage:\n")
@@ -170,7 +191,7 @@ func (c *Command) GetHelp() []byte {
170191
if len(c.subCommands) > 0 {
171192
buffer.WriteString("\nSub commands:\n\n")
172193
for _, cmd := range c.subCommands {
173-
buffer.WriteString(cmd.name)
194+
buffer.WriteString(cmd.Name())
174195
buffer.WriteByte('\n')
175196
if len(cmd.summary) > 0 {
176197
buffer.WriteString(cmd.summary)

src/goNixArgParser/commandParse_test.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ func getGitCommand() *Command {
1111
cmdGit.options.AddFlag("version", "--version", "", "display version")
1212
cmdGit.options.AddFlag("help", "--help", "", "show git help")
1313

14-
cmdSetUrl := cmdGit.NewSimpleSubCommand("remote", "manage remotes").NewSimpleSubCommand("set-url", "set remote url")
14+
cmdRemote := cmdGit.NewSimpleSubCommand("remote", "manage remotes", "rmt", "rt")
15+
cmdSetUrl := cmdRemote.NewSimpleSubCommand("set-url", "set remote url")
1516
cmdSetUrl.options.AddFlag("push", "--push", "", "")
1617
cmdSetUrl.options.AddFlagValue("dummy", "--dummy", "", "", "dummy option")
18+
cmdSetUrl.options.AddFlagValue("dummyX", "--dummy-x", "", "", "dummy-x option")
1719

1820
cmdReset := cmdGit.NewSimpleSubCommand("reset", "reset command")
1921
cmdReset.options.AddFlag("hard", "--hard", "", "hard reset")
@@ -25,7 +27,7 @@ func getGitCommand() *Command {
2527

2628
func TestNormalizeCmdArgs(t *testing.T) {
2729
cmd := getGitCommand()
28-
args := []string{"git", "remote", "set-url", "--push", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
30+
args := []string{"git", "rmt", "set-url", "--push", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
2931
_, normalizedArgs := cmd.getNormalizedArgs(args)
3032
for i, arg := range normalizedArgs {
3133
fmt.Printf("%d %+v\n", i, arg)
@@ -34,7 +36,7 @@ func TestNormalizeCmdArgs(t *testing.T) {
3436

3537
func TestParseCommand1(t *testing.T) {
3638
cmd := getGitCommand()
37-
args := []string{"git", "remote", "set-url", "--push", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
39+
args := []string{"git", "rmt", "set-url", "--push", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
3840

3941
result := cmd.Parse(args, nil)
4042
if result.commands[0] != "git" ||
@@ -75,8 +77,8 @@ func TestParseCommand2(t *testing.T) {
7577

7678
func TestParseCommand3(t *testing.T) {
7779
cmd := getGitCommand()
78-
args := []string{"git", "remote", "set-url", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
79-
configArgs := []string{"git", "remote", "set-url", "--dummy", "dummyconfigvalue"}
80+
args := []string{"git", "rmt", "set-url", "origin", "https://github.com/mjpclab/goNixArgParser.git"}
81+
configArgs := []string{"git", "rt", "set-url", "--dummy", "dummyconfigvalue"}
8082
result := cmd.Parse(args, configArgs)
8183

8284
dummy, _ := result.GetString("dummy")
@@ -98,20 +100,38 @@ func TestParseCommand3(t *testing.T) {
98100
func TestParseCommand4(t *testing.T) {
99101
cmd := getGitCommand()
100102
args := []string{"git", "remote", "set-url", "--dummy", "dummy0", "github", "https://github.com/mjpclab/goNixArgParser.git", ",,", "--dummy", "dummy1", "bitbucket", "https://bitbucket.com/mjpclab/goNixArgParser.git"}
101-
results := cmd.ParseGroups(args, nil)
103+
configArgs := []string{"git", "remote", "set-url", "--dummy-x", "dummyXValue"}
104+
results := cmd.ParseGroups(args, configArgs)
102105

103106
dummy0, _ := results[0].GetString("dummy")
104107
if dummy0 != "dummy0" {
105108
t.Error(results[0].GetStrings("dummy"))
106109
}
107110

111+
dummyX, _ := results[0].GetString("dummyX")
112+
if dummyX != "dummyXValue" {
113+
t.Error(results[0].GetStrings("dummyX"))
114+
}
115+
108116
dummy1, _ := results[1].GetString("dummy")
109117
if dummy1 != "dummy1" {
110118
t.Error(results[1].GetStrings("dummy"))
111119
}
112120
}
113121

114122
func TestParseCommand5(t *testing.T) {
123+
cmd := getGitCommand()
124+
args := []string{"git", "remote", "set-url", "--dummy", "dummy0"}
125+
configArgs := []string{"git", "no-such-cmd", "set-url", "--dummy-x", "dummyXValue"}
126+
result := cmd.Parse(args, configArgs)
127+
128+
dummyX, _ := result.GetString("dummyX")
129+
if dummyX != "" {
130+
t.Error("dummyX")
131+
}
132+
}
133+
134+
func TestParseCommand6(t *testing.T) {
115135
cmd := getGitCommand()
116136
args := []string{"git", "remote", "set-url", "github", "https://github.com/mjpclab/goNixArgParser.git", ",,", "bitbucket", "https://bitbucket.com/mjpclab/goNixArgParser.git"}
117137
configArgs := []string{"git", "remote", "set-url", "--dummy", "dummy0", ",,", "--dummy", "dummy1"}

src/goNixArgParser/flag.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,27 @@
11
package goNixArgParser
22

3-
func NewFlag(name string, canMerge, canFollowAssign, canEqualAssign, canConcatAssign bool) *Flag {
3+
func NewFlag(name string, canMerge, canFollowAssign, canConcatAssign bool, assignSigns []string) *Flag {
44
return &Flag{
55
Name: name,
66
canMerge: canMerge,
77
canFollowAssign: canFollowAssign,
8-
canEqualAssign: canEqualAssign,
98
canConcatAssign: canConcatAssign,
9+
assignSigns: assignSigns,
1010
}
1111
}
1212

1313
func NewSimpleFlag(name string) *Flag {
1414
isSingleChar := len(name) == 1 || (len(name) == 2 && name[0] == '-')
15-
return NewFlag(name, isSingleChar, true, !isSingleChar, false)
15+
16+
canMerge := isSingleChar
17+
canConcatAssign := isSingleChar
18+
19+
assignSigns := make([]string, 0, 1)
20+
if !isSingleChar {
21+
assignSigns = append(assignSigns, "=")
22+
}
23+
24+
return NewFlag(name, canMerge, true, canConcatAssign, assignSigns)
1625
}
1726

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

src/goNixArgParser/optionSet.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ func (s *OptionSet) Append(opt *Option) error {
105105
if flag.canMerge {
106106
s.hasCanMerge = true
107107
}
108-
if flag.canEqualAssign {
109-
s.hasCanEqualAssign = true
110-
}
111108
if flag.canConcatAssign {
112109
s.hasCanConcatAssign = true
113110
}
111+
if len(flag.assignSigns) > 0 {
112+
s.hasAssignSigns = true
113+
}
114114

115115
flagName := flag.Name
116116
s.flagOptionMap[flagName] = option

src/goNixArgParser/optionSetParse.go

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
func (s *OptionSet) splitMergedArg(arg *Arg) (args []*Arg, success bool) {
88
flagMap := s.flagMap
9+
optionMap := s.flagOptionMap
910
argText := arg.Text
1011

1112
if arg.Type != UnknownArg ||
@@ -18,20 +19,38 @@ func (s *OptionSet) splitMergedArg(arg *Arg) (args []*Arg, success bool) {
1819
return
1920
}
2021

22+
var prevFlag *Flag
2123
mergedArgs := argText[len(s.mergeFlagPrefix):]
2224
splittedArgs := make([]*Arg, 0, len(mergedArgs))
2325
for i, mergedArg := range mergedArgs {
2426
splittedArg := s.mergeFlagPrefix + string(mergedArg)
2527
flag := flagMap[splittedArg]
26-
if flag == nil || !flag.canMerge {
28+
29+
if flag != nil {
30+
if !flag.canMerge {
31+
return
32+
}
33+
splittedArgs = append(splittedArgs, NewArg(splittedArg, FlagArg))
34+
prevFlag = flag
35+
continue
36+
}
37+
38+
if len(splittedArg) <= 1 {
39+
return
40+
}
41+
42+
if prevFlag == nil {
2743
return
2844
}
29-
splittedArgs = append(splittedArgs, NewArg(splittedArg, FlagArg))
3045

31-
if flag.canEqualAssign && i < len(mergedArgs)-1 && mergedArgs[i+1] == '=' {
32-
splittedArgs = append(splittedArgs, NewArg(mergedArgs[i+2:], ValueArg))
33-
break
46+
option := optionMap[prevFlag.Name]
47+
if option == nil || !option.AcceptValue {
48+
return
3449
}
50+
51+
// re-generate standalone flag with values
52+
splittedArgs[len(splittedArgs)-1] = NewArg(prevFlag.Name+mergedArgs[i:], UnknownArg)
53+
break
3554
}
3655

3756
return splittedArgs, true
@@ -50,7 +69,7 @@ func (s *OptionSet) splitMergedArgs(initArgs []*Arg) []*Arg {
5069
return args
5170
}
5271

53-
func (s *OptionSet) splitEqualAssignArg(arg *Arg) (args []*Arg) {
72+
func (s *OptionSet) splitAssignSignArg(arg *Arg) (args []*Arg) {
5473
args = make([]*Arg, 0, 2)
5574

5675
if arg.Type != UnknownArg {
@@ -59,32 +78,35 @@ func (s *OptionSet) splitEqualAssignArg(arg *Arg) (args []*Arg) {
5978
}
6079

6180
argText := arg.Text
62-
equalIndex := strings.IndexByte(argText, '=')
63-
if equalIndex == -1 {
64-
args = append(args, arg)
65-
return
66-
}
81+
for _, flag := range s.flagMap {
82+
for _, assignSign := range flag.assignSigns {
83+
flagName := flag.Name
6784

68-
flagName := argText[:equalIndex]
69-
flagValue := argText[equalIndex+1:]
70-
flag := s.flagMap[flagName]
71-
if flag == nil ||
72-
!flag.canEqualAssign ||
73-
!s.flagOptionMap[flagName].AcceptValue {
74-
args = append(args, arg)
75-
return
85+
if len(assignSign) == 0 || !s.flagOptionMap[flagName].AcceptValue {
86+
continue
87+
}
88+
89+
prefix := flagName + assignSign
90+
if !strings.HasPrefix(argText, prefix) {
91+
continue
92+
}
93+
flagValue := argText[len(prefix):]
94+
95+
args = append(args, NewArg(flagName, FlagArg))
96+
args = append(args, NewArg(flagValue, ValueArg))
97+
return
98+
}
7699
}
77100

78-
args = append(args, NewArg(flagName, FlagArg))
79-
args = append(args, NewArg(flagValue, ValueArg))
101+
args = append(args, arg)
80102
return
81103
}
82104

83-
func (s *OptionSet) splitEqualAssignArgs(initArgs []*Arg) []*Arg {
105+
func (s *OptionSet) splitAssignSignArgs(initArgs []*Arg) []*Arg {
84106
args := make([]*Arg, 0, len(initArgs))
85107

86108
for _, initArg := range initArgs {
87-
args = append(args, s.splitEqualAssignArg(initArg)...)
109+
args = append(args, s.splitAssignSignArg(initArg)...)
88110
}
89111

90112
return args
@@ -148,8 +170,8 @@ func (s *OptionSet) parseArgsInGroup(argObjs []*Arg) (args map[string][]string,
148170
if s.hasCanMerge {
149171
argObjs = s.splitMergedArgs(argObjs)
150172
}
151-
if s.hasCanEqualAssign {
152-
argObjs = s.splitEqualAssignArgs(argObjs)
173+
if s.hasAssignSigns {
174+
argObjs = s.splitAssignSignArgs(argObjs)
153175
}
154176
if s.hasCanConcatAssign {
155177
argObjs = s.splitConcatAssignArgs(argObjs)

0 commit comments

Comments
 (0)