-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmapping.go
More file actions
94 lines (74 loc) · 3.22 KB
/
mapping.go
File metadata and controls
94 lines (74 loc) · 3.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package console
import (
"strings"
"github.com/eidolon/console/parameters"
)
// Mapping and parsing when combined check all input provided as application arguments and
// environment variables against all input defined in a Definition.
// MapInput2 iterates over all defined possible input in the definition, and attempts to set the
// value defined in the input, or the environment. In the process of mapping, the input will also be
// validated (i.e. missing required params or values will be identified, and values of the wrong
// type in the input or env will be identified).
func MapInput2(definition *Definition, input Input, env []string) error {
return nil
}
// ParseInput2 takes the raw input, and regardless of what is actually defined in the definition,
// categorising the input as either arguments or options. In other words, the raw input is iterated
// over, not the definition's parameters. The definition is used so that we can identify options
// that should have values and consume the next argument as it's value.
func ParseInput2(definition *Definition, args []string) *Input {
var input Input
var optsEnded bool
// We don't range, because we can modify `i` in the middle of the loop this way. This allows us
// to consume the next argument if we want (and if it's available).
for i := 0; i < len(args); i++ {
arg := args[i]
if arg == "--" {
optsEnded = true
continue
}
argLen := len(arg)
isLongOpt := argLen > 2 && strings.HasPrefix(arg, "--")
isShortOpt := argLen > 1 && strings.HasPrefix(arg, "-")
if !optsEnded && (isLongOpt || isShortOpt) {
var options []InputOption
if isLongOpt {
options = parseOption(arg, "--")
} else {
options = parseOption(arg, "-")
}
// mappedOptions is a temporary place for the options parsed from this one argument to
// be stored. We need this so we can always identify if we actually parsed any options
// at all, and so we can get the last option for this argument all of the time.
var mappedOptions []InputOption
for _, option := range options {
// All options will be mapped, regardless. Only the last option will have any value.
mappedOptions = append(mappedOptions, option)
}
mappedOptionsLen := len(mappedOptions)
if mappedOptionsLen > 0 {
lastOption := mappedOptions[mappedOptionsLen-1]
defOpt, exists := definition.options[lastOption.Name]
if !exists {
// We don't care about options that don't exist in the definition. We shouldn't
// be consuming arguments for them, because they won't require a value.
break
}
isRequired := defOpt.ValueMode == parameters.OptionValueRequired
hasArgsLeft := len(args) > (i + 1) // Length required for next is +2, not +1.
hasNoValYet := lastOption.Value == ""
// If the value is required, but we don't yet have a value on the option, this means
// we'll consume the next argument following the option and treat it as the value.
if isRequired && hasNoValYet && hasArgsLeft {
lastOption.Value = args[i+1]
i++
}
mappedOptions[mappedOptionsLen-1] = lastOption
}
input.Options = append(input.Options, mappedOptions...)
} else {
input.Arguments = append(input.Arguments, InputArgument{Value: arg})
}
}
return &input
}