parse.go 2.1 KB
Newer Older
1 2 3 4 5 6 7 8 9
package cli

import (
  "strings"
  "fmt"

  "github.com/jbenet/go-ipfs/commands"
)

10
func Parse(input []string, root *commands.Command) (*commands.Request, error) {
11
  path, input, err := parsePath(input, root)
12
  if err != nil {
13
    return nil, err
14 15
  }

16 17
  options, err := root.GetOptions(path)
  if err != nil {
18
    return nil, err
19 20 21
  }

  opts, args, err := parseOptions(input, options)
22
  if err != nil {
23
    return nil, err
24 25
  }

26
  return commands.NewRequest(path, opts, args), nil
27 28
}

29
// parsePath gets the command path from the command line input
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
func parsePath(input []string, root *commands.Command) ([]string, []string, error) {
  cmd := root
  i := 0

  for _, blob := range input {
    if strings.HasPrefix(blob, "-") {
      break
    }

    cmd := cmd.Sub(blob)
    if cmd == nil {
      break
    }

    i++
  }

  return input[:i], input[i:], nil
}

50
// parseOptions parses the raw string values of the given options
51
// returns the parsed options as strings, along with the CLI args
52 53
func parseOptions(input []string, options map[string]commands.Option) (map[string]interface{}, []string, error) {
  opts := make(map[string]interface{})
54
  args := make([]string, 0)
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

  // 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]
      }

      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])
      }

80
      nameS := ""
81
      for _, name := range blob {
82 83
        nameS = string(name)
        opts[nameS] = ""
84 85
      }

86 87 88 89 90 91 92 93 94
      if nameS != "" {
        opt, ok := options[nameS]
        if ok && opt.Type != commands.Bool {
          i++
          if i <= len(input) {
            opts[nameS] = input[i]
          }
        }
      }
95 96

    } else {
97
      args = append(args, blob)
98 99 100
    }
  }

101
  return opts, args, nil
102
}