quoting of arguments
diff --git a/convert.go b/convert.go
index 450751d..d5675c5 100644
--- a/convert.go
+++ b/convert.go
@@ -312,6 +312,14 @@
return s
}
+func unquoteIfPossible(s string) (string, error) {
+ if s[0] != '"' {
+ return s, nil
+ }
+
+ return strconv.Unquote(s)
+}
+
func wrapText(s string, l int, prefix string) string {
// Basic text wrapping of s at spaces to fit in l
var ret string
diff --git a/parser_private.go b/parser_private.go
index ee637e9..67a5b02 100644
--- a/parser_private.go
+++ b/parser_private.go
@@ -164,11 +164,22 @@
}
err = option.set(nil)
- } else if argument != nil {
- err = option.set(argument)
- } else if canarg && !s.eof() {
- arg := s.pop()
- err = option.set(&arg)
+ } else if argument != nil || (canarg && !s.eof()) {
+ var arg string
+
+ if argument != nil {
+ arg = *argument
+ } else {
+ arg = s.pop()
+ }
+
+ if option.tag.Get("unquote") != "false" {
+ arg, err = unquoteIfPossible(arg)
+ }
+
+ if err == nil {
+ err = option.set(&arg)
+ }
} else if option.OptionalArgument {
option.empty()
diff --git a/parser_test.go b/parser_test.go
index add87d8..444705d 100644
--- a/parser_test.go
+++ b/parser_test.go
@@ -3,6 +3,7 @@
import (
"os"
"reflect"
+ "strconv"
"strings"
"testing"
"time"
@@ -12,6 +13,10 @@
Int int `long:"i"`
IntDefault int `long:"id" default:"1"`
+ String string `long:"str"`
+ StringDefault string `long:"strd" default:"abc"`
+ StringNotUnquoted string `long:"strnot" unquote:"false"`
+
Time time.Duration `long:"t"`
TimeDefault time.Duration `long:"td" default:"1m"`
@@ -35,6 +40,9 @@
Int: 0,
IntDefault: 1,
+ String: "",
+ StringDefault: "abc",
+
Time: 0,
TimeDefault: time.Minute,
@@ -47,11 +55,14 @@
},
{
msg: "non-zero value arguments, expecting overwritten arguments",
- args: []string{"--i=3", "--id=3", "--t=3ms", "--td=3ms", "--m=c:3", "--md=c:3", "--s=3", "--sd=3"},
+ args: []string{"--i=3", "--id=3", "--str=def", "--strd=def", "--t=3ms", "--td=3ms", "--m=c:3", "--md=c:3", "--s=3", "--sd=3"},
expected: defaultOptions{
Int: 3,
IntDefault: 3,
+ String: "def",
+ StringDefault: "def",
+
Time: 3 * time.Millisecond,
TimeDefault: 3 * time.Millisecond,
@@ -64,11 +75,14 @@
},
{
msg: "zero value arguments, expecting overwritten arguments",
- args: []string{"--i=0", "--id=0", "--t=0ms", "--td=0s", "--m=:0", "--md=:0", "--s=0", "--sd=0"},
+ args: []string{"--i=0", "--id=0", "--str=\"\"", "--strd=\"\"", "--t=0ms", "--td=0s", "--m=:0", "--md=:0", "--s=0", "--sd=0"},
expected: defaultOptions{
Int: 0,
IntDefault: 0,
+ String: "",
+ StringDefault: "",
+
Time: 0,
TimeDefault: 0,
@@ -99,6 +113,76 @@
}
}
+func TestUnquoting(t *testing.T) {
+ var tests = []struct {
+ arg string
+ err error
+ value string
+ }{
+ {
+ arg: "\"abc",
+ err: strconv.ErrSyntax,
+ value: "",
+ },
+ {
+ arg: "\"\"abc\"",
+ err: strconv.ErrSyntax,
+ value: "",
+ },
+ {
+ arg: "\"abc\"",
+ err: nil,
+ value: "abc",
+ },
+ {
+ arg: "\"\\\"abc\\\"\"",
+ err: nil,
+ value: "\"abc\"",
+ },
+ {
+ arg: "\"\\\"abc\"",
+ err: nil,
+ value: "\"abc",
+ },
+ }
+
+ for _, test := range tests {
+ var opts defaultOptions
+
+ for _, delimiter := range []bool{false, true} {
+ p := NewParser(&opts, None)
+
+ var err error
+ if delimiter {
+ _, err = p.ParseArgs([]string{"--str=" + test.arg, "--strnot=" + test.arg})
+ } else {
+ _, err = p.ParseArgs([]string{"--str", test.arg, "--strnot", test.arg})
+ }
+
+ if test.err == nil {
+ if err != nil {
+ t.Fatalf("Expected no error but got: %v", err)
+ }
+
+ if test.value != opts.String {
+ t.Fatalf("Expected String to be %q but got %q", test.value, opts.String)
+ }
+ if q := strconv.Quote(test.value); q != opts.StringNotUnquoted {
+ t.Fatalf("Expected StringDefault to be %q but got %q", q, opts.StringNotUnquoted)
+ }
+ } else {
+ if err == nil {
+ t.Fatalf("Expected error")
+ } else if e, ok := err.(*Error); ok {
+ if strings.HasPrefix(e.Message, test.err.Error()) {
+ t.Fatalf("Expected error message to end with %q but got %v", test.err.Error(), e.Message)
+ }
+ }
+ }
+ }
+ }
+}
+
// envRestorer keeps a copy of a set of env variables and can restore the env from them
type envRestorer struct {
env map[string]string