aboutsummaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
authorCalle Pettersson <carlpett@users.noreply.github.com>2017-08-12 15:07:24 +0200
committerBen Kochie <superq@gmail.com>2017-08-12 15:07:24 +0200
commitdfe07eaae84b205873567ad95cdb83b52a5243df (patch)
tree5492eb4ef850037f9cbb59227a39a255590574cc /vendor
parent1467d845fbed398e54f5c28d8bdb3060c64ae3fa (diff)
downloadprometheus_node_collector-dfe07eaae84b205873567ad95cdb83b52a5243df.tar.bz2
prometheus_node_collector-dfe07eaae84b205873567ad95cdb83b52a5243df.tar.xz
prometheus_node_collector-dfe07eaae84b205873567ad95cdb83b52a5243df.zip
Switch to kingpin flags (#639)
* Switch to kingpin flags * Fix logrus vendoring * Fix flags in main tests * Fix vendoring versions
Diffstat (limited to 'vendor')
-rw-r--r--vendor/github.com/alecthomas/template/LICENSE27
-rw-r--r--vendor/github.com/alecthomas/template/README.md25
-rw-r--r--vendor/github.com/alecthomas/template/doc.go406
-rw-r--r--vendor/github.com/alecthomas/template/exec.go845
-rw-r--r--vendor/github.com/alecthomas/template/funcs.go598
-rw-r--r--vendor/github.com/alecthomas/template/helper.go108
-rw-r--r--vendor/github.com/alecthomas/template/parse/lex.go556
-rw-r--r--vendor/github.com/alecthomas/template/parse/node.go834
-rw-r--r--vendor/github.com/alecthomas/template/parse/parse.go700
-rw-r--r--vendor/github.com/alecthomas/template/template.go218
-rw-r--r--vendor/github.com/alecthomas/units/COPYING19
-rw-r--r--vendor/github.com/alecthomas/units/README.md11
-rw-r--r--vendor/github.com/alecthomas/units/bytes.go83
-rw-r--r--vendor/github.com/alecthomas/units/doc.go13
-rw-r--r--vendor/github.com/alecthomas/units/si.go26
-rw-r--r--vendor/github.com/alecthomas/units/util.go138
-rw-r--r--vendor/github.com/prometheus/common/expfmt/text_parse.go4
-rw-r--r--vendor/github.com/prometheus/common/log/eventlog_formatter.go10
-rw-r--r--vendor/github.com/prometheus/common/log/log.go162
-rw-r--r--vendor/github.com/prometheus/common/log/syslog_formatter.go10
-rw-r--r--vendor/github.com/prometheus/common/model/time.go14
-rw-r--r--vendor/github.com/sirupsen/logrus/CHANGELOG.md (renamed from vendor/github.com/Sirupsen/logrus/CHANGELOG.md)0
-rw-r--r--vendor/github.com/sirupsen/logrus/LICENSE (renamed from vendor/github.com/Sirupsen/logrus/LICENSE)0
-rw-r--r--vendor/github.com/sirupsen/logrus/README.md (renamed from vendor/github.com/Sirupsen/logrus/README.md)0
-rw-r--r--vendor/github.com/sirupsen/logrus/alt_exit.go (renamed from vendor/github.com/Sirupsen/logrus/alt_exit.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/doc.go (renamed from vendor/github.com/Sirupsen/logrus/doc.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/entry.go (renamed from vendor/github.com/Sirupsen/logrus/entry.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/exported.go (renamed from vendor/github.com/Sirupsen/logrus/exported.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/formatter.go (renamed from vendor/github.com/Sirupsen/logrus/formatter.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/hooks.go (renamed from vendor/github.com/Sirupsen/logrus/hooks.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/json_formatter.go (renamed from vendor/github.com/Sirupsen/logrus/json_formatter.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/logger.go (renamed from vendor/github.com/Sirupsen/logrus/logger.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/logrus.go (renamed from vendor/github.com/Sirupsen/logrus/logrus.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_appengine.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_appengine.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_bsd.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_bsd.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_linux.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_linux.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_notwindows.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_notwindows.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_solaris.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_solaris.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/terminal_windows.go (renamed from vendor/github.com/Sirupsen/logrus/terminal_windows.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/text_formatter.go (renamed from vendor/github.com/Sirupsen/logrus/text_formatter.go)0
-rw-r--r--vendor/github.com/sirupsen/logrus/writer.go (renamed from vendor/github.com/Sirupsen/logrus/writer.go)0
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/COPYING19
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/README.md674
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/actions.go42
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/app.go685
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/args.go184
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go274
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/completions.go33
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/doc.go68
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/envar.go45
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/flags.go308
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/global.go94
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go9
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go38
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/model.go227
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/parser.go382
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go212
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/templates.go262
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/usage.go211
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/values.go470
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/values.json25
-rw-r--r--vendor/gopkg.in/alecthomas/kingpin.v2/values_generated.go821
-rw-r--r--vendor/vendor.json52
63 files changed, 9833 insertions, 109 deletions
diff --git a/vendor/github.com/alecthomas/template/LICENSE b/vendor/github.com/alecthomas/template/LICENSE
new file mode 100644
index 0000000..7448756
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/LICENSE
@@ -0,0 +1,27 @@
1Copyright (c) 2012 The Go Authors. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without
4modification, are permitted provided that the following conditions are
5met:
6
7 * Redistributions of source code must retain the above copyright
8notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the
12distribution.
13 * Neither the name of Google Inc. nor the names of its
14contributors may be used to endorse or promote products derived from
15this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/alecthomas/template/README.md b/vendor/github.com/alecthomas/template/README.md
new file mode 100644
index 0000000..ef6a8ee
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/README.md
@@ -0,0 +1,25 @@
1# Go's `text/template` package with newline elision
2
3This is a fork of Go 1.4's [text/template](http://golang.org/pkg/text/template/) package with one addition: a backslash immediately after a closing delimiter will delete all subsequent newlines until a non-newline.
4
5eg.
6
7```
8{{if true}}\
9hello
10{{end}}\
11```
12
13Will result in:
14
15```
16hello\n
17```
18
19Rather than:
20
21```
22\n
23hello\n
24\n
25```
diff --git a/vendor/github.com/alecthomas/template/doc.go b/vendor/github.com/alecthomas/template/doc.go
new file mode 100644
index 0000000..223c595
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/doc.go
@@ -0,0 +1,406 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5/*
6Package template implements data-driven templates for generating textual output.
7
8To generate HTML output, see package html/template, which has the same interface
9as this package but automatically secures HTML output against certain attacks.
10
11Templates are executed by applying them to a data structure. Annotations in the
12template refer to elements of the data structure (typically a field of a struct
13or a key in a map) to control execution and derive values to be displayed.
14Execution of the template walks the structure and sets the cursor, represented
15by a period '.' and called "dot", to the value at the current location in the
16structure as execution proceeds.
17
18The input text for a template is UTF-8-encoded text in any format.
19"Actions"--data evaluations or control structures--are delimited by
20"{{" and "}}"; all text outside actions is copied to the output unchanged.
21Actions may not span newlines, although comments can.
22
23Once parsed, a template may be executed safely in parallel.
24
25Here is a trivial example that prints "17 items are made of wool".
26
27 type Inventory struct {
28 Material string
29 Count uint
30 }
31 sweaters := Inventory{"wool", 17}
32 tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
33 if err != nil { panic(err) }
34 err = tmpl.Execute(os.Stdout, sweaters)
35 if err != nil { panic(err) }
36
37More intricate examples appear below.
38
39Actions
40
41Here is the list of actions. "Arguments" and "pipelines" are evaluations of
42data, defined in detail below.
43
44*/
45// {{/* a comment */}}
46// A comment; discarded. May contain newlines.
47// Comments do not nest and must start and end at the
48// delimiters, as shown here.
49/*
50
51 {{pipeline}}
52 The default textual representation of the value of the pipeline
53 is copied to the output.
54
55 {{if pipeline}} T1 {{end}}
56 If the value of the pipeline is empty, no output is generated;
57 otherwise, T1 is executed. The empty values are false, 0, any
58 nil pointer or interface value, and any array, slice, map, or
59 string of length zero.
60 Dot is unaffected.
61
62 {{if pipeline}} T1 {{else}} T0 {{end}}
63 If the value of the pipeline is empty, T0 is executed;
64 otherwise, T1 is executed. Dot is unaffected.
65
66 {{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
67 To simplify the appearance of if-else chains, the else action
68 of an if may include another if directly; the effect is exactly
69 the same as writing
70 {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
71
72 {{range pipeline}} T1 {{end}}
73 The value of the pipeline must be an array, slice, map, or channel.
74 If the value of the pipeline has length zero, nothing is output;
75 otherwise, dot is set to the successive elements of the array,
76 slice, or map and T1 is executed. If the value is a map and the
77 keys are of basic type with a defined order ("comparable"), the
78 elements will be visited in sorted key order.
79
80 {{range pipeline}} T1 {{else}} T0 {{end}}
81 The value of the pipeline must be an array, slice, map, or channel.
82 If the value of the pipeline has length zero, dot is unaffected and
83 T0 is executed; otherwise, dot is set to the successive elements
84 of the array, slice, or map and T1 is executed.
85
86 {{template "name"}}
87 The template with the specified name is executed with nil data.
88
89 {{template "name" pipeline}}
90 The template with the specified name is executed with dot set
91 to the value of the pipeline.
92
93 {{with pipeline}} T1 {{end}}
94 If the value of the pipeline is empty, no output is generated;
95 otherwise, dot is set to the value of the pipeline and T1 is
96 executed.
97
98 {{with pipeline}} T1 {{else}} T0 {{end}}
99 If the value of the pipeline is empty, dot is unaffected and T0
100 is executed; otherwise, dot is set to the value of the pipeline
101 and T1 is executed.
102
103Arguments
104
105An argument is a simple value, denoted by one of the following.
106
107 - A boolean, string, character, integer, floating-point, imaginary
108 or complex constant in Go syntax. These behave like Go's untyped
109 constants, although raw strings may not span newlines.
110 - The keyword nil, representing an untyped Go nil.
111 - The character '.' (period):
112 .
113 The result is the value of dot.
114 - A variable name, which is a (possibly empty) alphanumeric string
115 preceded by a dollar sign, such as
116 $piOver2
117 or
118 $
119 The result is the value of the variable.
120 Variables are described below.
121 - The name of a field of the data, which must be a struct, preceded
122 by a period, such as
123 .Field
124 The result is the value of the field. Field invocations may be
125 chained:
126 .Field1.Field2
127 Fields can also be evaluated on variables, including chaining:
128 $x.Field1.Field2
129 - The name of a key of the data, which must be a map, preceded
130 by a period, such as
131 .Key
132 The result is the map element value indexed by the key.
133 Key invocations may be chained and combined with fields to any
134 depth:
135 .Field1.Key1.Field2.Key2
136 Although the key must be an alphanumeric identifier, unlike with
137 field names they do not need to start with an upper case letter.
138 Keys can also be evaluated on variables, including chaining:
139 $x.key1.key2
140 - The name of a niladic method of the data, preceded by a period,
141 such as
142 .Method
143 The result is the value of invoking the method with dot as the
144 receiver, dot.Method(). Such a method must have one return value (of
145 any type) or two return values, the second of which is an error.
146 If it has two and the returned error is non-nil, execution terminates
147 and an error is returned to the caller as the value of Execute.
148 Method invocations may be chained and combined with fields and keys
149 to any depth:
150 .Field1.Key1.Method1.Field2.Key2.Method2
151 Methods can also be evaluated on variables, including chaining:
152 $x.Method1.Field
153 - The name of a niladic function, such as
154 fun
155 The result is the value of invoking the function, fun(). The return
156 types and values behave as in methods. Functions and function
157 names are described below.
158 - A parenthesized instance of one the above, for grouping. The result
159 may be accessed by a field or map key invocation.
160 print (.F1 arg1) (.F2 arg2)
161 (.StructValuedMethod "arg").Field
162
163Arguments may evaluate to any type; if they are pointers the implementation
164automatically indirects to the base type when required.
165If an evaluation yields a function value, such as a function-valued
166field of a struct, the function is not invoked automatically, but it
167can be used as a truth value for an if action and the like. To invoke
168it, use the call function, defined below.
169
170A pipeline is a possibly chained sequence of "commands". A command is a simple
171value (argument) or a function or method call, possibly with multiple arguments:
172
173 Argument
174 The result is the value of evaluating the argument.
175 .Method [Argument...]
176 The method can be alone or the last element of a chain but,
177 unlike methods in the middle of a chain, it can take arguments.
178 The result is the value of calling the method with the
179 arguments:
180 dot.Method(Argument1, etc.)
181 functionName [Argument...]
182 The result is the value of calling the function associated
183 with the name:
184 function(Argument1, etc.)
185 Functions and function names are described below.
186
187Pipelines
188
189A pipeline may be "chained" by separating a sequence of commands with pipeline
190characters '|'. In a chained pipeline, the result of the each command is
191passed as the last argument of the following command. The output of the final
192command in the pipeline is the value of the pipeline.
193
194The output of a command will be either one value or two values, the second of
195which has type error. If that second value is present and evaluates to
196non-nil, execution terminates and the error is returned to the caller of
197Execute.
198
199Variables
200
201A pipeline inside an action may initialize a variable to capture the result.
202The initialization has syntax
203
204 $variable := pipeline
205
206where $variable is the name of the variable. An action that declares a
207variable produces no output.
208
209If a "range" action initializes a variable, the variable is set to the
210successive elements of the iteration. Also, a "range" may declare two
211variables, separated by a comma:
212
213 range $index, $element := pipeline
214
215in which case $index and $element are set to the successive values of the
216array/slice index or map key and element, respectively. Note that if there is
217only one variable, it is assigned the element; this is opposite to the
218convention in Go range clauses.
219
220A variable's scope extends to the "end" action of the control structure ("if",
221"with", or "range") in which it is declared, or to the end of the template if
222there is no such control structure. A template invocation does not inherit
223variables from the point of its invocation.
224
225When execution begins, $ is set to the data argument passed to Execute, that is,
226to the starting value of dot.
227
228Examples
229
230Here are some example one-line templates demonstrating pipelines and variables.
231All produce the quoted word "output":
232
233 {{"\"output\""}}
234 A string constant.
235 {{`"output"`}}
236 A raw string constant.
237 {{printf "%q" "output"}}
238 A function call.
239 {{"output" | printf "%q"}}
240 A function call whose final argument comes from the previous
241 command.
242 {{printf "%q" (print "out" "put")}}
243 A parenthesized argument.
244 {{"put" | printf "%s%s" "out" | printf "%q"}}
245 A more elaborate call.
246 {{"output" | printf "%s" | printf "%q"}}
247 A longer chain.
248 {{with "output"}}{{printf "%q" .}}{{end}}
249 A with action using dot.
250 {{with $x := "output" | printf "%q"}}{{$x}}{{end}}
251 A with action that creates and uses a variable.
252 {{with $x := "output"}}{{printf "%q" $x}}{{end}}
253 A with action that uses the variable in another action.
254 {{with $x := "output"}}{{$x | printf "%q"}}{{end}}
255 The same, but pipelined.
256
257Functions
258
259During execution functions are found in two function maps: first in the
260template, then in the global function map. By default, no functions are defined
261in the template but the Funcs method can be used to add them.
262
263Predefined global functions are named as follows.
264
265 and
266 Returns the boolean AND of its arguments by returning the
267 first empty argument or the last argument, that is,
268 "and x y" behaves as "if x then y else x". All the
269 arguments are evaluated.
270 call
271 Returns the result of calling the first argument, which
272 must be a function, with the remaining arguments as parameters.
273 Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
274 Y is a func-valued field, map entry, or the like.
275 The first argument must be the result of an evaluation
276 that yields a value of function type (as distinct from
277 a predefined function such as print). The function must
278 return either one or two result values, the second of which
279 is of type error. If the arguments don't match the function
280 or the returned error value is non-nil, execution stops.
281 html
282 Returns the escaped HTML equivalent of the textual
283 representation of its arguments.
284 index
285 Returns the result of indexing its first argument by the
286 following arguments. Thus "index x 1 2 3" is, in Go syntax,
287 x[1][2][3]. Each indexed item must be a map, slice, or array.
288 js
289 Returns the escaped JavaScript equivalent of the textual
290 representation of its arguments.
291 len
292 Returns the integer length of its argument.
293 not
294 Returns the boolean negation of its single argument.
295 or
296 Returns the boolean OR of its arguments by returning the
297 first non-empty argument or the last argument, that is,
298 "or x y" behaves as "if x then x else y". All the
299 arguments are evaluated.
300 print
301 An alias for fmt.Sprint
302 printf
303 An alias for fmt.Sprintf
304 println
305 An alias for fmt.Sprintln
306 urlquery
307 Returns the escaped value of the textual representation of
308 its arguments in a form suitable for embedding in a URL query.
309
310The boolean functions take any zero value to be false and a non-zero
311value to be true.
312
313There is also a set of binary comparison operators defined as
314functions:
315
316 eq
317 Returns the boolean truth of arg1 == arg2
318 ne
319 Returns the boolean truth of arg1 != arg2
320 lt
321 Returns the boolean truth of arg1 < arg2
322 le
323 Returns the boolean truth of arg1 <= arg2
324 gt
325 Returns the boolean truth of arg1 > arg2
326 ge
327 Returns the boolean truth of arg1 >= arg2
328
329For simpler multi-way equality tests, eq (only) accepts two or more
330arguments and compares the second and subsequent to the first,
331returning in effect
332
333 arg1==arg2 || arg1==arg3 || arg1==arg4 ...
334
335(Unlike with || in Go, however, eq is a function call and all the
336arguments will be evaluated.)
337
338The comparison functions work on basic types only (or named basic
339types, such as "type Celsius float32"). They implement the Go rules
340for comparison of values, except that size and exact type are
341ignored, so any integer value, signed or unsigned, may be compared
342with any other integer value. (The arithmetic value is compared,
343not the bit pattern, so all negative integers are less than all
344unsigned integers.) However, as usual, one may not compare an int
345with a float32 and so on.
346
347Associated templates
348
349Each template is named by a string specified when it is created. Also, each
350template is associated with zero or more other templates that it may invoke by
351name; such associations are transitive and form a name space of templates.
352
353A template may use a template invocation to instantiate another associated
354template; see the explanation of the "template" action above. The name must be
355that of a template associated with the template that contains the invocation.
356
357Nested template definitions
358
359When parsing a template, another template may be defined and associated with the
360template being parsed. Template definitions must appear at the top level of the
361template, much like global variables in a Go program.
362
363The syntax of such definitions is to surround each template declaration with a
364"define" and "end" action.
365
366The define action names the template being created by providing a string
367constant. Here is a simple example:
368
369 `{{define "T1"}}ONE{{end}}
370 {{define "T2"}}TWO{{end}}
371 {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
372 {{template "T3"}}`
373
374This defines two templates, T1 and T2, and a third T3 that invokes the other two
375when it is executed. Finally it invokes T3. If executed this template will
376produce the text
377
378 ONE TWO
379
380By construction, a template may reside in only one association. If it's
381necessary to have a template addressable from multiple associations, the
382template definition must be parsed multiple times to create distinct *Template
383values, or must be copied with the Clone or AddParseTree method.
384
385Parse may be called multiple times to assemble the various associated templates;
386see the ParseFiles and ParseGlob functions and methods for simple ways to parse
387related templates stored in files.
388
389A template may be executed directly or through ExecuteTemplate, which executes
390an associated template identified by name. To invoke our example above, we
391might write,
392
393 err := tmpl.Execute(os.Stdout, "no data needed")
394 if err != nil {
395 log.Fatalf("execution failed: %s", err)
396 }
397
398or to invoke a particular template explicitly by name,
399
400 err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
401 if err != nil {
402 log.Fatalf("execution failed: %s", err)
403 }
404
405*/
406package template
diff --git a/vendor/github.com/alecthomas/template/exec.go b/vendor/github.com/alecthomas/template/exec.go
new file mode 100644
index 0000000..c3078e5
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/exec.go
@@ -0,0 +1,845 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package template
6
7import (
8 "bytes"
9 "fmt"
10 "io"
11 "reflect"
12 "runtime"
13 "sort"
14 "strings"
15
16 "github.com/alecthomas/template/parse"
17)
18
19// state represents the state of an execution. It's not part of the
20// template so that multiple executions of the same template
21// can execute in parallel.
22type state struct {
23 tmpl *Template
24 wr io.Writer
25 node parse.Node // current node, for errors
26 vars []variable // push-down stack of variable values.
27}
28
29// variable holds the dynamic value of a variable such as $, $x etc.
30type variable struct {
31 name string
32 value reflect.Value
33}
34
35// push pushes a new variable on the stack.
36func (s *state) push(name string, value reflect.Value) {
37 s.vars = append(s.vars, variable{name, value})
38}
39
40// mark returns the length of the variable stack.
41func (s *state) mark() int {
42 return len(s.vars)
43}
44
45// pop pops the variable stack up to the mark.
46func (s *state) pop(mark int) {
47 s.vars = s.vars[0:mark]
48}
49
50// setVar overwrites the top-nth variable on the stack. Used by range iterations.
51func (s *state) setVar(n int, value reflect.Value) {
52 s.vars[len(s.vars)-n].value = value
53}
54
55// varValue returns the value of the named variable.
56func (s *state) varValue(name string) reflect.Value {
57 for i := s.mark() - 1; i >= 0; i-- {
58 if s.vars[i].name == name {
59 return s.vars[i].value
60 }
61 }
62 s.errorf("undefined variable: %s", name)
63 return zero
64}
65
66var zero reflect.Value
67
68// at marks the state to be on node n, for error reporting.
69func (s *state) at(node parse.Node) {
70 s.node = node
71}
72
73// doublePercent returns the string with %'s replaced by %%, if necessary,
74// so it can be used safely inside a Printf format string.
75func doublePercent(str string) string {
76 if strings.Contains(str, "%") {
77 str = strings.Replace(str, "%", "%%", -1)
78 }
79 return str
80}
81
82// errorf formats the error and terminates processing.
83func (s *state) errorf(format string, args ...interface{}) {
84 name := doublePercent(s.tmpl.Name())
85 if s.node == nil {
86 format = fmt.Sprintf("template: %s: %s", name, format)
87 } else {
88 location, context := s.tmpl.ErrorContext(s.node)
89 format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
90 }
91 panic(fmt.Errorf(format, args...))
92}
93
94// errRecover is the handler that turns panics into returns from the top
95// level of Parse.
96func errRecover(errp *error) {
97 e := recover()
98 if e != nil {
99 switch err := e.(type) {
100 case runtime.Error:
101 panic(e)
102 case error:
103 *errp = err
104 default:
105 panic(e)
106 }
107 }
108}
109
110// ExecuteTemplate applies the template associated with t that has the given name
111// to the specified data object and writes the output to wr.
112// If an error occurs executing the template or writing its output,
113// execution stops, but partial results may already have been written to
114// the output writer.
115// A template may be executed safely in parallel.
116func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
117 tmpl := t.tmpl[name]
118 if tmpl == nil {
119 return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
120 }
121 return tmpl.Execute(wr, data)
122}
123
124// Execute applies a parsed template to the specified data object,
125// and writes the output to wr.
126// If an error occurs executing the template or writing its output,
127// execution stops, but partial results may already have been written to
128// the output writer.
129// A template may be executed safely in parallel.
130func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
131 defer errRecover(&err)
132 value := reflect.ValueOf(data)
133 state := &state{
134 tmpl: t,
135 wr: wr,
136 vars: []variable{{"$", value}},
137 }
138 t.init()
139 if t.Tree == nil || t.Root == nil {
140 var b bytes.Buffer
141 for name, tmpl := range t.tmpl {
142 if tmpl.Tree == nil || tmpl.Root == nil {
143 continue
144 }
145 if b.Len() > 0 {
146 b.WriteString(", ")
147 }
148 fmt.Fprintf(&b, "%q", name)
149 }
150 var s string
151 if b.Len() > 0 {
152 s = "; defined templates are: " + b.String()
153 }
154 state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
155 }
156 state.walk(value, t.Root)
157 return
158}
159
160// Walk functions step through the major pieces of the template structure,
161// generating output as they go.
162func (s *state) walk(dot reflect.Value, node parse.Node) {
163 s.at(node)
164 switch node := node.(type) {
165 case *parse.ActionNode:
166 // Do not pop variables so they persist until next end.
167 // Also, if the action declares variables, don't print the result.
168 val := s.evalPipeline(dot, node.Pipe)
169 if len(node.Pipe.Decl) == 0 {
170 s.printValue(node, val)
171 }
172 case *parse.IfNode:
173 s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
174 case *parse.ListNode:
175 for _, node := range node.Nodes {
176 s.walk(dot, node)
177 }
178 case *parse.RangeNode:
179 s.walkRange(dot, node)
180 case *parse.TemplateNode:
181 s.walkTemplate(dot, node)
182 case *parse.TextNode:
183 if _, err := s.wr.Write(node.Text); err != nil {
184 s.errorf("%s", err)
185 }
186 case *parse.WithNode:
187 s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
188 default:
189 s.errorf("unknown node: %s", node)
190 }
191}
192
193// walkIfOrWith walks an 'if' or 'with' node. The two control structures
194// are identical in behavior except that 'with' sets dot.
195func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
196 defer s.pop(s.mark())
197 val := s.evalPipeline(dot, pipe)
198 truth, ok := isTrue(val)
199 if !ok {
200 s.errorf("if/with can't use %v", val)
201 }
202 if truth {
203 if typ == parse.NodeWith {
204 s.walk(val, list)
205 } else {
206 s.walk(dot, list)
207 }
208 } else if elseList != nil {
209 s.walk(dot, elseList)
210 }
211}
212
213// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
214// and whether the value has a meaningful truth value.
215func isTrue(val reflect.Value) (truth, ok bool) {
216 if !val.IsValid() {
217 // Something like var x interface{}, never set. It's a form of nil.
218 return false, true
219 }
220 switch val.Kind() {
221 case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
222 truth = val.Len() > 0
223 case reflect.Bool:
224 truth = val.Bool()
225 case reflect.Complex64, reflect.Complex128:
226 truth = val.Complex() != 0
227 case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
228 truth = !val.IsNil()
229 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
230 truth = val.Int() != 0
231 case reflect.Float32, reflect.Float64:
232 truth = val.Float() != 0
233 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
234 truth = val.Uint() != 0
235 case reflect.Struct:
236 truth = true // Struct values are always true.
237 default:
238 return
239 }
240 return truth, true
241}
242
243func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
244 s.at(r)
245 defer s.pop(s.mark())
246 val, _ := indirect(s.evalPipeline(dot, r.Pipe))
247 // mark top of stack before any variables in the body are pushed.
248 mark := s.mark()
249 oneIteration := func(index, elem reflect.Value) {
250 // Set top var (lexically the second if there are two) to the element.
251 if len(r.Pipe.Decl) > 0 {
252 s.setVar(1, elem)
253 }
254 // Set next var (lexically the first if there are two) to the index.
255 if len(r.Pipe.Decl) > 1 {
256 s.setVar(2, index)
257 }
258 s.walk(elem, r.List)
259 s.pop(mark)
260 }
261 switch val.Kind() {
262 case reflect.Array, reflect.Slice:
263 if val.Len() == 0 {
264 break
265 }
266 for i := 0; i < val.Len(); i++ {
267 oneIteration(reflect.ValueOf(i), val.Index(i))
268 }
269 return
270 case reflect.Map:
271 if val.Len() == 0 {
272 break
273 }
274 for _, key := range sortKeys(val.MapKeys()) {
275 oneIteration(key, val.MapIndex(key))
276 }
277 return
278 case reflect.Chan:
279 if val.IsNil() {
280 break
281 }
282 i := 0
283 for ; ; i++ {
284 elem, ok := val.Recv()
285 if !ok {
286 break
287 }
288 oneIteration(reflect.ValueOf(i), elem)
289 }
290 if i == 0 {
291 break
292 }
293 return
294 case reflect.Invalid:
295 break // An invalid value is likely a nil map, etc. and acts like an empty map.
296 default:
297 s.errorf("range can't iterate over %v", val)
298 }
299 if r.ElseList != nil {
300 s.walk(dot, r.ElseList)
301 }
302}
303
304func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
305 s.at(t)
306 tmpl := s.tmpl.tmpl[t.Name]
307 if tmpl == nil {
308 s.errorf("template %q not defined", t.Name)
309 }
310 // Variables declared by the pipeline persist.
311 dot = s.evalPipeline(dot, t.Pipe)
312 newState := *s
313 newState.tmpl = tmpl
314 // No dynamic scoping: template invocations inherit no variables.
315 newState.vars = []variable{{"$", dot}}
316 newState.walk(dot, tmpl.Root)
317}
318
319// Eval functions evaluate pipelines, commands, and their elements and extract
320// values from the data structure by examining fields, calling methods, and so on.
321// The printing of those values happens only through walk functions.
322
323// evalPipeline returns the value acquired by evaluating a pipeline. If the
324// pipeline has a variable declaration, the variable will be pushed on the
325// stack. Callers should therefore pop the stack after they are finished
326// executing commands depending on the pipeline value.
327func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
328 if pipe == nil {
329 return
330 }
331 s.at(pipe)
332 for _, cmd := range pipe.Cmds {
333 value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
334 // If the object has type interface{}, dig down one level to the thing inside.
335 if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
336 value = reflect.ValueOf(value.Interface()) // lovely!
337 }
338 }
339 for _, variable := range pipe.Decl {
340 s.push(variable.Ident[0], value)
341 }
342 return value
343}
344
345func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
346 if len(args) > 1 || final.IsValid() {
347 s.errorf("can't give argument to non-function %s", args[0])
348 }
349}
350
351func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
352 firstWord := cmd.Args[0]
353 switch n := firstWord.(type) {
354 case *parse.FieldNode:
355 return s.evalFieldNode(dot, n, cmd.Args, final)
356 case *parse.ChainNode:
357 return s.evalChainNode(dot, n, cmd.Args, final)
358 case *parse.IdentifierNode:
359 // Must be a function.
360 return s.evalFunction(dot, n, cmd, cmd.Args, final)
361 case *parse.PipeNode:
362 // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
363 return s.evalPipeline(dot, n)
364 case *parse.VariableNode:
365 return s.evalVariableNode(dot, n, cmd.Args, final)
366 }
367 s.at(firstWord)
368 s.notAFunction(cmd.Args, final)
369 switch word := firstWord.(type) {
370 case *parse.BoolNode:
371 return reflect.ValueOf(word.True)
372 case *parse.DotNode:
373 return dot
374 case *parse.NilNode:
375 s.errorf("nil is not a command")
376 case *parse.NumberNode:
377 return s.idealConstant(word)
378 case *parse.StringNode:
379 return reflect.ValueOf(word.Text)
380 }
381 s.errorf("can't evaluate command %q", firstWord)
382 panic("not reached")
383}
384
385// idealConstant is called to return the value of a number in a context where
386// we don't know the type. In that case, the syntax of the number tells us
387// its type, and we use Go rules to resolve. Note there is no such thing as
388// a uint ideal constant in this situation - the value must be of int type.
389func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
390 // These are ideal constants but we don't know the type
391 // and we have no context. (If it was a method argument,
392 // we'd know what we need.) The syntax guides us to some extent.
393 s.at(constant)
394 switch {
395 case constant.IsComplex:
396 return reflect.ValueOf(constant.Complex128) // incontrovertible.
397 case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0:
398 return reflect.ValueOf(constant.Float64)
399 case constant.IsInt:
400 n := int(constant.Int64)
401 if int64(n) != constant.Int64 {
402 s.errorf("%s overflows int", constant.Text)
403 }
404 return reflect.ValueOf(n)
405 case constant.IsUint:
406 s.errorf("%s overflows int", constant.Text)
407 }
408 return zero
409}
410
411func isHexConstant(s string) bool {
412 return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')
413}
414
415func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
416 s.at(field)
417 return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
418}
419
420func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
421 s.at(chain)
422 // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
423 pipe := s.evalArg(dot, nil, chain.Node)
424 if len(chain.Field) == 0 {
425 s.errorf("internal error: no fields in evalChainNode")
426 }
427 return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
428}
429
430func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
431 // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
432 s.at(variable)
433 value := s.varValue(variable.Ident[0])
434 if len(variable.Ident) == 1 {
435 s.notAFunction(args, final)
436 return value
437 }
438 return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
439}
440
441// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
442// dot is the environment in which to evaluate arguments, while
443// receiver is the value being walked along the chain.
444func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
445 n := len(ident)
446 for i := 0; i < n-1; i++ {
447 receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
448 }
449 // Now if it's a method, it gets the arguments.
450 return s.evalField(dot, ident[n-1], node, args, final, receiver)
451}
452
453func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
454 s.at(node)
455 name := node.Ident
456 function, ok := findFunction(name, s.tmpl)
457 if !ok {
458 s.errorf("%q is not a defined function", name)
459 }
460 return s.evalCall(dot, function, cmd, name, args, final)
461}
462
463// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
464// The 'final' argument represents the return value from the preceding
465// value of the pipeline, if any.
466func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
467 if !receiver.IsValid() {
468 return zero
469 }
470 typ := receiver.Type()
471 receiver, _ = indirect(receiver)
472 // Unless it's an interface, need to get to a value of type *T to guarantee
473 // we see all methods of T and *T.
474 ptr := receiver
475 if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
476 ptr = ptr.Addr()
477 }
478 if method := ptr.MethodByName(fieldName); method.IsValid() {
479 return s.evalCall(dot, method, node, fieldName, args, final)
480 }
481 hasArgs := len(args) > 1 || final.IsValid()
482 // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
483 receiver, isNil := indirect(receiver)
484 if isNil {
485 s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
486 }
487 switch receiver.Kind() {
488 case reflect.Struct:
489 tField, ok := receiver.Type().FieldByName(fieldName)
490 if ok {
491 field := receiver.FieldByIndex(tField.Index)
492 if tField.PkgPath != "" { // field is unexported
493 s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
494 }
495 // If it's a function, we must call it.
496 if hasArgs {
497 s.errorf("%s has arguments but cannot be invoked as function", fieldName)
498 }
499 return field
500 }
501 s.errorf("%s is not a field of struct type %s", fieldName, typ)
502 case reflect.Map:
503 // If it's a map, attempt to use the field name as a key.
504 nameVal := reflect.ValueOf(fieldName)
505 if nameVal.Type().AssignableTo(receiver.Type().Key()) {
506 if hasArgs {
507 s.errorf("%s is not a method but has arguments", fieldName)
508 }
509 return receiver.MapIndex(nameVal)
510 }
511 }
512 s.errorf("can't evaluate field %s in type %s", fieldName, typ)
513 panic("not reached")
514}
515
516var (
517 errorType = reflect.TypeOf((*error)(nil)).Elem()
518 fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
519)
520
521// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
522// it looks just like a function call. The arg list, if non-nil, includes (in the manner of the shell), arg[0]
523// as the function itself.
524func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
525 if args != nil {
526 args = args[1:] // Zeroth arg is function name/node; not passed to function.
527 }
528 typ := fun.Type()
529 numIn := len(args)
530 if final.IsValid() {
531 numIn++
532 }
533 numFixed := len(args)
534 if typ.IsVariadic() {
535 numFixed = typ.NumIn() - 1 // last arg is the variadic one.
536 if numIn < numFixed {
537 s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
538 }
539 } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
540 s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
541 }
542 if !goodFunc(typ) {
543 // TODO: This could still be a confusing error; maybe goodFunc should provide info.
544 s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
545 }
546 // Build the arg list.
547 argv := make([]reflect.Value, numIn)
548 // Args must be evaluated. Fixed args first.
549 i := 0
550 for ; i < numFixed && i < len(args); i++ {
551 argv[i] = s.evalArg(dot, typ.In(i), args[i])
552 }
553 // Now the ... args.
554 if typ.IsVariadic() {
555 argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
556 for ; i < len(args); i++ {
557 argv[i] = s.evalArg(dot, argType, args[i])
558 }
559 }
560 // Add final value if necessary.
561 if final.IsValid() {
562 t := typ.In(typ.NumIn() - 1)
563 if typ.IsVariadic() {
564 t = t.Elem()
565 }
566 argv[i] = s.validateType(final, t)
567 }
568 result := fun.Call(argv)
569 // If we have an error that is not nil, stop execution and return that error to the caller.
570 if len(result) == 2 && !result[1].IsNil() {
571 s.at(node)
572 s.errorf("error calling %s: %s", name, result[1].Interface().(error))
573 }
574 return result[0]
575}
576
577// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
578func canBeNil(typ reflect.Type) bool {
579 switch typ.Kind() {
580 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
581 return true
582 }
583 return false
584}
585
586// validateType guarantees that the value is valid and assignable to the type.
587func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
588 if !value.IsValid() {
589 if typ == nil || canBeNil(typ) {
590 // An untyped nil interface{}. Accept as a proper nil value.
591 return reflect.Zero(typ)
592 }
593 s.errorf("invalid value; expected %s", typ)
594 }
595 if typ != nil && !value.Type().AssignableTo(typ) {
596 if value.Kind() == reflect.Interface && !value.IsNil() {
597 value = value.Elem()
598 if value.Type().AssignableTo(typ) {
599 return value
600 }
601 // fallthrough
602 }
603 // Does one dereference or indirection work? We could do more, as we
604 // do with method receivers, but that gets messy and method receivers
605 // are much more constrained, so it makes more sense there than here.
606 // Besides, one is almost always all you need.
607 switch {
608 case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
609 value = value.Elem()
610 if !value.IsValid() {
611 s.errorf("dereference of nil pointer of type %s", typ)
612 }
613 case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
614 value = value.Addr()
615 default:
616 s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
617 }
618 }
619 return value
620}
621
622func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
623 s.at(n)
624 switch arg := n.(type) {
625 case *parse.DotNode:
626 return s.validateType(dot, typ)
627 case *parse.NilNode:
628 if canBeNil(typ) {
629 return reflect.Zero(typ)
630 }
631 s.errorf("cannot assign nil to %s", typ)
632 case *parse.FieldNode:
633 return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
634 case *parse.VariableNode:
635 return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
636 case *parse.PipeNode:
637 return s.validateType(s.evalPipeline(dot, arg), typ)
638 case *parse.IdentifierNode:
639 return s.evalFunction(dot, arg, arg, nil, zero)
640 case *parse.ChainNode:
641 return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ)
642 }
643 switch typ.Kind() {
644 case reflect.Bool:
645 return s.evalBool(typ, n)
646 case reflect.Complex64, reflect.Complex128:
647 return s.evalComplex(typ, n)
648 case reflect.Float32, reflect.Float64:
649 return s.evalFloat(typ, n)
650 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
651 return s.evalInteger(typ, n)
652 case reflect.Interface:
653 if typ.NumMethod() == 0 {
654 return s.evalEmptyInterface(dot, n)
655 }
656 case reflect.String:
657 return s.evalString(typ, n)
658 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
659 return s.evalUnsignedInteger(typ, n)
660 }
661 s.errorf("can't handle %s for arg of type %s", n, typ)
662 panic("not reached")
663}
664
665func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
666 s.at(n)
667 if n, ok := n.(*parse.BoolNode); ok {
668 value := reflect.New(typ).Elem()
669 value.SetBool(n.True)
670 return value
671 }
672 s.errorf("expected bool; found %s", n)
673 panic("not reached")
674}
675
676func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
677 s.at(n)
678 if n, ok := n.(*parse.StringNode); ok {
679 value := reflect.New(typ).Elem()
680 value.SetString(n.Text)
681 return value
682 }
683 s.errorf("expected string; found %s", n)
684 panic("not reached")
685}
686
687func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
688 s.at(n)
689 if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
690 value := reflect.New(typ).Elem()
691 value.SetInt(n.Int64)
692 return value
693 }
694 s.errorf("expected integer; found %s", n)
695 panic("not reached")
696}
697
698func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
699 s.at(n)
700 if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
701 value := reflect.New(typ).Elem()
702 value.SetUint(n.Uint64)
703 return value
704 }
705 s.errorf("expected unsigned integer; found %s", n)
706 panic("not reached")
707}
708
709func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
710 s.at(n)
711 if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
712 value := reflect.New(typ).Elem()
713 value.SetFloat(n.Float64)
714 return value
715 }
716 s.errorf("expected float; found %s", n)
717 panic("not reached")
718}
719
720func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
721 if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
722 value := reflect.New(typ).Elem()
723 value.SetComplex(n.Complex128)
724 return value
725 }
726 s.errorf("expected complex; found %s", n)
727 panic("not reached")
728}
729
730func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
731 s.at(n)
732 switch n := n.(type) {
733 case *parse.BoolNode:
734 return reflect.ValueOf(n.True)
735 case *parse.DotNode:
736 return dot
737 case *parse.FieldNode:
738 return s.evalFieldNode(dot, n, nil, zero)
739 case *parse.IdentifierNode:
740 return s.evalFunction(dot, n, n, nil, zero)
741 case *parse.NilNode:
742 // NilNode is handled in evalArg, the only place that calls here.
743 s.errorf("evalEmptyInterface: nil (can't happen)")
744 case *parse.NumberNode:
745 return s.idealConstant(n)
746 case *parse.StringNode:
747 return reflect.ValueOf(n.Text)
748 case *parse.VariableNode:
749 return s.evalVariableNode(dot, n, nil, zero)
750 case *parse.PipeNode:
751 return s.evalPipeline(dot, n)
752 }
753 s.errorf("can't handle assignment of %s to empty interface argument", n)
754 panic("not reached")
755}
756
757// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
758// We indirect through pointers and empty interfaces (only) because
759// non-empty interfaces have methods we might need.
760func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
761 for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
762 if v.IsNil() {
763 return v, true
764 }
765 if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
766 break
767 }
768 }
769 return v, false
770}
771
772// printValue writes the textual representation of the value to the output of
773// the template.
774func (s *state) printValue(n parse.Node, v reflect.Value) {
775 s.at(n)
776 iface, ok := printableValue(v)
777 if !ok {
778 s.errorf("can't print %s of type %s", n, v.Type())
779 }
780 fmt.Fprint(s.wr, iface)
781}
782
783// printableValue returns the, possibly indirected, interface value inside v that
784// is best for a call to formatted printer.
785func printableValue(v reflect.Value) (interface{}, bool) {
786 if v.Kind() == reflect.Ptr {
787 v, _ = indirect(v) // fmt.Fprint handles nil.
788 }
789 if !v.IsValid() {
790 return "<no value>", true
791 }
792
793 if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
794 if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
795 v = v.Addr()
796 } else {
797 switch v.Kind() {
798 case reflect.Chan, reflect.Func:
799 return nil, false
800 }
801 }
802 }
803 return v.Interface(), true
804}
805
806// Types to help sort the keys in a map for reproducible output.
807
808type rvs []reflect.Value
809
810func (x rvs) Len() int { return len(x) }
811func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
812
813type rvInts struct{ rvs }
814
815func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() }
816
817type rvUints struct{ rvs }
818
819func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() }
820
821type rvFloats struct{ rvs }
822
823func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() }
824
825type rvStrings struct{ rvs }
826
827func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() }
828
829// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys.
830func sortKeys(v []reflect.Value) []reflect.Value {
831 if len(v) <= 1 {
832 return v
833 }
834 switch v[0].Kind() {
835 case reflect.Float32, reflect.Float64:
836 sort.Sort(rvFloats{v})
837 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
838 sort.Sort(rvInts{v})
839 case reflect.String:
840 sort.Sort(rvStrings{v})
841 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
842 sort.Sort(rvUints{v})
843 }
844 return v
845}
diff --git a/vendor/github.com/alecthomas/template/funcs.go b/vendor/github.com/alecthomas/template/funcs.go
new file mode 100644
index 0000000..39ee5ed
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/funcs.go
@@ -0,0 +1,598 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package template
6
7import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "net/url"
13 "reflect"
14 "strings"
15 "unicode"
16 "unicode/utf8"
17)
18
19// FuncMap is the type of the map defining the mapping from names to functions.
20// Each function must have either a single return value, or two return values of
21// which the second has type error. In that case, if the second (error)
22// return value evaluates to non-nil during execution, execution terminates and
23// Execute returns that error.
24type FuncMap map[string]interface{}
25
26var builtins = FuncMap{
27 "and": and,
28 "call": call,
29 "html": HTMLEscaper,
30 "index": index,
31 "js": JSEscaper,
32 "len": length,
33 "not": not,
34 "or": or,
35 "print": fmt.Sprint,
36 "printf": fmt.Sprintf,
37 "println": fmt.Sprintln,
38 "urlquery": URLQueryEscaper,
39
40 // Comparisons
41 "eq": eq, // ==
42 "ge": ge, // >=
43 "gt": gt, // >
44 "le": le, // <=
45 "lt": lt, // <
46 "ne": ne, // !=
47}
48
49var builtinFuncs = createValueFuncs(builtins)
50
51// createValueFuncs turns a FuncMap into a map[string]reflect.Value
52func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
53 m := make(map[string]reflect.Value)
54 addValueFuncs(m, funcMap)
55 return m
56}
57
58// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
59func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
60 for name, fn := range in {
61 v := reflect.ValueOf(fn)
62 if v.Kind() != reflect.Func {
63 panic("value for " + name + " not a function")
64 }
65 if !goodFunc(v.Type()) {
66 panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
67 }
68 out[name] = v
69 }
70}
71
72// addFuncs adds to values the functions in funcs. It does no checking of the input -
73// call addValueFuncs first.
74func addFuncs(out, in FuncMap) {
75 for name, fn := range in {
76 out[name] = fn
77 }
78}
79
80// goodFunc checks that the function or method has the right result signature.
81func goodFunc(typ reflect.Type) bool {
82 // We allow functions with 1 result or 2 results where the second is an error.
83 switch {
84 case typ.NumOut() == 1:
85 return true
86 case typ.NumOut() == 2 && typ.Out(1) == errorType:
87 return true
88 }
89 return false
90}
91
92// findFunction looks for a function in the template, and global map.
93func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
94 if tmpl != nil && tmpl.common != nil {
95 if fn := tmpl.execFuncs[name]; fn.IsValid() {
96 return fn, true
97 }
98 }
99 if fn := builtinFuncs[name]; fn.IsValid() {
100 return fn, true
101 }
102 return reflect.Value{}, false
103}
104
105// Indexing.
106
107// index returns the result of indexing its first argument by the following
108// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
109// indexed item must be a map, slice, or array.
110func index(item interface{}, indices ...interface{}) (interface{}, error) {
111 v := reflect.ValueOf(item)
112 for _, i := range indices {
113 index := reflect.ValueOf(i)
114 var isNil bool
115 if v, isNil = indirect(v); isNil {
116 return nil, fmt.Errorf("index of nil pointer")
117 }
118 switch v.Kind() {
119 case reflect.Array, reflect.Slice, reflect.String:
120 var x int64
121 switch index.Kind() {
122 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
123 x = index.Int()
124 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
125 x = int64(index.Uint())
126 default:
127 return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
128 }
129 if x < 0 || x >= int64(v.Len()) {
130 return nil, fmt.Errorf("index out of range: %d", x)
131 }
132 v = v.Index(int(x))
133 case reflect.Map:
134 if !index.IsValid() {
135 index = reflect.Zero(v.Type().Key())
136 }
137 if !index.Type().AssignableTo(v.Type().Key()) {
138 return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
139 }
140 if x := v.MapIndex(index); x.IsValid() {
141 v = x
142 } else {
143 v = reflect.Zero(v.Type().Elem())
144 }
145 default:
146 return nil, fmt.Errorf("can't index item of type %s", v.Type())
147 }
148 }
149 return v.Interface(), nil
150}
151
152// Length
153
154// length returns the length of the item, with an error if it has no defined length.
155func length(item interface{}) (int, error) {
156 v, isNil := indirect(reflect.ValueOf(item))
157 if isNil {
158 return 0, fmt.Errorf("len of nil pointer")
159 }
160 switch v.Kind() {
161 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
162 return v.Len(), nil
163 }
164 return 0, fmt.Errorf("len of type %s", v.Type())
165}
166
167// Function invocation
168
169// call returns the result of evaluating the first argument as a function.
170// The function must return 1 result, or 2 results, the second of which is an error.
171func call(fn interface{}, args ...interface{}) (interface{}, error) {
172 v := reflect.ValueOf(fn)
173 typ := v.Type()
174 if typ.Kind() != reflect.Func {
175 return nil, fmt.Errorf("non-function of type %s", typ)
176 }
177 if !goodFunc(typ) {
178 return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
179 }
180 numIn := typ.NumIn()
181 var dddType reflect.Type
182 if typ.IsVariadic() {
183 if len(args) < numIn-1 {
184 return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
185 }
186 dddType = typ.In(numIn - 1).Elem()
187 } else {
188 if len(args) != numIn {
189 return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
190 }
191 }
192 argv := make([]reflect.Value, len(args))
193 for i, arg := range args {
194 value := reflect.ValueOf(arg)
195 // Compute the expected type. Clumsy because of variadics.
196 var argType reflect.Type
197 if !typ.IsVariadic() || i < numIn-1 {
198 argType = typ.In(i)
199 } else {
200 argType = dddType
201 }
202 if !value.IsValid() && canBeNil(argType) {
203 value = reflect.Zero(argType)
204 }
205 if !value.Type().AssignableTo(argType) {
206 return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
207 }
208 argv[i] = value
209 }
210 result := v.Call(argv)
211 if len(result) == 2 && !result[1].IsNil() {
212 return result[0].Interface(), result[1].Interface().(error)
213 }
214 return result[0].Interface(), nil
215}
216
217// Boolean logic.
218
219func truth(a interface{}) bool {
220 t, _ := isTrue(reflect.ValueOf(a))
221 return t
222}
223
224// and computes the Boolean AND of its arguments, returning
225// the first false argument it encounters, or the last argument.
226func and(arg0 interface{}, args ...interface{}) interface{} {
227 if !truth(arg0) {
228 return arg0
229 }
230 for i := range args {
231 arg0 = args[i]
232 if !truth(arg0) {
233 break
234 }
235 }
236 return arg0
237}
238
239// or computes the Boolean OR of its arguments, returning
240// the first true argument it encounters, or the last argument.
241func or(arg0 interface{}, args ...interface{}) interface{} {
242 if truth(arg0) {
243 return arg0
244 }
245 for i := range args {
246 arg0 = args[i]
247 if truth(arg0) {
248 break
249 }
250 }
251 return arg0
252}
253
254// not returns the Boolean negation of its argument.
255func not(arg interface{}) (truth bool) {
256 truth, _ = isTrue(reflect.ValueOf(arg))
257 return !truth
258}
259
260// Comparison.
261
262// TODO: Perhaps allow comparison between signed and unsigned integers.
263
264var (
265 errBadComparisonType = errors.New("invalid type for comparison")
266 errBadComparison = errors.New("incompatible types for comparison")
267 errNoComparison = errors.New("missing argument for comparison")
268)
269
270type kind int
271
272const (
273 invalidKind kind = iota
274 boolKind
275 complexKind
276 intKind
277 floatKind
278 integerKind
279 stringKind
280 uintKind
281)
282
283func basicKind(v reflect.Value) (kind, error) {
284 switch v.Kind() {
285 case reflect.Bool:
286 return boolKind, nil
287 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
288 return intKind, nil
289 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
290 return uintKind, nil
291 case reflect.Float32, reflect.Float64:
292 return floatKind, nil
293 case reflect.Complex64, reflect.Complex128:
294 return complexKind, nil
295 case reflect.String:
296 return stringKind, nil
297 }
298 return invalidKind, errBadComparisonType
299}
300
301// eq evaluates the comparison a == b || a == c || ...
302func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
303 v1 := reflect.ValueOf(arg1)
304 k1, err := basicKind(v1)
305 if err != nil {
306 return false, err
307 }
308 if len(arg2) == 0 {
309 return false, errNoComparison
310 }
311 for _, arg := range arg2 {
312 v2 := reflect.ValueOf(arg)
313 k2, err := basicKind(v2)
314 if err != nil {
315 return false, err
316 }
317 truth := false
318 if k1 != k2 {
319 // Special case: Can compare integer values regardless of type's sign.
320 switch {
321 case k1 == intKind && k2 == uintKind:
322 truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
323 case k1 == uintKind && k2 == intKind:
324 truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
325 default:
326 return false, errBadComparison
327 }
328 } else {
329 switch k1 {
330 case boolKind:
331 truth = v1.Bool() == v2.Bool()
332 case complexKind:
333 truth = v1.Complex() == v2.Complex()
334 case floatKind:
335 truth = v1.Float() == v2.Float()
336 case intKind:
337 truth = v1.Int() == v2.Int()
338 case stringKind:
339 truth = v1.String() == v2.String()
340 case uintKind:
341 truth = v1.Uint() == v2.Uint()
342 default:
343 panic("invalid kind")
344 }
345 }
346 if truth {
347 return true, nil
348 }
349 }
350 return false, nil
351}
352
353// ne evaluates the comparison a != b.
354func ne(arg1, arg2 interface{}) (bool, error) {
355 // != is the inverse of ==.
356 equal, err := eq(arg1, arg2)
357 return !equal, err
358}
359
360// lt evaluates the comparison a < b.
361func lt(arg1, arg2 interface{}) (bool, error) {
362 v1 := reflect.ValueOf(arg1)
363 k1, err := basicKind(v1)
364 if err != nil {
365 return false, err
366 }
367 v2 := reflect.ValueOf(arg2)
368 k2, err := basicKind(v2)
369 if err != nil {
370 return false, err
371 }
372 truth := false
373 if k1 != k2 {
374 // Special case: Can compare integer values regardless of type's sign.
375 switch {
376 case k1 == intKind && k2 == uintKind:
377 truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
378 case k1 == uintKind && k2 == intKind:
379 truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
380 default:
381 return false, errBadComparison
382 }
383 } else {
384 switch k1 {
385 case boolKind, complexKind:
386 return false, errBadComparisonType
387 case floatKind:
388 truth = v1.Float() < v2.Float()
389 case intKind:
390 truth = v1.Int() < v2.Int()
391 case stringKind:
392 truth = v1.String() < v2.String()
393 case uintKind:
394 truth = v1.Uint() < v2.Uint()
395 default:
396 panic("invalid kind")
397 }
398 }
399 return truth, nil
400}
401
402// le evaluates the comparison <= b.
403func le(arg1, arg2 interface{}) (bool, error) {
404 // <= is < or ==.
405 lessThan, err := lt(arg1, arg2)
406 if lessThan || err != nil {
407 return lessThan, err
408 }
409 return eq(arg1, arg2)
410}
411
412// gt evaluates the comparison a > b.
413func gt(arg1, arg2 interface{}) (bool, error) {
414 // > is the inverse of <=.
415 lessOrEqual, err := le(arg1, arg2)
416 if err != nil {
417 return false, err
418 }
419 return !lessOrEqual, nil
420}
421
422// ge evaluates the comparison a >= b.
423func ge(arg1, arg2 interface{}) (bool, error) {
424 // >= is the inverse of <.
425 lessThan, err := lt(arg1, arg2)
426 if err != nil {
427 return false, err
428 }
429 return !lessThan, nil
430}
431
432// HTML escaping.
433
434var (
435 htmlQuot = []byte("&#34;") // shorter than "&quot;"
436 htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
437 htmlAmp = []byte("&amp;")
438 htmlLt = []byte("&lt;")
439 htmlGt = []byte("&gt;")
440)
441
442// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
443func HTMLEscape(w io.Writer, b []byte) {
444 last := 0
445 for i, c := range b {
446 var html []byte
447 switch c {
448 case '"':
449 html = htmlQuot
450 case '\'':
451 html = htmlApos
452 case '&':
453 html = htmlAmp
454 case '<':
455 html = htmlLt
456 case '>':
457 html = htmlGt
458 default:
459 continue
460 }
461 w.Write(b[last:i])
462 w.Write(html)
463 last = i + 1
464 }
465 w.Write(b[last:])
466}
467
468// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
469func HTMLEscapeString(s string) string {
470 // Avoid allocation if we can.
471 if strings.IndexAny(s, `'"&<>`) < 0 {
472 return s
473 }
474 var b bytes.Buffer
475 HTMLEscape(&b, []byte(s))
476 return b.String()
477}
478
479// HTMLEscaper returns the escaped HTML equivalent of the textual
480// representation of its arguments.
481func HTMLEscaper(args ...interface{}) string {
482 return HTMLEscapeString(evalArgs(args))
483}
484
485// JavaScript escaping.
486
487var (
488 jsLowUni = []byte(`\u00`)
489 hex = []byte("0123456789ABCDEF")
490
491 jsBackslash = []byte(`\\`)
492 jsApos = []byte(`\'`)
493 jsQuot = []byte(`\"`)
494 jsLt = []byte(`\x3C`)
495 jsGt = []byte(`\x3E`)
496)
497
498// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
499func JSEscape(w io.Writer, b []byte) {
500 last := 0
501 for i := 0; i < len(b); i++ {
502 c := b[i]
503
504 if !jsIsSpecial(rune(c)) {
505 // fast path: nothing to do
506 continue
507 }
508 w.Write(b[last:i])
509
510 if c < utf8.RuneSelf {
511 // Quotes, slashes and angle brackets get quoted.
512 // Control characters get written as \u00XX.
513 switch c {
514 case '\\':
515 w.Write(jsBackslash)
516 case '\'':
517 w.Write(jsApos)
518 case '"':
519 w.Write(jsQuot)
520 case '<':
521 w.Write(jsLt)
522 case '>':
523 w.Write(jsGt)
524 default:
525 w.Write(jsLowUni)
526 t, b := c>>4, c&0x0f
527 w.Write(hex[t : t+1])
528 w.Write(hex[b : b+1])
529 }
530 } else {
531 // Unicode rune.
532 r, size := utf8.DecodeRune(b[i:])
533 if unicode.IsPrint(r) {
534 w.Write(b[i : i+size])
535 } else {
536 fmt.Fprintf(w, "\\u%04X", r)
537 }
538 i += size - 1
539 }
540 last = i + 1
541 }
542 w.Write(b[last:])
543}
544
545// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
546func JSEscapeString(s string) string {
547 // Avoid allocation if we can.
548 if strings.IndexFunc(s, jsIsSpecial) < 0 {
549 return s
550 }
551 var b bytes.Buffer
552 JSEscape(&b, []byte(s))
553 return b.String()
554}
555
556func jsIsSpecial(r rune) bool {
557 switch r {
558 case '\\', '\'', '"', '<', '>':
559 return true
560 }
561 return r < ' ' || utf8.RuneSelf <= r
562}
563
564// JSEscaper returns the escaped JavaScript equivalent of the textual
565// representation of its arguments.
566func JSEscaper(args ...interface{}) string {
567 return JSEscapeString(evalArgs(args))
568}
569
570// URLQueryEscaper returns the escaped value of the textual representation of
571// its arguments in a form suitable for embedding in a URL query.
572func URLQueryEscaper(args ...interface{}) string {
573 return url.QueryEscape(evalArgs(args))
574}
575
576// evalArgs formats the list of arguments into a string. It is therefore equivalent to
577// fmt.Sprint(args...)
578// except that each argument is indirected (if a pointer), as required,
579// using the same rules as the default string evaluation during template
580// execution.
581func evalArgs(args []interface{}) string {
582 ok := false
583 var s string
584 // Fast path for simple common case.
585 if len(args) == 1 {
586 s, ok = args[0].(string)
587 }
588 if !ok {
589 for i, arg := range args {
590 a, ok := printableValue(reflect.ValueOf(arg))
591 if ok {
592 args[i] = a
593 } // else left fmt do its thing
594 }
595 s = fmt.Sprint(args...)
596 }
597 return s
598}
diff --git a/vendor/github.com/alecthomas/template/helper.go b/vendor/github.com/alecthomas/template/helper.go
new file mode 100644
index 0000000..3636fb5
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/helper.go
@@ -0,0 +1,108 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Helper functions to make constructing templates easier.
6
7package template
8
9import (
10 "fmt"
11 "io/ioutil"
12 "path/filepath"
13)
14
15// Functions and methods to parse templates.
16
17// Must is a helper that wraps a call to a function returning (*Template, error)
18// and panics if the error is non-nil. It is intended for use in variable
19// initializations such as
20// var t = template.Must(template.New("name").Parse("text"))
21func Must(t *Template, err error) *Template {
22 if err != nil {
23 panic(err)
24 }
25 return t
26}
27
28// ParseFiles creates a new Template and parses the template definitions from
29// the named files. The returned template's name will have the (base) name and
30// (parsed) contents of the first file. There must be at least one file.
31// If an error occurs, parsing stops and the returned *Template is nil.
32func ParseFiles(filenames ...string) (*Template, error) {
33 return parseFiles(nil, filenames...)
34}
35
36// ParseFiles parses the named files and associates the resulting templates with
37// t. If an error occurs, parsing stops and the returned template is nil;
38// otherwise it is t. There must be at least one file.
39func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
40 return parseFiles(t, filenames...)
41}
42
43// parseFiles is the helper for the method and function. If the argument
44// template is nil, it is created from the first file.
45func parseFiles(t *Template, filenames ...string) (*Template, error) {
46 if len(filenames) == 0 {
47 // Not really a problem, but be consistent.
48 return nil, fmt.Errorf("template: no files named in call to ParseFiles")
49 }
50 for _, filename := range filenames {
51 b, err := ioutil.ReadFile(filename)
52 if err != nil {
53 return nil, err
54 }
55 s := string(b)
56 name := filepath.Base(filename)
57 // First template becomes return value if not already defined,
58 // and we use that one for subsequent New calls to associate
59 // all the templates together. Also, if this file has the same name
60 // as t, this file becomes the contents of t, so
61 // t, err := New(name).Funcs(xxx).ParseFiles(name)
62 // works. Otherwise we create a new template associated with t.
63 var tmpl *Template
64 if t == nil {
65 t = New(name)
66 }
67 if name == t.Name() {
68 tmpl = t
69 } else {
70 tmpl = t.New(name)
71 }
72 _, err = tmpl.Parse(s)
73 if err != nil {
74 return nil, err
75 }
76 }
77 return t, nil
78}
79
80// ParseGlob creates a new Template and parses the template definitions from the
81// files identified by the pattern, which must match at least one file. The
82// returned template will have the (base) name and (parsed) contents of the
83// first file matched by the pattern. ParseGlob is equivalent to calling
84// ParseFiles with the list of files matched by the pattern.
85func ParseGlob(pattern string) (*Template, error) {
86 return parseGlob(nil, pattern)
87}
88
89// ParseGlob parses the template definitions in the files identified by the
90// pattern and associates the resulting templates with t. The pattern is
91// processed by filepath.Glob and must match at least one file. ParseGlob is
92// equivalent to calling t.ParseFiles with the list of files matched by the
93// pattern.
94func (t *Template) ParseGlob(pattern string) (*Template, error) {
95 return parseGlob(t, pattern)
96}
97
98// parseGlob is the implementation of the function and method ParseGlob.
99func parseGlob(t *Template, pattern string) (*Template, error) {
100 filenames, err := filepath.Glob(pattern)
101 if err != nil {
102 return nil, err
103 }
104 if len(filenames) == 0 {
105 return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
106 }
107 return parseFiles(t, filenames...)
108}
diff --git a/vendor/github.com/alecthomas/template/parse/lex.go b/vendor/github.com/alecthomas/template/parse/lex.go
new file mode 100644
index 0000000..55f1c05
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/parse/lex.go
@@ -0,0 +1,556 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package parse
6
7import (
8 "fmt"
9 "strings"
10 "unicode"
11 "unicode/utf8"
12)
13
14// item represents a token or text string returned from the scanner.
15type item struct {
16 typ itemType // The type of this item.
17 pos Pos // The starting position, in bytes, of this item in the input string.
18 val string // The value of this item.
19}
20
21func (i item) String() string {
22 switch {
23 case i.typ == itemEOF:
24 return "EOF"
25 case i.typ == itemError:
26 return i.val
27 case i.typ > itemKeyword:
28 return fmt.Sprintf("<%s>", i.val)
29 case len(i.val) > 10:
30 return fmt.Sprintf("%.10q...", i.val)
31 }
32 return fmt.Sprintf("%q", i.val)
33}
34
35// itemType identifies the type of lex items.
36type itemType int
37
38const (
39 itemError itemType = iota // error occurred; value is text of error
40 itemBool // boolean constant
41 itemChar // printable ASCII character; grab bag for comma etc.
42 itemCharConstant // character constant
43 itemComplex // complex constant (1+2i); imaginary is just a number
44 itemColonEquals // colon-equals (':=') introducing a declaration
45 itemEOF
46 itemField // alphanumeric identifier starting with '.'
47 itemIdentifier // alphanumeric identifier not starting with '.'
48 itemLeftDelim // left action delimiter
49 itemLeftParen // '(' inside action
50 itemNumber // simple number, including imaginary
51 itemPipe // pipe symbol
52 itemRawString // raw quoted string (includes quotes)
53 itemRightDelim // right action delimiter
54 itemElideNewline // elide newline after right delim
55 itemRightParen // ')' inside action
56 itemSpace // run of spaces separating arguments
57 itemString // quoted string (includes quotes)
58 itemText // plain text
59 itemVariable // variable starting with '$', such as '$' or '$1' or '$hello'
60 // Keywords appear after all the rest.
61 itemKeyword // used only to delimit the keywords
62 itemDot // the cursor, spelled '.'
63 itemDefine // define keyword
64 itemElse // else keyword
65 itemEnd // end keyword
66 itemIf // if keyword
67 itemNil // the untyped nil constant, easiest to treat as a keyword
68 itemRange // range keyword
69 itemTemplate // template keyword
70 itemWith // with keyword
71)
72
73var key = map[string]itemType{
74 ".": itemDot,
75 "define": itemDefine,
76 "else": itemElse,
77 "end": itemEnd,
78 "if": itemIf,
79 "range": itemRange,
80 "nil": itemNil,
81 "template": itemTemplate,
82 "with": itemWith,
83}
84
85const eof = -1
86
87// stateFn represents the state of the scanner as a function that returns the next state.
88type stateFn func(*lexer) stateFn
89
90// lexer holds the state of the scanner.
91type lexer struct {
92 name string // the name of the input; used only for error reports
93 input string // the string being scanned
94 leftDelim string // start of action
95 rightDelim string // end of action
96 state stateFn // the next lexing function to enter
97 pos Pos // current position in the input
98 start Pos // start position of this item
99 width Pos // width of last rune read from input
100 lastPos Pos // position of most recent item returned by nextItem
101 items chan item // channel of scanned items
102 parenDepth int // nesting depth of ( ) exprs
103}
104
105// next returns the next rune in the input.
106func (l *lexer) next() rune {
107 if int(l.pos) >= len(l.input) {
108 l.width = 0
109 return eof
110 }
111 r, w := utf8.DecodeRuneInString(l.input[l.pos:])
112 l.width = Pos(w)
113 l.pos += l.width
114 return r
115}
116
117// peek returns but does not consume the next rune in the input.
118func (l *lexer) peek() rune {
119 r := l.next()
120 l.backup()
121 return r
122}
123
124// backup steps back one rune. Can only be called once per call of next.
125func (l *lexer) backup() {
126 l.pos -= l.width
127}
128
129// emit passes an item back to the client.
130func (l *lexer) emit(t itemType) {
131 l.items <- item{t, l.start, l.input[l.start:l.pos]}
132 l.start = l.pos
133}
134
135// ignore skips over the pending input before this point.
136func (l *lexer) ignore() {
137 l.start = l.pos
138}
139
140// accept consumes the next rune if it's from the valid set.
141func (l *lexer) accept(valid string) bool {
142 if strings.IndexRune(valid, l.next()) >= 0 {
143 return true
144 }
145 l.backup()
146 return false
147}
148
149// acceptRun consumes a run of runes from the valid set.
150func (l *lexer) acceptRun(valid string) {
151 for strings.IndexRune(valid, l.next()) >= 0 {
152 }
153 l.backup()
154}
155
156// lineNumber reports which line we're on, based on the position of
157// the previous item returned by nextItem. Doing it this way
158// means we don't have to worry about peek double counting.
159func (l *lexer) lineNumber() int {
160 return 1 + strings.Count(l.input[:l.lastPos], "\n")
161}
162
163// errorf returns an error token and terminates the scan by passing
164// back a nil pointer that will be the next state, terminating l.nextItem.
165func (l *lexer) errorf(format string, args ...interface{}) stateFn {
166 l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
167 return nil
168}
169
170// nextItem returns the next item from the input.
171func (l *lexer) nextItem() item {
172 item := <-l.items
173 l.lastPos = item.pos
174 return item
175}
176
177// lex creates a new scanner for the input string.
178func lex(name, input, left, right string) *lexer {
179 if left == "" {
180 left = leftDelim
181 }
182 if right == "" {
183 right = rightDelim
184 }
185 l := &lexer{
186 name: name,
187 input: input,
188 leftDelim: left,
189 rightDelim: right,
190 items: make(chan item),
191 }
192 go l.run()
193 return l
194}
195
196// run runs the state machine for the lexer.
197func (l *lexer) run() {
198 for l.state = lexText; l.state != nil; {
199 l.state = l.state(l)
200 }
201}
202
203// state functions
204
205const (
206 leftDelim = "{{"
207 rightDelim = "}}"
208 leftComment = "/*"
209 rightComment = "*/"
210)
211
212// lexText scans until an opening action delimiter, "{{".
213func lexText(l *lexer) stateFn {
214 for {
215 if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
216 if l.pos > l.start {
217 l.emit(itemText)
218 }
219 return lexLeftDelim
220 }
221 if l.next() == eof {
222 break
223 }
224 }
225 // Correctly reached EOF.
226 if l.pos > l.start {
227 l.emit(itemText)
228 }
229 l.emit(itemEOF)
230 return nil
231}
232
233// lexLeftDelim scans the left delimiter, which is known to be present.
234func lexLeftDelim(l *lexer) stateFn {
235 l.pos += Pos(len(l.leftDelim))
236 if strings.HasPrefix(l.input[l.pos:], leftComment) {
237 return lexComment
238 }
239 l.emit(itemLeftDelim)
240 l.parenDepth = 0
241 return lexInsideAction
242}
243
244// lexComment scans a comment. The left comment marker is known to be present.
245func lexComment(l *lexer) stateFn {
246 l.pos += Pos(len(leftComment))
247 i := strings.Index(l.input[l.pos:], rightComment)
248 if i < 0 {
249 return l.errorf("unclosed comment")
250 }
251 l.pos += Pos(i + len(rightComment))
252 if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
253 return l.errorf("comment ends before closing delimiter")
254
255 }
256 l.pos += Pos(len(l.rightDelim))
257 l.ignore()
258 return lexText
259}
260
261// lexRightDelim scans the right delimiter, which is known to be present.
262func lexRightDelim(l *lexer) stateFn {
263 l.pos += Pos(len(l.rightDelim))
264 l.emit(itemRightDelim)
265 if l.peek() == '\\' {
266 l.pos++
267 l.emit(itemElideNewline)
268 }
269 return lexText
270}
271
272// lexInsideAction scans the elements inside action delimiters.
273func lexInsideAction(l *lexer) stateFn {
274 // Either number, quoted string, or identifier.
275 // Spaces separate arguments; runs of spaces turn into itemSpace.
276 // Pipe symbols separate and are emitted.
277 if strings.HasPrefix(l.input[l.pos:], l.rightDelim+"\\") || strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
278 if l.parenDepth == 0 {
279 return lexRightDelim
280 }
281 return l.errorf("unclosed left paren")
282 }
283 switch r := l.next(); {
284 case r == eof || isEndOfLine(r):
285 return l.errorf("unclosed action")
286 case isSpace(r):
287 return lexSpace
288 case r == ':':
289 if l.next() != '=' {
290 return l.errorf("expected :=")
291 }
292 l.emit(itemColonEquals)
293 case r == '|':
294 l.emit(itemPipe)
295 case r == '"':
296 return lexQuote
297 case r == '`':
298 return lexRawQuote
299 case r == '$':
300 return lexVariable
301 case r == '\'':
302 return lexChar
303 case r == '.':
304 // special look-ahead for ".field" so we don't break l.backup().
305 if l.pos < Pos(len(l.input)) {
306 r := l.input[l.pos]
307 if r < '0' || '9' < r {
308 return lexField
309 }
310 }
311 fallthrough // '.' can start a number.
312 case r == '+' || r == '-' || ('0' <= r && r <= '9'):
313 l.backup()
314 return lexNumber
315 case isAlphaNumeric(r):
316 l.backup()
317 return lexIdentifier
318 case r == '(':
319 l.emit(itemLeftParen)
320 l.parenDepth++
321 return lexInsideAction
322 case r == ')':
323 l.emit(itemRightParen)
324 l.parenDepth--
325 if l.parenDepth < 0 {
326 return l.errorf("unexpected right paren %#U", r)
327 }
328 return lexInsideAction
329 case r <= unicode.MaxASCII && unicode.IsPrint(r):
330 l.emit(itemChar)
331 return lexInsideAction
332 default:
333 return l.errorf("unrecognized character in action: %#U", r)
334 }
335 return lexInsideAction
336}
337
338// lexSpace scans a run of space characters.
339// One space has already been seen.
340func lexSpace(l *lexer) stateFn {
341 for isSpace(l.peek()) {
342 l.next()
343 }
344 l.emit(itemSpace)
345 return lexInsideAction
346}
347
348// lexIdentifier scans an alphanumeric.
349func lexIdentifier(l *lexer) stateFn {
350Loop:
351 for {
352 switch r := l.next(); {
353 case isAlphaNumeric(r):
354 // absorb.
355 default:
356 l.backup()
357 word := l.input[l.start:l.pos]
358 if !l.atTerminator() {
359 return l.errorf("bad character %#U", r)
360 }
361 switch {
362 case key[word] > itemKeyword:
363 l.emit(key[word])
364 case word[0] == '.':
365 l.emit(itemField)
366 case word == "true", word == "false":
367 l.emit(itemBool)
368 default:
369 l.emit(itemIdentifier)
370 }
371 break Loop
372 }
373 }
374 return lexInsideAction
375}
376
377// lexField scans a field: .Alphanumeric.
378// The . has been scanned.
379func lexField(l *lexer) stateFn {
380 return lexFieldOrVariable(l, itemField)
381}
382
383// lexVariable scans a Variable: $Alphanumeric.
384// The $ has been scanned.
385func lexVariable(l *lexer) stateFn {
386 if l.atTerminator() { // Nothing interesting follows -> "$".
387 l.emit(itemVariable)
388 return lexInsideAction
389 }
390 return lexFieldOrVariable(l, itemVariable)
391}
392
393// lexVariable scans a field or variable: [.$]Alphanumeric.
394// The . or $ has been scanned.
395func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
396 if l.atTerminator() { // Nothing interesting follows -> "." or "$".
397 if typ == itemVariable {
398 l.emit(itemVariable)
399 } else {
400 l.emit(itemDot)
401 }
402 return lexInsideAction
403 }
404 var r rune
405 for {
406 r = l.next()
407 if !isAlphaNumeric(r) {
408 l.backup()
409 break
410 }
411 }
412 if !l.atTerminator() {
413 return l.errorf("bad character %#U", r)
414 }
415 l.emit(typ)
416 return lexInsideAction
417}
418
419// atTerminator reports whether the input is at valid termination character to
420// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
421// like "$x+2" not being acceptable without a space, in case we decide one
422// day to implement arithmetic.
423func (l *lexer) atTerminator() bool {
424 r := l.peek()
425 if isSpace(r) || isEndOfLine(r) {
426 return true
427 }
428 switch r {
429 case eof, '.', ',', '|', ':', ')', '(':
430 return true
431 }
432 // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
433 // succeed but should fail) but only in extremely rare cases caused by willfully
434 // bad choice of delimiter.
435 if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
436 return true
437 }
438 return false
439}
440
441// lexChar scans a character constant. The initial quote is already
442// scanned. Syntax checking is done by the parser.
443func lexChar(l *lexer) stateFn {
444Loop:
445 for {
446 switch l.next() {
447 case '\\':
448 if r := l.next(); r != eof && r != '\n' {
449 break
450 }
451 fallthrough
452 case eof, '\n':
453 return l.errorf("unterminated character constant")
454 case '\'':
455 break Loop
456 }
457 }
458 l.emit(itemCharConstant)
459 return lexInsideAction
460}
461
462// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
463// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
464// and "089" - but when it's wrong the input is invalid and the parser (via
465// strconv) will notice.
466func lexNumber(l *lexer) stateFn {
467 if !l.scanNumber() {
468 return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
469 }
470 if sign := l.peek(); sign == '+' || sign == '-' {
471 // Complex: 1+2i. No spaces, must end in 'i'.
472 if !l.scanNumber() || l.input[l.pos-1] != 'i' {
473 return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
474 }
475 l.emit(itemComplex)
476 } else {
477 l.emit(itemNumber)
478 }
479 return lexInsideAction
480}
481
482func (l *lexer) scanNumber() bool {
483 // Optional leading sign.
484 l.accept("+-")
485 // Is it hex?
486 digits := "0123456789"
487 if l.accept("0") && l.accept("xX") {
488 digits = "0123456789abcdefABCDEF"
489 }
490 l.acceptRun(digits)
491 if l.accept(".") {
492 l.acceptRun(digits)
493 }
494 if l.accept("eE") {
495 l.accept("+-")
496 l.acceptRun("0123456789")
497 }
498 // Is it imaginary?
499 l.accept("i")
500 // Next thing mustn't be alphanumeric.
501 if isAlphaNumeric(l.peek()) {
502 l.next()
503 return false
504 }
505 return true
506}
507
508// lexQuote scans a quoted string.
509func lexQuote(l *lexer) stateFn {
510Loop:
511 for {
512 switch l.next() {
513 case '\\':
514 if r := l.next(); r != eof && r != '\n' {
515 break
516 }
517 fallthrough
518 case eof, '\n':
519 return l.errorf("unterminated quoted string")
520 case '"':
521 break Loop
522 }
523 }
524 l.emit(itemString)
525 return lexInsideAction
526}
527
528// lexRawQuote scans a raw quoted string.
529func lexRawQuote(l *lexer) stateFn {
530Loop:
531 for {
532 switch l.next() {
533 case eof, '\n':
534 return l.errorf("unterminated raw quoted string")
535 case '`':
536 break Loop
537 }
538 }
539 l.emit(itemRawString)
540 return lexInsideAction
541}
542
543// isSpace reports whether r is a space character.
544func isSpace(r rune) bool {
545 return r == ' ' || r == '\t'
546}
547
548// isEndOfLine reports whether r is an end-of-line character.
549func isEndOfLine(r rune) bool {
550 return r == '\r' || r == '\n'
551}
552
553// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
554func isAlphaNumeric(r rune) bool {
555 return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
556}
diff --git a/vendor/github.com/alecthomas/template/parse/node.go b/vendor/github.com/alecthomas/template/parse/node.go
new file mode 100644
index 0000000..55c37f6
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/parse/node.go
@@ -0,0 +1,834 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Parse nodes.
6
7package parse
8
9import (
10 "bytes"
11 "fmt"
12 "strconv"
13 "strings"
14)
15
16var textFormat = "%s" // Changed to "%q" in tests for better error messages.
17
18// A Node is an element in the parse tree. The interface is trivial.
19// The interface contains an unexported method so that only
20// types local to this package can satisfy it.
21type Node interface {
22 Type() NodeType
23 String() string
24 // Copy does a deep copy of the Node and all its components.
25 // To avoid type assertions, some XxxNodes also have specialized
26 // CopyXxx methods that return *XxxNode.
27 Copy() Node
28 Position() Pos // byte position of start of node in full original input string
29 // tree returns the containing *Tree.
30 // It is unexported so all implementations of Node are in this package.
31 tree() *Tree
32}
33
34// NodeType identifies the type of a parse tree node.
35type NodeType int
36
37// Pos represents a byte position in the original input text from which
38// this template was parsed.
39type Pos int
40
41func (p Pos) Position() Pos {
42 return p
43}
44
45// Type returns itself and provides an easy default implementation
46// for embedding in a Node. Embedded in all non-trivial Nodes.
47func (t NodeType) Type() NodeType {
48 return t
49}
50
51const (
52 NodeText NodeType = iota // Plain text.
53 NodeAction // A non-control action such as a field evaluation.
54 NodeBool // A boolean constant.
55 NodeChain // A sequence of field accesses.
56 NodeCommand // An element of a pipeline.
57 NodeDot // The cursor, dot.
58 nodeElse // An else action. Not added to tree.
59 nodeEnd // An end action. Not added to tree.
60 NodeField // A field or method name.
61 NodeIdentifier // An identifier; always a function name.
62 NodeIf // An if action.
63 NodeList // A list of Nodes.
64 NodeNil // An untyped nil constant.
65 NodeNumber // A numerical constant.
66 NodePipe // A pipeline of commands.
67 NodeRange // A range action.
68 NodeString // A string constant.
69 NodeTemplate // A template invocation action.
70 NodeVariable // A $ variable.
71 NodeWith // A with action.
72)
73
74// Nodes.
75
76// ListNode holds a sequence of nodes.
77type ListNode struct {
78 NodeType
79 Pos
80 tr *Tree
81 Nodes []Node // The element nodes in lexical order.
82}
83
84func (t *Tree) newList(pos Pos) *ListNode {
85 return &ListNode{tr: t, NodeType: NodeList, Pos: pos}
86}
87
88func (l *ListNode) append(n Node) {
89 l.Nodes = append(l.Nodes, n)
90}
91
92func (l *ListNode) tree() *Tree {
93 return l.tr
94}
95
96func (l *ListNode) String() string {
97 b := new(bytes.Buffer)
98 for _, n := range l.Nodes {
99 fmt.Fprint(b, n)
100 }
101 return b.String()
102}
103
104func (l *ListNode) CopyList() *ListNode {
105 if l == nil {
106 return l
107 }
108 n := l.tr.newList(l.Pos)
109 for _, elem := range l.Nodes {
110 n.append(elem.Copy())
111 }
112 return n
113}
114
115func (l *ListNode) Copy() Node {
116 return l.CopyList()
117}
118
119// TextNode holds plain text.
120type TextNode struct {
121 NodeType
122 Pos
123 tr *Tree
124 Text []byte // The text; may span newlines.
125}
126
127func (t *Tree) newText(pos Pos, text string) *TextNode {
128 return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)}
129}
130
131func (t *TextNode) String() string {
132 return fmt.Sprintf(textFormat, t.Text)
133}
134
135func (t *TextNode) tree() *Tree {
136 return t.tr
137}
138
139func (t *TextNode) Copy() Node {
140 return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
141}
142
143// PipeNode holds a pipeline with optional declaration
144type PipeNode struct {
145 NodeType
146 Pos
147 tr *Tree
148 Line int // The line number in the input (deprecated; kept for compatibility)
149 Decl []*VariableNode // Variable declarations in lexical order.
150 Cmds []*CommandNode // The commands in lexical order.
151}
152
153func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
154 return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
155}
156
157func (p *PipeNode) append(command *CommandNode) {
158 p.Cmds = append(p.Cmds, command)
159}
160
161func (p *PipeNode) String() string {
162 s := ""
163 if len(p.Decl) > 0 {
164 for i, v := range p.Decl {
165 if i > 0 {
166 s += ", "
167 }
168 s += v.String()
169 }
170 s += " := "
171 }
172 for i, c := range p.Cmds {
173 if i > 0 {
174 s += " | "
175 }
176 s += c.String()
177 }
178 return s
179}
180
181func (p *PipeNode) tree() *Tree {
182 return p.tr
183}
184
185func (p *PipeNode) CopyPipe() *PipeNode {
186 if p == nil {
187 return p
188 }
189 var decl []*VariableNode
190 for _, d := range p.Decl {
191 decl = append(decl, d.Copy().(*VariableNode))
192 }
193 n := p.tr.newPipeline(p.Pos, p.Line, decl)
194 for _, c := range p.Cmds {
195 n.append(c.Copy().(*CommandNode))
196 }
197 return n
198}
199
200func (p *PipeNode) Copy() Node {
201 return p.CopyPipe()
202}
203
204// ActionNode holds an action (something bounded by delimiters).
205// Control actions have their own nodes; ActionNode represents simple
206// ones such as field evaluations and parenthesized pipelines.
207type ActionNode struct {
208 NodeType
209 Pos
210 tr *Tree
211 Line int // The line number in the input (deprecated; kept for compatibility)
212 Pipe *PipeNode // The pipeline in the action.
213}
214
215func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
216 return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
217}
218
219func (a *ActionNode) String() string {
220 return fmt.Sprintf("{{%s}}", a.Pipe)
221
222}
223
224func (a *ActionNode) tree() *Tree {
225 return a.tr
226}
227
228func (a *ActionNode) Copy() Node {
229 return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
230
231}
232
233// CommandNode holds a command (a pipeline inside an evaluating action).
234type CommandNode struct {
235 NodeType
236 Pos
237 tr *Tree
238 Args []Node // Arguments in lexical order: Identifier, field, or constant.
239}
240
241func (t *Tree) newCommand(pos Pos) *CommandNode {
242 return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos}
243}
244
245func (c *CommandNode) append(arg Node) {
246 c.Args = append(c.Args, arg)
247}
248
249func (c *CommandNode) String() string {
250 s := ""
251 for i, arg := range c.Args {
252 if i > 0 {
253 s += " "
254 }
255 if arg, ok := arg.(*PipeNode); ok {
256 s += "(" + arg.String() + ")"
257 continue
258 }
259 s += arg.String()
260 }
261 return s
262}
263
264func (c *CommandNode) tree() *Tree {
265 return c.tr
266}
267
268func (c *CommandNode) Copy() Node {
269 if c == nil {
270 return c
271 }
272 n := c.tr.newCommand(c.Pos)
273 for _, c := range c.Args {
274 n.append(c.Copy())
275 }
276 return n
277}
278
279// IdentifierNode holds an identifier.
280type IdentifierNode struct {
281 NodeType
282 Pos
283 tr *Tree
284 Ident string // The identifier's name.
285}
286
287// NewIdentifier returns a new IdentifierNode with the given identifier name.
288func NewIdentifier(ident string) *IdentifierNode {
289 return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
290}
291
292// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
293// Chained for convenience.
294// TODO: fix one day?
295func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
296 i.Pos = pos
297 return i
298}
299
300// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature.
301// Chained for convenience.
302// TODO: fix one day?
303func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode {
304 i.tr = t
305 return i
306}
307
308func (i *IdentifierNode) String() string {
309 return i.Ident
310}
311
312func (i *IdentifierNode) tree() *Tree {
313 return i.tr
314}
315
316func (i *IdentifierNode) Copy() Node {
317 return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
318}
319
320// VariableNode holds a list of variable names, possibly with chained field
321// accesses. The dollar sign is part of the (first) name.
322type VariableNode struct {
323 NodeType
324 Pos
325 tr *Tree
326 Ident []string // Variable name and fields in lexical order.
327}
328
329func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
330 return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
331}
332
333func (v *VariableNode) String() string {
334 s := ""
335 for i, id := range v.Ident {
336 if i > 0 {
337 s += "."
338 }
339 s += id
340 }
341 return s
342}
343
344func (v *VariableNode) tree() *Tree {
345 return v.tr
346}
347
348func (v *VariableNode) Copy() Node {
349 return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
350}
351
352// DotNode holds the special identifier '.'.
353type DotNode struct {
354 NodeType
355 Pos
356 tr *Tree
357}
358
359func (t *Tree) newDot(pos Pos) *DotNode {
360 return &DotNode{tr: t, NodeType: NodeDot, Pos: pos}
361}
362
363func (d *DotNode) Type() NodeType {
364 // Override method on embedded NodeType for API compatibility.
365 // TODO: Not really a problem; could change API without effect but
366 // api tool complains.
367 return NodeDot
368}
369
370func (d *DotNode) String() string {
371 return "."
372}
373
374func (d *DotNode) tree() *Tree {
375 return d.tr
376}
377
378func (d *DotNode) Copy() Node {
379 return d.tr.newDot(d.Pos)
380}
381
382// NilNode holds the special identifier 'nil' representing an untyped nil constant.
383type NilNode struct {
384 NodeType
385 Pos
386 tr *Tree
387}
388
389func (t *Tree) newNil(pos Pos) *NilNode {
390 return &NilNode{tr: t, NodeType: NodeNil, Pos: pos}
391}
392
393func (n *NilNode) Type() NodeType {
394 // Override method on embedded NodeType for API compatibility.
395 // TODO: Not really a problem; could change API without effect but
396 // api tool complains.
397 return NodeNil
398}
399
400func (n *NilNode) String() string {
401 return "nil"
402}
403
404func (n *NilNode) tree() *Tree {
405 return n.tr
406}
407
408func (n *NilNode) Copy() Node {
409 return n.tr.newNil(n.Pos)
410}
411
412// FieldNode holds a field (identifier starting with '.').
413// The names may be chained ('.x.y').
414// The period is dropped from each ident.
415type FieldNode struct {
416 NodeType
417 Pos
418 tr *Tree
419 Ident []string // The identifiers in lexical order.
420}
421
422func (t *Tree) newField(pos Pos, ident string) *FieldNode {
423 return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
424}
425
426func (f *FieldNode) String() string {
427 s := ""
428 for _, id := range f.Ident {
429 s += "." + id
430 }
431 return s
432}
433
434func (f *FieldNode) tree() *Tree {
435 return f.tr
436}
437
438func (f *FieldNode) Copy() Node {
439 return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
440}
441
442// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
443// The names may be chained ('.x.y').
444// The periods are dropped from each ident.
445type ChainNode struct {
446 NodeType
447 Pos
448 tr *Tree
449 Node Node
450 Field []string // The identifiers in lexical order.
451}
452
453func (t *Tree) newChain(pos Pos, node Node) *ChainNode {
454 return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node}
455}
456
457// Add adds the named field (which should start with a period) to the end of the chain.
458func (c *ChainNode) Add(field string) {
459 if len(field) == 0 || field[0] != '.' {
460 panic("no dot in field")
461 }
462 field = field[1:] // Remove leading dot.
463 if field == "" {
464 panic("empty field")
465 }
466 c.Field = append(c.Field, field)
467}
468
469func (c *ChainNode) String() string {
470 s := c.Node.String()
471 if _, ok := c.Node.(*PipeNode); ok {
472 s = "(" + s + ")"
473 }
474 for _, field := range c.Field {
475 s += "." + field
476 }
477 return s
478}
479
480func (c *ChainNode) tree() *Tree {
481 return c.tr
482}
483
484func (c *ChainNode) Copy() Node {
485 return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
486}
487
488// BoolNode holds a boolean constant.
489type BoolNode struct {
490 NodeType
491 Pos
492 tr *Tree
493 True bool // The value of the boolean constant.
494}
495
496func (t *Tree) newBool(pos Pos, true bool) *BoolNode {
497 return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true}
498}
499
500func (b *BoolNode) String() string {
501 if b.True {
502 return "true"
503 }
504 return "false"
505}
506
507func (b *BoolNode) tree() *Tree {
508 return b.tr
509}
510
511func (b *BoolNode) Copy() Node {
512 return b.tr.newBool(b.Pos, b.True)
513}
514
515// NumberNode holds a number: signed or unsigned integer, float, or complex.
516// The value is parsed and stored under all the types that can represent the value.
517// This simulates in a small amount of code the behavior of Go's ideal constants.
518type NumberNode struct {
519 NodeType
520 Pos
521 tr *Tree
522 IsInt bool // Number has an integral value.
523 IsUint bool // Number has an unsigned integral value.
524 IsFloat bool // Number has a floating-point value.
525 IsComplex bool // Number is complex.
526 Int64 int64 // The signed integer value.
527 Uint64 uint64 // The unsigned integer value.
528 Float64 float64 // The floating-point value.
529 Complex128 complex128 // The complex value.
530 Text string // The original textual representation from the input.
531}
532
533func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
534 n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text}
535 switch typ {
536 case itemCharConstant:
537 rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
538 if err != nil {
539 return nil, err
540 }
541 if tail != "'" {
542 return nil, fmt.Errorf("malformed character constant: %s", text)
543 }
544 n.Int64 = int64(rune)
545 n.IsInt = true
546 n.Uint64 = uint64(rune)
547 n.IsUint = true
548 n.Float64 = float64(rune) // odd but those are the rules.
549 n.IsFloat = true
550 return n, nil
551 case itemComplex:
552 // fmt.Sscan can parse the pair, so let it do the work.
553 if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
554 return nil, err
555 }
556 n.IsComplex = true
557 n.simplifyComplex()
558 return n, nil
559 }
560 // Imaginary constants can only be complex unless they are zero.
561 if len(text) > 0 && text[len(text)-1] == 'i' {
562 f, err := strconv.ParseFloat(text[:len(text)-1], 64)
563 if err == nil {
564 n.IsComplex = true
565 n.Complex128 = complex(0, f)
566 n.simplifyComplex()
567 return n, nil
568 }
569 }
570 // Do integer test first so we get 0x123 etc.
571 u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
572 if err == nil {
573 n.IsUint = true
574 n.Uint64 = u
575 }
576 i, err := strconv.ParseInt(text, 0, 64)
577 if err == nil {
578 n.IsInt = true
579 n.Int64 = i
580 if i == 0 {
581 n.IsUint = true // in case of -0.
582 n.Uint64 = u
583 }
584 }
585 // If an integer extraction succeeded, promote the float.
586 if n.IsInt {
587 n.IsFloat = true
588 n.Float64 = float64(n.Int64)
589 } else if n.IsUint {
590 n.IsFloat = true
591 n.Float64 = float64(n.Uint64)
592 } else {
593 f, err := strconv.ParseFloat(text, 64)
594 if err == nil {
595 n.IsFloat = true
596 n.Float64 = f
597 // If a floating-point extraction succeeded, extract the int if needed.
598 if !n.IsInt && float64(int64(f)) == f {
599 n.IsInt = true
600 n.Int64 = int64(f)
601 }
602 if !n.IsUint && float64(uint64(f)) == f {
603 n.IsUint = true
604 n.Uint64 = uint64(f)
605 }
606 }
607 }
608 if !n.IsInt && !n.IsUint && !n.IsFloat {
609 return nil, fmt.Errorf("illegal number syntax: %q", text)
610 }
611 return n, nil
612}
613
614// simplifyComplex pulls out any other types that are represented by the complex number.
615// These all require that the imaginary part be zero.
616func (n *NumberNode) simplifyComplex() {
617 n.IsFloat = imag(n.Complex128) == 0
618 if n.IsFloat {
619 n.Float64 = real(n.Complex128)
620 n.IsInt = float64(int64(n.Float64)) == n.Float64
621 if n.IsInt {
622 n.Int64 = int64(n.Float64)
623 }
624 n.IsUint = float64(uint64(n.Float64)) == n.Float64
625 if n.IsUint {
626 n.Uint64 = uint64(n.Float64)
627 }
628 }
629}
630
631func (n *NumberNode) String() string {
632 return n.Text
633}
634
635func (n *NumberNode) tree() *Tree {
636 return n.tr
637}
638
639func (n *NumberNode) Copy() Node {
640 nn := new(NumberNode)
641 *nn = *n // Easy, fast, correct.
642 return nn
643}
644
645// StringNode holds a string constant. The value has been "unquoted".
646type StringNode struct {
647 NodeType
648 Pos
649 tr *Tree
650 Quoted string // The original text of the string, with quotes.
651 Text string // The string, after quote processing.
652}
653
654func (t *Tree) newString(pos Pos, orig, text string) *StringNode {
655 return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
656}
657
658func (s *StringNode) String() string {
659 return s.Quoted
660}
661
662func (s *StringNode) tree() *Tree {
663 return s.tr
664}
665
666func (s *StringNode) Copy() Node {
667 return s.tr.newString(s.Pos, s.Quoted, s.Text)
668}
669
670// endNode represents an {{end}} action.
671// It does not appear in the final parse tree.
672type endNode struct {
673 NodeType
674 Pos
675 tr *Tree
676}
677
678func (t *Tree) newEnd(pos Pos) *endNode {
679 return &endNode{tr: t, NodeType: nodeEnd, Pos: pos}
680}
681
682func (e *endNode) String() string {
683 return "{{end}}"
684}
685
686func (e *endNode) tree() *Tree {
687 return e.tr
688}
689
690func (e *endNode) Copy() Node {
691 return e.tr.newEnd(e.Pos)
692}
693
694// elseNode represents an {{else}} action. Does not appear in the final tree.
695type elseNode struct {
696 NodeType
697 Pos
698 tr *Tree
699 Line int // The line number in the input (deprecated; kept for compatibility)
700}
701
702func (t *Tree) newElse(pos Pos, line int) *elseNode {
703 return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line}
704}
705
706func (e *elseNode) Type() NodeType {
707 return nodeElse
708}
709
710func (e *elseNode) String() string {
711 return "{{else}}"
712}
713
714func (e *elseNode) tree() *Tree {
715 return e.tr
716}
717
718func (e *elseNode) Copy() Node {
719 return e.tr.newElse(e.Pos, e.Line)
720}
721
722// BranchNode is the common representation of if, range, and with.
723type BranchNode struct {
724 NodeType
725 Pos
726 tr *Tree
727 Line int // The line number in the input (deprecated; kept for compatibility)
728 Pipe *PipeNode // The pipeline to be evaluated.
729 List *ListNode // What to execute if the value is non-empty.
730 ElseList *ListNode // What to execute if the value is empty (nil if absent).
731}
732
733func (b *BranchNode) String() string {
734 name := ""
735 switch b.NodeType {
736 case NodeIf:
737 name = "if"
738 case NodeRange:
739 name = "range"
740 case NodeWith:
741 name = "with"
742 default:
743 panic("unknown branch type")
744 }
745 if b.ElseList != nil {
746 return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
747 }
748 return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
749}
750
751func (b *BranchNode) tree() *Tree {
752 return b.tr
753}
754
755func (b *BranchNode) Copy() Node {
756 switch b.NodeType {
757 case NodeIf:
758 return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
759 case NodeRange:
760 return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
761 case NodeWith:
762 return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
763 default:
764 panic("unknown branch type")
765 }
766}
767
768// IfNode represents an {{if}} action and its commands.
769type IfNode struct {
770 BranchNode
771}
772
773func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
774 return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
775}
776
777func (i *IfNode) Copy() Node {
778 return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
779}
780
781// RangeNode represents a {{range}} action and its commands.
782type RangeNode struct {
783 BranchNode
784}
785
786func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
787 return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
788}
789
790func (r *RangeNode) Copy() Node {
791 return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
792}
793
794// WithNode represents a {{with}} action and its commands.
795type WithNode struct {
796 BranchNode
797}
798
799func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
800 return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
801}
802
803func (w *WithNode) Copy() Node {
804 return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
805}
806
807// TemplateNode represents a {{template}} action.
808type TemplateNode struct {
809 NodeType
810 Pos
811 tr *Tree
812 Line int // The line number in the input (deprecated; kept for compatibility)
813 Name string // The name of the template (unquoted).
814 Pipe *PipeNode // The command to evaluate as dot for the template.
815}
816
817func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
818 return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
819}
820
821func (t *TemplateNode) String() string {
822 if t.Pipe == nil {
823 return fmt.Sprintf("{{template %q}}", t.Name)
824 }
825 return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
826}
827
828func (t *TemplateNode) tree() *Tree {
829 return t.tr
830}
831
832func (t *TemplateNode) Copy() Node {
833 return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
834}
diff --git a/vendor/github.com/alecthomas/template/parse/parse.go b/vendor/github.com/alecthomas/template/parse/parse.go
new file mode 100644
index 0000000..0d77ade
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/parse/parse.go
@@ -0,0 +1,700 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package parse builds parse trees for templates as defined by text/template
6// and html/template. Clients should use those packages to construct templates
7// rather than this one, which provides shared internal data structures not
8// intended for general use.
9package parse
10
11import (
12 "bytes"
13 "fmt"
14 "runtime"
15 "strconv"
16 "strings"
17)
18
19// Tree is the representation of a single parsed template.
20type Tree struct {
21 Name string // name of the template represented by the tree.
22 ParseName string // name of the top-level template during parsing, for error messages.
23 Root *ListNode // top-level root of the tree.
24 text string // text parsed to create the template (or its parent)
25 // Parsing only; cleared after parse.
26 funcs []map[string]interface{}
27 lex *lexer
28 token [3]item // three-token lookahead for parser.
29 peekCount int
30 vars []string // variables defined at the moment.
31}
32
33// Copy returns a copy of the Tree. Any parsing state is discarded.
34func (t *Tree) Copy() *Tree {
35 if t == nil {
36 return nil
37 }
38 return &Tree{
39 Name: t.Name,
40 ParseName: t.ParseName,
41 Root: t.Root.CopyList(),
42 text: t.text,
43 }
44}
45
46// Parse returns a map from template name to parse.Tree, created by parsing the
47// templates described in the argument string. The top-level template will be
48// given the specified name. If an error is encountered, parsing stops and an
49// empty map is returned with the error.
50func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
51 treeSet = make(map[string]*Tree)
52 t := New(name)
53 t.text = text
54 _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
55 return
56}
57
58// next returns the next token.
59func (t *Tree) next() item {
60 if t.peekCount > 0 {
61 t.peekCount--
62 } else {
63 t.token[0] = t.lex.nextItem()
64 }
65 return t.token[t.peekCount]
66}
67
68// backup backs the input stream up one token.
69func (t *Tree) backup() {
70 t.peekCount++
71}
72
73// backup2 backs the input stream up two tokens.
74// The zeroth token is already there.
75func (t *Tree) backup2(t1 item) {
76 t.token[1] = t1
77 t.peekCount = 2
78}
79
80// backup3 backs the input stream up three tokens
81// The zeroth token is already there.
82func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
83 t.token[1] = t1
84 t.token[2] = t2
85 t.peekCount = 3
86}
87
88// peek returns but does not consume the next token.
89func (t *Tree) peek() item {
90 if t.peekCount > 0 {
91 return t.token[t.peekCount-1]
92 }
93 t.peekCount = 1
94 t.token[0] = t.lex.nextItem()
95 return t.token[0]
96}
97
98// nextNonSpace returns the next non-space token.
99func (t *Tree) nextNonSpace() (token item) {
100 for {
101 token = t.next()
102 if token.typ != itemSpace {
103 break
104 }
105 }
106 return token
107}
108
109// peekNonSpace returns but does not consume the next non-space token.
110func (t *Tree) peekNonSpace() (token item) {
111 for {
112 token = t.next()
113 if token.typ != itemSpace {
114 break
115 }
116 }
117 t.backup()
118 return token
119}
120
121// Parsing.
122
123// New allocates a new parse tree with the given name.
124func New(name string, funcs ...map[string]interface{}) *Tree {
125 return &Tree{
126 Name: name,
127 funcs: funcs,
128 }
129}
130
131// ErrorContext returns a textual representation of the location of the node in the input text.
132// The receiver is only used when the node does not have a pointer to the tree inside,
133// which can occur in old code.
134func (t *Tree) ErrorContext(n Node) (location, context string) {
135 pos := int(n.Position())
136 tree := n.tree()
137 if tree == nil {
138 tree = t
139 }
140 text := tree.text[:pos]
141 byteNum := strings.LastIndex(text, "\n")
142 if byteNum == -1 {
143 byteNum = pos // On first line.
144 } else {
145 byteNum++ // After the newline.
146 byteNum = pos - byteNum
147 }
148 lineNum := 1 + strings.Count(text, "\n")
149 context = n.String()
150 if len(context) > 20 {
151 context = fmt.Sprintf("%.20s...", context)
152 }
153 return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
154}
155
156// errorf formats the error and terminates processing.
157func (t *Tree) errorf(format string, args ...interface{}) {
158 t.Root = nil
159 format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
160 panic(fmt.Errorf(format, args...))
161}
162
163// error terminates processing.
164func (t *Tree) error(err error) {
165 t.errorf("%s", err)
166}
167
168// expect consumes the next token and guarantees it has the required type.
169func (t *Tree) expect(expected itemType, context string) item {
170 token := t.nextNonSpace()
171 if token.typ != expected {
172 t.unexpected(token, context)
173 }
174 return token
175}
176
177// expectOneOf consumes the next token and guarantees it has one of the required types.
178func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
179 token := t.nextNonSpace()
180 if token.typ != expected1 && token.typ != expected2 {
181 t.unexpected(token, context)
182 }
183 return token
184}
185
186// unexpected complains about the token and terminates processing.
187func (t *Tree) unexpected(token item, context string) {
188 t.errorf("unexpected %s in %s", token, context)
189}
190
191// recover is the handler that turns panics into returns from the top level of Parse.
192func (t *Tree) recover(errp *error) {
193 e := recover()
194 if e != nil {
195 if _, ok := e.(runtime.Error); ok {
196 panic(e)
197 }
198 if t != nil {
199 t.stopParse()
200 }
201 *errp = e.(error)
202 }
203 return
204}
205
206// startParse initializes the parser, using the lexer.
207func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
208 t.Root = nil
209 t.lex = lex
210 t.vars = []string{"$"}
211 t.funcs = funcs
212}
213
214// stopParse terminates parsing.
215func (t *Tree) stopParse() {
216 t.lex = nil
217 t.vars = nil
218 t.funcs = nil
219}
220
221// Parse parses the template definition string to construct a representation of
222// the template for execution. If either action delimiter string is empty, the
223// default ("{{" or "}}") is used. Embedded template definitions are added to
224// the treeSet map.
225func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
226 defer t.recover(&err)
227 t.ParseName = t.Name
228 t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
229 t.text = text
230 t.parse(treeSet)
231 t.add(treeSet)
232 t.stopParse()
233 return t, nil
234}
235
236// add adds tree to the treeSet.
237func (t *Tree) add(treeSet map[string]*Tree) {
238 tree := treeSet[t.Name]
239 if tree == nil || IsEmptyTree(tree.Root) {
240 treeSet[t.Name] = t
241 return
242 }
243 if !IsEmptyTree(t.Root) {
244 t.errorf("template: multiple definition of template %q", t.Name)
245 }
246}
247
248// IsEmptyTree reports whether this tree (node) is empty of everything but space.
249func IsEmptyTree(n Node) bool {
250 switch n := n.(type) {
251 case nil:
252 return true
253 case *ActionNode:
254 case *IfNode:
255 case *ListNode:
256 for _, node := range n.Nodes {
257 if !IsEmptyTree(node) {
258 return false
259 }
260 }
261 return true
262 case *RangeNode:
263 case *TemplateNode:
264 case *TextNode:
265 return len(bytes.TrimSpace(n.Text)) == 0
266 case *WithNode:
267 default:
268 panic("unknown node: " + n.String())
269 }
270 return false
271}
272
273// parse is the top-level parser for a template, essentially the same
274// as itemList except it also parses {{define}} actions.
275// It runs to EOF.
276func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
277 t.Root = t.newList(t.peek().pos)
278 for t.peek().typ != itemEOF {
279 if t.peek().typ == itemLeftDelim {
280 delim := t.next()
281 if t.nextNonSpace().typ == itemDefine {
282 newT := New("definition") // name will be updated once we know it.
283 newT.text = t.text
284 newT.ParseName = t.ParseName
285 newT.startParse(t.funcs, t.lex)
286 newT.parseDefinition(treeSet)
287 continue
288 }
289 t.backup2(delim)
290 }
291 n := t.textOrAction()
292 if n.Type() == nodeEnd {
293 t.errorf("unexpected %s", n)
294 }
295 t.Root.append(n)
296 }
297 return nil
298}
299
300// parseDefinition parses a {{define}} ... {{end}} template definition and
301// installs the definition in the treeSet map. The "define" keyword has already
302// been scanned.
303func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
304 const context = "define clause"
305 name := t.expectOneOf(itemString, itemRawString, context)
306 var err error
307 t.Name, err = strconv.Unquote(name.val)
308 if err != nil {
309 t.error(err)
310 }
311 t.expect(itemRightDelim, context)
312 var end Node
313 t.Root, end = t.itemList()
314 if end.Type() != nodeEnd {
315 t.errorf("unexpected %s in %s", end, context)
316 }
317 t.add(treeSet)
318 t.stopParse()
319}
320
321// itemList:
322// textOrAction*
323// Terminates at {{end}} or {{else}}, returned separately.
324func (t *Tree) itemList() (list *ListNode, next Node) {
325 list = t.newList(t.peekNonSpace().pos)
326 for t.peekNonSpace().typ != itemEOF {
327 n := t.textOrAction()
328 switch n.Type() {
329 case nodeEnd, nodeElse:
330 return list, n
331 }
332 list.append(n)
333 }
334 t.errorf("unexpected EOF")
335 return
336}
337
338// textOrAction:
339// text | action
340func (t *Tree) textOrAction() Node {
341 switch token := t.nextNonSpace(); token.typ {
342 case itemElideNewline:
343 return t.elideNewline()
344 case itemText:
345 return t.newText(token.pos, token.val)
346 case itemLeftDelim:
347 return t.action()
348 default:
349 t.unexpected(token, "input")
350 }
351 return nil
352}
353
354// elideNewline:
355// Remove newlines trailing rightDelim if \\ is present.
356func (t *Tree) elideNewline() Node {
357 token := t.peek()
358 if token.typ != itemText {
359 t.unexpected(token, "input")
360 return nil
361 }
362
363 t.next()
364 stripped := strings.TrimLeft(token.val, "\n\r")
365 diff := len(token.val) - len(stripped)
366 if diff > 0 {
367 // This is a bit nasty. We mutate the token in-place to remove
368 // preceding newlines.
369 token.pos += Pos(diff)
370 token.val = stripped
371 }
372 return t.newText(token.pos, token.val)
373}
374
375// Action:
376// control
377// command ("|" command)*
378// Left delim is past. Now get actions.
379// First word could be a keyword such as range.
380func (t *Tree) action() (n Node) {
381 switch token := t.nextNonSpace(); token.typ {
382 case itemElse:
383 return t.elseControl()
384 case itemEnd:
385 return t.endControl()
386 case itemIf:
387 return t.ifControl()
388 case itemRange:
389 return t.rangeControl()
390 case itemTemplate:
391 return t.templateControl()
392 case itemWith:
393 return t.withControl()
394 }
395 t.backup()
396 // Do not pop variables; they persist until "end".
397 return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
398}
399
400// Pipeline:
401// declarations? command ('|' command)*
402func (t *Tree) pipeline(context string) (pipe *PipeNode) {
403 var decl []*VariableNode
404 pos := t.peekNonSpace().pos
405 // Are there declarations?
406 for {
407 if v := t.peekNonSpace(); v.typ == itemVariable {
408 t.next()
409 // Since space is a token, we need 3-token look-ahead here in the worst case:
410 // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
411 // argument variable rather than a declaration. So remember the token
412 // adjacent to the variable so we can push it back if necessary.
413 tokenAfterVariable := t.peek()
414 if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
415 t.nextNonSpace()
416 variable := t.newVariable(v.pos, v.val)
417 decl = append(decl, variable)
418 t.vars = append(t.vars, v.val)
419 if next.typ == itemChar && next.val == "," {
420 if context == "range" && len(decl) < 2 {
421 continue
422 }
423 t.errorf("too many declarations in %s", context)
424 }
425 } else if tokenAfterVariable.typ == itemSpace {
426 t.backup3(v, tokenAfterVariable)
427 } else {
428 t.backup2(v)
429 }
430 }
431 break
432 }
433 pipe = t.newPipeline(pos, t.lex.lineNumber(), decl)
434 for {
435 switch token := t.nextNonSpace(); token.typ {
436 case itemRightDelim, itemRightParen:
437 if len(pipe.Cmds) == 0 {
438 t.errorf("missing value for %s", context)
439 }
440 if token.typ == itemRightParen {
441 t.backup()
442 }
443 return
444 case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
445 itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
446 t.backup()
447 pipe.append(t.command())
448 default:
449 t.unexpected(token, context)
450 }
451 }
452}
453
454func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
455 defer t.popVars(len(t.vars))
456 line = t.lex.lineNumber()
457 pipe = t.pipeline(context)
458 var next Node
459 list, next = t.itemList()
460 switch next.Type() {
461 case nodeEnd: //done
462 case nodeElse:
463 if allowElseIf {
464 // Special case for "else if". If the "else" is followed immediately by an "if",
465 // the elseControl will have left the "if" token pending. Treat
466 // {{if a}}_{{else if b}}_{{end}}
467 // as
468 // {{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
469 // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
470 // is assumed. This technique works even for long if-else-if chains.
471 // TODO: Should we allow else-if in with and range?
472 if t.peek().typ == itemIf {
473 t.next() // Consume the "if" token.
474 elseList = t.newList(next.Position())
475 elseList.append(t.ifControl())
476 // Do not consume the next item - only one {{end}} required.
477 break
478 }
479 }
480 elseList, next = t.itemList()
481 if next.Type() != nodeEnd {
482 t.errorf("expected end; found %s", next)
483 }
484 }
485 return pipe.Position(), line, pipe, list, elseList
486}
487
488// If:
489// {{if pipeline}} itemList {{end}}
490// {{if pipeline}} itemList {{else}} itemList {{end}}
491// If keyword is past.
492func (t *Tree) ifControl() Node {
493 return t.newIf(t.parseControl(true, "if"))
494}
495
496// Range:
497// {{range pipeline}} itemList {{end}}
498// {{range pipeline}} itemList {{else}} itemList {{end}}
499// Range keyword is past.
500func (t *Tree) rangeControl() Node {
501 return t.newRange(t.parseControl(false, "range"))
502}
503
504// With:
505// {{with pipeline}} itemList {{end}}
506// {{with pipeline}} itemList {{else}} itemList {{end}}
507// If keyword is past.
508func (t *Tree) withControl() Node {
509 return t.newWith(t.parseControl(false, "with"))
510}
511
512// End:
513// {{end}}
514// End keyword is past.
515func (t *Tree) endControl() Node {
516 return t.newEnd(t.expect(itemRightDelim, "end").pos)
517}
518
519// Else:
520// {{else}}
521// Else keyword is past.
522func (t *Tree) elseControl() Node {
523 // Special case for "else if".
524 peek := t.peekNonSpace()
525 if peek.typ == itemIf {
526 // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
527 return t.newElse(peek.pos, t.lex.lineNumber())
528 }
529 return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
530}
531
532// Template:
533// {{template stringValue pipeline}}
534// Template keyword is past. The name must be something that can evaluate
535// to a string.
536func (t *Tree) templateControl() Node {
537 var name string
538 token := t.nextNonSpace()
539 switch token.typ {
540 case itemString, itemRawString:
541 s, err := strconv.Unquote(token.val)
542 if err != nil {
543 t.error(err)
544 }
545 name = s
546 default:
547 t.unexpected(token, "template invocation")
548 }
549 var pipe *PipeNode
550 if t.nextNonSpace().typ != itemRightDelim {
551 t.backup()
552 // Do not pop variables; they persist until "end".
553 pipe = t.pipeline("template")
554 }
555 return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
556}
557
558// command:
559// operand (space operand)*
560// space-separated arguments up to a pipeline character or right delimiter.
561// we consume the pipe character but leave the right delim to terminate the action.
562func (t *Tree) command() *CommandNode {
563 cmd := t.newCommand(t.peekNonSpace().pos)
564 for {
565 t.peekNonSpace() // skip leading spaces.
566 operand := t.operand()
567 if operand != nil {
568 cmd.append(operand)
569 }
570 switch token := t.next(); token.typ {
571 case itemSpace:
572 continue
573 case itemError:
574 t.errorf("%s", token.val)
575 case itemRightDelim, itemRightParen:
576 t.backup()
577 case itemPipe:
578 default:
579 t.errorf("unexpected %s in operand; missing space?", token)
580 }
581 break
582 }
583 if len(cmd.Args) == 0 {
584 t.errorf("empty command")
585 }
586 return cmd
587}
588
589// operand:
590// term .Field*
591// An operand is a space-separated component of a command,
592// a term possibly followed by field accesses.
593// A nil return means the next item is not an operand.
594func (t *Tree) operand() Node {
595 node := t.term()
596 if node == nil {
597 return nil
598 }
599 if t.peek().typ == itemField {
600 chain := t.newChain(t.peek().pos, node)
601 for t.peek().typ == itemField {
602 chain.Add(t.next().val)
603 }
604 // Compatibility with original API: If the term is of type NodeField
605 // or NodeVariable, just put more fields on the original.
606 // Otherwise, keep the Chain node.
607 // TODO: Switch to Chains always when we can.
608 switch node.Type() {
609 case NodeField:
610 node = t.newField(chain.Position(), chain.String())
611 case NodeVariable:
612 node = t.newVariable(chain.Position(), chain.String())
613 default:
614 node = chain
615 }
616 }
617 return node
618}
619
620// term:
621// literal (number, string, nil, boolean)
622// function (identifier)
623// .
624// .Field
625// $
626// '(' pipeline ')'
627// A term is a simple "expression".
628// A nil return means the next item is not a term.
629func (t *Tree) term() Node {
630 switch token := t.nextNonSpace(); token.typ {
631 case itemError:
632 t.errorf("%s", token.val)
633 case itemIdentifier:
634 if !t.hasFunction(token.val) {
635 t.errorf("function %q not defined", token.val)
636 }
637 return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
638 case itemDot:
639 return t.newDot(token.pos)
640 case itemNil:
641 return t.newNil(token.pos)
642 case itemVariable:
643 return t.useVar(token.pos, token.val)
644 case itemField:
645 return t.newField(token.pos, token.val)
646 case itemBool:
647 return t.newBool(token.pos, token.val == "true")
648 case itemCharConstant, itemComplex, itemNumber:
649 number, err := t.newNumber(token.pos, token.val, token.typ)
650 if err != nil {
651 t.error(err)
652 }
653 return number
654 case itemLeftParen:
655 pipe := t.pipeline("parenthesized pipeline")
656 if token := t.next(); token.typ != itemRightParen {
657 t.errorf("unclosed right paren: unexpected %s", token)
658 }
659 return pipe
660 case itemString, itemRawString:
661 s, err := strconv.Unquote(token.val)
662 if err != nil {
663 t.error(err)
664 }
665 return t.newString(token.pos, token.val, s)
666 }
667 t.backup()
668 return nil
669}
670
671// hasFunction reports if a function name exists in the Tree's maps.
672func (t *Tree) hasFunction(name string) bool {
673 for _, funcMap := range t.funcs {
674 if funcMap == nil {
675 continue
676 }
677 if funcMap[name] != nil {
678 return true
679 }
680 }
681 return false
682}
683
684// popVars trims the variable list to the specified length
685func (t *Tree) popVars(n int) {
686 t.vars = t.vars[:n]
687}
688
689// useVar returns a node for a variable reference. It errors if the
690// variable is not defined.
691func (t *Tree) useVar(pos Pos, name string) Node {
692 v := t.newVariable(pos, name)
693 for _, varName := range t.vars {
694 if varName == v.Ident[0] {
695 return v
696 }
697 }
698 t.errorf("undefined variable %q", v.Ident[0])
699 return nil
700}
diff --git a/vendor/github.com/alecthomas/template/template.go b/vendor/github.com/alecthomas/template/template.go
new file mode 100644
index 0000000..447ed2a
--- /dev/null
+++ b/vendor/github.com/alecthomas/template/template.go
@@ -0,0 +1,218 @@
1// Copyright 2011 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package template
6
7import (
8 "fmt"
9 "reflect"
10
11 "github.com/alecthomas/template/parse"
12)
13
14// common holds the information shared by related templates.
15type common struct {
16 tmpl map[string]*Template
17 // We use two maps, one for parsing and one for execution.
18 // This separation makes the API cleaner since it doesn't
19 // expose reflection to the client.
20 parseFuncs FuncMap
21 execFuncs map[string]reflect.Value
22}
23
24// Template is the representation of a parsed template. The *parse.Tree
25// field is exported only for use by html/template and should be treated
26// as unexported by all other clients.
27type Template struct {
28 name string
29 *parse.Tree
30 *common
31 leftDelim string
32 rightDelim string
33}
34
35// New allocates a new template with the given name.
36func New(name string) *Template {
37 return &Template{
38 name: name,
39 }
40}
41
42// Name returns the name of the template.
43func (t *Template) Name() string {
44 return t.name
45}
46
47// New allocates a new template associated with the given one and with the same
48// delimiters. The association, which is transitive, allows one template to
49// invoke another with a {{template}} action.
50func (t *Template) New(name string) *Template {
51 t.init()
52 return &Template{
53 name: name,
54 common: t.common,
55 leftDelim: t.leftDelim,
56 rightDelim: t.rightDelim,
57 }
58}
59
60func (t *Template) init() {
61 if t.common == nil {
62 t.common = new(common)
63 t.tmpl = make(map[string]*Template)
64 t.parseFuncs = make(FuncMap)
65 t.execFuncs = make(map[string]reflect.Value)
66 }
67}
68
69// Clone returns a duplicate of the template, including all associated
70// templates. The actual representation is not copied, but the name space of
71// associated templates is, so further calls to Parse in the copy will add
72// templates to the copy but not to the original. Clone can be used to prepare
73// common templates and use them with variant definitions for other templates
74// by adding the variants after the clone is made.
75func (t *Template) Clone() (*Template, error) {
76 nt := t.copy(nil)
77 nt.init()
78 nt.tmpl[t.name] = nt
79 for k, v := range t.tmpl {
80 if k == t.name { // Already installed.
81 continue
82 }
83 // The associated templates share nt's common structure.
84 tmpl := v.copy(nt.common)
85 nt.tmpl[k] = tmpl
86 }
87 for k, v := range t.parseFuncs {
88 nt.parseFuncs[k] = v
89 }
90 for k, v := range t.execFuncs {
91 nt.execFuncs[k] = v
92 }
93 return nt, nil
94}
95
96// copy returns a shallow copy of t, with common set to the argument.
97func (t *Template) copy(c *common) *Template {
98 nt := New(t.name)
99 nt.Tree = t.Tree
100 nt.common = c
101 nt.leftDelim = t.leftDelim
102 nt.rightDelim = t.rightDelim
103 return nt
104}
105
106// AddParseTree creates a new template with the name and parse tree
107// and associates it with t.
108func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
109 if t.common != nil && t.tmpl[name] != nil {
110 return nil, fmt.Errorf("template: redefinition of template %q", name)
111 }
112 nt := t.New(name)
113 nt.Tree = tree
114 t.tmpl[name] = nt
115 return nt, nil
116}
117
118// Templates returns a slice of the templates associated with t, including t
119// itself.
120func (t *Template) Templates() []*Template {
121 if t.common == nil {
122 return nil
123 }
124 // Return a slice so we don't expose the map.
125 m := make([]*Template, 0, len(t.tmpl))
126 for _, v := range t.tmpl {
127 m = append(m, v)
128 }
129 return m
130}
131
132// Delims sets the action delimiters to the specified strings, to be used in
133// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
134// definitions will inherit the settings. An empty delimiter stands for the
135// corresponding default: {{ or }}.
136// The return value is the template, so calls can be chained.
137func (t *Template) Delims(left, right string) *Template {
138 t.leftDelim = left
139 t.rightDelim = right
140 return t
141}
142
143// Funcs adds the elements of the argument map to the template's function map.
144// It panics if a value in the map is not a function with appropriate return
145// type. However, it is legal to overwrite elements of the map. The return
146// value is the template, so calls can be chained.
147func (t *Template) Funcs(funcMap FuncMap) *Template {
148 t.init()
149 addValueFuncs(t.execFuncs, funcMap)
150 addFuncs(t.parseFuncs, funcMap)
151 return t
152}
153
154// Lookup returns the template with the given name that is associated with t,
155// or nil if there is no such template.
156func (t *Template) Lookup(name string) *Template {
157 if t.common == nil {
158 return nil
159 }
160 return t.tmpl[name]
161}
162
163// Parse parses a string into a template. Nested template definitions will be
164// associated with the top-level template t. Parse may be called multiple times
165// to parse definitions of templates to associate with t. It is an error if a
166// resulting template is non-empty (contains content other than template
167// definitions) and would replace a non-empty template with the same name.
168// (In multiple calls to Parse with the same receiver template, only one call
169// can contain text other than space, comments, and template definitions.)
170func (t *Template) Parse(text string) (*Template, error) {
171 t.init()
172 trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
173 if err != nil {
174 return nil, err
175 }
176 // Add the newly parsed trees, including the one for t, into our common structure.
177 for name, tree := range trees {
178 // If the name we parsed is the name of this template, overwrite this template.
179 // The associate method checks it's not a redefinition.
180 tmpl := t
181 if name != t.name {
182 tmpl = t.New(name)
183 }
184 // Even if t == tmpl, we need to install it in the common.tmpl map.
185 if replace, err := t.associate(tmpl, tree); err != nil {
186 return nil, err
187 } else if replace {
188 tmpl.Tree = tree
189 }
190 tmpl.leftDelim = t.leftDelim
191 tmpl.rightDelim = t.rightDelim
192 }
193 return t, nil
194}
195
196// associate installs the new template into the group of templates associated
197// with t. It is an error to reuse a name except to overwrite an empty
198// template. The two are already known to share the common structure.
199// The boolean return value reports wither to store this tree as t.Tree.
200func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
201 if new.common != t.common {
202 panic("internal error: associate not common")
203 }
204 name := new.name
205 if old := t.tmpl[name]; old != nil {
206 oldIsEmpty := parse.IsEmptyTree(old.Root)
207 newIsEmpty := parse.IsEmptyTree(tree.Root)
208 if newIsEmpty {
209 // Whether old is empty or not, new is empty; no reason to replace old.
210 return false, nil
211 }
212 if !oldIsEmpty {
213 return false, fmt.Errorf("template: redefinition of template %q", name)
214 }
215 }
216 t.tmpl[name] = new
217 return true, nil
218}
diff --git a/vendor/github.com/alecthomas/units/COPYING b/vendor/github.com/alecthomas/units/COPYING
new file mode 100644
index 0000000..2993ec0
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/COPYING
@@ -0,0 +1,19 @@
1Copyright (C) 2014 Alec Thomas
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/vendor/github.com/alecthomas/units/README.md b/vendor/github.com/alecthomas/units/README.md
new file mode 100644
index 0000000..bee884e
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/README.md
@@ -0,0 +1,11 @@
1# Units - Helpful unit multipliers and functions for Go
2
3The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package.
4
5It allows for code like this:
6
7```go
8n, err := ParseBase2Bytes("1KB")
9// n == 1024
10n = units.Mebibyte * 512
11```
diff --git a/vendor/github.com/alecthomas/units/bytes.go b/vendor/github.com/alecthomas/units/bytes.go
new file mode 100644
index 0000000..eaadeb8
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/bytes.go
@@ -0,0 +1,83 @@
1package units
2
3// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte,
4// etc.).
5type Base2Bytes int64
6
7// Base-2 byte units.
8const (
9 Kibibyte Base2Bytes = 1024
10 KiB = Kibibyte
11 Mebibyte = Kibibyte * 1024
12 MiB = Mebibyte
13 Gibibyte = Mebibyte * 1024
14 GiB = Gibibyte
15 Tebibyte = Gibibyte * 1024
16 TiB = Tebibyte
17 Pebibyte = Tebibyte * 1024
18 PiB = Pebibyte
19 Exbibyte = Pebibyte * 1024
20 EiB = Exbibyte
21)
22
23var (
24 bytesUnitMap = MakeUnitMap("iB", "B", 1024)
25 oldBytesUnitMap = MakeUnitMap("B", "B", 1024)
26)
27
28// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB
29// and KiB are both 1024.
30func ParseBase2Bytes(s string) (Base2Bytes, error) {
31 n, err := ParseUnit(s, bytesUnitMap)
32 if err != nil {
33 n, err = ParseUnit(s, oldBytesUnitMap)
34 }
35 return Base2Bytes(n), err
36}
37
38func (b Base2Bytes) String() string {
39 return ToString(int64(b), 1024, "iB", "B")
40}
41
42var (
43 metricBytesUnitMap = MakeUnitMap("B", "B", 1000)
44)
45
46// MetricBytes are SI byte units (1000 bytes in a kilobyte).
47type MetricBytes SI
48
49// SI base-10 byte units.
50const (
51 Kilobyte MetricBytes = 1000
52 KB = Kilobyte
53 Megabyte = Kilobyte * 1000
54 MB = Megabyte
55 Gigabyte = Megabyte * 1000
56 GB = Gigabyte
57 Terabyte = Gigabyte * 1000
58 TB = Terabyte
59 Petabyte = Terabyte * 1000
60 PB = Petabyte
61 Exabyte = Petabyte * 1000
62 EB = Exabyte
63)
64
65// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes.
66func ParseMetricBytes(s string) (MetricBytes, error) {
67 n, err := ParseUnit(s, metricBytesUnitMap)
68 return MetricBytes(n), err
69}
70
71func (m MetricBytes) String() string {
72 return ToString(int64(m), 1000, "B", "B")
73}
74
75// ParseStrictBytes supports both iB and B suffixes for base 2 and metric,
76// respectively. That is, KiB represents 1024 and KB represents 1000.
77func ParseStrictBytes(s string) (int64, error) {
78 n, err := ParseUnit(s, bytesUnitMap)
79 if err != nil {
80 n, err = ParseUnit(s, metricBytesUnitMap)
81 }
82 return int64(n), err
83}
diff --git a/vendor/github.com/alecthomas/units/doc.go b/vendor/github.com/alecthomas/units/doc.go
new file mode 100644
index 0000000..156ae38
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/doc.go
@@ -0,0 +1,13 @@
1// Package units provides helpful unit multipliers and functions for Go.
2//
3// The goal of this package is to have functionality similar to the time [1] package.
4//
5//
6// [1] http://golang.org/pkg/time/
7//
8// It allows for code like this:
9//
10// n, err := ParseBase2Bytes("1KB")
11// // n == 1024
12// n = units.Mebibyte * 512
13package units
diff --git a/vendor/github.com/alecthomas/units/si.go b/vendor/github.com/alecthomas/units/si.go
new file mode 100644
index 0000000..8234a9d
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/si.go
@@ -0,0 +1,26 @@
1package units
2
3// SI units.
4type SI int64
5
6// SI unit multiples.
7const (
8 Kilo SI = 1000
9 Mega = Kilo * 1000
10 Giga = Mega * 1000
11 Tera = Giga * 1000
12 Peta = Tera * 1000
13 Exa = Peta * 1000
14)
15
16func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 {
17 return map[string]float64{
18 shortSuffix: 1,
19 "K" + suffix: float64(scale),
20 "M" + suffix: float64(scale * scale),
21 "G" + suffix: float64(scale * scale * scale),
22 "T" + suffix: float64(scale * scale * scale * scale),
23 "P" + suffix: float64(scale * scale * scale * scale * scale),
24 "E" + suffix: float64(scale * scale * scale * scale * scale * scale),
25 }
26}
diff --git a/vendor/github.com/alecthomas/units/util.go b/vendor/github.com/alecthomas/units/util.go
new file mode 100644
index 0000000..6527e92
--- /dev/null
+++ b/vendor/github.com/alecthomas/units/util.go
@@ -0,0 +1,138 @@
1package units
2
3import (
4 "errors"
5 "fmt"
6 "strings"
7)
8
9var (
10 siUnits = []string{"", "K", "M", "G", "T", "P", "E"}
11)
12
13func ToString(n int64, scale int64, suffix, baseSuffix string) string {
14 mn := len(siUnits)
15 out := make([]string, mn)
16 for i, m := range siUnits {
17 if n%scale != 0 || i == 0 && n == 0 {
18 s := suffix
19 if i == 0 {
20 s = baseSuffix
21 }
22 out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s)
23 }
24 n /= scale
25 if n == 0 {
26 break
27 }
28 }
29 return strings.Join(out, "")
30}
31
32// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123
33var errLeadingInt = errors.New("units: bad [0-9]*") // never printed
34
35// leadingInt consumes the leading [0-9]* from s.
36func leadingInt(s string) (x int64, rem string, err error) {
37 i := 0
38 for ; i < len(s); i++ {
39 c := s[i]
40 if c < '0' || c > '9' {
41 break
42 }
43 if x >= (1<<63-10)/10 {
44 // overflow
45 return 0, "", errLeadingInt
46 }
47 x = x*10 + int64(c) - '0'
48 }
49 return x, s[i:], nil
50}
51
52func ParseUnit(s string, unitMap map[string]float64) (int64, error) {
53 // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
54 orig := s
55 f := float64(0)
56 neg := false
57
58 // Consume [-+]?
59 if s != "" {
60 c := s[0]
61 if c == '-' || c == '+' {
62 neg = c == '-'
63 s = s[1:]
64 }
65 }
66 // Special case: if all that is left is "0", this is zero.
67 if s == "0" {
68 return 0, nil
69 }
70 if s == "" {
71 return 0, errors.New("units: invalid " + orig)
72 }
73 for s != "" {
74 g := float64(0) // this element of the sequence
75
76 var x int64
77 var err error
78
79 // The next character must be [0-9.]
80 if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
81 return 0, errors.New("units: invalid " + orig)
82 }
83 // Consume [0-9]*
84 pl := len(s)
85 x, s, err = leadingInt(s)
86 if err != nil {
87 return 0, errors.New("units: invalid " + orig)
88 }
89 g = float64(x)
90 pre := pl != len(s) // whether we consumed anything before a period
91
92 // Consume (\.[0-9]*)?
93 post := false
94 if s != "" && s[0] == '.' {
95 s = s[1:]
96 pl := len(s)
97 x, s, err = leadingInt(s)
98 if err != nil {
99 return 0, errors.New("units: invalid " + orig)
100 }
101 scale := 1.0
102 for n := pl - len(s); n > 0; n-- {
103 scale *= 10
104 }
105 g += float64(x) / scale
106 post = pl != len(s)
107 }
108 if !pre && !post {
109 // no digits (e.g. ".s" or "-.s")
110 return 0, errors.New("units: invalid " + orig)
111 }
112
113 // Consume unit.
114 i := 0
115 for ; i < len(s); i++ {
116 c := s[i]
117 if c == '.' || ('0' <= c && c <= '9') {
118 break
119 }
120 }
121 u := s[:i]
122 s = s[i:]
123 unit, ok := unitMap[u]
124 if !ok {
125 return 0, errors.New("units: unknown unit " + u + " in " + orig)
126 }
127
128 f += g * unit
129 }
130
131 if neg {
132 f = -f
133 }
134 if f < float64(-1<<63) || f > float64(1<<63-1) {
135 return 0, errors.New("units: overflow parsing unit")
136 }
137 return int64(f), nil
138}
diff --git a/vendor/github.com/prometheus/common/expfmt/text_parse.go b/vendor/github.com/prometheus/common/expfmt/text_parse.go
index ef9a150..54bcfde 100644
--- a/vendor/github.com/prometheus/common/expfmt/text_parse.go
+++ b/vendor/github.com/prometheus/common/expfmt/text_parse.go
@@ -315,6 +315,10 @@ func (p *TextParser) startLabelValue() stateFn {
315 if p.readTokenAsLabelValue(); p.err != nil { 315 if p.readTokenAsLabelValue(); p.err != nil {
316 return nil 316 return nil
317 } 317 }
318 if !model.LabelValue(p.currentToken.String()).IsValid() {
319 p.parseError(fmt.Sprintf("invalid label value %q", p.currentToken.String()))
320 return nil
321 }
318 p.currentLabelPair.Value = proto.String(p.currentToken.String()) 322 p.currentLabelPair.Value = proto.String(p.currentToken.String())
319 // Special treatment of summaries: 323 // Special treatment of summaries:
320 // - Quantile labels are special, will result in dto.Quantile later. 324 // - Quantile labels are special, will result in dto.Quantile later.
diff --git a/vendor/github.com/prometheus/common/log/eventlog_formatter.go b/vendor/github.com/prometheus/common/log/eventlog_formatter.go
index 6d41284..bcf68e6 100644
--- a/vendor/github.com/prometheus/common/log/eventlog_formatter.go
+++ b/vendor/github.com/prometheus/common/log/eventlog_formatter.go
@@ -21,22 +21,22 @@ import (
21 21
22 "golang.org/x/sys/windows/svc/eventlog" 22 "golang.org/x/sys/windows/svc/eventlog"
23 23
24 "github.com/Sirupsen/logrus" 24 "github.com/sirupsen/logrus"
25) 25)
26 26
27func init() { 27func init() {
28 setEventlogFormatter = func(name string, debugAsInfo bool) error { 28 setEventlogFormatter = func(l logger, name string, debugAsInfo bool) error {
29 if name == "" { 29 if name == "" {
30 return fmt.Errorf("missing name parameter") 30 return fmt.Errorf("missing name parameter")
31 } 31 }
32 32
33 fmter, err := newEventlogger(name, debugAsInfo, origLogger.Formatter) 33 fmter, err := newEventlogger(name, debugAsInfo, l.entry.Logger.Formatter)
34 if err != nil { 34 if err != nil {
35 fmt.Fprintf(os.Stderr, "error creating eventlog formatter: %v\n", err) 35 fmt.Fprintf(os.Stderr, "error creating eventlog formatter: %v\n", err)
36 origLogger.Errorf("can't connect logger to eventlog: %v", err) 36 l.Errorf("can't connect logger to eventlog: %v", err)
37 return err 37 return err
38 } 38 }
39 origLogger.Formatter = fmter 39 l.entry.Logger.Formatter = fmter
40 return nil 40 return nil
41 } 41 }
42} 42}
diff --git a/vendor/github.com/prometheus/common/log/log.go b/vendor/github.com/prometheus/common/log/log.go
index efad484..04e906c 100644
--- a/vendor/github.com/prometheus/common/log/log.go
+++ b/vendor/github.com/prometheus/common/log/log.go
@@ -14,7 +14,6 @@
14package log 14package log
15 15
16import ( 16import (
17 "flag"
18 "fmt" 17 "fmt"
19 "io" 18 "io"
20 "io/ioutil" 19 "io/ioutil"
@@ -25,106 +24,46 @@ import (
25 "strconv" 24 "strconv"
26 "strings" 25 "strings"
27 26
28 "github.com/Sirupsen/logrus" 27 "github.com/sirupsen/logrus"
28 "gopkg.in/alecthomas/kingpin.v2"
29) 29)
30 30
31type levelFlag string
32
33// String implements flag.Value.
34func (f levelFlag) String() string {
35 return fmt.Sprintf("%q", string(f))
36}
37
38// Set implements flag.Value.
39func (f levelFlag) Set(level string) error {
40 l, err := logrus.ParseLevel(level)
41 if err != nil {
42 return err
43 }
44 origLogger.Level = l
45 return nil
46}
47
48// setSyslogFormatter is nil if the target architecture does not support syslog. 31// setSyslogFormatter is nil if the target architecture does not support syslog.
49var setSyslogFormatter func(string, string) error 32var setSyslogFormatter func(logger, string, string) error
50 33
51// setEventlogFormatter is nil if the target OS does not support Eventlog (i.e., is not Windows). 34// setEventlogFormatter is nil if the target OS does not support Eventlog (i.e., is not Windows).
52var setEventlogFormatter func(string, bool) error 35var setEventlogFormatter func(logger, string, bool) error
53 36
54func setJSONFormatter() { 37func setJSONFormatter() {
55 origLogger.Formatter = &logrus.JSONFormatter{} 38 origLogger.Formatter = &logrus.JSONFormatter{}
56} 39}
57 40
58type logFormatFlag url.URL 41type loggerSettings struct {
59 42 level string
60// String implements flag.Value. 43 format string
61func (f logFormatFlag) String() string {
62 u := url.URL(f)
63 return fmt.Sprintf("%q", u.String())
64} 44}
65 45
66// Set implements flag.Value. 46func (s *loggerSettings) apply(ctx *kingpin.ParseContext) error {
67func (f logFormatFlag) Set(format string) error { 47 err := baseLogger.SetLevel(s.level)
68 u, err := url.Parse(format)
69 if err != nil { 48 if err != nil {
70 return err 49 return err
71 } 50 }
72 if u.Scheme != "logger" { 51 err = baseLogger.SetFormat(s.format)
73 return fmt.Errorf("invalid scheme %s", u.Scheme) 52 return err
74 }
75 jsonq := u.Query().Get("json")
76 if jsonq == "true" {
77 setJSONFormatter()
78 }
79
80 switch u.Opaque {
81 case "syslog":
82 if setSyslogFormatter == nil {
83 return fmt.Errorf("system does not support syslog")
84 }
85 appname := u.Query().Get("appname")
86 facility := u.Query().Get("local")
87 return setSyslogFormatter(appname, facility)
88 case "eventlog":
89 if setEventlogFormatter == nil {
90 return fmt.Errorf("system does not support eventlog")
91 }
92 name := u.Query().Get("name")
93 debugAsInfo := false
94 debugAsInfoRaw := u.Query().Get("debugAsInfo")
95 if parsedDebugAsInfo, err := strconv.ParseBool(debugAsInfoRaw); err == nil {
96 debugAsInfo = parsedDebugAsInfo
97 }
98 return setEventlogFormatter(name, debugAsInfo)
99 case "stdout":
100 origLogger.Out = os.Stdout
101 case "stderr":
102 origLogger.Out = os.Stderr
103 default:
104 return fmt.Errorf("unsupported logger %q", u.Opaque)
105 }
106 return nil
107} 53}
108 54
109func init() { 55// AddFlags adds the flags used by this package to the Kingpin application.
110 AddFlags(flag.CommandLine) 56// To use the default Kingpin application, call AddFlags(kingpin.CommandLine)
111} 57func AddFlags(a *kingpin.Application) {
112 58 s := loggerSettings{}
113// AddFlags adds the flags used by this package to the given FlagSet. That's 59 kingpin.Flag("log.level", "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]").
114// useful if working with a custom FlagSet. The init function of this package 60 Default(origLogger.Level.String()).
115// adds the flags to flag.CommandLine anyway. Thus, it's usually enough to call 61 StringVar(&s.level)
116// flag.Parse() to make the logging flags take effect. 62 defaultFormat := url.URL{Scheme: "logger", Opaque: "stderr"}
117func AddFlags(fs *flag.FlagSet) { 63 kingpin.Flag("log.format", `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`).
118 fs.Var( 64 Default(defaultFormat.String()).
119 levelFlag(origLogger.Level.String()), 65 StringVar(&s.format)
120 "log.level", 66 a.Action(s.apply)
121 "Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]",
122 )
123 fs.Var(
124 logFormatFlag(url.URL{Scheme: "logger", Opaque: "stderr"}),
125 "log.format",
126 `Set the log target and format. Example: "logger:syslog?appname=bob&local=7" or "logger:stdout?json=true"`,
127 )
128} 67}
129 68
130// Logger is the interface for loggers used in the Prometheus components. 69// Logger is the interface for loggers used in the Prometheus components.
@@ -150,6 +89,9 @@ type Logger interface {
150 Fatalf(string, ...interface{}) 89 Fatalf(string, ...interface{})
151 90
152 With(key string, value interface{}) Logger 91 With(key string, value interface{}) Logger
92
93 SetFormat(string) error
94 SetLevel(string) error
153} 95}
154 96
155type logger struct { 97type logger struct {
@@ -235,6 +177,58 @@ func (l logger) Fatalf(format string, args ...interface{}) {
235 l.sourced().Fatalf(format, args...) 177 l.sourced().Fatalf(format, args...)
236} 178}
237 179
180func (l logger) SetLevel(level string) error {
181 lvl, err := logrus.ParseLevel(level)
182 if err != nil {
183 return err
184 }
185
186 l.entry.Logger.Level = lvl
187 return nil
188}
189
190func (l logger) SetFormat(format string) error {
191 u, err := url.Parse(format)
192 if err != nil {
193 return err
194 }
195 if u.Scheme != "logger" {
196 return fmt.Errorf("invalid scheme %s", u.Scheme)
197 }
198 jsonq := u.Query().Get("json")
199 if jsonq == "true" {
200 setJSONFormatter()
201 }
202
203 switch u.Opaque {
204 case "syslog":
205 if setSyslogFormatter == nil {
206 return fmt.Errorf("system does not support syslog")
207 }
208 appname := u.Query().Get("appname")
209 facility := u.Query().Get("local")
210 return setSyslogFormatter(l, appname, facility)
211 case "eventlog":
212 if setEventlogFormatter == nil {
213 return fmt.Errorf("system does not support eventlog")
214 }
215 name := u.Query().Get("name")
216 debugAsInfo := false
217 debugAsInfoRaw := u.Query().Get("debugAsInfo")
218 if parsedDebugAsInfo, err := strconv.ParseBool(debugAsInfoRaw); err == nil {
219 debugAsInfo = parsedDebugAsInfo
220 }
221 return setEventlogFormatter(l, name, debugAsInfo)
222 case "stdout":
223 l.entry.Logger.Out = os.Stdout
224 case "stderr":
225 l.entry.Logger.Out = os.Stderr
226 default:
227 return fmt.Errorf("unsupported logger %q", u.Opaque)
228 }
229 return nil
230}
231
238// sourced adds a source field to the logger that contains 232// sourced adds a source field to the logger that contains
239// the file name and line where the logging happened. 233// the file name and line where the logging happened.
240func (l logger) sourced() *logrus.Entry { 234func (l logger) sourced() *logrus.Entry {
diff --git a/vendor/github.com/prometheus/common/log/syslog_formatter.go b/vendor/github.com/prometheus/common/log/syslog_formatter.go
index 64f5fda..f882f2f 100644
--- a/vendor/github.com/prometheus/common/log/syslog_formatter.go
+++ b/vendor/github.com/prometheus/common/log/syslog_formatter.go
@@ -20,13 +20,13 @@ import (
20 "log/syslog" 20 "log/syslog"
21 "os" 21 "os"
22 22
23 "github.com/Sirupsen/logrus" 23 "github.com/sirupsen/logrus"
24) 24)
25 25
26var _ logrus.Formatter = (*syslogger)(nil) 26var _ logrus.Formatter = (*syslogger)(nil)
27 27
28func init() { 28func init() {
29 setSyslogFormatter = func(appname, local string) error { 29 setSyslogFormatter = func(l logger, appname, local string) error {
30 if appname == "" { 30 if appname == "" {
31 return fmt.Errorf("missing appname parameter") 31 return fmt.Errorf("missing appname parameter")
32 } 32 }
@@ -34,13 +34,13 @@ func init() {
34 return fmt.Errorf("missing local parameter") 34 return fmt.Errorf("missing local parameter")
35 } 35 }
36 36
37 fmter, err := newSyslogger(appname, local, origLogger.Formatter) 37 fmter, err := newSyslogger(appname, local, l.entry.Logger.Formatter)
38 if err != nil { 38 if err != nil {
39 fmt.Fprintf(os.Stderr, "error creating syslog formatter: %v\n", err) 39 fmt.Fprintf(os.Stderr, "error creating syslog formatter: %v\n", err)
40 origLogger.Errorf("can't connect logger to syslog: %v", err) 40 l.entry.Errorf("can't connect logger to syslog: %v", err)
41 return err 41 return err
42 } 42 }
43 origLogger.Formatter = fmter 43 l.entry.Logger.Formatter = fmter
44 return nil 44 return nil
45 } 45 }
46} 46}
diff --git a/vendor/github.com/prometheus/common/model/time.go b/vendor/github.com/prometheus/common/model/time.go
index 548968a..7e87f1a 100644
--- a/vendor/github.com/prometheus/common/model/time.go
+++ b/vendor/github.com/prometheus/common/model/time.go
@@ -163,9 +163,21 @@ func (t *Time) UnmarshalJSON(b []byte) error {
163// This type should not propagate beyond the scope of input/output processing. 163// This type should not propagate beyond the scope of input/output processing.
164type Duration time.Duration 164type Duration time.Duration
165 165
166// Set implements pflag/flag.Value
167func (d *Duration) Set(s string) error {
168 var err error
169 *d, err = ParseDuration(s)
170 return err
171}
172
173// Type implements pflag.Value
174func (d *Duration) Type() string {
175 return "duration"
176}
177
166var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$") 178var durationRE = regexp.MustCompile("^([0-9]+)(y|w|d|h|m|s|ms)$")
167 179
168// StringToDuration parses a string into a time.Duration, assuming that a year 180// ParseDuration parses a string into a time.Duration, assuming that a year
169// always has 365d, a week always has 7d, and a day always has 24h. 181// always has 365d, a week always has 7d, and a day always has 24h.
170func ParseDuration(durationStr string) (Duration, error) { 182func ParseDuration(durationStr string) (Duration, error) {
171 matches := durationRE.FindStringSubmatch(durationStr) 183 matches := durationRE.FindStringSubmatch(durationStr)
diff --git a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
index 4c9418f..4c9418f 100644
--- a/vendor/github.com/Sirupsen/logrus/CHANGELOG.md
+++ b/vendor/github.com/sirupsen/logrus/CHANGELOG.md
diff --git a/vendor/github.com/Sirupsen/logrus/LICENSE b/vendor/github.com/sirupsen/logrus/LICENSE
index f090cb4..f090cb4 100644
--- a/vendor/github.com/Sirupsen/logrus/LICENSE
+++ b/vendor/github.com/sirupsen/logrus/LICENSE
diff --git a/vendor/github.com/Sirupsen/logrus/README.md b/vendor/github.com/sirupsen/logrus/README.md
index 640cf61..640cf61 100644
--- a/vendor/github.com/Sirupsen/logrus/README.md
+++ b/vendor/github.com/sirupsen/logrus/README.md
diff --git a/vendor/github.com/Sirupsen/logrus/alt_exit.go b/vendor/github.com/sirupsen/logrus/alt_exit.go
index b4c9e84..b4c9e84 100644
--- a/vendor/github.com/Sirupsen/logrus/alt_exit.go
+++ b/vendor/github.com/sirupsen/logrus/alt_exit.go
diff --git a/vendor/github.com/Sirupsen/logrus/doc.go b/vendor/github.com/sirupsen/logrus/doc.go
index dddd5f8..dddd5f8 100644
--- a/vendor/github.com/Sirupsen/logrus/doc.go
+++ b/vendor/github.com/sirupsen/logrus/doc.go
diff --git a/vendor/github.com/Sirupsen/logrus/entry.go b/vendor/github.com/sirupsen/logrus/entry.go
index 4edbe7a..4edbe7a 100644
--- a/vendor/github.com/Sirupsen/logrus/entry.go
+++ b/vendor/github.com/sirupsen/logrus/entry.go
diff --git a/vendor/github.com/Sirupsen/logrus/exported.go b/vendor/github.com/sirupsen/logrus/exported.go
index 9a0120a..9a0120a 100644
--- a/vendor/github.com/Sirupsen/logrus/exported.go
+++ b/vendor/github.com/sirupsen/logrus/exported.go
diff --git a/vendor/github.com/Sirupsen/logrus/formatter.go b/vendor/github.com/sirupsen/logrus/formatter.go
index b5fbe93..b5fbe93 100644
--- a/vendor/github.com/Sirupsen/logrus/formatter.go
+++ b/vendor/github.com/sirupsen/logrus/formatter.go
diff --git a/vendor/github.com/Sirupsen/logrus/hooks.go b/vendor/github.com/sirupsen/logrus/hooks.go
index 3f151cd..3f151cd 100644
--- a/vendor/github.com/Sirupsen/logrus/hooks.go
+++ b/vendor/github.com/sirupsen/logrus/hooks.go
diff --git a/vendor/github.com/Sirupsen/logrus/json_formatter.go b/vendor/github.com/sirupsen/logrus/json_formatter.go
index 266554e..266554e 100644
--- a/vendor/github.com/Sirupsen/logrus/json_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/json_formatter.go
diff --git a/vendor/github.com/Sirupsen/logrus/logger.go b/vendor/github.com/sirupsen/logrus/logger.go
index b769f3d..b769f3d 100644
--- a/vendor/github.com/Sirupsen/logrus/logger.go
+++ b/vendor/github.com/sirupsen/logrus/logger.go
diff --git a/vendor/github.com/Sirupsen/logrus/logrus.go b/vendor/github.com/sirupsen/logrus/logrus.go
index e596691..e596691 100644
--- a/vendor/github.com/Sirupsen/logrus/logrus.go
+++ b/vendor/github.com/sirupsen/logrus/logrus.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go b/vendor/github.com/sirupsen/logrus/terminal_appengine.go
index e011a86..e011a86 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_appengine.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_appengine.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go b/vendor/github.com/sirupsen/logrus/terminal_bsd.go
index 5f6be4d..5f6be4d 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_bsd.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_bsd.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_linux.go b/vendor/github.com/sirupsen/logrus/terminal_linux.go
index 308160c..308160c 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_linux.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_linux.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go b/vendor/github.com/sirupsen/logrus/terminal_notwindows.go
index 190297a..190297a 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_notwindows.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_notwindows.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go b/vendor/github.com/sirupsen/logrus/terminal_solaris.go
index 3c86b1a..3c86b1a 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_solaris.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_solaris.go
diff --git a/vendor/github.com/Sirupsen/logrus/terminal_windows.go b/vendor/github.com/sirupsen/logrus/terminal_windows.go
index 05d2f91..05d2f91 100644
--- a/vendor/github.com/Sirupsen/logrus/terminal_windows.go
+++ b/vendor/github.com/sirupsen/logrus/terminal_windows.go
diff --git a/vendor/github.com/Sirupsen/logrus/text_formatter.go b/vendor/github.com/sirupsen/logrus/text_formatter.go
index ba88854..ba88854 100644
--- a/vendor/github.com/Sirupsen/logrus/text_formatter.go
+++ b/vendor/github.com/sirupsen/logrus/text_formatter.go
diff --git a/vendor/github.com/Sirupsen/logrus/writer.go b/vendor/github.com/sirupsen/logrus/writer.go
index f74d2aa..f74d2aa 100644
--- a/vendor/github.com/Sirupsen/logrus/writer.go
+++ b/vendor/github.com/sirupsen/logrus/writer.go
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/COPYING b/vendor/gopkg.in/alecthomas/kingpin.v2/COPYING
new file mode 100644
index 0000000..2993ec0
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/COPYING
@@ -0,0 +1,19 @@
1Copyright (C) 2014 Alec Thomas
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/README.md b/vendor/gopkg.in/alecthomas/kingpin.v2/README.md
new file mode 100644
index 0000000..cd4edeb
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/README.md
@@ -0,0 +1,674 @@
1# Kingpin - A Go (golang) command line and flag parser
2[![](https://godoc.org/github.com/alecthomas/kingpin?status.svg)](http://godoc.org/github.com/alecthomas/kingpin) [![Build Status](https://travis-ci.org/alecthomas/kingpin.svg?branch=master)](https://travis-ci.org/alecthomas/kingpin) [![Gitter chat](https://badges.gitter.im/alecthomas.png)](https://gitter.im/alecthomas/Lobby)
3
4
5
6<!-- MarkdownTOC -->
7
8- [Overview](#overview)
9- [Features](#features)
10- [User-visible changes between v1 and v2](#user-visible-changes-between-v1-and-v2)
11 - [Flags can be used at any point after their definition.](#flags-can-be-used-at-any-point-after-their-definition)
12 - [Short flags can be combined with their parameters](#short-flags-can-be-combined-with-their-parameters)
13- [API changes between v1 and v2](#api-changes-between-v1-and-v2)
14- [Versions](#versions)
15 - [V2 is the current stable version](#v2-is-the-current-stable-version)
16 - [V1 is the OLD stable version](#v1-is-the-old-stable-version)
17- [Change History](#change-history)
18- [Examples](#examples)
19 - [Simple Example](#simple-example)
20 - [Complex Example](#complex-example)
21- [Reference Documentation](#reference-documentation)
22 - [Displaying errors and usage information](#displaying-errors-and-usage-information)
23 - [Sub-commands](#sub-commands)
24 - [Custom Parsers](#custom-parsers)
25 - [Repeatable flags](#repeatable-flags)
26 - [Boolean Values](#boolean-values)
27 - [Default Values](#default-values)
28 - [Place-holders in Help](#place-holders-in-help)
29 - [Consuming all remaining arguments](#consuming-all-remaining-arguments)
30 - [Bash/ZSH Shell Completion](#bashzsh-shell-completion)
31 - [Supporting -h for help](#supporting--h-for-help)
32 - [Custom help](#custom-help)
33
34<!-- /MarkdownTOC -->
35
36## Overview
37
38Kingpin is a [fluent-style](http://en.wikipedia.org/wiki/Fluent_interface),
39type-safe command-line parser. It supports flags, nested commands, and
40positional arguments.
41
42Install it with:
43
44 $ go get gopkg.in/alecthomas/kingpin.v2
45
46It looks like this:
47
48```go
49var (
50 verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
51 name = kingpin.Arg("name", "Name of user.").Required().String()
52)
53
54func main() {
55 kingpin.Parse()
56 fmt.Printf("%v, %s\n", *verbose, *name)
57}
58```
59
60More [examples](https://github.com/alecthomas/kingpin/tree/master/_examples) are available.
61
62Second to parsing, providing the user with useful help is probably the most
63important thing a command-line parser does. Kingpin tries to provide detailed
64contextual help if `--help` is encountered at any point in the command line
65(excluding after `--`).
66
67## Features
68
69- Help output that isn't as ugly as sin.
70- Fully [customisable help](#custom-help), via Go templates.
71- Parsed, type-safe flags (`kingpin.Flag("f", "help").Int()`)
72- Parsed, type-safe positional arguments (`kingpin.Arg("a", "help").Int()`).
73- Parsed, type-safe, arbitrarily deep commands (`kingpin.Command("c", "help")`).
74- Support for required flags and required positional arguments (`kingpin.Flag("f", "").Required().Int()`).
75- Support for arbitrarily nested default commands (`command.Default()`).
76- Callbacks per command, flag and argument (`kingpin.Command("c", "").Action(myAction)`).
77- POSIX-style short flag combining (`-a -b` -> `-ab`).
78- Short-flag+parameter combining (`-a parm` -> `-aparm`).
79- Read command-line from files (`@<file>`).
80- Automatically generate man pages (`--help-man`).
81
82## User-visible changes between v1 and v2
83
84### Flags can be used at any point after their definition.
85
86Flags can be specified at any point after their definition, not just
87*immediately after their associated command*. From the chat example below, the
88following used to be required:
89
90```
91$ chat --server=chat.server.com:8080 post --image=~/Downloads/owls.jpg pics
92```
93
94But the following will now work:
95
96```
97$ chat post --server=chat.server.com:8080 --image=~/Downloads/owls.jpg pics
98```
99
100### Short flags can be combined with their parameters
101
102Previously, if a short flag was used, any argument to that flag would have to
103be separated by a space. That is no longer the case.
104
105## API changes between v1 and v2
106
107- `ParseWithFileExpansion()` is gone. The new parser directly supports expanding `@<file>`.
108- Added `FatalUsage()` and `FatalUsageContext()` for displaying an error + usage and terminating.
109- `Dispatch()` renamed to `Action()`.
110- Added `ParseContext()` for parsing a command line into its intermediate context form without executing.
111- Added `Terminate()` function to override the termination function.
112- Added `UsageForContextWithTemplate()` for printing usage via a custom template.
113- Added `UsageTemplate()` for overriding the default template to use. Two templates are included:
114 1. `DefaultUsageTemplate` - default template.
115 2. `CompactUsageTemplate` - compact command template for larger applications.
116
117## Versions
118
119Kingpin uses [gopkg.in](https://gopkg.in/alecthomas/kingpin) for versioning.
120
121The current stable version is [gopkg.in/alecthomas/kingpin.v2](https://gopkg.in/alecthomas/kingpin.v2). The previous version, [gopkg.in/alecthomas/kingpin.v1](https://gopkg.in/alecthomas/kingpin.v1), is deprecated and in maintenance mode.
122
123### [V2](https://gopkg.in/alecthomas/kingpin.v2) is the current stable version
124
125Installation:
126
127```sh
128$ go get gopkg.in/alecthomas/kingpin.v2
129```
130
131### [V1](https://gopkg.in/alecthomas/kingpin.v1) is the OLD stable version
132
133Installation:
134
135```sh
136$ go get gopkg.in/alecthomas/kingpin.v1
137```
138
139## Change History
140
141- *2015-09-19* -- Stable v2.1.0 release.
142 - Added `command.Default()` to specify a default command to use if no other
143 command matches. This allows for convenient user shortcuts.
144 - Exposed `HelpFlag` and `VersionFlag` for further customisation.
145 - `Action()` and `PreAction()` added and both now support an arbitrary
146 number of callbacks.
147 - `kingpin.SeparateOptionalFlagsUsageTemplate`.
148 - `--help-long` and `--help-man` (hidden by default) flags.
149 - Flags are "interspersed" by default, but can be disabled with `app.Interspersed(false)`.
150 - Added flags for all simple builtin types (int8, uint16, etc.) and slice variants.
151 - Use `app.Writer(os.Writer)` to specify the default writer for all output functions.
152 - Dropped `os.Writer` prefix from all printf-like functions.
153
154- *2015-05-22* -- Stable v2.0.0 release.
155 - Initial stable release of v2.0.0.
156 - Fully supports interspersed flags, commands and arguments.
157 - Flags can be present at any point after their logical definition.
158 - Application.Parse() terminates if commands are present and a command is not parsed.
159 - Dispatch() -> Action().
160 - Actions are dispatched after all values are populated.
161 - Override termination function (defaults to os.Exit).
162 - Override output stream (defaults to os.Stderr).
163 - Templatised usage help, with default and compact templates.
164 - Make error/usage functions more consistent.
165 - Support argument expansion from files by default (with @<file>).
166 - Fully public data model is available via .Model().
167 - Parser has been completely refactored.
168 - Parsing and execution has been split into distinct stages.
169 - Use `go generate` to generate repeated flags.
170 - Support combined short-flag+argument: -fARG.
171
172- *2015-01-23* -- Stable v1.3.4 release.
173 - Support "--" for separating flags from positional arguments.
174 - Support loading flags from files (ParseWithFileExpansion()). Use @FILE as an argument.
175 - Add post-app and post-cmd validation hooks. This allows arbitrary validation to be added.
176 - A bunch of improvements to help usage and formatting.
177 - Support arbitrarily nested sub-commands.
178
179- *2014-07-08* -- Stable v1.2.0 release.
180 - Pass any value through to `Strings()` when final argument.
181 Allows for values that look like flags to be processed.
182 - Allow `--help` to be used with commands.
183 - Support `Hidden()` flags.
184 - Parser for [units.Base2Bytes](https://github.com/alecthomas/units)
185 type. Allows for flags like `--ram=512MB` or `--ram=1GB`.
186 - Add an `Enum()` value, allowing only one of a set of values
187 to be selected. eg. `Flag(...).Enum("debug", "info", "warning")`.
188
189- *2014-06-27* -- Stable v1.1.0 release.
190 - Bug fixes.
191 - Always return an error (rather than panicing) when misconfigured.
192 - `OpenFile(flag, perm)` value type added, for finer control over opening files.
193 - Significantly improved usage formatting.
194
195- *2014-06-19* -- Stable v1.0.0 release.
196 - Support [cumulative positional](#consuming-all-remaining-arguments) arguments.
197 - Return error rather than panic when there are fatal errors not caught by
198 the type system. eg. when a default value is invalid.
199 - Use gokpg.in.
200
201- *2014-06-10* -- Place-holder streamlining.
202 - Renamed `MetaVar` to `PlaceHolder`.
203 - Removed `MetaVarFromDefault`. Kingpin now uses [heuristics](#place-holders-in-help)
204 to determine what to display.
205
206## Examples
207
208### Simple Example
209
210Kingpin can be used for simple flag+arg applications like so:
211
212```
213$ ping --help
214usage: ping [<flags>] <ip> [<count>]
215
216Flags:
217 --debug Enable debug mode.
218 --help Show help.
219 -t, --timeout=5s Timeout waiting for ping.
220
221Args:
222 <ip> IP address to ping.
223 [<count>] Number of packets to send
224$ ping 1.2.3.4 5
225Would ping: 1.2.3.4 with timeout 5s and count 0
226```
227
228From the following source:
229
230```go
231package main
232
233import (
234 "fmt"
235
236 "gopkg.in/alecthomas/kingpin.v2"
237)
238
239var (
240 debug = kingpin.Flag("debug", "Enable debug mode.").Bool()
241 timeout = kingpin.Flag("timeout", "Timeout waiting for ping.").Default("5s").OverrideDefaultFromEnvar("PING_TIMEOUT").Short('t').Duration()
242 ip = kingpin.Arg("ip", "IP address to ping.").Required().IP()
243 count = kingpin.Arg("count", "Number of packets to send").Int()
244)
245
246func main() {
247 kingpin.Version("0.0.1")
248 kingpin.Parse()
249 fmt.Printf("Would ping: %s with timeout %s and count %d\n", *ip, *timeout, *count)
250}
251```
252
253### Complex Example
254
255Kingpin can also produce complex command-line applications with global flags,
256subcommands, and per-subcommand flags, like this:
257
258```
259$ chat --help
260usage: chat [<flags>] <command> [<flags>] [<args> ...]
261
262A command-line chat application.
263
264Flags:
265 --help Show help.
266 --debug Enable debug mode.
267 --server=127.0.0.1 Server address.
268
269Commands:
270 help [<command>]
271 Show help for a command.
272
273 register <nick> <name>
274 Register a new user.
275
276 post [<flags>] <channel> [<text>]
277 Post a message to a channel.
278
279$ chat help post
280usage: chat [<flags>] post [<flags>] <channel> [<text>]
281
282Post a message to a channel.
283
284Flags:
285 --image=IMAGE Image to post.
286
287Args:
288 <channel> Channel to post to.
289 [<text>] Text to post.
290
291$ chat post --image=~/Downloads/owls.jpg pics
292...
293```
294
295From this code:
296
297```go
298package main
299
300import (
301 "os"
302 "strings"
303 "gopkg.in/alecthomas/kingpin.v2"
304)
305
306var (
307 app = kingpin.New("chat", "A command-line chat application.")
308 debug = app.Flag("debug", "Enable debug mode.").Bool()
309 serverIP = app.Flag("server", "Server address.").Default("127.0.0.1").IP()
310
311 register = app.Command("register", "Register a new user.")
312 registerNick = register.Arg("nick", "Nickname for user.").Required().String()
313 registerName = register.Arg("name", "Name of user.").Required().String()
314
315 post = app.Command("post", "Post a message to a channel.")
316 postImage = post.Flag("image", "Image to post.").File()
317 postChannel = post.Arg("channel", "Channel to post to.").Required().String()
318 postText = post.Arg("text", "Text to post.").Strings()
319)
320
321func main() {
322 switch kingpin.MustParse(app.Parse(os.Args[1:])) {
323 // Register user
324 case register.FullCommand():
325 println(*registerNick)
326
327 // Post message
328 case post.FullCommand():
329 if *postImage != nil {
330 }
331 text := strings.Join(*postText, " ")
332 println("Post:", text)
333 }
334}
335```
336
337## Reference Documentation
338
339### Displaying errors and usage information
340
341Kingpin exports a set of functions to provide consistent errors and usage
342information to the user.
343
344Error messages look something like this:
345
346 <app>: error: <message>
347
348The functions on `Application` are:
349
350Function | Purpose
351---------|--------------
352`Errorf(format, args)` | Display a printf formatted error to the user.
353`Fatalf(format, args)` | As with Errorf, but also call the termination handler.
354`FatalUsage(format, args)` | As with Fatalf, but also print contextual usage information.
355`FatalUsageContext(context, format, args)` | As with Fatalf, but also print contextual usage information from a `ParseContext`.
356`FatalIfError(err, format, args)` | Conditionally print an error prefixed with format+args, then call the termination handler
357
358There are equivalent global functions in the kingpin namespace for the default
359`kingpin.CommandLine` instance.
360
361### Sub-commands
362
363Kingpin supports nested sub-commands, with separate flag and positional
364arguments per sub-command. Note that positional arguments may only occur after
365sub-commands.
366
367For example:
368
369```go
370var (
371 deleteCommand = kingpin.Command("delete", "Delete an object.")
372 deleteUserCommand = deleteCommand.Command("user", "Delete a user.")
373 deleteUserUIDFlag = deleteUserCommand.Flag("uid", "Delete user by UID rather than username.")
374 deleteUserUsername = deleteUserCommand.Arg("username", "Username to delete.")
375 deletePostCommand = deleteCommand.Command("post", "Delete a post.")
376)
377
378func main() {
379 switch kingpin.Parse() {
380 case "delete user":
381 case "delete post":
382 }
383}
384```
385
386### Custom Parsers
387
388Kingpin supports both flag and positional argument parsers for converting to
389Go types. For example, some included parsers are `Int()`, `Float()`,
390`Duration()` and `ExistingFile()` (see [parsers.go](./parsers.go) for a complete list of included parsers).
391
392Parsers conform to Go's [`flag.Value`](http://godoc.org/flag#Value)
393interface, so any existing implementations will work.
394
395For example, a parser for accumulating HTTP header values might look like this:
396
397```go
398type HTTPHeaderValue http.Header
399
400func (h *HTTPHeaderValue) Set(value string) error {
401 parts := strings.SplitN(value, ":", 2)
402 if len(parts) != 2 {
403 return fmt.Errorf("expected HEADER:VALUE got '%s'", value)
404 }
405 (*http.Header)(h).Add(parts[0], parts[1])
406 return nil
407}
408
409func (h *HTTPHeaderValue) String() string {
410 return ""
411}
412```
413
414As a convenience, I would recommend something like this:
415
416```go
417func HTTPHeader(s Settings) (target *http.Header) {
418 target = &http.Header{}
419 s.SetValue((*HTTPHeaderValue)(target))
420 return
421}
422```
423
424You would use it like so:
425
426```go
427headers = HTTPHeader(kingpin.Flag("header", "Add a HTTP header to the request.").Short('H'))
428```
429
430### Repeatable flags
431
432Depending on the `Value` they hold, some flags may be repeated. The
433`IsCumulative() bool` function on `Value` tells if it's safe to call `Set()`
434multiple times or if an error should be raised if several values are passed.
435
436The built-in `Value`s returning slices and maps, as well as `Counter` are
437examples of `Value`s that make a flag repeatable.
438
439### Boolean values
440
441Boolean values are uniquely managed by Kingpin. Each boolean flag will have a negative complement:
442`--<name>` and `--no-<name>`.
443
444### Default Values
445
446The default value is the zero value for a type. This can be overridden with
447the `Default(value...)` function on flags and arguments. This function accepts
448one or several strings, which are parsed by the value itself, so they *must*
449be compliant with the format expected.
450
451### Place-holders in Help
452
453The place-holder value for a flag is the value used in the help to describe
454the value of a non-boolean flag.
455
456The value provided to PlaceHolder() is used if provided, then the value
457provided by Default() if provided, then finally the capitalised flag name is
458used.
459
460Here are some examples of flags with various permutations:
461
462 --name=NAME // Flag(...).String()
463 --name="Harry" // Flag(...).Default("Harry").String()
464 --name=FULL-NAME // flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
465
466### Consuming all remaining arguments
467
468A common command-line idiom is to use all remaining arguments for some
469purpose. eg. The following command accepts an arbitrary number of
470IP addresses as positional arguments:
471
472 ./cmd ping 10.1.1.1 192.168.1.1
473
474Such arguments are similar to [repeatable flags](#repeatable-flags), but for
475arguments. Therefore they use the same `IsCumulative() bool` function on the
476underlying `Value`, so the built-in `Value`s for which the `Set()` function
477can be called several times will consume multiple arguments.
478
479To implement the above example with a custom `Value`, we might do something
480like this:
481
482```go
483type ipList []net.IP
484
485func (i *ipList) Set(value string) error {
486 if ip := net.ParseIP(value); ip == nil {
487 return fmt.Errorf("'%s' is not an IP address", value)
488 } else {
489 *i = append(*i, ip)
490 return nil
491 }
492}
493
494func (i *ipList) String() string {
495 return ""
496}
497
498func (i *ipList) IsCumulative() bool {
499 return true
500}
501
502func IPList(s Settings) (target *[]net.IP) {
503 target = new([]net.IP)
504 s.SetValue((*ipList)(target))
505 return
506}
507```
508
509And use it like so:
510
511```go
512ips := IPList(kingpin.Arg("ips", "IP addresses to ping."))
513```
514
515### Bash/ZSH Shell Completion
516
517By default, all flags and commands/subcommands generate completions
518internally.
519
520Out of the box, CLI tools using kingpin should be able to take advantage
521of completion hinting for flags and commands. By specifying
522`--completion-bash` as the first argument, your CLI tool will show
523possible subcommands. By ending your argv with `--`, hints for flags
524will be shown.
525
526To allow your end users to take advantage you must package a
527`/etc/bash_completion.d` script with your distribution (or the equivalent
528for your target platform/shell). An alternative is to instruct your end
529user to source a script from their `bash_profile` (or equivalent).
530
531Fortunately Kingpin makes it easy to generate or source a script for use
532with end users shells. `./yourtool --completion-script-bash` and
533`./yourtool --completion-script-zsh` will generate these scripts for you.
534
535**Installation by Package**
536
537For the best user experience, you should bundle your pre-created
538completion script with your CLI tool and install it inside
539`/etc/bash_completion.d` (or equivalent). A good suggestion is to add
540this as an automated step to your build pipeline, in the implementation
541is improved for bug fixed.
542
543**Installation by `bash_profile`**
544
545Alternatively, instruct your users to add an additional statement to
546their `bash_profile` (or equivalent):
547
548```
549eval "$(your-cli-tool --completion-script-bash)"
550```
551
552Or for ZSH
553
554```
555eval "$(your-cli-tool --completion-script-zsh)"
556```
557
558#### Additional API
559To provide more flexibility, a completion option API has been
560exposed for flags to allow user defined completion options, to extend
561completions further than just EnumVar/Enum.
562
563
564**Provide Static Options**
565
566When using an `Enum` or `EnumVar`, users are limited to only the options
567given. Maybe we wish to hint possible options to the user, but also
568allow them to provide their own custom option. `HintOptions` gives
569this functionality to flags.
570
571```
572app := kingpin.New("completion", "My application with bash completion.")
573app.Flag("port", "Provide a port to connect to").
574 Required().
575 HintOptions("80", "443", "8080").
576 IntVar(&c.port)
577```
578
579**Provide Dynamic Options**
580Consider the case that you needed to read a local database or a file to
581provide suggestions. You can dynamically generate the options
582
583```
584func listHosts() []string {
585 // Provide a dynamic list of hosts from a hosts file or otherwise
586 // for bash completion. In this example we simply return static slice.
587
588 // You could use this functionality to reach into a hosts file to provide
589 // completion for a list of known hosts.
590 return []string{"sshhost.example", "webhost.example", "ftphost.example"}
591}
592
593app := kingpin.New("completion", "My application with bash completion.")
594app.Flag("flag-1", "").HintAction(listHosts).String()
595```
596
597**EnumVar/Enum**
598When using `Enum` or `EnumVar`, any provided options will be automatically
599used for bash autocompletion. However, if you wish to provide a subset or
600different options, you can use `HintOptions` or `HintAction` which will override
601the default completion options for `Enum`/`EnumVar`.
602
603
604**Examples**
605You can see an in depth example of the completion API within
606`examples/completion/main.go`
607
608
609### Supporting -h for help
610
611`kingpin.CommandLine.HelpFlag.Short('h')`
612
613### Custom help
614
615Kingpin v2 supports templatised help using the text/template library (actually, [a fork](https://github.com/alecthomas/template)).
616
617You can specify the template to use with the [Application.UsageTemplate()](http://godoc.org/gopkg.in/alecthomas/kingpin.v2#Application.UsageTemplate) function.
618
619There are four included templates: `kingpin.DefaultUsageTemplate` is the default,
620`kingpin.CompactUsageTemplate` provides a more compact representation for more complex command-line structures,
621`kingpin.SeparateOptionalFlagsUsageTemplate` looks like the default template, but splits required
622and optional command flags into separate lists, and `kingpin.ManPageTemplate` is used to generate man pages.
623
624See the above templates for examples of usage, and the the function [UsageForContextWithTemplate()](https://github.com/alecthomas/kingpin/blob/master/usage.go#L198) method for details on the context.
625
626#### Default help template
627
628```
629$ go run ./examples/curl/curl.go --help
630usage: curl [<flags>] <command> [<args> ...]
631
632An example implementation of curl.
633
634Flags:
635 --help Show help.
636 -t, --timeout=5s Set connection timeout.
637 -H, --headers=HEADER=VALUE
638 Add HTTP headers to the request.
639
640Commands:
641 help [<command>...]
642 Show help.
643
644 get url <url>
645 Retrieve a URL.
646
647 get file <file>
648 Retrieve a file.
649
650 post [<flags>] <url>
651 POST a resource.
652```
653
654#### Compact help template
655
656```
657$ go run ./examples/curl/curl.go --help
658usage: curl [<flags>] <command> [<args> ...]
659
660An example implementation of curl.
661
662Flags:
663 --help Show help.
664 -t, --timeout=5s Set connection timeout.
665 -H, --headers=HEADER=VALUE
666 Add HTTP headers to the request.
667
668Commands:
669 help [<command>...]
670 get [<flags>]
671 url <url>
672 file <file>
673 post [<flags>] <url>
674```
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/actions.go b/vendor/gopkg.in/alecthomas/kingpin.v2/actions.go
new file mode 100644
index 0000000..72d6cbd
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/actions.go
@@ -0,0 +1,42 @@
1package kingpin
2
3// Action callback executed at various stages after all values are populated.
4// The application, commands, arguments and flags all have corresponding
5// actions.
6type Action func(*ParseContext) error
7
8type actionMixin struct {
9 actions []Action
10 preActions []Action
11}
12
13type actionApplier interface {
14 applyActions(*ParseContext) error
15 applyPreActions(*ParseContext) error
16}
17
18func (a *actionMixin) addAction(action Action) {
19 a.actions = append(a.actions, action)
20}
21
22func (a *actionMixin) addPreAction(action Action) {
23 a.preActions = append(a.preActions, action)
24}
25
26func (a *actionMixin) applyActions(context *ParseContext) error {
27 for _, action := range a.actions {
28 if err := action(context); err != nil {
29 return err
30 }
31 }
32 return nil
33}
34
35func (a *actionMixin) applyPreActions(context *ParseContext) error {
36 for _, preAction := range a.preActions {
37 if err := preAction(context); err != nil {
38 return err
39 }
40 }
41 return nil
42}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/app.go b/vendor/gopkg.in/alecthomas/kingpin.v2/app.go
new file mode 100644
index 0000000..a5e8b80
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/app.go
@@ -0,0 +1,685 @@
1package kingpin
2
3import (
4 "fmt"
5 "io"
6 "os"
7 "regexp"
8 "strings"
9)
10
11var (
12 ErrCommandNotSpecified = fmt.Errorf("command not specified")
13)
14
15var (
16 envarTransformRegexp = regexp.MustCompile(`[^a-zA-Z0-9_]+`)
17)
18
19type ApplicationValidator func(*Application) error
20
21// An Application contains the definitions of flags, arguments and commands
22// for an application.
23type Application struct {
24 cmdMixin
25 initialized bool
26
27 Name string
28 Help string
29
30 author string
31 version string
32 errorWriter io.Writer // Destination for errors.
33 usageWriter io.Writer // Destination for usage
34 usageTemplate string
35 validator ApplicationValidator
36 terminate func(status int) // See Terminate()
37 noInterspersed bool // can flags be interspersed with args (or must they come first)
38 defaultEnvars bool
39 completion bool
40
41 // Help flag. Exposed for user customisation.
42 HelpFlag *FlagClause
43 // Help command. Exposed for user customisation. May be nil.
44 HelpCommand *CmdClause
45 // Version flag. Exposed for user customisation. May be nil.
46 VersionFlag *FlagClause
47}
48
49// New creates a new Kingpin application instance.
50func New(name, help string) *Application {
51 a := &Application{
52 Name: name,
53 Help: help,
54 errorWriter: os.Stderr, // Left for backwards compatibility purposes.
55 usageWriter: os.Stderr,
56 usageTemplate: DefaultUsageTemplate,
57 terminate: os.Exit,
58 }
59 a.flagGroup = newFlagGroup()
60 a.argGroup = newArgGroup()
61 a.cmdGroup = newCmdGroup(a)
62 a.HelpFlag = a.Flag("help", "Show context-sensitive help (also try --help-long and --help-man).")
63 a.HelpFlag.Bool()
64 a.Flag("help-long", "Generate long help.").Hidden().PreAction(a.generateLongHelp).Bool()
65 a.Flag("help-man", "Generate a man page.").Hidden().PreAction(a.generateManPage).Bool()
66 a.Flag("completion-bash", "Output possible completions for the given args.").Hidden().BoolVar(&a.completion)
67 a.Flag("completion-script-bash", "Generate completion script for bash.").Hidden().PreAction(a.generateBashCompletionScript).Bool()
68 a.Flag("completion-script-zsh", "Generate completion script for ZSH.").Hidden().PreAction(a.generateZSHCompletionScript).Bool()
69
70 return a
71}
72
73func (a *Application) generateLongHelp(c *ParseContext) error {
74 a.Writer(os.Stdout)
75 if err := a.UsageForContextWithTemplate(c, 2, LongHelpTemplate); err != nil {
76 return err
77 }
78 a.terminate(0)
79 return nil
80}
81
82func (a *Application) generateManPage(c *ParseContext) error {
83 a.Writer(os.Stdout)
84 if err := a.UsageForContextWithTemplate(c, 2, ManPageTemplate); err != nil {
85 return err
86 }
87 a.terminate(0)
88 return nil
89}
90
91func (a *Application) generateBashCompletionScript(c *ParseContext) error {
92 a.Writer(os.Stdout)
93 if err := a.UsageForContextWithTemplate(c, 2, BashCompletionTemplate); err != nil {
94 return err
95 }
96 a.terminate(0)
97 return nil
98}
99
100func (a *Application) generateZSHCompletionScript(c *ParseContext) error {
101 a.Writer(os.Stdout)
102 if err := a.UsageForContextWithTemplate(c, 2, ZshCompletionTemplate); err != nil {
103 return err
104 }
105 a.terminate(0)
106 return nil
107}
108
109// DefaultEnvars configures all flags (that do not already have an associated
110// envar) to use a default environment variable in the form "<app>_<flag>".
111//
112// For example, if the application is named "foo" and a flag is named "bar-
113// waz" the environment variable: "FOO_BAR_WAZ".
114func (a *Application) DefaultEnvars() *Application {
115 a.defaultEnvars = true
116 return a
117}
118
119// Terminate specifies the termination handler. Defaults to os.Exit(status).
120// If nil is passed, a no-op function will be used.
121func (a *Application) Terminate(terminate func(int)) *Application {
122 if terminate == nil {
123 terminate = func(int) {}
124 }
125 a.terminate = terminate
126 return a
127}
128
129// Writer specifies the writer to use for usage and errors. Defaults to os.Stderr.
130// DEPRECATED: See ErrorWriter and UsageWriter.
131func (a *Application) Writer(w io.Writer) *Application {
132 a.errorWriter = w
133 a.usageWriter = w
134 return a
135}
136
137// ErrorWriter sets the io.Writer to use for errors.
138func (a *Application) ErrorWriter(w io.Writer) *Application {
139 a.errorWriter = w
140 return a
141}
142
143// UsageWriter sets the io.Writer to use for errors.
144func (a *Application) UsageWriter(w io.Writer) *Application {
145 a.usageWriter = w
146 return a
147}
148
149// UsageTemplate specifies the text template to use when displaying usage
150// information. The default is UsageTemplate.
151func (a *Application) UsageTemplate(template string) *Application {
152 a.usageTemplate = template
153 return a
154}
155
156// Validate sets a validation function to run when parsing.
157func (a *Application) Validate(validator ApplicationValidator) *Application {
158 a.validator = validator
159 return a
160}
161
162// ParseContext parses the given command line and returns the fully populated
163// ParseContext.
164func (a *Application) ParseContext(args []string) (*ParseContext, error) {
165 return a.parseContext(false, args)
166}
167
168func (a *Application) parseContext(ignoreDefault bool, args []string) (*ParseContext, error) {
169 if err := a.init(); err != nil {
170 return nil, err
171 }
172 context := tokenize(args, ignoreDefault)
173 err := parse(context, a)
174 return context, err
175}
176
177// Parse parses command-line arguments. It returns the selected command and an
178// error. The selected command will be a space separated subcommand, if
179// subcommands have been configured.
180//
181// This will populate all flag and argument values, call all callbacks, and so
182// on.
183func (a *Application) Parse(args []string) (command string, err error) {
184
185 context, parseErr := a.ParseContext(args)
186 selected := []string{}
187 var setValuesErr error
188
189 if context == nil {
190 // Since we do not throw error immediately, there could be a case
191 // where a context returns nil. Protect against that.
192 return "", parseErr
193 }
194
195 if err = a.setDefaults(context); err != nil {
196 return "", err
197 }
198
199 selected, setValuesErr = a.setValues(context)
200
201 if err = a.applyPreActions(context, !a.completion); err != nil {
202 return "", err
203 }
204
205 if a.completion {
206 a.generateBashCompletion(context)
207 a.terminate(0)
208 } else {
209 if parseErr != nil {
210 return "", parseErr
211 }
212
213 a.maybeHelp(context)
214 if !context.EOL() {
215 return "", fmt.Errorf("unexpected argument '%s'", context.Peek())
216 }
217
218 if setValuesErr != nil {
219 return "", setValuesErr
220 }
221
222 command, err = a.execute(context, selected)
223 if err == ErrCommandNotSpecified {
224 a.writeUsage(context, nil)
225 }
226 }
227 return command, err
228}
229
230func (a *Application) writeUsage(context *ParseContext, err error) {
231 if err != nil {
232 a.Errorf("%s", err)
233 }
234 if err := a.UsageForContext(context); err != nil {
235 panic(err)
236 }
237 if err != nil {
238 a.terminate(1)
239 } else {
240 a.terminate(0)
241 }
242}
243
244func (a *Application) maybeHelp(context *ParseContext) {
245 for _, element := range context.Elements {
246 if flag, ok := element.Clause.(*FlagClause); ok && flag == a.HelpFlag {
247 // Re-parse the command-line ignoring defaults, so that help works correctly.
248 context, _ = a.parseContext(true, context.rawArgs)
249 a.writeUsage(context, nil)
250 }
251 }
252}
253
254// Version adds a --version flag for displaying the application version.
255func (a *Application) Version(version string) *Application {
256 a.version = version
257 a.VersionFlag = a.Flag("version", "Show application version.").PreAction(func(*ParseContext) error {
258 fmt.Fprintln(a.usageWriter, version)
259 a.terminate(0)
260 return nil
261 })
262 a.VersionFlag.Bool()
263 return a
264}
265
266// Author sets the author output by some help templates.
267func (a *Application) Author(author string) *Application {
268 a.author = author
269 return a
270}
271
272// Action callback to call when all values are populated and parsing is
273// complete, but before any command, flag or argument actions.
274//
275// All Action() callbacks are called in the order they are encountered on the
276// command line.
277func (a *Application) Action(action Action) *Application {
278 a.addAction(action)
279 return a
280}
281
282// Action called after parsing completes but before validation and execution.
283func (a *Application) PreAction(action Action) *Application {
284 a.addPreAction(action)
285 return a
286}
287
288// Command adds a new top-level command.
289func (a *Application) Command(name, help string) *CmdClause {
290 return a.addCommand(name, help)
291}
292
293// Interspersed control if flags can be interspersed with positional arguments
294//
295// true (the default) means that they can, false means that all the flags must appear before the first positional arguments.
296func (a *Application) Interspersed(interspersed bool) *Application {
297 a.noInterspersed = !interspersed
298 return a
299}
300
301func (a *Application) defaultEnvarPrefix() string {
302 if a.defaultEnvars {
303 return a.Name
304 }
305 return ""
306}
307
308func (a *Application) init() error {
309 if a.initialized {
310 return nil
311 }
312 if a.cmdGroup.have() && a.argGroup.have() {
313 return fmt.Errorf("can't mix top-level Arg()s with Command()s")
314 }
315
316 // If we have subcommands, add a help command at the top-level.
317 if a.cmdGroup.have() {
318 var command []string
319 a.HelpCommand = a.Command("help", "Show help.").PreAction(func(context *ParseContext) error {
320 a.Usage(command)
321 a.terminate(0)
322 return nil
323 })
324 a.HelpCommand.Arg("command", "Show help on command.").StringsVar(&command)
325 // Make help first command.
326 l := len(a.commandOrder)
327 a.commandOrder = append(a.commandOrder[l-1:l], a.commandOrder[:l-1]...)
328 }
329
330 if err := a.flagGroup.init(a.defaultEnvarPrefix()); err != nil {
331 return err
332 }
333 if err := a.cmdGroup.init(); err != nil {
334 return err
335 }
336 if err := a.argGroup.init(); err != nil {
337 return err
338 }
339 for _, cmd := range a.commands {
340 if err := cmd.init(); err != nil {
341 return err
342 }
343 }
344 flagGroups := []*flagGroup{a.flagGroup}
345 for _, cmd := range a.commandOrder {
346 if err := checkDuplicateFlags(cmd, flagGroups); err != nil {
347 return err
348 }
349 }
350 a.initialized = true
351 return nil
352}
353
354// Recursively check commands for duplicate flags.
355func checkDuplicateFlags(current *CmdClause, flagGroups []*flagGroup) error {
356 // Check for duplicates.
357 for _, flags := range flagGroups {
358 for _, flag := range current.flagOrder {
359 if flag.shorthand != 0 {
360 if _, ok := flags.short[string(flag.shorthand)]; ok {
361 return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
362 }
363 }
364 if _, ok := flags.long[flag.name]; ok {
365 return fmt.Errorf("duplicate long flag --%s", flag.name)
366 }
367 }
368 }
369 flagGroups = append(flagGroups, current.flagGroup)
370 // Check subcommands.
371 for _, subcmd := range current.commandOrder {
372 if err := checkDuplicateFlags(subcmd, flagGroups); err != nil {
373 return err
374 }
375 }
376 return nil
377}
378
379func (a *Application) execute(context *ParseContext, selected []string) (string, error) {
380 var err error
381
382 if err = a.validateRequired(context); err != nil {
383 return "", err
384 }
385
386 if err = a.applyValidators(context); err != nil {
387 return "", err
388 }
389
390 if err = a.applyActions(context); err != nil {
391 return "", err
392 }
393
394 command := strings.Join(selected, " ")
395 if command == "" && a.cmdGroup.have() {
396 return "", ErrCommandNotSpecified
397 }
398 return command, err
399}
400
401func (a *Application) setDefaults(context *ParseContext) error {
402 flagElements := map[string]*ParseElement{}
403 for _, element := range context.Elements {
404 if flag, ok := element.Clause.(*FlagClause); ok {
405 flagElements[flag.name] = element
406 }
407 }
408
409 argElements := map[string]*ParseElement{}
410 for _, element := range context.Elements {
411 if arg, ok := element.Clause.(*ArgClause); ok {
412 argElements[arg.name] = element
413 }
414 }
415
416 // Check required flags and set defaults.
417 for _, flag := range context.flags.long {
418 if flagElements[flag.name] == nil {
419 if err := flag.setDefault(); err != nil {
420 return err
421 }
422 }
423 }
424
425 for _, arg := range context.arguments.args {
426 if argElements[arg.name] == nil {
427 if err := arg.setDefault(); err != nil {
428 return err
429 }
430 }
431 }
432
433 return nil
434}
435
436func (a *Application) validateRequired(context *ParseContext) error {
437 flagElements := map[string]*ParseElement{}
438 for _, element := range context.Elements {
439 if flag, ok := element.Clause.(*FlagClause); ok {
440 flagElements[flag.name] = element
441 }
442 }
443
444 argElements := map[string]*ParseElement{}
445 for _, element := range context.Elements {
446 if arg, ok := element.Clause.(*ArgClause); ok {
447 argElements[arg.name] = element
448 }
449 }
450
451 // Check required flags and set defaults.
452 for _, flag := range context.flags.long {
453 if flagElements[flag.name] == nil {
454 // Check required flags were provided.
455 if flag.needsValue() {
456 return fmt.Errorf("required flag --%s not provided", flag.name)
457 }
458 }
459 }
460
461 for _, arg := range context.arguments.args {
462 if argElements[arg.name] == nil {
463 if arg.needsValue() {
464 return fmt.Errorf("required argument '%s' not provided", arg.name)
465 }
466 }
467 }
468 return nil
469}
470
471func (a *Application) setValues(context *ParseContext) (selected []string, err error) {
472 // Set all arg and flag values.
473 var (
474 lastCmd *CmdClause
475 flagSet = map[string]struct{}{}
476 )
477 for _, element := range context.Elements {
478 switch clause := element.Clause.(type) {
479 case *FlagClause:
480 if _, ok := flagSet[clause.name]; ok {
481 if v, ok := clause.value.(repeatableFlag); !ok || !v.IsCumulative() {
482 return nil, fmt.Errorf("flag '%s' cannot be repeated", clause.name)
483 }
484 }
485 if err = clause.value.Set(*element.Value); err != nil {
486 return
487 }
488 flagSet[clause.name] = struct{}{}
489
490 case *ArgClause:
491 if err = clause.value.Set(*element.Value); err != nil {
492 return
493 }
494
495 case *CmdClause:
496 if clause.validator != nil {
497 if err = clause.validator(clause); err != nil {
498 return
499 }
500 }
501 selected = append(selected, clause.name)
502 lastCmd = clause
503 }
504 }
505
506 if lastCmd != nil && len(lastCmd.commands) > 0 {
507 return nil, fmt.Errorf("must select a subcommand of '%s'", lastCmd.FullCommand())
508 }
509
510 return
511}
512
513func (a *Application) applyValidators(context *ParseContext) (err error) {
514 // Call command validation functions.
515 for _, element := range context.Elements {
516 if cmd, ok := element.Clause.(*CmdClause); ok && cmd.validator != nil {
517 if err = cmd.validator(cmd); err != nil {
518 return err
519 }
520 }
521 }
522
523 if a.validator != nil {
524 err = a.validator(a)
525 }
526 return err
527}
528
529func (a *Application) applyPreActions(context *ParseContext, dispatch bool) error {
530 if err := a.actionMixin.applyPreActions(context); err != nil {
531 return err
532 }
533 // Dispatch to actions.
534 if dispatch {
535 for _, element := range context.Elements {
536 if applier, ok := element.Clause.(actionApplier); ok {
537 if err := applier.applyPreActions(context); err != nil {
538 return err
539 }
540 }
541 }
542 }
543
544 return nil
545}
546
547func (a *Application) applyActions(context *ParseContext) error {
548 if err := a.actionMixin.applyActions(context); err != nil {
549 return err
550 }
551 // Dispatch to actions.
552 for _, element := range context.Elements {
553 if applier, ok := element.Clause.(actionApplier); ok {
554 if err := applier.applyActions(context); err != nil {
555 return err
556 }
557 }
558 }
559 return nil
560}
561
562// Errorf prints an error message to w in the format "<appname>: error: <message>".
563func (a *Application) Errorf(format string, args ...interface{}) {
564 fmt.Fprintf(a.errorWriter, a.Name+": error: "+format+"\n", args...)
565}
566
567// Fatalf writes a formatted error to w then terminates with exit status 1.
568func (a *Application) Fatalf(format string, args ...interface{}) {
569 a.Errorf(format, args...)
570 a.terminate(1)
571}
572
573// FatalUsage prints an error message followed by usage information, then
574// exits with a non-zero status.
575func (a *Application) FatalUsage(format string, args ...interface{}) {
576 a.Errorf(format, args...)
577 // Force usage to go to error output.
578 a.usageWriter = a.errorWriter
579 a.Usage([]string{})
580 a.terminate(1)
581}
582
583// FatalUsageContext writes a printf formatted error message to w, then usage
584// information for the given ParseContext, before exiting.
585func (a *Application) FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
586 a.Errorf(format, args...)
587 if err := a.UsageForContext(context); err != nil {
588 panic(err)
589 }
590 a.terminate(1)
591}
592
593// FatalIfError prints an error and exits if err is not nil. The error is printed
594// with the given formatted string, if any.
595func (a *Application) FatalIfError(err error, format string, args ...interface{}) {
596 if err != nil {
597 prefix := ""
598 if format != "" {
599 prefix = fmt.Sprintf(format, args...) + ": "
600 }
601 a.Errorf(prefix+"%s", err)
602 a.terminate(1)
603 }
604}
605
606func (a *Application) completionOptions(context *ParseContext) []string {
607 args := context.rawArgs
608
609 var (
610 currArg string
611 prevArg string
612 target cmdMixin
613 )
614
615 numArgs := len(args)
616 if numArgs > 1 {
617 args = args[1:]
618 currArg = args[len(args)-1]
619 }
620 if numArgs > 2 {
621 prevArg = args[len(args)-2]
622 }
623
624 target = a.cmdMixin
625 if context.SelectedCommand != nil {
626 // A subcommand was in use. We will use it as the target
627 target = context.SelectedCommand.cmdMixin
628 }
629
630 if (currArg != "" && strings.HasPrefix(currArg, "--")) || strings.HasPrefix(prevArg, "--") {
631 // Perform completion for A flag. The last/current argument started with "-"
632 var (
633 flagName string // The name of a flag if given (could be half complete)
634 flagValue string // The value assigned to a flag (if given) (could be half complete)
635 )
636
637 if strings.HasPrefix(prevArg, "--") && !strings.HasPrefix(currArg, "--") {
638 // Matches: ./myApp --flag value
639 // Wont Match: ./myApp --flag --
640 flagName = prevArg[2:] // Strip the "--"
641 flagValue = currArg
642 } else if strings.HasPrefix(currArg, "--") {
643 // Matches: ./myApp --flag --
644 // Matches: ./myApp --flag somevalue --
645 // Matches: ./myApp --
646 flagName = currArg[2:] // Strip the "--"
647 }
648
649 options, flagMatched, valueMatched := target.FlagCompletion(flagName, flagValue)
650 if valueMatched {
651 // Value Matched. Show cmdCompletions
652 return target.CmdCompletion(context)
653 }
654
655 // Add top level flags if we're not at the top level and no match was found.
656 if context.SelectedCommand != nil && !flagMatched {
657 topOptions, topFlagMatched, topValueMatched := a.FlagCompletion(flagName, flagValue)
658 if topValueMatched {
659 // Value Matched. Back to cmdCompletions
660 return target.CmdCompletion(context)
661 }
662
663 if topFlagMatched {
664 // Top level had a flag which matched the input. Return it's options.
665 options = topOptions
666 } else {
667 // Add top level flags
668 options = append(options, topOptions...)
669 }
670 }
671 return options
672 }
673
674 // Perform completion for sub commands and arguments.
675 return target.CmdCompletion(context)
676}
677
678func (a *Application) generateBashCompletion(context *ParseContext) {
679 options := a.completionOptions(context)
680 fmt.Printf("%s", strings.Join(options, "\n"))
681}
682
683func envarTransform(name string) string {
684 return strings.ToUpper(envarTransformRegexp.ReplaceAllString(name, "_"))
685}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/args.go b/vendor/gopkg.in/alecthomas/kingpin.v2/args.go
new file mode 100644
index 0000000..3400694
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/args.go
@@ -0,0 +1,184 @@
1package kingpin
2
3import (
4 "fmt"
5)
6
7type argGroup struct {
8 args []*ArgClause
9}
10
11func newArgGroup() *argGroup {
12 return &argGroup{}
13}
14
15func (a *argGroup) have() bool {
16 return len(a.args) > 0
17}
18
19// GetArg gets an argument definition.
20//
21// This allows existing arguments to be modified after definition but before parsing. Useful for
22// modular applications.
23func (a *argGroup) GetArg(name string) *ArgClause {
24 for _, arg := range a.args {
25 if arg.name == name {
26 return arg
27 }
28 }
29 return nil
30}
31
32func (a *argGroup) Arg(name, help string) *ArgClause {
33 arg := newArg(name, help)
34 a.args = append(a.args, arg)
35 return arg
36}
37
38func (a *argGroup) init() error {
39 required := 0
40 seen := map[string]struct{}{}
41 previousArgMustBeLast := false
42 for i, arg := range a.args {
43 if previousArgMustBeLast {
44 return fmt.Errorf("Args() can't be followed by another argument '%s'", arg.name)
45 }
46 if arg.consumesRemainder() {
47 previousArgMustBeLast = true
48 }
49 if _, ok := seen[arg.name]; ok {
50 return fmt.Errorf("duplicate argument '%s'", arg.name)
51 }
52 seen[arg.name] = struct{}{}
53 if arg.required && required != i {
54 return fmt.Errorf("required arguments found after non-required")
55 }
56 if arg.required {
57 required++
58 }
59 if err := arg.init(); err != nil {
60 return err
61 }
62 }
63 return nil
64}
65
66type ArgClause struct {
67 actionMixin
68 parserMixin
69 completionsMixin
70 envarMixin
71 name string
72 help string
73 defaultValues []string
74 required bool
75}
76
77func newArg(name, help string) *ArgClause {
78 a := &ArgClause{
79 name: name,
80 help: help,
81 }
82 return a
83}
84
85func (a *ArgClause) setDefault() error {
86 if a.HasEnvarValue() {
87 if v, ok := a.value.(remainderArg); !ok || !v.IsCumulative() {
88 // Use the value as-is
89 return a.value.Set(a.GetEnvarValue())
90 }
91 for _, value := range a.GetSplitEnvarValue() {
92 if err := a.value.Set(value); err != nil {
93 return err
94 }
95 }
96 return nil
97 }
98
99 if len(a.defaultValues) > 0 {
100 for _, defaultValue := range a.defaultValues {
101 if err := a.value.Set(defaultValue); err != nil {
102 return err
103 }
104 }
105 return nil
106 }
107
108 return nil
109}
110
111func (a *ArgClause) needsValue() bool {
112 haveDefault := len(a.defaultValues) > 0
113 return a.required && !(haveDefault || a.HasEnvarValue())
114}
115
116func (a *ArgClause) consumesRemainder() bool {
117 if r, ok := a.value.(remainderArg); ok {
118 return r.IsCumulative()
119 }
120 return false
121}
122
123// Required arguments must be input by the user. They can not have a Default() value provided.
124func (a *ArgClause) Required() *ArgClause {
125 a.required = true
126 return a
127}
128
129// Default values for this argument. They *must* be parseable by the value of the argument.
130func (a *ArgClause) Default(values ...string) *ArgClause {
131 a.defaultValues = values
132 return a
133}
134
135// Envar overrides the default value(s) for a flag from an environment variable,
136// if it is set. Several default values can be provided by using new lines to
137// separate them.
138func (a *ArgClause) Envar(name string) *ArgClause {
139 a.envar = name
140 a.noEnvar = false
141 return a
142}
143
144// NoEnvar forces environment variable defaults to be disabled for this flag.
145// Most useful in conjunction with app.DefaultEnvars().
146func (a *ArgClause) NoEnvar() *ArgClause {
147 a.envar = ""
148 a.noEnvar = true
149 return a
150}
151
152func (a *ArgClause) Action(action Action) *ArgClause {
153 a.addAction(action)
154 return a
155}
156
157func (a *ArgClause) PreAction(action Action) *ArgClause {
158 a.addPreAction(action)
159 return a
160}
161
162// HintAction registers a HintAction (function) for the arg to provide completions
163func (a *ArgClause) HintAction(action HintAction) *ArgClause {
164 a.addHintAction(action)
165 return a
166}
167
168// HintOptions registers any number of options for the flag to provide completions
169func (a *ArgClause) HintOptions(options ...string) *ArgClause {
170 a.addHintAction(func() []string {
171 return options
172 })
173 return a
174}
175
176func (a *ArgClause) init() error {
177 if a.required && len(a.defaultValues) > 0 {
178 return fmt.Errorf("required argument '%s' with unusable default value", a.name)
179 }
180 if a.value == nil {
181 return fmt.Errorf("no parser defined for arg '%s'", a.name)
182 }
183 return nil
184}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go b/vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go
new file mode 100644
index 0000000..0473b87
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go
@@ -0,0 +1,274 @@
1package kingpin
2
3import (
4 "fmt"
5 "strings"
6)
7
8type cmdMixin struct {
9 *flagGroup
10 *argGroup
11 *cmdGroup
12 actionMixin
13}
14
15// CmdCompletion returns completion options for arguments, if that's where
16// parsing left off, or commands if there aren't any unsatisfied args.
17func (c *cmdMixin) CmdCompletion(context *ParseContext) []string {
18 var options []string
19
20 // Count args already satisfied - we won't complete those, and add any
21 // default commands' alternatives, since they weren't listed explicitly
22 // and the user may want to explicitly list something else.
23 argsSatisfied := 0
24 for _, el := range context.Elements {
25 switch clause := el.Clause.(type) {
26 case *ArgClause:
27 if el.Value != nil && *el.Value != "" {
28 argsSatisfied++
29 }
30 case *CmdClause:
31 options = append(options, clause.completionAlts...)
32 default:
33 }
34 }
35
36 if argsSatisfied < len(c.argGroup.args) {
37 // Since not all args have been satisfied, show options for the current one
38 options = append(options, c.argGroup.args[argsSatisfied].resolveCompletions()...)
39 } else {
40 // If all args are satisfied, then go back to completing commands
41 for _, cmd := range c.cmdGroup.commandOrder {
42 if !cmd.hidden {
43 options = append(options, cmd.name)
44 }
45 }
46 }
47
48 return options
49}
50
51func (c *cmdMixin) FlagCompletion(flagName string, flagValue string) (choices []string, flagMatch bool, optionMatch bool) {
52 // Check if flagName matches a known flag.
53 // If it does, show the options for the flag
54 // Otherwise, show all flags
55
56 options := []string{}
57
58 for _, flag := range c.flagGroup.flagOrder {
59 // Loop through each flag and determine if a match exists
60 if flag.name == flagName {
61 // User typed entire flag. Need to look for flag options.
62 options = flag.resolveCompletions()
63 if len(options) == 0 {
64 // No Options to Choose From, Assume Match.
65 return options, true, true
66 }
67
68 // Loop options to find if the user specified value matches
69 isPrefix := false
70 matched := false
71
72 for _, opt := range options {
73 if flagValue == opt {
74 matched = true
75 } else if strings.HasPrefix(opt, flagValue) {
76 isPrefix = true
77 }
78 }
79
80 // Matched Flag Directly
81 // Flag Value Not Prefixed, and Matched Directly
82 return options, true, !isPrefix && matched
83 }
84
85 if !flag.hidden {
86 options = append(options, "--"+flag.name)
87 }
88 }
89 // No Flag directly matched.
90 return options, false, false
91
92}
93
94type cmdGroup struct {
95 app *Application
96 parent *CmdClause
97 commands map[string]*CmdClause
98 commandOrder []*CmdClause
99}
100
101func (c *cmdGroup) defaultSubcommand() *CmdClause {
102 for _, cmd := range c.commandOrder {
103 if cmd.isDefault {
104 return cmd
105 }
106 }
107 return nil
108}
109
110func (c *cmdGroup) cmdNames() []string {
111 names := make([]string, 0, len(c.commandOrder))
112 for _, cmd := range c.commandOrder {
113 names = append(names, cmd.name)
114 }
115 return names
116}
117
118// GetArg gets a command definition.
119//
120// This allows existing commands to be modified after definition but before parsing. Useful for
121// modular applications.
122func (c *cmdGroup) GetCommand(name string) *CmdClause {
123 return c.commands[name]
124}
125
126func newCmdGroup(app *Application) *cmdGroup {
127 return &cmdGroup{
128 app: app,
129 commands: make(map[string]*CmdClause),
130 }
131}
132
133func (c *cmdGroup) flattenedCommands() (out []*CmdClause) {
134 for _, cmd := range c.commandOrder {
135 if len(cmd.commands) == 0 {
136 out = append(out, cmd)
137 }
138 out = append(out, cmd.flattenedCommands()...)
139 }
140 return
141}
142
143func (c *cmdGroup) addCommand(name, help string) *CmdClause {
144 cmd := newCommand(c.app, name, help)
145 c.commands[name] = cmd
146 c.commandOrder = append(c.commandOrder, cmd)
147 return cmd
148}
149
150func (c *cmdGroup) init() error {
151 seen := map[string]bool{}
152 if c.defaultSubcommand() != nil && !c.have() {
153 return fmt.Errorf("default subcommand %q provided but no subcommands defined", c.defaultSubcommand().name)
154 }
155 defaults := []string{}
156 for _, cmd := range c.commandOrder {
157 if cmd.isDefault {
158 defaults = append(defaults, cmd.name)
159 }
160 if seen[cmd.name] {
161 return fmt.Errorf("duplicate command %q", cmd.name)
162 }
163 seen[cmd.name] = true
164 for _, alias := range cmd.aliases {
165 if seen[alias] {
166 return fmt.Errorf("alias duplicates existing command %q", alias)
167 }
168 c.commands[alias] = cmd
169 }
170 if err := cmd.init(); err != nil {
171 return err
172 }
173 }
174 if len(defaults) > 1 {
175 return fmt.Errorf("more than one default subcommand exists: %s", strings.Join(defaults, ", "))
176 }
177 return nil
178}
179
180func (c *cmdGroup) have() bool {
181 return len(c.commands) > 0
182}
183
184type CmdClauseValidator func(*CmdClause) error
185
186// A CmdClause is a single top-level command. It encapsulates a set of flags
187// and either subcommands or positional arguments.
188type CmdClause struct {
189 cmdMixin
190 app *Application
191 name string
192 aliases []string
193 help string
194 isDefault bool
195 validator CmdClauseValidator
196 hidden bool
197 completionAlts []string
198}
199
200func newCommand(app *Application, name, help string) *CmdClause {
201 c := &CmdClause{
202 app: app,
203 name: name,
204 help: help,
205 }
206 c.flagGroup = newFlagGroup()
207 c.argGroup = newArgGroup()
208 c.cmdGroup = newCmdGroup(app)
209 return c
210}
211
212// Add an Alias for this command.
213func (c *CmdClause) Alias(name string) *CmdClause {
214 c.aliases = append(c.aliases, name)
215 return c
216}
217
218// Validate sets a validation function to run when parsing.
219func (c *CmdClause) Validate(validator CmdClauseValidator) *CmdClause {
220 c.validator = validator
221 return c
222}
223
224func (c *CmdClause) FullCommand() string {
225 out := []string{c.name}
226 for p := c.parent; p != nil; p = p.parent {
227 out = append([]string{p.name}, out...)
228 }
229 return strings.Join(out, " ")
230}
231
232// Command adds a new sub-command.
233func (c *CmdClause) Command(name, help string) *CmdClause {
234 cmd := c.addCommand(name, help)
235 cmd.parent = c
236 return cmd
237}
238
239// Default makes this command the default if commands don't match.
240func (c *CmdClause) Default() *CmdClause {
241 c.isDefault = true
242 return c
243}
244
245func (c *CmdClause) Action(action Action) *CmdClause {
246 c.addAction(action)
247 return c
248}
249
250func (c *CmdClause) PreAction(action Action) *CmdClause {
251 c.addPreAction(action)
252 return c
253}
254
255func (c *CmdClause) init() error {
256 if err := c.flagGroup.init(c.app.defaultEnvarPrefix()); err != nil {
257 return err
258 }
259 if c.argGroup.have() && c.cmdGroup.have() {
260 return fmt.Errorf("can't mix Arg()s with Command()s")
261 }
262 if err := c.argGroup.init(); err != nil {
263 return err
264 }
265 if err := c.cmdGroup.init(); err != nil {
266 return err
267 }
268 return nil
269}
270
271func (c *CmdClause) Hidden() *CmdClause {
272 c.hidden = true
273 return c
274}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/completions.go b/vendor/gopkg.in/alecthomas/kingpin.v2/completions.go
new file mode 100644
index 0000000..6e7b409
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/completions.go
@@ -0,0 +1,33 @@
1package kingpin
2
3// HintAction is a function type who is expected to return a slice of possible
4// command line arguments.
5type HintAction func() []string
6type completionsMixin struct {
7 hintActions []HintAction
8 builtinHintActions []HintAction
9}
10
11func (a *completionsMixin) addHintAction(action HintAction) {
12 a.hintActions = append(a.hintActions, action)
13}
14
15// Allow adding of HintActions which are added internally, ie, EnumVar
16func (a *completionsMixin) addHintActionBuiltin(action HintAction) {
17 a.builtinHintActions = append(a.builtinHintActions, action)
18}
19
20func (a *completionsMixin) resolveCompletions() []string {
21 var hints []string
22
23 options := a.builtinHintActions
24 if len(a.hintActions) > 0 {
25 // User specified their own hintActions. Use those instead.
26 options = a.hintActions
27 }
28
29 for _, hintAction := range options {
30 hints = append(hints, hintAction()...)
31 }
32 return hints
33}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/doc.go b/vendor/gopkg.in/alecthomas/kingpin.v2/doc.go
new file mode 100644
index 0000000..cb951a8
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/doc.go
@@ -0,0 +1,68 @@
1// Package kingpin provides command line interfaces like this:
2//
3// $ chat
4// usage: chat [<flags>] <command> [<flags>] [<args> ...]
5//
6// Flags:
7// --debug enable debug mode
8// --help Show help.
9// --server=127.0.0.1 server address
10//
11// Commands:
12// help <command>
13// Show help for a command.
14//
15// post [<flags>] <channel>
16// Post a message to a channel.
17//
18// register <nick> <name>
19// Register a new user.
20//
21// $ chat help post
22// usage: chat [<flags>] post [<flags>] <channel> [<text>]
23//
24// Post a message to a channel.
25//
26// Flags:
27// --image=IMAGE image to post
28//
29// Args:
30// <channel> channel to post to
31// [<text>] text to post
32// $ chat post --image=~/Downloads/owls.jpg pics
33//
34// From code like this:
35//
36// package main
37//
38// import "gopkg.in/alecthomas/kingpin.v2"
39//
40// var (
41// debug = kingpin.Flag("debug", "enable debug mode").Default("false").Bool()
42// serverIP = kingpin.Flag("server", "server address").Default("127.0.0.1").IP()
43//
44// register = kingpin.Command("register", "Register a new user.")
45// registerNick = register.Arg("nick", "nickname for user").Required().String()
46// registerName = register.Arg("name", "name of user").Required().String()
47//
48// post = kingpin.Command("post", "Post a message to a channel.")
49// postImage = post.Flag("image", "image to post").ExistingFile()
50// postChannel = post.Arg("channel", "channel to post to").Required().String()
51// postText = post.Arg("text", "text to post").String()
52// )
53//
54// func main() {
55// switch kingpin.Parse() {
56// // Register user
57// case "register":
58// println(*registerNick)
59//
60// // Post message
61// case "post":
62// if *postImage != nil {
63// }
64// if *postText != "" {
65// }
66// }
67// }
68package kingpin
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/envar.go b/vendor/gopkg.in/alecthomas/kingpin.v2/envar.go
new file mode 100644
index 0000000..c01a27d
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/envar.go
@@ -0,0 +1,45 @@
1package kingpin
2
3import (
4 "os"
5 "regexp"
6)
7
8var (
9 envVarValuesSeparator = "\r?\n"
10 envVarValuesTrimmer = regexp.MustCompile(envVarValuesSeparator + "$")
11 envVarValuesSplitter = regexp.MustCompile(envVarValuesSeparator)
12)
13
14type envarMixin struct {
15 envar string
16 noEnvar bool
17}
18
19func (e *envarMixin) HasEnvarValue() bool {
20 return e.GetEnvarValue() != ""
21}
22
23func (e *envarMixin) GetEnvarValue() string {
24 if e.noEnvar || e.envar == "" {
25 return ""
26 }
27 return os.Getenv(e.envar)
28}
29
30func (e *envarMixin) GetSplitEnvarValue() []string {
31 values := make([]string, 0)
32
33 envarValue := e.GetEnvarValue()
34 if envarValue == "" {
35 return values
36 }
37
38 // Split by new line to extract multiple values, if any.
39 trimmed := envVarValuesTrimmer.ReplaceAllString(envarValue, "")
40 for _, value := range envVarValuesSplitter.Split(trimmed, -1) {
41 values = append(values, value)
42 }
43
44 return values
45}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/flags.go b/vendor/gopkg.in/alecthomas/kingpin.v2/flags.go
new file mode 100644
index 0000000..8f33721
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/flags.go
@@ -0,0 +1,308 @@
1package kingpin
2
3import (
4 "fmt"
5 "strings"
6)
7
8type flagGroup struct {
9 short map[string]*FlagClause
10 long map[string]*FlagClause
11 flagOrder []*FlagClause
12}
13
14func newFlagGroup() *flagGroup {
15 return &flagGroup{
16 short: map[string]*FlagClause{},
17 long: map[string]*FlagClause{},
18 }
19}
20
21// GetFlag gets a flag definition.
22//
23// This allows existing flags to be modified after definition but before parsing. Useful for
24// modular applications.
25func (f *flagGroup) GetFlag(name string) *FlagClause {
26 return f.long[name]
27}
28
29// Flag defines a new flag with the given long name and help.
30func (f *flagGroup) Flag(name, help string) *FlagClause {
31 flag := newFlag(name, help)
32 f.long[name] = flag
33 f.flagOrder = append(f.flagOrder, flag)
34 return flag
35}
36
37func (f *flagGroup) init(defaultEnvarPrefix string) error {
38 if err := f.checkDuplicates(); err != nil {
39 return err
40 }
41 for _, flag := range f.long {
42 if defaultEnvarPrefix != "" && !flag.noEnvar && flag.envar == "" {
43 flag.envar = envarTransform(defaultEnvarPrefix + "_" + flag.name)
44 }
45 if err := flag.init(); err != nil {
46 return err
47 }
48 if flag.shorthand != 0 {
49 f.short[string(flag.shorthand)] = flag
50 }
51 }
52 return nil
53}
54
55func (f *flagGroup) checkDuplicates() error {
56 seenShort := map[rune]bool{}
57 seenLong := map[string]bool{}
58 for _, flag := range f.flagOrder {
59 if flag.shorthand != 0 {
60 if _, ok := seenShort[flag.shorthand]; ok {
61 return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
62 }
63 seenShort[flag.shorthand] = true
64 }
65 if _, ok := seenLong[flag.name]; ok {
66 return fmt.Errorf("duplicate long flag --%s", flag.name)
67 }
68 seenLong[flag.name] = true
69 }
70 return nil
71}
72
73func (f *flagGroup) parse(context *ParseContext) (*FlagClause, error) {
74 var token *Token
75
76loop:
77 for {
78 token = context.Peek()
79 switch token.Type {
80 case TokenEOL:
81 break loop
82
83 case TokenLong, TokenShort:
84 flagToken := token
85 defaultValue := ""
86 var flag *FlagClause
87 var ok bool
88 invert := false
89
90 name := token.Value
91 if token.Type == TokenLong {
92 flag, ok = f.long[name]
93 if !ok {
94 if strings.HasPrefix(name, "no-") {
95 name = name[3:]
96 invert = true
97 }
98 flag, ok = f.long[name]
99 }
100 if !ok {
101 return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
102 }
103 } else {
104 flag, ok = f.short[name]
105 if !ok {
106 return nil, fmt.Errorf("unknown short flag '%s'", flagToken)
107 }
108 }
109
110 context.Next()
111
112 fb, ok := flag.value.(boolFlag)
113 if ok && fb.IsBoolFlag() {
114 if invert {
115 defaultValue = "false"
116 } else {
117 defaultValue = "true"
118 }
119 } else {
120 if invert {
121 context.Push(token)
122 return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
123 }
124 token = context.Peek()
125 if token.Type != TokenArg {
126 context.Push(token)
127 return nil, fmt.Errorf("expected argument for flag '%s'", flagToken)
128 }
129 context.Next()
130 defaultValue = token.Value
131 }
132
133 context.matchedFlag(flag, defaultValue)
134 return flag, nil
135
136 default:
137 break loop
138 }
139 }
140 return nil, nil
141}
142
143// FlagClause is a fluid interface used to build flags.
144type FlagClause struct {
145 parserMixin
146 actionMixin
147 completionsMixin
148 envarMixin
149 name string
150 shorthand rune
151 help string
152 defaultValues []string
153 placeholder string
154 hidden bool
155}
156
157func newFlag(name, help string) *FlagClause {
158 f := &FlagClause{
159 name: name,
160 help: help,
161 }
162 return f
163}
164
165func (f *FlagClause) setDefault() error {
166 if f.HasEnvarValue() {
167 if v, ok := f.value.(repeatableFlag); !ok || !v.IsCumulative() {
168 // Use the value as-is
169 return f.value.Set(f.GetEnvarValue())
170 } else {
171 for _, value := range f.GetSplitEnvarValue() {
172 if err := f.value.Set(value); err != nil {
173 return err
174 }
175 }
176 return nil
177 }
178 }
179
180 if len(f.defaultValues) > 0 {
181 for _, defaultValue := range f.defaultValues {
182 if err := f.value.Set(defaultValue); err != nil {
183 return err
184 }
185 }
186 return nil
187 }
188
189 return nil
190}
191
192func (f *FlagClause) needsValue() bool {
193 haveDefault := len(f.defaultValues) > 0
194 return f.required && !(haveDefault || f.HasEnvarValue())
195}
196
197func (f *FlagClause) init() error {
198 if f.required && len(f.defaultValues) > 0 {
199 return fmt.Errorf("required flag '--%s' with default value that will never be used", f.name)
200 }
201 if f.value == nil {
202 return fmt.Errorf("no type defined for --%s (eg. .String())", f.name)
203 }
204 if v, ok := f.value.(repeatableFlag); (!ok || !v.IsCumulative()) && len(f.defaultValues) > 1 {
205 return fmt.Errorf("invalid default for '--%s', expecting single value", f.name)
206 }
207 return nil
208}
209
210// Dispatch to the given function after the flag is parsed and validated.
211func (f *FlagClause) Action(action Action) *FlagClause {
212 f.addAction(action)
213 return f
214}
215
216func (f *FlagClause) PreAction(action Action) *FlagClause {
217 f.addPreAction(action)
218 return f
219}
220
221// HintAction registers a HintAction (function) for the flag to provide completions
222func (a *FlagClause) HintAction(action HintAction) *FlagClause {
223 a.addHintAction(action)
224 return a
225}
226
227// HintOptions registers any number of options for the flag to provide completions
228func (a *FlagClause) HintOptions(options ...string) *FlagClause {
229 a.addHintAction(func() []string {
230 return options
231 })
232 return a
233}
234
235func (a *FlagClause) EnumVar(target *string, options ...string) {
236 a.parserMixin.EnumVar(target, options...)
237 a.addHintActionBuiltin(func() []string {
238 return options
239 })
240}
241
242func (a *FlagClause) Enum(options ...string) (target *string) {
243 a.addHintActionBuiltin(func() []string {
244 return options
245 })
246 return a.parserMixin.Enum(options...)
247}
248
249// Default values for this flag. They *must* be parseable by the value of the flag.
250func (f *FlagClause) Default(values ...string) *FlagClause {
251 f.defaultValues = values
252 return f
253}
254
255// DEPRECATED: Use Envar(name) instead.
256func (f *FlagClause) OverrideDefaultFromEnvar(envar string) *FlagClause {
257 return f.Envar(envar)
258}
259
260// Envar overrides the default value(s) for a flag from an environment variable,
261// if it is set. Several default values can be provided by using new lines to
262// separate them.
263func (f *FlagClause) Envar(name string) *FlagClause {
264 f.envar = name
265 f.noEnvar = false
266 return f
267}
268
269// NoEnvar forces environment variable defaults to be disabled for this flag.
270// Most useful in conjunction with app.DefaultEnvars().
271func (f *FlagClause) NoEnvar() *FlagClause {
272 f.envar = ""
273 f.noEnvar = true
274 return f
275}
276
277// PlaceHolder sets the place-holder string used for flag values in the help. The
278// default behaviour is to use the value provided by Default() if provided,
279// then fall back on the capitalized flag name.
280func (f *FlagClause) PlaceHolder(placeholder string) *FlagClause {
281 f.placeholder = placeholder
282 return f
283}
284
285// Hidden hides a flag from usage but still allows it to be used.
286func (f *FlagClause) Hidden() *FlagClause {
287 f.hidden = true
288 return f
289}
290
291// Required makes the flag required. You can not provide a Default() value to a Required() flag.
292func (f *FlagClause) Required() *FlagClause {
293 f.required = true
294 return f
295}
296
297// Short sets the short flag name.
298func (f *FlagClause) Short(name rune) *FlagClause {
299 f.shorthand = name
300 return f
301}
302
303// Bool makes this flag a boolean flag.
304func (f *FlagClause) Bool() (target *bool) {
305 target = new(bool)
306 f.SetValue(newBoolValue(target))
307 return
308}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/global.go b/vendor/gopkg.in/alecthomas/kingpin.v2/global.go
new file mode 100644
index 0000000..10a2913
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/global.go
@@ -0,0 +1,94 @@
1package kingpin
2
3import (
4 "os"
5 "path/filepath"
6)
7
8var (
9 // CommandLine is the default Kingpin parser.
10 CommandLine = New(filepath.Base(os.Args[0]), "")
11 // Global help flag. Exposed for user customisation.
12 HelpFlag = CommandLine.HelpFlag
13 // Top-level help command. Exposed for user customisation. May be nil.
14 HelpCommand = CommandLine.HelpCommand
15 // Global version flag. Exposed for user customisation. May be nil.
16 VersionFlag = CommandLine.VersionFlag
17)
18
19// Command adds a new command to the default parser.
20func Command(name, help string) *CmdClause {
21 return CommandLine.Command(name, help)
22}
23
24// Flag adds a new flag to the default parser.
25func Flag(name, help string) *FlagClause {
26 return CommandLine.Flag(name, help)
27}
28
29// Arg adds a new argument to the top-level of the default parser.
30func Arg(name, help string) *ArgClause {
31 return CommandLine.Arg(name, help)
32}
33
34// Parse and return the selected command. Will call the termination handler if
35// an error is encountered.
36func Parse() string {
37 selected := MustParse(CommandLine.Parse(os.Args[1:]))
38 if selected == "" && CommandLine.cmdGroup.have() {
39 Usage()
40 CommandLine.terminate(0)
41 }
42 return selected
43}
44
45// Errorf prints an error message to stderr.
46func Errorf(format string, args ...interface{}) {
47 CommandLine.Errorf(format, args...)
48}
49
50// Fatalf prints an error message to stderr and exits.
51func Fatalf(format string, args ...interface{}) {
52 CommandLine.Fatalf(format, args...)
53}
54
55// FatalIfError prints an error and exits if err is not nil. The error is printed
56// with the given prefix.
57func FatalIfError(err error, format string, args ...interface{}) {
58 CommandLine.FatalIfError(err, format, args...)
59}
60
61// FatalUsage prints an error message followed by usage information, then
62// exits with a non-zero status.
63func FatalUsage(format string, args ...interface{}) {
64 CommandLine.FatalUsage(format, args...)
65}
66
67// FatalUsageContext writes a printf formatted error message to stderr, then
68// usage information for the given ParseContext, before exiting.
69func FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
70 CommandLine.FatalUsageContext(context, format, args...)
71}
72
73// Usage prints usage to stderr.
74func Usage() {
75 CommandLine.Usage(os.Args[1:])
76}
77
78// Set global usage template to use (defaults to DefaultUsageTemplate).
79func UsageTemplate(template string) *Application {
80 return CommandLine.UsageTemplate(template)
81}
82
83// MustParse can be used with app.Parse(args) to exit with an error if parsing fails.
84func MustParse(command string, err error) string {
85 if err != nil {
86 Fatalf("%s, try --help", err)
87 }
88 return command
89}
90
91// Version adds a flag for displaying the application version number.
92func Version(version string) *Application {
93 return CommandLine.Version(version)
94}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go b/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go
new file mode 100644
index 0000000..a269531
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go
@@ -0,0 +1,9 @@
1// +build appengine !linux,!freebsd,!darwin,!dragonfly,!netbsd,!openbsd
2
3package kingpin
4
5import "io"
6
7func guessWidth(w io.Writer) int {
8 return 80
9}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go b/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go
new file mode 100644
index 0000000..ad8163f
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go
@@ -0,0 +1,38 @@
1// +build !appengine,linux freebsd darwin dragonfly netbsd openbsd
2
3package kingpin
4
5import (
6 "io"
7 "os"
8 "strconv"
9 "syscall"
10 "unsafe"
11)
12
13func guessWidth(w io.Writer) int {
14 // check if COLUMNS env is set to comply with
15 // http://pubs.opengroup.org/onlinepubs/009604499/basedefs/xbd_chap08.html
16 colsStr := os.Getenv("COLUMNS")
17 if colsStr != "" {
18 if cols, err := strconv.Atoi(colsStr); err == nil {
19 return cols
20 }
21 }
22
23 if t, ok := w.(*os.File); ok {
24 fd := t.Fd()
25 var dimensions [4]uint16
26
27 if _, _, err := syscall.Syscall6(
28 syscall.SYS_IOCTL,
29 uintptr(fd),
30 uintptr(syscall.TIOCGWINSZ),
31 uintptr(unsafe.Pointer(&dimensions)),
32 0, 0, 0,
33 ); err == 0 {
34 return int(dimensions[1])
35 }
36 }
37 return 80
38}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/model.go b/vendor/gopkg.in/alecthomas/kingpin.v2/model.go
new file mode 100644
index 0000000..a4ee83b
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/model.go
@@ -0,0 +1,227 @@
1package kingpin
2
3import (
4 "fmt"
5 "strconv"
6 "strings"
7)
8
9// Data model for Kingpin command-line structure.
10
11type FlagGroupModel struct {
12 Flags []*FlagModel
13}
14
15func (f *FlagGroupModel) FlagSummary() string {
16 out := []string{}
17 count := 0
18 for _, flag := range f.Flags {
19 if flag.Name != "help" {
20 count++
21 }
22 if flag.Required {
23 if flag.IsBoolFlag() {
24 out = append(out, fmt.Sprintf("--[no-]%s", flag.Name))
25 } else {
26 out = append(out, fmt.Sprintf("--%s=%s", flag.Name, flag.FormatPlaceHolder()))
27 }
28 }
29 }
30 if count != len(out) {
31 out = append(out, "[<flags>]")
32 }
33 return strings.Join(out, " ")
34}
35
36type FlagModel struct {
37 Name string
38 Help string
39 Short rune
40 Default []string
41 Envar string
42 PlaceHolder string
43 Required bool
44 Hidden bool
45 Value Value
46}
47
48func (f *FlagModel) String() string {
49 return f.Value.String()
50}
51
52func (f *FlagModel) IsBoolFlag() bool {
53 if fl, ok := f.Value.(boolFlag); ok {
54 return fl.IsBoolFlag()
55 }
56 return false
57}
58
59func (f *FlagModel) FormatPlaceHolder() string {
60 if f.PlaceHolder != "" {
61 return f.PlaceHolder
62 }
63 if len(f.Default) > 0 {
64 ellipsis := ""
65 if len(f.Default) > 1 {
66 ellipsis = "..."
67 }
68 if _, ok := f.Value.(*stringValue); ok {
69 return strconv.Quote(f.Default[0]) + ellipsis
70 }
71 return f.Default[0] + ellipsis
72 }
73 return strings.ToUpper(f.Name)
74}
75
76type ArgGroupModel struct {
77 Args []*ArgModel
78}
79
80func (a *ArgGroupModel) ArgSummary() string {
81 depth := 0
82 out := []string{}
83 for _, arg := range a.Args {
84 h := "<" + arg.Name + ">"
85 if !arg.Required {
86 h = "[" + h
87 depth++
88 }
89 out = append(out, h)
90 }
91 out[len(out)-1] = out[len(out)-1] + strings.Repeat("]", depth)
92 return strings.Join(out, " ")
93}
94
95type ArgModel struct {
96 Name string
97 Help string
98 Default []string
99 Envar string
100 Required bool
101 Value Value
102}
103
104func (a *ArgModel) String() string {
105 return a.Value.String()
106}
107
108type CmdGroupModel struct {
109 Commands []*CmdModel
110}
111
112func (c *CmdGroupModel) FlattenedCommands() (out []*CmdModel) {
113 for _, cmd := range c.Commands {
114 if len(cmd.Commands) == 0 {
115 out = append(out, cmd)
116 }
117 out = append(out, cmd.FlattenedCommands()...)
118 }
119 return
120}
121
122type CmdModel struct {
123 Name string
124 Aliases []string
125 Help string
126 FullCommand string
127 Depth int
128 Hidden bool
129 Default bool
130 *FlagGroupModel
131 *ArgGroupModel
132 *CmdGroupModel
133}
134
135func (c *CmdModel) String() string {
136 return c.FullCommand
137}
138
139type ApplicationModel struct {
140 Name string
141 Help string
142 Version string
143 Author string
144 *ArgGroupModel
145 *CmdGroupModel
146 *FlagGroupModel
147}
148
149func (a *Application) Model() *ApplicationModel {
150 return &ApplicationModel{
151 Name: a.Name,
152 Help: a.Help,
153 Version: a.version,
154 Author: a.author,
155 FlagGroupModel: a.flagGroup.Model(),
156 ArgGroupModel: a.argGroup.Model(),
157 CmdGroupModel: a.cmdGroup.Model(),
158 }
159}
160
161func (a *argGroup) Model() *ArgGroupModel {
162 m := &ArgGroupModel{}
163 for _, arg := range a.args {
164 m.Args = append(m.Args, arg.Model())
165 }
166 return m
167}
168
169func (a *ArgClause) Model() *ArgModel {
170 return &ArgModel{
171 Name: a.name,
172 Help: a.help,
173 Default: a.defaultValues,
174 Envar: a.envar,
175 Required: a.required,
176 Value: a.value,
177 }
178}
179
180func (f *flagGroup) Model() *FlagGroupModel {
181 m := &FlagGroupModel{}
182 for _, fl := range f.flagOrder {
183 m.Flags = append(m.Flags, fl.Model())
184 }
185 return m
186}
187
188func (f *FlagClause) Model() *FlagModel {
189 return &FlagModel{
190 Name: f.name,
191 Help: f.help,
192 Short: rune(f.shorthand),
193 Default: f.defaultValues,
194 Envar: f.envar,
195 PlaceHolder: f.placeholder,
196 Required: f.required,
197 Hidden: f.hidden,
198 Value: f.value,
199 }
200}
201
202func (c *cmdGroup) Model() *CmdGroupModel {
203 m := &CmdGroupModel{}
204 for _, cm := range c.commandOrder {
205 m.Commands = append(m.Commands, cm.Model())
206 }
207 return m
208}
209
210func (c *CmdClause) Model() *CmdModel {
211 depth := 0
212 for i := c; i != nil; i = i.parent {
213 depth++
214 }
215 return &CmdModel{
216 Name: c.name,
217 Aliases: c.aliases,
218 Help: c.help,
219 Depth: depth,
220 Hidden: c.hidden,
221 Default: c.isDefault,
222 FullCommand: c.FullCommand(),
223 FlagGroupModel: c.flagGroup.Model(),
224 ArgGroupModel: c.argGroup.Model(),
225 CmdGroupModel: c.cmdGroup.Model(),
226 }
227}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/parser.go b/vendor/gopkg.in/alecthomas/kingpin.v2/parser.go
new file mode 100644
index 0000000..efa198a
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/parser.go
@@ -0,0 +1,382 @@
1package kingpin
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strings"
8 "unicode/utf8"
9)
10
11type TokenType int
12
13// Token types.
14const (
15 TokenShort TokenType = iota
16 TokenLong
17 TokenArg
18 TokenError
19 TokenEOL
20)
21
22func (t TokenType) String() string {
23 switch t {
24 case TokenShort:
25 return "short flag"
26 case TokenLong:
27 return "long flag"
28 case TokenArg:
29 return "argument"
30 case TokenError:
31 return "error"
32 case TokenEOL:
33 return "<EOL>"
34 }
35 return "?"
36}
37
38var (
39 TokenEOLMarker = Token{-1, TokenEOL, ""}
40)
41
42type Token struct {
43 Index int
44 Type TokenType
45 Value string
46}
47
48func (t *Token) Equal(o *Token) bool {
49 return t.Index == o.Index
50}
51
52func (t *Token) IsFlag() bool {
53 return t.Type == TokenShort || t.Type == TokenLong
54}
55
56func (t *Token) IsEOF() bool {
57 return t.Type == TokenEOL
58}
59
60func (t *Token) String() string {
61 switch t.Type {
62 case TokenShort:
63 return "-" + t.Value
64 case TokenLong:
65 return "--" + t.Value
66 case TokenArg:
67 return t.Value
68 case TokenError:
69 return "error: " + t.Value
70 case TokenEOL:
71 return "<EOL>"
72 default:
73 panic("unhandled type")
74 }
75}
76
77// A union of possible elements in a parse stack.
78type ParseElement struct {
79 // Clause is either *CmdClause, *ArgClause or *FlagClause.
80 Clause interface{}
81 // Value is corresponding value for an ArgClause or FlagClause (if any).
82 Value *string
83}
84
85// ParseContext holds the current context of the parser. When passed to
86// Action() callbacks Elements will be fully populated with *FlagClause,
87// *ArgClause and *CmdClause values and their corresponding arguments (if
88// any).
89type ParseContext struct {
90 SelectedCommand *CmdClause
91 ignoreDefault bool
92 argsOnly bool
93 peek []*Token
94 argi int // Index of current command-line arg we're processing.
95 args []string
96 rawArgs []string
97 flags *flagGroup
98 arguments *argGroup
99 argumenti int // Cursor into arguments
100 // Flags, arguments and commands encountered and collected during parse.
101 Elements []*ParseElement
102}
103
104func (p *ParseContext) nextArg() *ArgClause {
105 if p.argumenti >= len(p.arguments.args) {
106 return nil
107 }
108 arg := p.arguments.args[p.argumenti]
109 if !arg.consumesRemainder() {
110 p.argumenti++
111 }
112 return arg
113}
114
115func (p *ParseContext) next() {
116 p.argi++
117 p.args = p.args[1:]
118}
119
120// HasTrailingArgs returns true if there are unparsed command-line arguments.
121// This can occur if the parser can not match remaining arguments.
122func (p *ParseContext) HasTrailingArgs() bool {
123 return len(p.args) > 0
124}
125
126func tokenize(args []string, ignoreDefault bool) *ParseContext {
127 return &ParseContext{
128 ignoreDefault: ignoreDefault,
129 args: args,
130 rawArgs: args,
131 flags: newFlagGroup(),
132 arguments: newArgGroup(),
133 }
134}
135
136func (p *ParseContext) mergeFlags(flags *flagGroup) {
137 for _, flag := range flags.flagOrder {
138 if flag.shorthand != 0 {
139 p.flags.short[string(flag.shorthand)] = flag
140 }
141 p.flags.long[flag.name] = flag
142 p.flags.flagOrder = append(p.flags.flagOrder, flag)
143 }
144}
145
146func (p *ParseContext) mergeArgs(args *argGroup) {
147 for _, arg := range args.args {
148 p.arguments.args = append(p.arguments.args, arg)
149 }
150}
151
152func (p *ParseContext) EOL() bool {
153 return p.Peek().Type == TokenEOL
154}
155
156// Next token in the parse context.
157func (p *ParseContext) Next() *Token {
158 if len(p.peek) > 0 {
159 return p.pop()
160 }
161
162 // End of tokens.
163 if len(p.args) == 0 {
164 return &Token{Index: p.argi, Type: TokenEOL}
165 }
166
167 arg := p.args[0]
168 p.next()
169
170 if p.argsOnly {
171 return &Token{p.argi, TokenArg, arg}
172 }
173
174 // All remaining args are passed directly.
175 if arg == "--" {
176 p.argsOnly = true
177 return p.Next()
178 }
179
180 if strings.HasPrefix(arg, "--") {
181 parts := strings.SplitN(arg[2:], "=", 2)
182 token := &Token{p.argi, TokenLong, parts[0]}
183 if len(parts) == 2 {
184 p.Push(&Token{p.argi, TokenArg, parts[1]})
185 }
186 return token
187 }
188
189 if strings.HasPrefix(arg, "-") {
190 if len(arg) == 1 {
191 return &Token{Index: p.argi, Type: TokenShort}
192 }
193 shortRune, size := utf8.DecodeRuneInString(arg[1:])
194 short := string(shortRune)
195 flag, ok := p.flags.short[short]
196 // Not a known short flag, we'll just return it anyway.
197 if !ok {
198 } else if fb, ok := flag.value.(boolFlag); ok && fb.IsBoolFlag() {
199 // Bool short flag.
200 } else {
201 // Short flag with combined argument: -fARG
202 token := &Token{p.argi, TokenShort, short}
203 if len(arg) > size+1 {
204 p.Push(&Token{p.argi, TokenArg, arg[size+1:]})
205 }
206 return token
207 }
208
209 if len(arg) > size+1 {
210 p.args = append([]string{"-" + arg[size+1:]}, p.args...)
211 }
212 return &Token{p.argi, TokenShort, short}
213 } else if strings.HasPrefix(arg, "@") {
214 expanded, err := ExpandArgsFromFile(arg[1:])
215 if err != nil {
216 return &Token{p.argi, TokenError, err.Error()}
217 }
218 if len(p.args) == 0 {
219 p.args = expanded
220 } else {
221 p.args = append(expanded, p.args...)
222 }
223 return p.Next()
224 }
225
226 return &Token{p.argi, TokenArg, arg}
227}
228
229func (p *ParseContext) Peek() *Token {
230 if len(p.peek) == 0 {
231 return p.Push(p.Next())
232 }
233 return p.peek[len(p.peek)-1]
234}
235
236func (p *ParseContext) Push(token *Token) *Token {
237 p.peek = append(p.peek, token)
238 return token
239}
240
241func (p *ParseContext) pop() *Token {
242 end := len(p.peek) - 1
243 token := p.peek[end]
244 p.peek = p.peek[0:end]
245 return token
246}
247
248func (p *ParseContext) String() string {
249 return p.SelectedCommand.FullCommand()
250}
251
252func (p *ParseContext) matchedFlag(flag *FlagClause, value string) {
253 p.Elements = append(p.Elements, &ParseElement{Clause: flag, Value: &value})
254}
255
256func (p *ParseContext) matchedArg(arg *ArgClause, value string) {
257 p.Elements = append(p.Elements, &ParseElement{Clause: arg, Value: &value})
258}
259
260func (p *ParseContext) matchedCmd(cmd *CmdClause) {
261 p.Elements = append(p.Elements, &ParseElement{Clause: cmd})
262 p.mergeFlags(cmd.flagGroup)
263 p.mergeArgs(cmd.argGroup)
264 p.SelectedCommand = cmd
265}
266
267// Expand arguments from a file. Lines starting with # will be treated as comments.
268func ExpandArgsFromFile(filename string) (out []string, err error) {
269 r, err := os.Open(filename)
270 if err != nil {
271 return nil, err
272 }
273 defer r.Close()
274 scanner := bufio.NewScanner(r)
275 for scanner.Scan() {
276 line := scanner.Text()
277 if strings.HasPrefix(line, "#") {
278 continue
279 }
280 out = append(out, line)
281 }
282 err = scanner.Err()
283 return
284}
285
286func parse(context *ParseContext, app *Application) (err error) {
287 context.mergeFlags(app.flagGroup)
288 context.mergeArgs(app.argGroup)
289
290 cmds := app.cmdGroup
291 ignoreDefault := context.ignoreDefault
292
293loop:
294 for !context.EOL() {
295 token := context.Peek()
296
297 switch token.Type {
298 case TokenLong, TokenShort:
299 if flag, err := context.flags.parse(context); err != nil {
300 if !ignoreDefault {
301 if cmd := cmds.defaultSubcommand(); cmd != nil {
302 cmd.completionAlts = cmds.cmdNames()
303 context.matchedCmd(cmd)
304 cmds = cmd.cmdGroup
305 break
306 }
307 }
308 return err
309 } else if flag == HelpFlag {
310 ignoreDefault = true
311 }
312
313 case TokenArg:
314 if cmds.have() {
315 selectedDefault := false
316 cmd, ok := cmds.commands[token.String()]
317 if !ok {
318 if !ignoreDefault {
319 if cmd = cmds.defaultSubcommand(); cmd != nil {
320 cmd.completionAlts = cmds.cmdNames()
321 selectedDefault = true
322 }
323 }
324 if cmd == nil {
325 return fmt.Errorf("expected command but got %q", token)
326 }
327 }
328 if cmd == HelpCommand {
329 ignoreDefault = true
330 }
331 cmd.completionAlts = nil
332 context.matchedCmd(cmd)
333 cmds = cmd.cmdGroup
334 if !selectedDefault {
335 context.Next()
336 }
337 } else if context.arguments.have() {
338 if app.noInterspersed {
339 // no more flags
340 context.argsOnly = true
341 }
342 arg := context.nextArg()
343 if arg == nil {
344 break loop
345 }
346 context.matchedArg(arg, token.String())
347 context.Next()
348 } else {
349 break loop
350 }
351
352 case TokenEOL:
353 break loop
354 }
355 }
356
357 // Move to innermost default command.
358 for !ignoreDefault {
359 if cmd := cmds.defaultSubcommand(); cmd != nil {
360 cmd.completionAlts = cmds.cmdNames()
361 context.matchedCmd(cmd)
362 cmds = cmd.cmdGroup
363 } else {
364 break
365 }
366 }
367
368 if !context.EOL() {
369 return fmt.Errorf("unexpected %s", context.Peek())
370 }
371
372 // Set defaults for all remaining args.
373 for arg := context.nextArg(); arg != nil && !arg.consumesRemainder(); arg = context.nextArg() {
374 for _, defaultValue := range arg.defaultValues {
375 if err := arg.value.Set(defaultValue); err != nil {
376 return fmt.Errorf("invalid default value '%s' for argument '%s'", defaultValue, arg.name)
377 }
378 }
379 }
380
381 return
382}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go b/vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go
new file mode 100644
index 0000000..d9ad57e
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go
@@ -0,0 +1,212 @@
1package kingpin
2
3import (
4 "net"
5 "net/url"
6 "os"
7 "time"
8
9 "github.com/alecthomas/units"
10)
11
12type Settings interface {
13 SetValue(value Value)
14}
15
16type parserMixin struct {
17 value Value
18 required bool
19}
20
21func (p *parserMixin) SetValue(value Value) {
22 p.value = value
23}
24
25// StringMap provides key=value parsing into a map.
26func (p *parserMixin) StringMap() (target *map[string]string) {
27 target = &(map[string]string{})
28 p.StringMapVar(target)
29 return
30}
31
32// Duration sets the parser to a time.Duration parser.
33func (p *parserMixin) Duration() (target *time.Duration) {
34 target = new(time.Duration)
35 p.DurationVar(target)
36 return
37}
38
39// Bytes parses numeric byte units. eg. 1.5KB
40func (p *parserMixin) Bytes() (target *units.Base2Bytes) {
41 target = new(units.Base2Bytes)
42 p.BytesVar(target)
43 return
44}
45
46// IP sets the parser to a net.IP parser.
47func (p *parserMixin) IP() (target *net.IP) {
48 target = new(net.IP)
49 p.IPVar(target)
50 return
51}
52
53// TCP (host:port) address.
54func (p *parserMixin) TCP() (target **net.TCPAddr) {
55 target = new(*net.TCPAddr)
56 p.TCPVar(target)
57 return
58}
59
60// TCPVar (host:port) address.
61func (p *parserMixin) TCPVar(target **net.TCPAddr) {
62 p.SetValue(newTCPAddrValue(target))
63}
64
65// ExistingFile sets the parser to one that requires and returns an existing file.
66func (p *parserMixin) ExistingFile() (target *string) {
67 target = new(string)
68 p.ExistingFileVar(target)
69 return
70}
71
72// ExistingDir sets the parser to one that requires and returns an existing directory.
73func (p *parserMixin) ExistingDir() (target *string) {
74 target = new(string)
75 p.ExistingDirVar(target)
76 return
77}
78
79// ExistingFileOrDir sets the parser to one that requires and returns an existing file OR directory.
80func (p *parserMixin) ExistingFileOrDir() (target *string) {
81 target = new(string)
82 p.ExistingFileOrDirVar(target)
83 return
84}
85
86// File returns an os.File against an existing file.
87func (p *parserMixin) File() (target **os.File) {
88 target = new(*os.File)
89 p.FileVar(target)
90 return
91}
92
93// File attempts to open a File with os.OpenFile(flag, perm).
94func (p *parserMixin) OpenFile(flag int, perm os.FileMode) (target **os.File) {
95 target = new(*os.File)
96 p.OpenFileVar(target, flag, perm)
97 return
98}
99
100// URL provides a valid, parsed url.URL.
101func (p *parserMixin) URL() (target **url.URL) {
102 target = new(*url.URL)
103 p.URLVar(target)
104 return
105}
106
107// StringMap provides key=value parsing into a map.
108func (p *parserMixin) StringMapVar(target *map[string]string) {
109 p.SetValue(newStringMapValue(target))
110}
111
112// Float sets the parser to a float64 parser.
113func (p *parserMixin) Float() (target *float64) {
114 return p.Float64()
115}
116
117// Float sets the parser to a float64 parser.
118func (p *parserMixin) FloatVar(target *float64) {
119 p.Float64Var(target)
120}
121
122// Duration sets the parser to a time.Duration parser.
123func (p *parserMixin) DurationVar(target *time.Duration) {
124 p.SetValue(newDurationValue(target))
125}
126
127// BytesVar parses numeric byte units. eg. 1.5KB
128func (p *parserMixin) BytesVar(target *units.Base2Bytes) {
129 p.SetValue(newBytesValue(target))
130}
131
132// IP sets the parser to a net.IP parser.
133func (p *parserMixin) IPVar(target *net.IP) {
134 p.SetValue(newIPValue(target))
135}
136
137// ExistingFile sets the parser to one that requires and returns an existing file.
138func (p *parserMixin) ExistingFileVar(target *string) {
139 p.SetValue(newExistingFileValue(target))
140}
141
142// ExistingDir sets the parser to one that requires and returns an existing directory.
143func (p *parserMixin) ExistingDirVar(target *string) {
144 p.SetValue(newExistingDirValue(target))
145}
146
147// ExistingDir sets the parser to one that requires and returns an existing directory.
148func (p *parserMixin) ExistingFileOrDirVar(target *string) {
149 p.SetValue(newExistingFileOrDirValue(target))
150}
151
152// FileVar opens an existing file.
153func (p *parserMixin) FileVar(target **os.File) {
154 p.SetValue(newFileValue(target, os.O_RDONLY, 0))
155}
156
157// OpenFileVar calls os.OpenFile(flag, perm)
158func (p *parserMixin) OpenFileVar(target **os.File, flag int, perm os.FileMode) {
159 p.SetValue(newFileValue(target, flag, perm))
160}
161
162// URL provides a valid, parsed url.URL.
163func (p *parserMixin) URLVar(target **url.URL) {
164 p.SetValue(newURLValue(target))
165}
166
167// URLList provides a parsed list of url.URL values.
168func (p *parserMixin) URLList() (target *[]*url.URL) {
169 target = new([]*url.URL)
170 p.URLListVar(target)
171 return
172}
173
174// URLListVar provides a parsed list of url.URL values.
175func (p *parserMixin) URLListVar(target *[]*url.URL) {
176 p.SetValue(newURLListValue(target))
177}
178
179// Enum allows a value from a set of options.
180func (p *parserMixin) Enum(options ...string) (target *string) {
181 target = new(string)
182 p.EnumVar(target, options...)
183 return
184}
185
186// EnumVar allows a value from a set of options.
187func (p *parserMixin) EnumVar(target *string, options ...string) {
188 p.SetValue(newEnumFlag(target, options...))
189}
190
191// Enums allows a set of values from a set of options.
192func (p *parserMixin) Enums(options ...string) (target *[]string) {
193 target = new([]string)
194 p.EnumsVar(target, options...)
195 return
196}
197
198// EnumVar allows a value from a set of options.
199func (p *parserMixin) EnumsVar(target *[]string, options ...string) {
200 p.SetValue(newEnumsFlag(target, options...))
201}
202
203// A Counter increments a number each time it is encountered.
204func (p *parserMixin) Counter() (target *int) {
205 target = new(int)
206 p.CounterVar(target)
207 return
208}
209
210func (p *parserMixin) CounterVar(target *int) {
211 p.SetValue(newCounterValue(target))
212}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/templates.go b/vendor/gopkg.in/alecthomas/kingpin.v2/templates.go
new file mode 100644
index 0000000..97b5c9f
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/templates.go
@@ -0,0 +1,262 @@
1package kingpin
2
3// Default usage template.
4var DefaultUsageTemplate = `{{define "FormatCommand"}}\
5{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
6{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
7{{end}}\
8
9{{define "FormatCommands"}}\
10{{range .FlattenedCommands}}\
11{{if not .Hidden}}\
12 {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
13{{.Help|Wrap 4}}
14{{end}}\
15{{end}}\
16{{end}}\
17
18{{define "FormatUsage"}}\
19{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
20{{if .Help}}
21{{.Help|Wrap 0}}\
22{{end}}\
23
24{{end}}\
25
26{{if .Context.SelectedCommand}}\
27usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
28{{else}}\
29usage: {{.App.Name}}{{template "FormatUsage" .App}}
30{{end}}\
31{{if .Context.Flags}}\
32Flags:
33{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
34{{end}}\
35{{if .Context.Args}}\
36Args:
37{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
38{{end}}\
39{{if .Context.SelectedCommand}}\
40{{if len .Context.SelectedCommand.Commands}}\
41Subcommands:
42{{template "FormatCommands" .Context.SelectedCommand}}
43{{end}}\
44{{else if .App.Commands}}\
45Commands:
46{{template "FormatCommands" .App}}
47{{end}}\
48`
49
50// Usage template where command's optional flags are listed separately
51var SeparateOptionalFlagsUsageTemplate = `{{define "FormatCommand"}}\
52{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
53{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
54{{end}}\
55
56{{define "FormatCommands"}}\
57{{range .FlattenedCommands}}\
58{{if not .Hidden}}\
59 {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
60{{.Help|Wrap 4}}
61{{end}}\
62{{end}}\
63{{end}}\
64
65{{define "FormatUsage"}}\
66{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
67{{if .Help}}
68{{.Help|Wrap 0}}\
69{{end}}\
70
71{{end}}\
72{{if .Context.SelectedCommand}}\
73usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
74{{else}}\
75usage: {{.App.Name}}{{template "FormatUsage" .App}}
76{{end}}\
77
78{{if .Context.Flags|RequiredFlags}}\
79Required flags:
80{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
81{{end}}\
82{{if .Context.Flags|OptionalFlags}}\
83Optional flags:
84{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
85{{end}}\
86{{if .Context.Args}}\
87Args:
88{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
89{{end}}\
90{{if .Context.SelectedCommand}}\
91Subcommands:
92{{if .Context.SelectedCommand.Commands}}\
93{{template "FormatCommands" .Context.SelectedCommand}}
94{{end}}\
95{{else if .App.Commands}}\
96Commands:
97{{template "FormatCommands" .App}}
98{{end}}\
99`
100
101// Usage template with compactly formatted commands.
102var CompactUsageTemplate = `{{define "FormatCommand"}}\
103{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
104{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
105{{end}}\
106
107{{define "FormatCommandList"}}\
108{{range .}}\
109{{if not .Hidden}}\
110{{.Depth|Indent}}{{.Name}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
111{{end}}\
112{{template "FormatCommandList" .Commands}}\
113{{end}}\
114{{end}}\
115
116{{define "FormatUsage"}}\
117{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
118{{if .Help}}
119{{.Help|Wrap 0}}\
120{{end}}\
121
122{{end}}\
123
124{{if .Context.SelectedCommand}}\
125usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
126{{else}}\
127usage: {{.App.Name}}{{template "FormatUsage" .App}}
128{{end}}\
129{{if .Context.Flags}}\
130Flags:
131{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
132{{end}}\
133{{if .Context.Args}}\
134Args:
135{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
136{{end}}\
137{{if .Context.SelectedCommand}}\
138{{if .Context.SelectedCommand.Commands}}\
139Commands:
140 {{.Context.SelectedCommand}}
141{{template "FormatCommandList" .Context.SelectedCommand.Commands}}
142{{end}}\
143{{else if .App.Commands}}\
144Commands:
145{{template "FormatCommandList" .App.Commands}}
146{{end}}\
147`
148
149var ManPageTemplate = `{{define "FormatFlags"}}\
150{{range .Flags}}\
151{{if not .Hidden}}\
152.TP
153\fB{{if .Short}}-{{.Short|Char}}, {{end}}--{{.Name}}{{if not .IsBoolFlag}}={{.FormatPlaceHolder}}{{end}}\\fR
154{{.Help}}
155{{end}}\
156{{end}}\
157{{end}}\
158
159{{define "FormatCommand"}}\
160{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
161{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}{{if .Default}}*{{end}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
162{{end}}\
163
164{{define "FormatCommands"}}\
165{{range .FlattenedCommands}}\
166{{if not .Hidden}}\
167.SS
168\fB{{.FullCommand}}{{template "FormatCommand" .}}\\fR
169.PP
170{{.Help}}
171{{template "FormatFlags" .}}\
172{{end}}\
173{{end}}\
174{{end}}\
175
176{{define "FormatUsage"}}\
177{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}\\fR
178{{end}}\
179
180.TH {{.App.Name}} 1 {{.App.Version}} "{{.App.Author}}"
181.SH "NAME"
182{{.App.Name}}
183.SH "SYNOPSIS"
184.TP
185\fB{{.App.Name}}{{template "FormatUsage" .App}}
186.SH "DESCRIPTION"
187{{.App.Help}}
188.SH "OPTIONS"
189{{template "FormatFlags" .App}}\
190{{if .App.Commands}}\
191.SH "COMMANDS"
192{{template "FormatCommands" .App}}\
193{{end}}\
194`
195
196// Default usage template.
197var LongHelpTemplate = `{{define "FormatCommand"}}\
198{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
199{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
200{{end}}\
201
202{{define "FormatCommands"}}\
203{{range .FlattenedCommands}}\
204{{if not .Hidden}}\
205 {{.FullCommand}}{{template "FormatCommand" .}}
206{{.Help|Wrap 4}}
207{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
208{{end}}\
209{{end}}\
210{{end}}\
211
212{{define "FormatUsage"}}\
213{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
214{{if .Help}}
215{{.Help|Wrap 0}}\
216{{end}}\
217
218{{end}}\
219
220usage: {{.App.Name}}{{template "FormatUsage" .App}}
221{{if .Context.Flags}}\
222Flags:
223{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
224{{end}}\
225{{if .Context.Args}}\
226Args:
227{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
228{{end}}\
229{{if .App.Commands}}\
230Commands:
231{{template "FormatCommands" .App}}
232{{end}}\
233`
234
235var BashCompletionTemplate = `
236_{{.App.Name}}_bash_autocomplete() {
237 local cur prev opts base
238 COMPREPLY=()
239 cur="${COMP_WORDS[COMP_CWORD]}"
240 opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
241 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
242 return 0
243}
244complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
245
246`
247
248var ZshCompletionTemplate = `
249#compdef {{.App.Name}}
250autoload -U compinit && compinit
251autoload -U bashcompinit && bashcompinit
252
253_{{.App.Name}}_bash_autocomplete() {
254 local cur prev opts base
255 COMPREPLY=()
256 cur="${COMP_WORDS[COMP_CWORD]}"
257 opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
258 COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
259 return 0
260}
261complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
262`
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/usage.go b/vendor/gopkg.in/alecthomas/kingpin.v2/usage.go
new file mode 100644
index 0000000..44af6f6
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/usage.go
@@ -0,0 +1,211 @@
1package kingpin
2
3import (
4 "bytes"
5 "fmt"
6 "go/doc"
7 "io"
8 "strings"
9
10 "github.com/alecthomas/template"
11)
12
13var (
14 preIndent = " "
15)
16
17func formatTwoColumns(w io.Writer, indent, padding, width int, rows [][2]string) {
18 // Find size of first column.
19 s := 0
20 for _, row := range rows {
21 if c := len(row[0]); c > s && c < 30 {
22 s = c
23 }
24 }
25
26 indentStr := strings.Repeat(" ", indent)
27 offsetStr := strings.Repeat(" ", s+padding)
28
29 for _, row := range rows {
30 buf := bytes.NewBuffer(nil)
31 doc.ToText(buf, row[1], "", preIndent, width-s-padding-indent)
32 lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n")
33 fmt.Fprintf(w, "%s%-*s%*s", indentStr, s, row[0], padding, "")
34 if len(row[0]) >= 30 {
35 fmt.Fprintf(w, "\n%s%s", indentStr, offsetStr)
36 }
37 fmt.Fprintf(w, "%s\n", lines[0])
38 for _, line := range lines[1:] {
39 fmt.Fprintf(w, "%s%s%s\n", indentStr, offsetStr, line)
40 }
41 }
42}
43
44// Usage writes application usage to w. It parses args to determine
45// appropriate help context, such as which command to show help for.
46func (a *Application) Usage(args []string) {
47 context, err := a.parseContext(true, args)
48 a.FatalIfError(err, "")
49 if err := a.UsageForContextWithTemplate(context, 2, a.usageTemplate); err != nil {
50 panic(err)
51 }
52}
53
54func formatAppUsage(app *ApplicationModel) string {
55 s := []string{app.Name}
56 if len(app.Flags) > 0 {
57 s = append(s, app.FlagSummary())
58 }
59 if len(app.Args) > 0 {
60 s = append(s, app.ArgSummary())
61 }
62 return strings.Join(s, " ")
63}
64
65func formatCmdUsage(app *ApplicationModel, cmd *CmdModel) string {
66 s := []string{app.Name, cmd.String()}
67 if len(app.Flags) > 0 {
68 s = append(s, app.FlagSummary())
69 }
70 if len(app.Args) > 0 {
71 s = append(s, app.ArgSummary())
72 }
73 return strings.Join(s, " ")
74}
75
76func formatFlag(haveShort bool, flag *FlagModel) string {
77 flagString := ""
78 if flag.Short != 0 {
79 flagString += fmt.Sprintf("-%c, --%s", flag.Short, flag.Name)
80 } else {
81 if haveShort {
82 flagString += fmt.Sprintf(" --%s", flag.Name)
83 } else {
84 flagString += fmt.Sprintf("--%s", flag.Name)
85 }
86 }
87 if !flag.IsBoolFlag() {
88 flagString += fmt.Sprintf("=%s", flag.FormatPlaceHolder())
89 }
90 if v, ok := flag.Value.(repeatableFlag); ok && v.IsCumulative() {
91 flagString += " ..."
92 }
93 return flagString
94}
95
96type templateParseContext struct {
97 SelectedCommand *CmdModel
98 *FlagGroupModel
99 *ArgGroupModel
100}
101
102type templateContext struct {
103 App *ApplicationModel
104 Width int
105 Context *templateParseContext
106}
107
108// UsageForContext displays usage information from a ParseContext (obtained from
109// Application.ParseContext() or Action(f) callbacks).
110func (a *Application) UsageForContext(context *ParseContext) error {
111 return a.UsageForContextWithTemplate(context, 2, a.usageTemplate)
112}
113
114// UsageForContextWithTemplate is the base usage function. You generally don't need to use this.
115func (a *Application) UsageForContextWithTemplate(context *ParseContext, indent int, tmpl string) error {
116 width := guessWidth(a.usageWriter)
117 funcs := template.FuncMap{
118 "Indent": func(level int) string {
119 return strings.Repeat(" ", level*indent)
120 },
121 "Wrap": func(indent int, s string) string {
122 buf := bytes.NewBuffer(nil)
123 indentText := strings.Repeat(" ", indent)
124 doc.ToText(buf, s, indentText, " "+indentText, width-indent)
125 return buf.String()
126 },
127 "FormatFlag": formatFlag,
128 "FlagsToTwoColumns": func(f []*FlagModel) [][2]string {
129 rows := [][2]string{}
130 haveShort := false
131 for _, flag := range f {
132 if flag.Short != 0 {
133 haveShort = true
134 break
135 }
136 }
137 for _, flag := range f {
138 if !flag.Hidden {
139 rows = append(rows, [2]string{formatFlag(haveShort, flag), flag.Help})
140 }
141 }
142 return rows
143 },
144 "RequiredFlags": func(f []*FlagModel) []*FlagModel {
145 requiredFlags := []*FlagModel{}
146 for _, flag := range f {
147 if flag.Required {
148 requiredFlags = append(requiredFlags, flag)
149 }
150 }
151 return requiredFlags
152 },
153 "OptionalFlags": func(f []*FlagModel) []*FlagModel {
154 optionalFlags := []*FlagModel{}
155 for _, flag := range f {
156 if !flag.Required {
157 optionalFlags = append(optionalFlags, flag)
158 }
159 }
160 return optionalFlags
161 },
162 "ArgsToTwoColumns": func(a []*ArgModel) [][2]string {
163 rows := [][2]string{}
164 for _, arg := range a {
165 s := "<" + arg.Name + ">"
166 if !arg.Required {
167 s = "[" + s + "]"
168 }
169 rows = append(rows, [2]string{s, arg.Help})
170 }
171 return rows
172 },
173 "FormatTwoColumns": func(rows [][2]string) string {
174 buf := bytes.NewBuffer(nil)
175 formatTwoColumns(buf, indent, indent, width, rows)
176 return buf.String()
177 },
178 "FormatTwoColumnsWithIndent": func(rows [][2]string, indent, padding int) string {
179 buf := bytes.NewBuffer(nil)
180 formatTwoColumns(buf, indent, padding, width, rows)
181 return buf.String()
182 },
183 "FormatAppUsage": formatAppUsage,
184 "FormatCommandUsage": formatCmdUsage,
185 "IsCumulative": func(value Value) bool {
186 r, ok := value.(remainderArg)
187 return ok && r.IsCumulative()
188 },
189 "Char": func(c rune) string {
190 return string(c)
191 },
192 }
193 t, err := template.New("usage").Funcs(funcs).Parse(tmpl)
194 if err != nil {
195 return err
196 }
197 var selectedCommand *CmdModel
198 if context.SelectedCommand != nil {
199 selectedCommand = context.SelectedCommand.Model()
200 }
201 ctx := templateContext{
202 App: a.Model(),
203 Width: width,
204 Context: &templateParseContext{
205 SelectedCommand: selectedCommand,
206 FlagGroupModel: context.flags.Model(),
207 ArgGroupModel: context.arguments.Model(),
208 },
209 }
210 return t.Execute(a.usageWriter, ctx)
211}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/values.go b/vendor/gopkg.in/alecthomas/kingpin.v2/values.go
new file mode 100644
index 0000000..7ee9a3b
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/values.go
@@ -0,0 +1,470 @@
1package kingpin
2
3//go:generate go run ./cmd/genvalues/main.go
4
5import (
6 "fmt"
7 "net"
8 "net/url"
9 "os"
10 "reflect"
11 "regexp"
12 "strings"
13 "time"
14
15 "github.com/alecthomas/units"
16)
17
18// NOTE: Most of the base type values were lifted from:
19// http://golang.org/src/pkg/flag/flag.go?s=20146:20222
20
21// Value is the interface to the dynamic value stored in a flag.
22// (The default value is represented as a string.)
23//
24// If a Value has an IsBoolFlag() bool method returning true, the command-line
25// parser makes --name equivalent to -name=true rather than using the next
26// command-line argument, and adds a --no-name counterpart for negating the
27// flag.
28type Value interface {
29 String() string
30 Set(string) error
31}
32
33// Getter is an interface that allows the contents of a Value to be retrieved.
34// It wraps the Value interface, rather than being part of it, because it
35// appeared after Go 1 and its compatibility rules. All Value types provided
36// by this package satisfy the Getter interface.
37type Getter interface {
38 Value
39 Get() interface{}
40}
41
42// Optional interface to indicate boolean flags that don't accept a value, and
43// implicitly have a --no-<x> negation counterpart.
44type boolFlag interface {
45 Value
46 IsBoolFlag() bool
47}
48
49// Optional interface for arguments that cumulatively consume all remaining
50// input.
51type remainderArg interface {
52 Value
53 IsCumulative() bool
54}
55
56// Optional interface for flags that can be repeated.
57type repeatableFlag interface {
58 Value
59 IsCumulative() bool
60}
61
62type accumulator struct {
63 element func(value interface{}) Value
64 typ reflect.Type
65 slice reflect.Value
66}
67
68// Use reflection to accumulate values into a slice.
69//
70// target := []string{}
71// newAccumulator(&target, func (value interface{}) Value {
72// return newStringValue(value.(*string))
73// })
74func newAccumulator(slice interface{}, element func(value interface{}) Value) *accumulator {
75 typ := reflect.TypeOf(slice)
76 if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Slice {
77 panic("expected a pointer to a slice")
78 }
79 return &accumulator{
80 element: element,
81 typ: typ.Elem().Elem(),
82 slice: reflect.ValueOf(slice),
83 }
84}
85
86func (a *accumulator) String() string {
87 out := []string{}
88 s := a.slice.Elem()
89 for i := 0; i < s.Len(); i++ {
90 out = append(out, a.element(s.Index(i).Addr().Interface()).String())
91 }
92 return strings.Join(out, ",")
93}
94
95func (a *accumulator) Set(value string) error {
96 e := reflect.New(a.typ)
97 if err := a.element(e.Interface()).Set(value); err != nil {
98 return err
99 }
100 slice := reflect.Append(a.slice.Elem(), e.Elem())
101 a.slice.Elem().Set(slice)
102 return nil
103}
104
105func (a *accumulator) Get() interface{} {
106 return a.slice.Interface()
107}
108
109func (a *accumulator) IsCumulative() bool {
110 return true
111}
112
113func (b *boolValue) IsBoolFlag() bool { return true }
114
115// -- time.Duration Value
116type durationValue time.Duration
117
118func newDurationValue(p *time.Duration) *durationValue {
119 return (*durationValue)(p)
120}
121
122func (d *durationValue) Set(s string) error {
123 v, err := time.ParseDuration(s)
124 *d = durationValue(v)
125 return err
126}
127
128func (d *durationValue) Get() interface{} { return time.Duration(*d) }
129
130func (d *durationValue) String() string { return (*time.Duration)(d).String() }
131
132// -- map[string]string Value
133type stringMapValue map[string]string
134
135func newStringMapValue(p *map[string]string) *stringMapValue {
136 return (*stringMapValue)(p)
137}
138
139var stringMapRegex = regexp.MustCompile("[:=]")
140
141func (s *stringMapValue) Set(value string) error {
142 parts := stringMapRegex.Split(value, 2)
143 if len(parts) != 2 {
144 return fmt.Errorf("expected KEY=VALUE got '%s'", value)
145 }
146 (*s)[parts[0]] = parts[1]
147 return nil
148}
149
150func (s *stringMapValue) Get() interface{} {
151 return (map[string]string)(*s)
152}
153
154func (s *stringMapValue) String() string {
155 return fmt.Sprintf("%s", map[string]string(*s))
156}
157
158func (s *stringMapValue) IsCumulative() bool {
159 return true
160}
161
162// -- net.IP Value
163type ipValue net.IP
164
165func newIPValue(p *net.IP) *ipValue {
166 return (*ipValue)(p)
167}
168
169func (i *ipValue) Set(value string) error {
170 if ip := net.ParseIP(value); ip == nil {
171 return fmt.Errorf("'%s' is not an IP address", value)
172 } else {
173 *i = *(*ipValue)(&ip)
174 return nil
175 }
176}
177
178func (i *ipValue) Get() interface{} {
179 return (net.IP)(*i)
180}
181
182func (i *ipValue) String() string {
183 return (*net.IP)(i).String()
184}
185
186// -- *net.TCPAddr Value
187type tcpAddrValue struct {
188 addr **net.TCPAddr
189}
190
191func newTCPAddrValue(p **net.TCPAddr) *tcpAddrValue {
192 return &tcpAddrValue{p}
193}
194
195func (i *tcpAddrValue) Set(value string) error {
196 if addr, err := net.ResolveTCPAddr("tcp", value); err != nil {
197 return fmt.Errorf("'%s' is not a valid TCP address: %s", value, err)
198 } else {
199 *i.addr = addr
200 return nil
201 }
202}
203
204func (t *tcpAddrValue) Get() interface{} {
205 return (*net.TCPAddr)(*t.addr)
206}
207
208func (i *tcpAddrValue) String() string {
209 return (*i.addr).String()
210}
211
212// -- existingFile Value
213
214type fileStatValue struct {
215 path *string
216 predicate func(os.FileInfo) error
217}
218
219func newFileStatValue(p *string, predicate func(os.FileInfo) error) *fileStatValue {
220 return &fileStatValue{
221 path: p,
222 predicate: predicate,
223 }
224}
225
226func (e *fileStatValue) Set(value string) error {
227 if s, err := os.Stat(value); os.IsNotExist(err) {
228 return fmt.Errorf("path '%s' does not exist", value)
229 } else if err != nil {
230 return err
231 } else if err := e.predicate(s); err != nil {
232 return err
233 }
234 *e.path = value
235 return nil
236}
237
238func (f *fileStatValue) Get() interface{} {
239 return (string)(*f.path)
240}
241
242func (e *fileStatValue) String() string {
243 return *e.path
244}
245
246// -- os.File value
247
248type fileValue struct {
249 f **os.File
250 flag int
251 perm os.FileMode
252}
253
254func newFileValue(p **os.File, flag int, perm os.FileMode) *fileValue {
255 return &fileValue{p, flag, perm}
256}
257
258func (f *fileValue) Set(value string) error {
259 if fd, err := os.OpenFile(value, f.flag, f.perm); err != nil {
260 return err
261 } else {
262 *f.f = fd
263 return nil
264 }
265}
266
267func (f *fileValue) Get() interface{} {
268 return (*os.File)(*f.f)
269}
270
271func (f *fileValue) String() string {
272 if *f.f == nil {
273 return "<nil>"
274 }
275 return (*f.f).Name()
276}
277
278// -- url.URL Value
279type urlValue struct {
280 u **url.URL
281}
282
283func newURLValue(p **url.URL) *urlValue {
284 return &urlValue{p}
285}
286
287func (u *urlValue) Set(value string) error {
288 if url, err := url.Parse(value); err != nil {
289 return fmt.Errorf("invalid URL: %s", err)
290 } else {
291 *u.u = url
292 return nil
293 }
294}
295
296func (u *urlValue) Get() interface{} {
297 return (*url.URL)(*u.u)
298}
299
300func (u *urlValue) String() string {
301 if *u.u == nil {
302 return "<nil>"
303 }
304 return (*u.u).String()
305}
306
307// -- []*url.URL Value
308type urlListValue []*url.URL
309
310func newURLListValue(p *[]*url.URL) *urlListValue {
311 return (*urlListValue)(p)
312}
313
314func (u *urlListValue) Set(value string) error {
315 if url, err := url.Parse(value); err != nil {
316 return fmt.Errorf("invalid URL: %s", err)
317 } else {
318 *u = append(*u, url)
319 return nil
320 }
321}
322
323func (u *urlListValue) Get() interface{} {
324 return ([]*url.URL)(*u)
325}
326
327func (u *urlListValue) String() string {
328 out := []string{}
329 for _, url := range *u {
330 out = append(out, url.String())
331 }
332 return strings.Join(out, ",")
333}
334
335func (u *urlListValue) IsCumulative() bool {
336 return true
337}
338
339// A flag whose value must be in a set of options.
340type enumValue struct {
341 value *string
342 options []string
343}
344
345func newEnumFlag(target *string, options ...string) *enumValue {
346 return &enumValue{
347 value: target,
348 options: options,
349 }
350}
351
352func (a *enumValue) String() string {
353 return *a.value
354}
355
356func (a *enumValue) Set(value string) error {
357 for _, v := range a.options {
358 if v == value {
359 *a.value = value
360 return nil
361 }
362 }
363 return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(a.options, ","), value)
364}
365
366func (e *enumValue) Get() interface{} {
367 return (string)(*e.value)
368}
369
370// -- []string Enum Value
371type enumsValue struct {
372 value *[]string
373 options []string
374}
375
376func newEnumsFlag(target *[]string, options ...string) *enumsValue {
377 return &enumsValue{
378 value: target,
379 options: options,
380 }
381}
382
383func (s *enumsValue) Set(value string) error {
384 for _, v := range s.options {
385 if v == value {
386 *s.value = append(*s.value, value)
387 return nil
388 }
389 }
390 return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(s.options, ","), value)
391}
392
393func (e *enumsValue) Get() interface{} {
394 return ([]string)(*e.value)
395}
396
397func (s *enumsValue) String() string {
398 return strings.Join(*s.value, ",")
399}
400
401func (s *enumsValue) IsCumulative() bool {
402 return true
403}
404
405// -- units.Base2Bytes Value
406type bytesValue units.Base2Bytes
407
408func newBytesValue(p *units.Base2Bytes) *bytesValue {
409 return (*bytesValue)(p)
410}
411
412func (d *bytesValue) Set(s string) error {
413 v, err := units.ParseBase2Bytes(s)
414 *d = bytesValue(v)
415 return err
416}
417
418func (d *bytesValue) Get() interface{} { return units.Base2Bytes(*d) }
419
420func (d *bytesValue) String() string { return (*units.Base2Bytes)(d).String() }
421
422func newExistingFileValue(target *string) *fileStatValue {
423 return newFileStatValue(target, func(s os.FileInfo) error {
424 if s.IsDir() {
425 return fmt.Errorf("'%s' is a directory", s.Name())
426 }
427 return nil
428 })
429}
430
431func newExistingDirValue(target *string) *fileStatValue {
432 return newFileStatValue(target, func(s os.FileInfo) error {
433 if !s.IsDir() {
434 return fmt.Errorf("'%s' is a file", s.Name())
435 }
436 return nil
437 })
438}
439
440func newExistingFileOrDirValue(target *string) *fileStatValue {
441 return newFileStatValue(target, func(s os.FileInfo) error { return nil })
442}
443
444type counterValue int
445
446func newCounterValue(n *int) *counterValue {
447 return (*counterValue)(n)
448}
449
450func (c *counterValue) Set(s string) error {
451 *c++
452 return nil
453}
454
455func (c *counterValue) Get() interface{} { return (int)(*c) }
456func (c *counterValue) IsBoolFlag() bool { return true }
457func (c *counterValue) String() string { return fmt.Sprintf("%d", *c) }
458func (c *counterValue) IsCumulative() bool { return true }
459
460func resolveHost(value string) (net.IP, error) {
461 if ip := net.ParseIP(value); ip != nil {
462 return ip, nil
463 } else {
464 if addr, err := net.ResolveIPAddr("ip", value); err != nil {
465 return nil, err
466 } else {
467 return addr.IP, nil
468 }
469 }
470}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/values.json b/vendor/gopkg.in/alecthomas/kingpin.v2/values.json
new file mode 100644
index 0000000..23c6744
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/values.json
@@ -0,0 +1,25 @@
1[
2 {"type": "bool", "parser": "strconv.ParseBool(s)"},
3 {"type": "string", "parser": "s, error(nil)", "format": "string(*f.v)", "plural": "Strings"},
4 {"type": "uint", "parser": "strconv.ParseUint(s, 0, 64)", "plural": "Uints"},
5 {"type": "uint8", "parser": "strconv.ParseUint(s, 0, 8)"},
6 {"type": "uint16", "parser": "strconv.ParseUint(s, 0, 16)"},
7 {"type": "uint32", "parser": "strconv.ParseUint(s, 0, 32)"},
8 {"type": "uint64", "parser": "strconv.ParseUint(s, 0, 64)"},
9 {"type": "int", "parser": "strconv.ParseFloat(s, 64)", "plural": "Ints"},
10 {"type": "int8", "parser": "strconv.ParseInt(s, 0, 8)"},
11 {"type": "int16", "parser": "strconv.ParseInt(s, 0, 16)"},
12 {"type": "int32", "parser": "strconv.ParseInt(s, 0, 32)"},
13 {"type": "int64", "parser": "strconv.ParseInt(s, 0, 64)"},
14 {"type": "float64", "parser": "strconv.ParseFloat(s, 64)"},
15 {"type": "float32", "parser": "strconv.ParseFloat(s, 32)"},
16 {"name": "Duration", "type": "time.Duration", "no_value_parser": true},
17 {"name": "IP", "type": "net.IP", "no_value_parser": true},
18 {"name": "TCPAddr", "Type": "*net.TCPAddr", "plural": "TCPList", "no_value_parser": true},
19 {"name": "ExistingFile", "Type": "string", "plural": "ExistingFiles", "no_value_parser": true},
20 {"name": "ExistingDir", "Type": "string", "plural": "ExistingDirs", "no_value_parser": true},
21 {"name": "ExistingFileOrDir", "Type": "string", "plural": "ExistingFilesOrDirs", "no_value_parser": true},
22 {"name": "Regexp", "Type": "*regexp.Regexp", "parser": "regexp.Compile(s)"},
23 {"name": "ResolvedIP", "Type": "net.IP", "parser": "resolveHost(s)", "help": "Resolve a hostname or IP to an IP."},
24 {"name": "HexBytes", "Type": "[]byte", "parser": "hex.DecodeString(s)", "help": "Bytes as a hex string."}
25]
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/values_generated.go b/vendor/gopkg.in/alecthomas/kingpin.v2/values_generated.go
new file mode 100644
index 0000000..8d492bf
--- /dev/null
+++ b/vendor/gopkg.in/alecthomas/kingpin.v2/values_generated.go
@@ -0,0 +1,821 @@
1package kingpin
2
3import (
4 "encoding/hex"
5 "fmt"
6 "net"
7 "regexp"
8 "strconv"
9 "time"
10)
11
12// This file is autogenerated by "go generate .". Do not modify.
13
14// -- bool Value
15type boolValue struct{ v *bool }
16
17func newBoolValue(p *bool) *boolValue {
18 return &boolValue{p}
19}
20
21func (f *boolValue) Set(s string) error {
22 v, err := strconv.ParseBool(s)
23 if err == nil {
24 *f.v = (bool)(v)
25 }
26 return err
27}
28
29func (f *boolValue) Get() interface{} { return (bool)(*f.v) }
30
31func (f *boolValue) String() string { return fmt.Sprintf("%v", *f.v) }
32
33// Bool parses the next command-line value as bool.
34func (p *parserMixin) Bool() (target *bool) {
35 target = new(bool)
36 p.BoolVar(target)
37 return
38}
39
40func (p *parserMixin) BoolVar(target *bool) {
41 p.SetValue(newBoolValue(target))
42}
43
44// BoolList accumulates bool values into a slice.
45func (p *parserMixin) BoolList() (target *[]bool) {
46 target = new([]bool)
47 p.BoolListVar(target)
48 return
49}
50
51func (p *parserMixin) BoolListVar(target *[]bool) {
52 p.SetValue(newAccumulator(target, func(v interface{}) Value {
53 return newBoolValue(v.(*bool))
54 }))
55}
56
57// -- string Value
58type stringValue struct{ v *string }
59
60func newStringValue(p *string) *stringValue {
61 return &stringValue{p}
62}
63
64func (f *stringValue) Set(s string) error {
65 v, err := s, error(nil)
66 if err == nil {
67 *f.v = (string)(v)
68 }
69 return err
70}
71
72func (f *stringValue) Get() interface{} { return (string)(*f.v) }
73
74func (f *stringValue) String() string { return string(*f.v) }
75
76// String parses the next command-line value as string.
77func (p *parserMixin) String() (target *string) {
78 target = new(string)
79 p.StringVar(target)
80 return
81}
82
83func (p *parserMixin) StringVar(target *string) {
84 p.SetValue(newStringValue(target))
85}
86
87// Strings accumulates string values into a slice.
88func (p *parserMixin) Strings() (target *[]string) {
89 target = new([]string)
90 p.StringsVar(target)
91 return
92}
93
94func (p *parserMixin) StringsVar(target *[]string) {
95 p.SetValue(newAccumulator(target, func(v interface{}) Value {
96 return newStringValue(v.(*string))
97 }))
98}
99
100// -- uint Value
101type uintValue struct{ v *uint }
102
103func newUintValue(p *uint) *uintValue {
104 return &uintValue{p}
105}
106
107func (f *uintValue) Set(s string) error {
108 v, err := strconv.ParseUint(s, 0, 64)
109 if err == nil {
110 *f.v = (uint)(v)
111 }
112 return err
113}
114
115func (f *uintValue) Get() interface{} { return (uint)(*f.v) }
116
117func (f *uintValue) String() string { return fmt.Sprintf("%v", *f.v) }
118
119// Uint parses the next command-line value as uint.
120func (p *parserMixin) Uint() (target *uint) {
121 target = new(uint)
122 p.UintVar(target)
123 return
124}
125
126func (p *parserMixin) UintVar(target *uint) {
127 p.SetValue(newUintValue(target))
128}
129
130// Uints accumulates uint values into a slice.
131func (p *parserMixin) Uints() (target *[]uint) {
132 target = new([]uint)
133 p.UintsVar(target)
134 return
135}
136
137func (p *parserMixin) UintsVar(target *[]uint) {
138 p.SetValue(newAccumulator(target, func(v interface{}) Value {
139 return newUintValue(v.(*uint))
140 }))
141}
142
143// -- uint8 Value
144type uint8Value struct{ v *uint8 }
145
146func newUint8Value(p *uint8) *uint8Value {
147 return &uint8Value{p}
148}
149
150func (f *uint8Value) Set(s string) error {
151 v, err := strconv.ParseUint(s, 0, 8)
152 if err == nil {
153 *f.v = (uint8)(v)
154 }
155 return err
156}
157
158func (f *uint8Value) Get() interface{} { return (uint8)(*f.v) }
159
160func (f *uint8Value) String() string { return fmt.Sprintf("%v", *f.v) }
161
162// Uint8 parses the next command-line value as uint8.
163func (p *parserMixin) Uint8() (target *uint8) {
164 target = new(uint8)
165 p.Uint8Var(target)
166 return
167}
168
169func (p *parserMixin) Uint8Var(target *uint8) {
170 p.SetValue(newUint8Value(target))
171}
172
173// Uint8List accumulates uint8 values into a slice.
174func (p *parserMixin) Uint8List() (target *[]uint8) {
175 target = new([]uint8)
176 p.Uint8ListVar(target)
177 return
178}
179
180func (p *parserMixin) Uint8ListVar(target *[]uint8) {
181 p.SetValue(newAccumulator(target, func(v interface{}) Value {
182 return newUint8Value(v.(*uint8))
183 }))
184}
185
186// -- uint16 Value
187type uint16Value struct{ v *uint16 }
188
189func newUint16Value(p *uint16) *uint16Value {
190 return &uint16Value{p}
191}
192
193func (f *uint16Value) Set(s string) error {
194 v, err := strconv.ParseUint(s, 0, 16)
195 if err == nil {
196 *f.v = (uint16)(v)
197 }
198 return err
199}
200
201func (f *uint16Value) Get() interface{} { return (uint16)(*f.v) }
202
203func (f *uint16Value) String() string { return fmt.Sprintf("%v", *f.v) }
204
205// Uint16 parses the next command-line value as uint16.
206func (p *parserMixin) Uint16() (target *uint16) {
207 target = new(uint16)
208 p.Uint16Var(target)
209 return
210}
211
212func (p *parserMixin) Uint16Var(target *uint16) {
213 p.SetValue(newUint16Value(target))
214}
215
216// Uint16List accumulates uint16 values into a slice.
217func (p *parserMixin) Uint16List() (target *[]uint16) {
218 target = new([]uint16)
219 p.Uint16ListVar(target)
220 return
221}
222
223func (p *parserMixin) Uint16ListVar(target *[]uint16) {
224 p.SetValue(newAccumulator(target, func(v interface{}) Value {
225 return newUint16Value(v.(*uint16))
226 }))
227}
228
229// -- uint32 Value
230type uint32Value struct{ v *uint32 }
231
232func newUint32Value(p *uint32) *uint32Value {
233 return &uint32Value{p}
234}
235
236func (f *uint32Value) Set(s string) error {
237 v, err := strconv.ParseUint(s, 0, 32)
238 if err == nil {
239 *f.v = (uint32)(v)
240 }
241 return err
242}
243
244func (f *uint32Value) Get() interface{} { return (uint32)(*f.v) }
245
246func (f *uint32Value) String() string { return fmt.Sprintf("%v", *f.v) }
247
248// Uint32 parses the next command-line value as uint32.
249func (p *parserMixin) Uint32() (target *uint32) {
250 target = new(uint32)
251 p.Uint32Var(target)
252 return
253}
254
255func (p *parserMixin) Uint32Var(target *uint32) {
256 p.SetValue(newUint32Value(target))
257}
258
259// Uint32List accumulates uint32 values into a slice.
260func (p *parserMixin) Uint32List() (target *[]uint32) {
261 target = new([]uint32)
262 p.Uint32ListVar(target)
263 return
264}
265
266func (p *parserMixin) Uint32ListVar(target *[]uint32) {
267 p.SetValue(newAccumulator(target, func(v interface{}) Value {
268 return newUint32Value(v.(*uint32))
269 }))
270}
271
272// -- uint64 Value
273type uint64Value struct{ v *uint64 }
274
275func newUint64Value(p *uint64) *uint64Value {
276 return &uint64Value{p}
277}
278
279func (f *uint64Value) Set(s string) error {
280 v, err := strconv.ParseUint(s, 0, 64)
281 if err == nil {
282 *f.v = (uint64)(v)
283 }
284 return err
285}
286
287func (f *uint64Value) Get() interface{} { return (uint64)(*f.v) }
288
289func (f *uint64Value) String() string { return fmt.Sprintf("%v", *f.v) }
290
291// Uint64 parses the next command-line value as uint64.
292func (p *parserMixin) Uint64() (target *uint64) {
293 target = new(uint64)
294 p.Uint64Var(target)
295 return
296}
297
298func (p *parserMixin) Uint64Var(target *uint64) {
299 p.SetValue(newUint64Value(target))
300}
301
302// Uint64List accumulates uint64 values into a slice.
303func (p *parserMixin) Uint64List() (target *[]uint64) {
304 target = new([]uint64)
305 p.Uint64ListVar(target)
306 return
307}
308
309func (p *parserMixin) Uint64ListVar(target *[]uint64) {
310 p.SetValue(newAccumulator(target, func(v interface{}) Value {
311 return newUint64Value(v.(*uint64))
312 }))
313}
314
315// -- int Value
316type intValue struct{ v *int }
317
318func newIntValue(p *int) *intValue {
319 return &intValue{p}
320}
321
322func (f *intValue) Set(s string) error {
323 v, err := strconv.ParseFloat(s, 64)
324 if err == nil {
325 *f.v = (int)(v)
326 }
327 return err
328}
329
330func (f *intValue) Get() interface{} { return (int)(*f.v) }
331
332func (f *intValue) String() string { return fmt.Sprintf("%v", *f.v) }
333
334// Int parses the next command-line value as int.
335func (p *parserMixin) Int() (target *int) {
336 target = new(int)
337 p.IntVar(target)
338 return
339}
340
341func (p *parserMixin) IntVar(target *int) {
342 p.SetValue(newIntValue(target))
343}
344
345// Ints accumulates int values into a slice.
346func (p *parserMixin) Ints() (target *[]int) {
347 target = new([]int)
348 p.IntsVar(target)
349 return
350}
351
352func (p *parserMixin) IntsVar(target *[]int) {
353 p.SetValue(newAccumulator(target, func(v interface{}) Value {
354 return newIntValue(v.(*int))
355 }))
356}
357
358// -- int8 Value
359type int8Value struct{ v *int8 }
360
361func newInt8Value(p *int8) *int8Value {
362 return &int8Value{p}
363}
364
365func (f *int8Value) Set(s string) error {
366 v, err := strconv.ParseInt(s, 0, 8)
367 if err == nil {
368 *f.v = (int8)(v)
369 }
370 return err
371}
372
373func (f *int8Value) Get() interface{} { return (int8)(*f.v) }
374
375func (f *int8Value) String() string { return fmt.Sprintf("%v", *f.v) }
376
377// Int8 parses the next command-line value as int8.
378func (p *parserMixin) Int8() (target *int8) {
379 target = new(int8)
380 p.Int8Var(target)
381 return
382}
383
384func (p *parserMixin) Int8Var(target *int8) {
385 p.SetValue(newInt8Value(target))
386}
387
388// Int8List accumulates int8 values into a slice.
389func (p *parserMixin) Int8List() (target *[]int8) {
390 target = new([]int8)
391 p.Int8ListVar(target)
392 return
393}
394
395func (p *parserMixin) Int8ListVar(target *[]int8) {
396 p.SetValue(newAccumulator(target, func(v interface{}) Value {
397 return newInt8Value(v.(*int8))
398 }))
399}
400
401// -- int16 Value
402type int16Value struct{ v *int16 }
403
404func newInt16Value(p *int16) *int16Value {
405 return &int16Value{p}
406}
407
408func (f *int16Value) Set(s string) error {
409 v, err := strconv.ParseInt(s, 0, 16)
410 if err == nil {
411 *f.v = (int16)(v)
412 }
413 return err
414}
415
416func (f *int16Value) Get() interface{} { return (int16)(*f.v) }
417
418func (f *int16Value) String() string { return fmt.Sprintf("%v", *f.v) }
419
420// Int16 parses the next command-line value as int16.
421func (p *parserMixin) Int16() (target *int16) {
422 target = new(int16)
423 p.Int16Var(target)
424 return
425}
426
427func (p *parserMixin) Int16Var(target *int16) {
428 p.SetValue(newInt16Value(target))
429}
430
431// Int16List accumulates int16 values into a slice.
432func (p *parserMixin) Int16List() (target *[]int16) {
433 target = new([]int16)
434 p.Int16ListVar(target)
435 return
436}
437
438func (p *parserMixin) Int16ListVar(target *[]int16) {
439 p.SetValue(newAccumulator(target, func(v interface{}) Value {
440 return newInt16Value(v.(*int16))
441 }))
442}
443
444// -- int32 Value
445type int32Value struct{ v *int32 }
446
447func newInt32Value(p *int32) *int32Value {
448 return &int32Value{p}
449}
450
451func (f *int32Value) Set(s string) error {
452 v, err := strconv.ParseInt(s, 0, 32)
453 if err == nil {
454 *f.v = (int32)(v)
455 }
456 return err
457}
458
459func (f *int32Value) Get() interface{} { return (int32)(*f.v) }
460
461func (f *int32Value) String() string { return fmt.Sprintf("%v", *f.v) }
462
463// Int32 parses the next command-line value as int32.
464func (p *parserMixin) Int32() (target *int32) {
465 target = new(int32)
466 p.Int32Var(target)
467 return
468}
469
470func (p *parserMixin) Int32Var(target *int32) {
471 p.SetValue(newInt32Value(target))
472}
473
474// Int32List accumulates int32 values into a slice.
475func (p *parserMixin) Int32List() (target *[]int32) {
476 target = new([]int32)
477 p.Int32ListVar(target)
478 return
479}
480
481func (p *parserMixin) Int32ListVar(target *[]int32) {
482 p.SetValue(newAccumulator(target, func(v interface{}) Value {
483 return newInt32Value(v.(*int32))
484 }))
485}
486
487// -- int64 Value
488type int64Value struct{ v *int64 }
489
490func newInt64Value(p *int64) *int64Value {
491 return &int64Value{p}
492}
493
494func (f *int64Value) Set(s string) error {
495 v, err := strconv.ParseInt(s, 0, 64)
496 if err == nil {
497 *f.v = (int64)(v)
498 }
499 return err
500}
501
502func (f *int64Value) Get() interface{} { return (int64)(*f.v) }
503
504func (f *int64Value) String() string { return fmt.Sprintf("%v", *f.v) }
505
506// Int64 parses the next command-line value as int64.
507func (p *parserMixin) Int64() (target *int64) {
508 target = new(int64)
509 p.Int64Var(target)
510 return
511}
512
513func (p *parserMixin) Int64Var(target *int64) {
514 p.SetValue(newInt64Value(target))
515}
516
517// Int64List accumulates int64 values into a slice.
518func (p *parserMixin) Int64List() (target *[]int64) {
519 target = new([]int64)
520 p.Int64ListVar(target)
521 return
522}
523
524func (p *parserMixin) Int64ListVar(target *[]int64) {
525 p.SetValue(newAccumulator(target, func(v interface{}) Value {
526 return newInt64Value(v.(*int64))
527 }))
528}
529
530// -- float64 Value
531type float64Value struct{ v *float64 }
532
533func newFloat64Value(p *float64) *float64Value {
534 return &float64Value{p}
535}
536
537func (f *float64Value) Set(s string) error {
538 v, err := strconv.ParseFloat(s, 64)
539 if err == nil {
540 *f.v = (float64)(v)
541 }
542 return err
543}
544
545func (f *float64Value) Get() interface{} { return (float64)(*f.v) }
546
547func (f *float64Value) String() string { return fmt.Sprintf("%v", *f.v) }
548
549// Float64 parses the next command-line value as float64.
550func (p *parserMixin) Float64() (target *float64) {
551 target = new(float64)
552 p.Float64Var(target)
553 return
554}
555
556func (p *parserMixin) Float64Var(target *float64) {
557 p.SetValue(newFloat64Value(target))
558}
559
560// Float64List accumulates float64 values into a slice.
561func (p *parserMixin) Float64List() (target *[]float64) {
562 target = new([]float64)
563 p.Float64ListVar(target)
564 return
565}
566
567func (p *parserMixin) Float64ListVar(target *[]float64) {
568 p.SetValue(newAccumulator(target, func(v interface{}) Value {
569 return newFloat64Value(v.(*float64))
570 }))
571}
572
573// -- float32 Value
574type float32Value struct{ v *float32 }
575
576func newFloat32Value(p *float32) *float32Value {
577 return &float32Value{p}
578}
579
580func (f *float32Value) Set(s string) error {
581 v, err := strconv.ParseFloat(s, 32)
582 if err == nil {
583 *f.v = (float32)(v)
584 }
585 return err
586}
587
588func (f *float32Value) Get() interface{} { return (float32)(*f.v) }
589
590func (f *float32Value) String() string { return fmt.Sprintf("%v", *f.v) }
591
592// Float32 parses the next command-line value as float32.
593func (p *parserMixin) Float32() (target *float32) {
594 target = new(float32)
595 p.Float32Var(target)
596 return
597}
598
599func (p *parserMixin) Float32Var(target *float32) {
600 p.SetValue(newFloat32Value(target))
601}
602
603// Float32List accumulates float32 values into a slice.
604func (p *parserMixin) Float32List() (target *[]float32) {
605 target = new([]float32)
606 p.Float32ListVar(target)
607 return
608}
609
610func (p *parserMixin) Float32ListVar(target *[]float32) {
611 p.SetValue(newAccumulator(target, func(v interface{}) Value {
612 return newFloat32Value(v.(*float32))
613 }))
614}
615
616// DurationList accumulates time.Duration values into a slice.
617func (p *parserMixin) DurationList() (target *[]time.Duration) {
618 target = new([]time.Duration)
619 p.DurationListVar(target)
620 return
621}
622
623func (p *parserMixin) DurationListVar(target *[]time.Duration) {
624 p.SetValue(newAccumulator(target, func(v interface{}) Value {
625 return newDurationValue(v.(*time.Duration))
626 }))
627}
628
629// IPList accumulates net.IP values into a slice.
630func (p *parserMixin) IPList() (target *[]net.IP) {
631 target = new([]net.IP)
632 p.IPListVar(target)
633 return
634}
635
636func (p *parserMixin) IPListVar(target *[]net.IP) {
637 p.SetValue(newAccumulator(target, func(v interface{}) Value {
638 return newIPValue(v.(*net.IP))
639 }))
640}
641
642// TCPList accumulates *net.TCPAddr values into a slice.
643func (p *parserMixin) TCPList() (target *[]*net.TCPAddr) {
644 target = new([]*net.TCPAddr)
645 p.TCPListVar(target)
646 return
647}
648
649func (p *parserMixin) TCPListVar(target *[]*net.TCPAddr) {
650 p.SetValue(newAccumulator(target, func(v interface{}) Value {
651 return newTCPAddrValue(v.(**net.TCPAddr))
652 }))
653}
654
655// ExistingFiles accumulates string values into a slice.
656func (p *parserMixin) ExistingFiles() (target *[]string) {
657 target = new([]string)
658 p.ExistingFilesVar(target)
659 return
660}
661
662func (p *parserMixin) ExistingFilesVar(target *[]string) {
663 p.SetValue(newAccumulator(target, func(v interface{}) Value {
664 return newExistingFileValue(v.(*string))
665 }))
666}
667
668// ExistingDirs accumulates string values into a slice.
669func (p *parserMixin) ExistingDirs() (target *[]string) {
670 target = new([]string)
671 p.ExistingDirsVar(target)
672 return
673}
674
675func (p *parserMixin) ExistingDirsVar(target *[]string) {
676 p.SetValue(newAccumulator(target, func(v interface{}) Value {
677 return newExistingDirValue(v.(*string))
678 }))
679}
680
681// ExistingFilesOrDirs accumulates string values into a slice.
682func (p *parserMixin) ExistingFilesOrDirs() (target *[]string) {
683 target = new([]string)
684 p.ExistingFilesOrDirsVar(target)
685 return
686}
687
688func (p *parserMixin) ExistingFilesOrDirsVar(target *[]string) {
689 p.SetValue(newAccumulator(target, func(v interface{}) Value {
690 return newExistingFileOrDirValue(v.(*string))
691 }))
692}
693
694// -- *regexp.Regexp Value
695type regexpValue struct{ v **regexp.Regexp }
696
697func newRegexpValue(p **regexp.Regexp) *regexpValue {
698 return &regexpValue{p}
699}
700
701func (f *regexpValue) Set(s string) error {
702 v, err := regexp.Compile(s)
703 if err == nil {
704 *f.v = (*regexp.Regexp)(v)
705 }
706 return err
707}
708
709func (f *regexpValue) Get() interface{} { return (*regexp.Regexp)(*f.v) }
710
711func (f *regexpValue) String() string { return fmt.Sprintf("%v", *f.v) }
712
713// Regexp parses the next command-line value as *regexp.Regexp.
714func (p *parserMixin) Regexp() (target **regexp.Regexp) {
715 target = new(*regexp.Regexp)
716 p.RegexpVar(target)
717 return
718}
719
720func (p *parserMixin) RegexpVar(target **regexp.Regexp) {
721 p.SetValue(newRegexpValue(target))
722}
723
724// RegexpList accumulates *regexp.Regexp values into a slice.
725func (p *parserMixin) RegexpList() (target *[]*regexp.Regexp) {
726 target = new([]*regexp.Regexp)
727 p.RegexpListVar(target)
728 return
729}
730
731func (p *parserMixin) RegexpListVar(target *[]*regexp.Regexp) {
732 p.SetValue(newAccumulator(target, func(v interface{}) Value {
733 return newRegexpValue(v.(**regexp.Regexp))
734 }))
735}
736
737// -- net.IP Value
738type resolvedIPValue struct{ v *net.IP }
739
740func newResolvedIPValue(p *net.IP) *resolvedIPValue {
741 return &resolvedIPValue{p}
742}
743
744func (f *resolvedIPValue) Set(s string) error {
745 v, err := resolveHost(s)
746 if err == nil {
747 *f.v = (net.IP)(v)
748 }
749 return err
750}
751
752func (f *resolvedIPValue) Get() interface{} { return (net.IP)(*f.v) }
753
754func (f *resolvedIPValue) String() string { return fmt.Sprintf("%v", *f.v) }
755
756// Resolve a hostname or IP to an IP.
757func (p *parserMixin) ResolvedIP() (target *net.IP) {
758 target = new(net.IP)
759 p.ResolvedIPVar(target)
760 return
761}
762
763func (p *parserMixin) ResolvedIPVar(target *net.IP) {
764 p.SetValue(newResolvedIPValue(target))
765}
766
767// ResolvedIPList accumulates net.IP values into a slice.
768func (p *parserMixin) ResolvedIPList() (target *[]net.IP) {
769 target = new([]net.IP)
770 p.ResolvedIPListVar(target)
771 return
772}
773
774func (p *parserMixin) ResolvedIPListVar(target *[]net.IP) {
775 p.SetValue(newAccumulator(target, func(v interface{}) Value {
776 return newResolvedIPValue(v.(*net.IP))
777 }))
778}
779
780// -- []byte Value
781type hexBytesValue struct{ v *[]byte }
782
783func newHexBytesValue(p *[]byte) *hexBytesValue {
784 return &hexBytesValue{p}
785}
786
787func (f *hexBytesValue) Set(s string) error {
788 v, err := hex.DecodeString(s)
789 if err == nil {
790 *f.v = ([]byte)(v)
791 }
792 return err
793}
794
795func (f *hexBytesValue) Get() interface{} { return ([]byte)(*f.v) }
796
797func (f *hexBytesValue) String() string { return fmt.Sprintf("%v", *f.v) }
798
799// Bytes as a hex string.
800func (p *parserMixin) HexBytes() (target *[]byte) {
801 target = new([]byte)
802 p.HexBytesVar(target)
803 return
804}
805
806func (p *parserMixin) HexBytesVar(target *[]byte) {
807 p.SetValue(newHexBytesValue(target))
808}
809
810// HexBytesList accumulates []byte values into a slice.
811func (p *parserMixin) HexBytesList() (target *[][]byte) {
812 target = new([][]byte)
813 p.HexBytesListVar(target)
814 return
815}
816
817func (p *parserMixin) HexBytesListVar(target *[][]byte) {
818 p.SetValue(newAccumulator(target, func(v interface{}) Value {
819 return newHexBytesValue(v.(*[]byte))
820 }))
821}
diff --git a/vendor/vendor.json b/vendor/vendor.json
index 35e4218..4de5950 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -4,11 +4,29 @@
4 "package": [ 4 "package": [
5 { 5 {
6 "checksumSHA1": "0Tugz8gj9KqqVj6JLkXUA7BXas4=", 6 "checksumSHA1": "0Tugz8gj9KqqVj6JLkXUA7BXas4=",
7 "path": "github.com/Sirupsen/logrus", 7 "path": "github.com/sirupsen/logrus",
8 "revision": "0208149b40d863d2c1a2f8fe5753096a9cf2cc8b", 8 "revision": "0208149b40d863d2c1a2f8fe5753096a9cf2cc8b",
9 "revisionTime": "2017-02-27T12:44:09Z" 9 "revisionTime": "2017-02-27T12:44:09Z"
10 }, 10 },
11 { 11 {
12 "checksumSHA1": "KmjnydoAbofMieIWm+it5OWERaM=",
13 "path": "github.com/alecthomas/template",
14 "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
15 "revisionTime": "2016-04-05T07:15:01Z"
16 },
17 {
18 "checksumSHA1": "3wt0pTXXeS+S93unwhGoLIyGX/Q=",
19 "path": "github.com/alecthomas/template/parse",
20 "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
21 "revisionTime": "2016-04-05T07:15:01Z"
22 },
23 {
24 "checksumSHA1": "fCc3grA7vIxfBru7R3SqjcW+oLI=",
25 "path": "github.com/alecthomas/units",
26 "revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a",
27 "revisionTime": "2015-10-22T06:55:26Z"
28 },
29 {
12 "checksumSHA1": "gDdXOAXWhLHmSRN+TJ6MiPJFjh4=", 30 "checksumSHA1": "gDdXOAXWhLHmSRN+TJ6MiPJFjh4=",
13 "path": "github.com/beevik/ntp", 31 "path": "github.com/beevik/ntp",
14 "revision": "a89df35c13954f2f8fd8e34784cfd23be611ca1e", 32 "revision": "a89df35c13954f2f8fd8e34784cfd23be611ca1e",
@@ -111,34 +129,34 @@
111 "revisionTime": "2017-02-16T18:52:47Z" 129 "revisionTime": "2017-02-16T18:52:47Z"
112 }, 130 },
113 { 131 {
114 "checksumSHA1": "Wtpzndm/+bdwwNU5PCTfb4oUhc8=", 132 "checksumSHA1": "xfnn0THnqNwjwimeTClsxahYrIo=",
115 "path": "github.com/prometheus/common/expfmt", 133 "path": "github.com/prometheus/common/expfmt",
116 "revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf", 134 "revision": "8ba51016a21456f1649877d7079f416d69eb3948",
117 "revisionTime": "2017-02-20T10:38:46Z" 135 "revisionTime": "2017-07-31T09:30:31Z"
118 }, 136 },
119 { 137 {
120 "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=", 138 "checksumSHA1": "GWlM3d2vPYyNATtTFgftS10/A9w=",
121 "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg", 139 "path": "github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg",
122 "revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf", 140 "revision": "8ba51016a21456f1649877d7079f416d69eb3948",
123 "revisionTime": "2017-02-20T10:38:46Z" 141 "revisionTime": "2017-07-31T09:30:31Z"
124 }, 142 },
125 { 143 {
126 "checksumSHA1": "ZA4MLHNAP905WiAOLy4BBzmcuxM=", 144 "checksumSHA1": "jYpLEs+wZ5LZubvOJEDSQ8I14MI=",
127 "path": "github.com/prometheus/common/log", 145 "path": "github.com/prometheus/common/log",
128 "revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf", 146 "revision": "8ba51016a21456f1649877d7079f416d69eb3948",
129 "revisionTime": "2017-02-20T10:38:46Z" 147 "revisionTime": "2017-07-31T09:30:31Z"
130 }, 148 },
131 { 149 {
132 "checksumSHA1": "0LL9u9tfv1KPBjNEiMDP6q7lpog=", 150 "checksumSHA1": "3VoqH7TFfzA6Ds0zFzIbKCUvBmw=",
133 "path": "github.com/prometheus/common/model", 151 "path": "github.com/prometheus/common/model",
134 "revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf", 152 "revision": "8ba51016a21456f1649877d7079f416d69eb3948",
135 "revisionTime": "2017-02-20T10:38:46Z" 153 "revisionTime": "2017-07-31T09:30:31Z"
136 }, 154 },
137 { 155 {
138 "checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=", 156 "checksumSHA1": "91KYK0SpvkaMJJA2+BcxbVnyRO0=",
139 "path": "github.com/prometheus/common/version", 157 "path": "github.com/prometheus/common/version",
140 "revision": "49fee292b27bfff7f354ee0f64e1bc4850462edf", 158 "revision": "8ba51016a21456f1649877d7079f416d69eb3948",
141 "revisionTime": "2017-02-20T10:38:46Z" 159 "revisionTime": "2017-07-31T09:30:31Z"
142 }, 160 },
143 { 161 {
144 "checksumSHA1": "K1HtPl6z/FoGkfWO7zZkzFqeDZ4=", 162 "checksumSHA1": "K1HtPl6z/FoGkfWO7zZkzFqeDZ4=",
@@ -199,6 +217,12 @@
199 "path": "golang.org/x/sys/windows/svc/eventlog", 217 "path": "golang.org/x/sys/windows/svc/eventlog",
200 "revision": "21f2569f6feb83b68a25c98c1b20eca5d4e1e6ae", 218 "revision": "21f2569f6feb83b68a25c98c1b20eca5d4e1e6ae",
201 "revisionTime": "2017-02-28T00:49:33Z" 219 "revisionTime": "2017-02-28T00:49:33Z"
220 },
221 {
222 "checksumSHA1": "3SZTatHIy9OTKc95YlVfXKnoySg=",
223 "path": "gopkg.in/alecthomas/kingpin.v2",
224 "revision": "1087e65c9441605df944fb12c33f0fe7072d18ca",
225 "revisionTime": "2017-07-27T04:22:29Z"
202 } 226 }
203 ], 227 ],
204 "rootPath": "github.com/prometheus/node_exporter" 228 "rootPath": "github.com/prometheus/node_exporter"