-
Notifications
You must be signed in to change notification settings - Fork 22
/
parse.go
66 lines (58 loc) · 1.7 KB
/
parse.go
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
package main
import (
"flag"
"fmt"
"io"
"strings"
)
// gentleParse takes a flag.FlagSet, calls Parse to get its flags parsed,
// and collects the arguments the FlagSet does not recognize, returning
// the collected list.
func gentleParse(flagset *flag.FlagSet, args []string) ([]string, error) {
if len(args) == 0 {
return nil, nil
}
const prefix = "flag provided but not defined: "
r := make([]string, 0, len(args))
flagset.Init(flagset.Name(), flag.ContinueOnError)
w := flagset.Output()
flagset.SetOutput(io.Discard)
// Put back the flagset's output, the flagset's Usage might be called later.
defer flagset.SetOutput(w)
next := args
for len(next) > 0 {
if !strings.HasPrefix(next[0], "-") {
r, next = append(r, next[0]), next[1:]
continue
}
if err := flagset.Parse(next); err != nil {
if strings.HasPrefix(err.Error(), prefix) {
pull := strings.TrimPrefix(err.Error(), prefix)
for next[0] != pull && !(strings.HasPrefix(next[0], pull) && strings.HasPrefix(next[0], pull+"=")) {
next = next[1:]
if len(next) == 0 {
panic("odd: pull not found: " + pull)
}
}
r, next = append(r, next[0]), next[1:]
continue
}
fmt.Fprintf(w, "%s\n", err)
flagset.SetOutput(w)
flagset.Usage()
return nil, err
}
// Check if the call to flagset.Parse ate a "--". If so, we're done
// and can return what's been built up on r along with the rest.
if len(next) > len(flagset.Args()) {
lastabsorbedpos := len(next) - len(flagset.Args()) - 1
lastabsorbed := next[lastabsorbedpos]
if lastabsorbed == "--" {
r = append(r, "--") // return the "--" too.
return append(r, flagset.Args()...), nil
}
}
next = flagset.Args()
}
return r, nil
}