...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package main
16
17 import (
18 "errors"
19 "fmt"
20 "go/build"
21 "strings"
22 "unicode"
23 )
24
25
26 type multiFlag []string
27
28 func (m *multiFlag) String() string {
29 if m == nil || len(*m) == 0 {
30 return ""
31 }
32 return fmt.Sprint(*m)
33 }
34
35 func (m *multiFlag) Set(v string) error {
36 (*m) = append(*m, v)
37 return nil
38 }
39
40
41
42
43 type quoteMultiFlag []string
44
45 func (m *quoteMultiFlag) String() string {
46 if m == nil || len(*m) == 0 {
47 return ""
48 }
49 return fmt.Sprint(*m)
50 }
51
52 func (m *quoteMultiFlag) Set(v string) error {
53 fs, err := splitQuoted(v)
54 if err != nil {
55 return err
56 }
57 *m = append(*m, fs...)
58 return nil
59 }
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 func splitQuoted(s string) (r []string, err error) {
79 var args []string
80 arg := make([]rune, len(s))
81 escaped := false
82 quoted := false
83 quote := '\x00'
84 i := 0
85 for _, rune := range s {
86 switch {
87 case escaped:
88 escaped = false
89 case rune == '\\':
90 escaped = true
91 continue
92 case quote != '\x00':
93 if rune == quote {
94 quote = '\x00'
95 continue
96 }
97 case rune == '"' || rune == '\'':
98 quoted = true
99 quote = rune
100 continue
101 case unicode.IsSpace(rune):
102 if quoted || i > 0 {
103 quoted = false
104 args = append(args, string(arg[:i]))
105 i = 0
106 }
107 continue
108 }
109 arg[i] = rune
110 i++
111 }
112 if quoted || i > 0 {
113 args = append(args, string(arg[:i]))
114 }
115 if quote != 0 {
116 err = errors.New("unclosed quote")
117 } else if escaped {
118 err = errors.New("unfinished escaping")
119 }
120 return args, err
121 }
122
123
124
125 type tagFlag struct{}
126
127 func (f *tagFlag) String() string {
128 return strings.Join(build.Default.BuildTags, ",")
129 }
130
131 func (f *tagFlag) Set(opt string) error {
132 tags := strings.Split(opt, ",")
133 build.Default.BuildTags = append(build.Default.BuildTags, tags...)
134 return nil
135 }
136
View as plain text