Implementing value capture for short flags
and ensuring all unknown ident/stdin nodes are retained
This commit is contained in:
parent
03edacc8ec
commit
3ea30a997a
@ -116,29 +116,32 @@ func (p *parser2) parseCommand(cCfg *CommandConfig) Node {
|
||||
case IDENT, STDIN_FLAG:
|
||||
tracef("parseCommand(...) handling %s", p.tok)
|
||||
|
||||
if !cCfg.NValue.Contains(identIndex) {
|
||||
tracef("parseCommand(...) identIndex=%d exceeds expected=%s; breaking", identIndex, cCfg.NValue)
|
||||
break
|
||||
if cCfg.NValue.Contains(identIndex) {
|
||||
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
|
||||
} 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++
|
||||
case LONG_FLAG, SHORT_FLAG, COMPOUND_SHORT_FLAG:
|
||||
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 {
|
||||
name := string(p.lit[1])
|
||||
node := &Flag{Name: name}
|
||||
tracef("parseShortFlag(...) TODO capture flag value(s)")
|
||||
return node
|
||||
}
|
||||
|
||||
func (p *parser2) parseLongFlag(flCfgMap map[string]FlagConfig) Node {
|
||||
node := &Flag{Name: string(p.lit[2:])}
|
||||
values := map[string]string{}
|
||||
nodes := []Node{}
|
||||
node := &Flag{Name: string(p.lit[1])}
|
||||
|
||||
flCfg, ok := flCfgMap[node.Name]
|
||||
if !ok {
|
||||
return node
|
||||
}
|
||||
|
||||
return p.parseConfiguredFlag(node, flCfg)
|
||||
}
|
||||
|
||||
func (p *parser2) parseLongFlag(flCfgMap map[string]FlagConfig) Node {
|
||||
node := &Flag{Name: string(p.lit[2:])}
|
||||
|
||||
flCfg, ok := flCfgMap[node.Name]
|
||||
if !ok {
|
||||
return node
|
||||
}
|
||||
|
||||
return p.parseConfiguredFlag(node, flCfg)
|
||||
}
|
||||
|
||||
func (p *parser2) parseConfiguredFlag(node *Flag, flCfg FlagConfig) Node {
|
||||
values := map[string]string{}
|
||||
nodes := []Node{}
|
||||
|
||||
identIndex := 0
|
||||
|
||||
for i := 0; p.tok != EOL; i++ {
|
||||
|
@ -243,65 +243,75 @@ func TestParser2(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
skip: true,
|
||||
|
||||
name: "short value-less flags",
|
||||
args: []string{"pizzas", "-t", "-f", "-s"},
|
||||
expPT: []argh.Node{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.Flag{Name: "t"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.Flag{Name: "f"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.Flag{Name: "s"},
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
&argh.ArgDelimiter{},
|
||||
&argh.Flag{Name: "t"},
|
||||
&argh.ArgDelimiter{},
|
||||
&argh.Flag{Name: "f"},
|
||||
&argh.ArgDelimiter{},
|
||||
&argh.Flag{Name: "s"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expAST: []argh.Node{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.Flag{Name: "t"},
|
||||
argh.Flag{Name: "f"},
|
||||
argh.Flag{Name: "s"},
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
&argh.Flag{Name: "t"},
|
||||
&argh.Flag{Name: "f"},
|
||||
&argh.Flag{Name: "s"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
skip: true,
|
||||
|
||||
name: "compound short flags",
|
||||
args: []string{"pizzas", "-aca", "-blol"},
|
||||
expPT: []argh.Node{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.CompoundShortFlag{
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
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{
|
||||
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"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
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"},
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
&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",
|
||||
args: []string{"pizzas", "-a", "--ca", "-b", "1312", "-lol"},
|
||||
cfg: &argh.ParserConfig{
|
||||
@ -313,52 +323,93 @@ func TestParser2(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expPT: []argh.Node{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.ArgDelimiter{},
|
||||
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{
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
argh.Flag{Name: "l"},
|
||||
argh.Flag{Name: "o"},
|
||||
argh.Flag{Name: "l"},
|
||||
&argh.ArgDelimiter{},
|
||||
&argh.Flag{Name: "a"},
|
||||
&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{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.Flag{Name: "a"},
|
||||
argh.Flag{Name: "ca"},
|
||||
argh.Flag{Name: "b", Values: map[string]string{"0": "1312"}},
|
||||
argh.Flag{Name: "l"},
|
||||
argh.Flag{Name: "o"},
|
||||
argh.Flag{Name: "l"},
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
&argh.Flag{Name: "a"},
|
||||
&argh.Flag{Name: "ca"},
|
||||
&argh.Flag{Name: "b", Values: map[string]string{"0": "1312"}},
|
||||
&argh.Flag{Name: "l"},
|
||||
&argh.Flag{Name: "o"},
|
||||
&argh.Flag{Name: "l"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
skip: true,
|
||||
|
||||
name: "commands",
|
||||
args: []string{"pizzas", "fly", "fry"},
|
||||
name: "nested commands with positional args",
|
||||
args: []string{"pizzas", "fly", "freely", "sometimes", "and", "other", "times", "fry", "deeply", "--forever"},
|
||||
cfg: &argh.ParserConfig{
|
||||
Prog: argh.CommandConfig{
|
||||
Commands: map[string]argh.CommandConfig{
|
||||
"fly": argh.CommandConfig{},
|
||||
"fry": argh.CommandConfig{},
|
||||
"fly": argh.CommandConfig{
|
||||
Commands: map[string]argh.CommandConfig{
|
||||
"fry": argh.CommandConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
Flags: map[string]argh.FlagConfig{},
|
||||
},
|
||||
},
|
||||
expPT: []argh.Node{
|
||||
argh.Command{Name: "pizzas"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.Command{Name: "fly"},
|
||||
argh.ArgDelimiter{},
|
||||
argh.Command{Name: "fry"},
|
||||
&argh.Command{
|
||||
Name: "pizzas",
|
||||
Nodes: []argh.Node{
|
||||
&argh.ArgDelimiter{},
|
||||
&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…
Reference in New Issue
Block a user