From bf328181cd7d8dacc2b15f537530956161b4dde3 Mon Sep 17 00:00:00 2001 From: Matt Bell Date: Mon, 13 Oct 2014 19:10:59 -0700 Subject: [PATCH] commands/cli: Added CLI option parsing --- commands/cli/parse.go | 92 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 commands/cli/parse.go diff --git a/commands/cli/parse.go b/commands/cli/parse.go new file mode 100644 index 000000000..84e0c2a2c --- /dev/null +++ b/commands/cli/parse.go @@ -0,0 +1,92 @@ +package cli + +import ( + "strings" + "fmt" + + "github.com/jbenet/go-ipfs/commands" +) + +func Parse(input []string, root *commands.Command) ([]string, []string, map[string]string, error) { + opts, input, err := options(input, root) + if err != nil { + return nil, nil, nil, err + } + + return nil, nil, opts, nil +} + +// options parses the raw string values of the given options +// returns the parsed options as strings, along with the CLI input minus option blobs +func options(input []string, root *commands.Command) (map[string]string, []string, error) { + opts := make(map[string]string) + cleanInput := make([]string, 0) + + // TODO: error if one option is defined multiple times + + for i := 0; i < len(input); i++ { + blob := input[i] + + if strings.HasPrefix(blob, "--") { + name := blob[2:] + value := "" + + if strings.Contains(name, "=") { + split := strings.SplitN(name, "=", 2) + name = split[0] + value = split[1] + } + + if strings.Contains(name, "-") { + return nil, nil, fmt.Errorf("Invalid option blob: '%s' (Shouldn't contain '-')", input[i]) + } + + if value != "" && strings.Contains(value, "\"") { + // TODO: ignore escaped quotations (--foo="\"") + if !strings.HasPrefix(value, "\"") { + return nil, nil, fmt.Errorf("Invalid option blob: '%s' (Quotation wasn't at the start of value)", input[i]) + } + + value = value[1:] + + for { + if strings.HasSuffix(value, "\"") { + value = value[:len(value)-1] + break + } + + i++ + if i >= len(input) { + return nil, nil, fmt.Errorf("Unterminated string: '%s'", value) + } + + value += " " + input[i] + } + + if strings.Contains(value, "\"") { + return nil, nil, fmt.Errorf("Invalid option blob: '%s' (Value contains unescaped quotation)", value) + } + } + + opts[name] = value + + } else if strings.HasPrefix(blob, "-") { + blob = blob[1:] + + if strings.ContainsAny(blob, "-=\"") { + return nil, nil, fmt.Errorf("Invalid option blob: '%s'", input[i]) + } + + for _, name := range blob { + opts[string(name)] = "" + } + + // TODO: interpret next blob as value if the last option isn't a bool + + } else { + cleanInput = append(cleanInput, blob) + } + } + + return opts, cleanInput, nil +}