Permalink
Browse files

Workaround for flynn cli optionsFirst usage

Refs flynn/flynn#193

Signed-off-by: Jonathan Rudenberg <jonathan@titanous.com>
  • Loading branch information...
titanous committed Sep 12, 2014
1 parent c4d72bb commit f6dd2ebbb31e9721c860cf1faf5c944aa73e3844
Showing with 25 additions and 10 deletions.
  1. +14 −3 docopt.go
  2. +11 −7 docopt_test.go
View
@@ -103,7 +103,7 @@ func parse(doc string, argv []string, help bool, version string, optionsFirst bo
return
}
patternArgv, err := parseArgv(newTokenList(argv, errorUser), &options, optionsFirst)
patternArgv, err := parseArgv(newTokenList(argv, errorUser), &options, optionsFirst, pat)
if err != nil {
output = handleError(err, usage)
return
@@ -199,7 +199,7 @@ func parsePattern(source string, options *patternList) (*pattern, error) {
return newRequired(result...), nil
}
func parseArgv(tokens *tokenList, options *patternList, optionsFirst bool) (patternList, error) {
func parseArgv(tokens *tokenList, options *patternList, optionsFirst bool, pat *pattern) (patternList, error) {
/*
Parse command-line argument vector.
@@ -209,6 +209,16 @@ func parseArgv(tokens *tokenList, options *patternList, optionsFirst bool) (patt
argv ::= [ long | shorts | argument ]* [ '--' [ argument ]* ] ;
*/
parsed := patternList{}
// This is a HACK that skips the command in:
// (*docopt.pattern)(0x208333dc0)(required(required(command(foo, false), ...)))
// when parsing with optionsFirst set. For more details see
// https://github.com/flynn/flynn/pull/193
skipArg := optionsFirst && pat != nil &&
pat.t == patternRequired && len(pat.children) == 1 &&
pat.children[0].t == patternRequired && len(pat.children[0].children) > 0 &&
pat.children[0].children[0].t == patternCommand
for tokens.current() != nil {
if tokens.current().eq("--") {
for _, v := range tokens.tokens {
@@ -227,13 +237,14 @@ func parseArgv(tokens *tokenList, options *patternList, optionsFirst bool) (patt
return nil, err
}
parsed = append(parsed, ps...)
} else if optionsFirst {
} else if !skipArg && optionsFirst {
for _, v := range tokens.tokens {
parsed = append(parsed, newArgument("", v))
}
return parsed, nil
} else {
parsed = append(parsed, newArgument("", tokens.move().String()))
skipArg = false
}
}
return parsed, nil
View
@@ -171,19 +171,19 @@ func TestParseArgv(t *testing.T) {
newOption("-f", "--file", 1, false),
}
p, err := parseArgv(tokenListFromString(""), &o, false)
p, err := parseArgv(tokenListFromString(""), &o, false, nil)
q := patternList{}
if reflect.DeepEqual(p, q) != true {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h"), &o, false)
p, err = parseArgv(tokenListFromString("-h"), &o, false, nil)
q = patternList{newOption("-h", "", 0, true)}
if reflect.DeepEqual(p, q) != true {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h --verbose"), &o, false)
p, err = parseArgv(tokenListFromString("-h --verbose"), &o, false, nil)
q = patternList{
newOption("-h", "", 0, true),
newOption("-v", "--verbose", 0, true),
@@ -192,7 +192,7 @@ func TestParseArgv(t *testing.T) {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h --file f.txt"), &o, false)
p, err = parseArgv(tokenListFromString("-h --file f.txt"), &o, false, nil)
q = patternList{
newOption("-h", "", 0, true),
newOption("-f", "--file", 1, "f.txt"),
@@ -201,7 +201,7 @@ func TestParseArgv(t *testing.T) {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h --file f.txt arg"), &o, false)
p, err = parseArgv(tokenListFromString("-h --file f.txt arg"), &o, false, nil)
q = patternList{
newOption("-h", "", 0, true),
newOption("-f", "--file", 1, "f.txt"),
@@ -211,7 +211,7 @@ func TestParseArgv(t *testing.T) {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h --file f.txt arg arg2"), &o, false)
p, err = parseArgv(tokenListFromString("-h --file f.txt arg arg2"), &o, false, nil)
q = patternList{
newOption("-h", "", 0, true),
newOption("-f", "--file", 1, "f.txt"),
@@ -222,7 +222,7 @@ func TestParseArgv(t *testing.T) {
t.Error(err)
}
p, err = parseArgv(tokenListFromString("-h arg -- -v"), &o, false)
p, err = parseArgv(tokenListFromString("-h arg -- -v"), &o, false, nil)
q = patternList{
newOption("-h", "", 0, true),
newArgument("", "arg"),
@@ -1295,6 +1295,10 @@ func TestOptionsFirst(t *testing.T) {
if v, err := Parse("usage: prog [--opt] [<args>...]", []string{"this", "that", "--opt"}, true, "", true, false); reflect.DeepEqual(v.All, map[string]interface{}{"--opt": false, "<args>": []string{"this", "that", "--opt"}}) != true {
t.Error(err)
}
if v, err := Parse("usage: prog foo [--opt] [<args>...]", []string{"foo", "--opt", "this", "that"}, true, "", true, false); reflect.DeepEqual(v.All, map[string]interface{}{"foo": true, "--opt": true, "<args>": []string{"this", "that"}}) != true {
t.Error(err)
}
}
func TestIssue68OptionsShortcutDoesNotIncludeOptionsInUsagePattern(t *testing.T) {

0 comments on commit f6dd2eb

Please sign in to comment.