Implementing value capture for short flags

and ensuring all unknown ident/stdin nodes are retained
arghing
Dan Buch 2 years ago
parent 03edacc8ec
commit 3ea30a997a
Signed by: meatballhat
GPG Key ID: A12F782281063434

@ -116,29 +116,32 @@ func (p *parser2) parseCommand(cCfg *CommandConfig) Node {
case IDENT, STDIN_FLAG: case IDENT, STDIN_FLAG:
tracef("parseCommand(...) handling %s", p.tok) tracef("parseCommand(...) handling %s", p.tok)
if !cCfg.NValue.Contains(identIndex) { if cCfg.NValue.Contains(identIndex) {
tracef("parseCommand(...) identIndex=%d exceeds expected=%s; breaking", identIndex, cCfg.NValue) name := fmt.Sprintf("%d", identIndex)
break
tracef("parseCommand(...) checking for name of identIndex=%d", identIndex)
if len(cCfg.ValueNames) > identIndex {
name = cCfg.ValueNames[identIndex]
tracef("parseCommand(...) setting name=%s from config value names", name)
} else if len(cCfg.ValueNames) == 1 && (cCfg.NValue == OneOrMoreValue || cCfg.NValue == ZeroOrMoreValue) {
name = fmt.Sprintf("%s.%d", cCfg.ValueNames[0], identIndex)
tracef("parseCommand(...) setting name=%s from repeating value name", name)
}
if node.Values == nil {
node.Values = map[string]string{}
}
node.Values[name] = p.lit
} else {
if p.tok == STDIN_FLAG {
nodes = append(nodes, &StdinFlag{})
} else {
nodes = append(nodes, &Ident{Literal: p.lit})
}
} }
name := fmt.Sprintf("%d", identIndex)
tracef("parseCommand(...) checking for name of identIndex=%d", identIndex)
if len(cCfg.ValueNames) > identIndex {
name = cCfg.ValueNames[identIndex]
tracef("parseCommand(...) setting name=%s from config value names", name)
} else if len(cCfg.ValueNames) == 1 && (cCfg.NValue == OneOrMoreValue || cCfg.NValue == ZeroOrMoreValue) {
name = fmt.Sprintf("%s.%d", cCfg.ValueNames[0], identIndex)
tracef("parseCommand(...) setting name=%s from repeating value name", name)
}
if node.Values == nil {
node.Values = map[string]string{}
}
node.Values[name] = p.lit
identIndex++ identIndex++
case LONG_FLAG, SHORT_FLAG, COMPOUND_SHORT_FLAG: case LONG_FLAG, SHORT_FLAG, COMPOUND_SHORT_FLAG:
tok := p.tok tok := p.tok
@ -185,22 +188,31 @@ func (p *parser2) parseFlag(flCfgMap map[string]FlagConfig) Node {
} }
func (p *parser2) parseShortFlag(flCfgMap map[string]FlagConfig) Node { func (p *parser2) parseShortFlag(flCfgMap map[string]FlagConfig) Node {
name := string(p.lit[1]) node := &Flag{Name: string(p.lit[1])}
node := &Flag{Name: name}
tracef("parseShortFlag(...) TODO capture flag value(s)") flCfg, ok := flCfgMap[node.Name]
return node if !ok {
return node
}
return p.parseConfiguredFlag(node, flCfg)
} }
func (p *parser2) parseLongFlag(flCfgMap map[string]FlagConfig) Node { func (p *parser2) parseLongFlag(flCfgMap map[string]FlagConfig) Node {
node := &Flag{Name: string(p.lit[2:])} node := &Flag{Name: string(p.lit[2:])}
values := map[string]string{}
nodes := []Node{}
flCfg, ok := flCfgMap[node.Name] flCfg, ok := flCfgMap[node.Name]
if !ok { if !ok {
return node return node
} }
return p.parseConfiguredFlag(node, flCfg)
}
func (p *parser2) parseConfiguredFlag(node *Flag, flCfg FlagConfig) Node {
values := map[string]string{}
nodes := []Node{}
identIndex := 0 identIndex := 0
for i := 0; p.tok != EOL; i++ { for i := 0; p.tok != EOL; i++ {

@ -243,65 +243,75 @@ func TestParser2(t *testing.T) {
}, },
}, },
{ {
skip: true,
name: "short value-less flags", name: "short value-less flags",
args: []string{"pizzas", "-t", "-f", "-s"}, args: []string{"pizzas", "-t", "-f", "-s"},
expPT: []argh.Node{ expPT: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.ArgDelimiter{}, Name: "pizzas",
argh.Flag{Name: "t"}, Nodes: []argh.Node{
argh.ArgDelimiter{}, &argh.ArgDelimiter{},
argh.Flag{Name: "f"}, &argh.Flag{Name: "t"},
argh.ArgDelimiter{}, &argh.ArgDelimiter{},
argh.Flag{Name: "s"}, &argh.Flag{Name: "f"},
&argh.ArgDelimiter{},
&argh.Flag{Name: "s"},
},
},
}, },
expAST: []argh.Node{ expAST: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.Flag{Name: "t"}, Name: "pizzas",
argh.Flag{Name: "f"}, Nodes: []argh.Node{
argh.Flag{Name: "s"}, &argh.Flag{Name: "t"},
&argh.Flag{Name: "f"},
&argh.Flag{Name: "s"},
},
},
}, },
}, },
{ {
skip: true,
name: "compound short flags", name: "compound short flags",
args: []string{"pizzas", "-aca", "-blol"}, args: []string{"pizzas", "-aca", "-blol"},
expPT: []argh.Node{ expPT: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.ArgDelimiter{}, Name: "pizzas",
argh.CompoundShortFlag{
Nodes: []argh.Node{ Nodes: []argh.Node{
argh.Flag{Name: "a"}, &argh.ArgDelimiter{},
argh.Flag{Name: "c"}, &argh.CompoundShortFlag{
argh.Flag{Name: "a"}, Nodes: []argh.Node{
&argh.Flag{Name: "a"},
&argh.Flag{Name: "c"},
&argh.Flag{Name: "a"},
},
},
&argh.ArgDelimiter{},
&argh.CompoundShortFlag{
Nodes: []argh.Node{
&argh.Flag{Name: "b"},
&argh.Flag{Name: "l"},
&argh.Flag{Name: "o"},
&argh.Flag{Name: "l"},
},
},
}, },
}, },
argh.ArgDelimiter{}, },
argh.CompoundShortFlag{ expAST: []argh.Node{
&argh.Command{
Name: "pizzas",
Nodes: []argh.Node{ Nodes: []argh.Node{
argh.Flag{Name: "b"}, &argh.Flag{Name: "a"},
argh.Flag{Name: "l"}, &argh.Flag{Name: "c"},
argh.Flag{Name: "o"}, &argh.Flag{Name: "a"},
argh.Flag{Name: "l"}, &argh.Flag{Name: "b"},
&argh.Flag{Name: "l"},
&argh.Flag{Name: "o"},
&argh.Flag{Name: "l"},
}, },
}, },
}, },
expAST: []argh.Node{
argh.Command{Name: "pizzas"},
argh.Flag{Name: "a"},
argh.Flag{Name: "c"},
argh.Flag{Name: "a"},
argh.Flag{Name: "b"},
argh.Flag{Name: "l"},
argh.Flag{Name: "o"},
argh.Flag{Name: "l"},
},
}, },
{ {
skip: true,
name: "mixed long short value flags", name: "mixed long short value flags",
args: []string{"pizzas", "-a", "--ca", "-b", "1312", "-lol"}, args: []string{"pizzas", "-a", "--ca", "-b", "1312", "-lol"},
cfg: &argh.ParserConfig{ cfg: &argh.ParserConfig{
@ -313,52 +323,93 @@ func TestParser2(t *testing.T) {
}, },
}, },
expPT: []argh.Node{ expPT: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.ArgDelimiter{}, Name: "pizzas",
argh.Flag{Name: "a"},
argh.ArgDelimiter{},
argh.Flag{Name: "ca"},
argh.ArgDelimiter{},
argh.Flag{Name: "b", Values: map[string]string{"0": "1312"}},
argh.ArgDelimiter{},
argh.CompoundShortFlag{
Nodes: []argh.Node{ Nodes: []argh.Node{
argh.Flag{Name: "l"}, &argh.ArgDelimiter{},
argh.Flag{Name: "o"}, &argh.Flag{Name: "a"},
argh.Flag{Name: "l"}, &argh.ArgDelimiter{},
&argh.Flag{Name: "ca"},
&argh.ArgDelimiter{},
&argh.Flag{
Name: "b",
Values: map[string]string{"0": "1312"},
Nodes: []argh.Node{
&argh.ArgDelimiter{},
},
},
&argh.ArgDelimiter{},
&argh.CompoundShortFlag{
Nodes: []argh.Node{
&argh.Flag{Name: "l"},
&argh.Flag{Name: "o"},
&argh.Flag{Name: "l"},
},
},
}, },
}, },
}, },
expAST: []argh.Node{ expAST: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.Flag{Name: "a"}, Name: "pizzas",
argh.Flag{Name: "ca"}, Nodes: []argh.Node{
argh.Flag{Name: "b", Values: map[string]string{"0": "1312"}}, &argh.Flag{Name: "a"},
argh.Flag{Name: "l"}, &argh.Flag{Name: "ca"},
argh.Flag{Name: "o"}, &argh.Flag{Name: "b", Values: map[string]string{"0": "1312"}},
argh.Flag{Name: "l"}, &argh.Flag{Name: "l"},
&argh.Flag{Name: "o"},
&argh.Flag{Name: "l"},
},
},
}, },
}, },
{ {
skip: true, name: "nested commands with positional args",
args: []string{"pizzas", "fly", "freely", "sometimes", "and", "other", "times", "fry", "deeply", "--forever"},
name: "commands",
args: []string{"pizzas", "fly", "fry"},
cfg: &argh.ParserConfig{ cfg: &argh.ParserConfig{
Prog: argh.CommandConfig{ Prog: argh.CommandConfig{
Commands: map[string]argh.CommandConfig{ Commands: map[string]argh.CommandConfig{
"fly": argh.CommandConfig{}, "fly": argh.CommandConfig{
"fry": argh.CommandConfig{}, Commands: map[string]argh.CommandConfig{
"fry": argh.CommandConfig{},
},
},
}, },
Flags: map[string]argh.FlagConfig{}, Flags: map[string]argh.FlagConfig{},
}, },
}, },
expPT: []argh.Node{ expPT: []argh.Node{
argh.Command{Name: "pizzas"}, &argh.Command{
argh.ArgDelimiter{}, Name: "pizzas",
argh.Command{Name: "fly"}, Nodes: []argh.Node{
argh.ArgDelimiter{}, &argh.ArgDelimiter{},
argh.Command{Name: "fry"}, &argh.Command{
Name: "fly",
Nodes: []argh.Node{
&argh.ArgDelimiter{},
&argh.Ident{Literal: "freely"},
&argh.ArgDelimiter{},
&argh.Ident{Literal: "sometimes"},
&argh.ArgDelimiter{},
&argh.Ident{Literal: "and"},
&argh.ArgDelimiter{},
&argh.Ident{Literal: "other"},
&argh.ArgDelimiter{},
&argh.Ident{Literal: "times"},
&argh.ArgDelimiter{},
&argh.Command{
Name: "fry",
Nodes: []argh.Node{
&argh.ArgDelimiter{},
&argh.Ident{Literal: "deeply"},
&argh.ArgDelimiter{},
&argh.Flag{Name: "forever"},
},
},
},
},
},
},
}, },
}, },
{ {

Loading…
Cancel
Save