Change to Kingpin flags (#199)
authorCalle Pettersson <carlpett@users.noreply.github.com>
Wed, 26 Jul 2017 09:27:04 +0000 (11:27 +0200)
committerBrian Brazil <brian.brazil@robustperception.io>
Wed, 26 Jul 2017 09:27:04 +0000 (10:27 +0100)
41 files changed:
Dockerfile
README.md
main.go
vendor/github.com/alecthomas/template/LICENSE [new file with mode: 0644]
vendor/github.com/alecthomas/template/README.md [new file with mode: 0644]
vendor/github.com/alecthomas/template/doc.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/exec.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/funcs.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/helper.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/parse/lex.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/parse/node.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/parse/parse.go [new file with mode: 0644]
vendor/github.com/alecthomas/template/template.go [new file with mode: 0644]
vendor/github.com/alecthomas/units/COPYING [new file with mode: 0644]
vendor/github.com/alecthomas/units/README.md [new file with mode: 0644]
vendor/github.com/alecthomas/units/bytes.go [new file with mode: 0644]
vendor/github.com/alecthomas/units/doc.go [new file with mode: 0644]
vendor/github.com/alecthomas/units/si.go [new file with mode: 0644]
vendor/github.com/alecthomas/units/util.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/COPYING [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/README.md [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/actions.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/app.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/args.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/completions.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/doc.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/envar.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/flags.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/global.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth_unix.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/model.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/parser.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/templates.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/usage.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/values.go [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/values.json [new file with mode: 0644]
vendor/gopkg.in/alecthomas/kingpin.v2/values_generated.go [new file with mode: 0644]
vendor/vendor.json

index ddea2b3c9c7b37a57ccd77a522cf5442cf1a19e2..1b66bb858a9fcb4f2260c00068c4470a74f8252a 100644 (file)
@@ -6,4 +6,4 @@ COPY blackbox.yml       /etc/blackbox_exporter/config.yml
 
 EXPOSE      9115
 ENTRYPOINT  [ "/bin/blackbox_exporter" ]
-CMD         [ "-config.file=/etc/blackbox_exporter/config.yml" ]
+CMD         [ "--config.file=/etc/blackbox_exporter/config.yml" ]
index 1accdfce2cca93659196a1a71b08943caf5a5e2c..859d383d1a0de045bd6f18551fad0239071142ce 100644 (file)
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ will return metrics for a HTTP probe against google.com. The `probe_success` met
 ### Building with Docker
 
     docker build -t blackbox_exporter .
-    docker run -d -p 9115:9115 --name blackbox_exporter -v `pwd`:/config blackbox_exporter -config.file=/config/blackbox.yml
+    docker run -d -p 9115:9115 --name blackbox_exporter -v `pwd`:/config blackbox_exporter --config.file=/config/blackbox.yml
 
 ## Configuration
 
@@ -31,7 +31,7 @@ A configuration reload is triggered by sending a `SIGHUP` to the Blackbox export
 
 To view all available command-line flags, run `./blackbox_exporter -h`.
 
-To specify which configuration file to load, use the `-config.file` flag.
+To specify which configuration file to load, use the `--config.file` flag.
 The file is written in [YAML format](https://en.wikipedia.org/wiki/YAML), defined by the scheme described which can be found [here.](https://github.com/prometheus/blackbox_exporter/blob/master/CONFIGURATION.md)
 
 Additionally, an [example configuration](https://github.com/prometheus/blackbox_exporter/blob/master/example.yml) is also available.
diff --git a/main.go b/main.go
index 58d72bc4456f9bd895b75d8cf228061d7d02bc95..e3cce95fb4ae0c145d8fd799ffd92f2b75a24ba9 100644 (file)
--- a/main.go
+++ b/main.go
@@ -15,7 +15,6 @@ package main
 
 import (
        "context"
-       "flag"
        "fmt"
        "io/ioutil"
        "net/http"
@@ -25,6 +24,7 @@ import (
        "syscall"
        "time"
 
+       "gopkg.in/alecthomas/kingpin.v2"
        "gopkg.in/yaml.v2"
 
        "github.com/prometheus/client_golang/prometheus"
@@ -37,10 +37,10 @@ var (
        sc = &SafeConfig{
                C: &Config{},
        }
-       configFile    = flag.String("config.file", "blackbox.yml", "Blackbox exporter configuration file.")
-       listenAddress = flag.String("web.listen-address", ":9115", "The address to listen on for HTTP requests.")
-       showVersion   = flag.Bool("version", false, "Print version information.")
-       timeoutOffset = flag.Float64("timeout-offset", 0.5, "Offset to subtract from timeout in seconds.")
+
+       configFile    = kingpin.Flag("config.flag", "Blackbox exporter configuration file.").Default("blackbox.yml").String()
+       listenAddress = kingpin.Flag("web.listen-address", "The address to listen on for HTTP requests.").Default(":9115").String()
+       timeoutOffset = kingpin.Flag("timeout-offset", "Offset to subtract from timeout in seconds.").Default("0.5").Float64()
 )
 
 var Probers = map[string]func(context.Context, string, Module, *prometheus.Registry) bool{
@@ -143,12 +143,9 @@ func init() {
 }
 
 func main() {
-       flag.Parse()
-
-       if *showVersion {
-               fmt.Fprintln(os.Stdout, version.Print("blackbox_exporter"))
-               os.Exit(0)
-       }
+       kingpin.Version(version.Print("blackbox_exporter"))
+       kingpin.HelpFlag.Short('h')
+       kingpin.Parse()
 
        log.Infoln("Starting blackbox_exporter", version.Info())
        log.Infoln("Build context", version.BuildContext())
diff --git a/vendor/github.com/alecthomas/template/LICENSE b/vendor/github.com/alecthomas/template/LICENSE
new file mode 100644 (file)
index 0000000..7448756
--- /dev/null
@@ -0,0 +1,27 @@
+Copyright (c) 2012 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF 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 (file)
index 0000000..ef6a8ee
--- /dev/null
@@ -0,0 +1,25 @@
+# Go's `text/template` package with newline elision
+
+This 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.
+
+eg.
+
+```
+{{if true}}\
+hello
+{{end}}\
+```
+
+Will result in:
+
+```
+hello\n
+```
+
+Rather than:
+
+```
+\n
+hello\n
+\n
+```
diff --git a/vendor/github.com/alecthomas/template/doc.go b/vendor/github.com/alecthomas/template/doc.go
new file mode 100644 (file)
index 0000000..223c595
--- /dev/null
@@ -0,0 +1,406 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package template implements data-driven templates for generating textual output.
+
+To generate HTML output, see package html/template, which has the same interface
+as this package but automatically secures HTML output against certain attacks.
+
+Templates are executed by applying them to a data structure. Annotations in the
+template refer to elements of the data structure (typically a field of a struct
+or a key in a map) to control execution and derive values to be displayed.
+Execution of the template walks the structure and sets the cursor, represented
+by a period '.' and called "dot", to the value at the current location in the
+structure as execution proceeds.
+
+The input text for a template is UTF-8-encoded text in any format.
+"Actions"--data evaluations or control structures--are delimited by
+"{{" and "}}"; all text outside actions is copied to the output unchanged.
+Actions may not span newlines, although comments can.
+
+Once parsed, a template may be executed safely in parallel.
+
+Here is a trivial example that prints "17 items are made of wool".
+
+       type Inventory struct {
+               Material string
+               Count    uint
+       }
+       sweaters := Inventory{"wool", 17}
+       tmpl, err := template.New("test").Parse("{{.Count}} items are made of {{.Material}}")
+       if err != nil { panic(err) }
+       err = tmpl.Execute(os.Stdout, sweaters)
+       if err != nil { panic(err) }
+
+More intricate examples appear below.
+
+Actions
+
+Here is the list of actions. "Arguments" and "pipelines" are evaluations of
+data, defined in detail below.
+
+*/
+//     {{/* a comment */}}
+//             A comment; discarded. May contain newlines.
+//             Comments do not nest and must start and end at the
+//             delimiters, as shown here.
+/*
+
+       {{pipeline}}
+               The default textual representation of the value of the pipeline
+               is copied to the output.
+
+       {{if pipeline}} T1 {{end}}
+               If the value of the pipeline is empty, no output is generated;
+               otherwise, T1 is executed.  The empty values are false, 0, any
+               nil pointer or interface value, and any array, slice, map, or
+               string of length zero.
+               Dot is unaffected.
+
+       {{if pipeline}} T1 {{else}} T0 {{end}}
+               If the value of the pipeline is empty, T0 is executed;
+               otherwise, T1 is executed.  Dot is unaffected.
+
+       {{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
+               To simplify the appearance of if-else chains, the else action
+               of an if may include another if directly; the effect is exactly
+               the same as writing
+                       {{if pipeline}} T1 {{else}}{{if pipeline}} T0 {{end}}{{end}}
+
+       {{range pipeline}} T1 {{end}}
+               The value of the pipeline must be an array, slice, map, or channel.
+               If the value of the pipeline has length zero, nothing is output;
+               otherwise, dot is set to the successive elements of the array,
+               slice, or map and T1 is executed. If the value is a map and the
+               keys are of basic type with a defined order ("comparable"), the
+               elements will be visited in sorted key order.
+
+       {{range pipeline}} T1 {{else}} T0 {{end}}
+               The value of the pipeline must be an array, slice, map, or channel.
+               If the value of the pipeline has length zero, dot is unaffected and
+               T0 is executed; otherwise, dot is set to the successive elements
+               of the array, slice, or map and T1 is executed.
+
+       {{template "name"}}
+               The template with the specified name is executed with nil data.
+
+       {{template "name" pipeline}}
+               The template with the specified name is executed with dot set
+               to the value of the pipeline.
+
+       {{with pipeline}} T1 {{end}}
+               If the value of the pipeline is empty, no output is generated;
+               otherwise, dot is set to the value of the pipeline and T1 is
+               executed.
+
+       {{with pipeline}} T1 {{else}} T0 {{end}}
+               If the value of the pipeline is empty, dot is unaffected and T0
+               is executed; otherwise, dot is set to the value of the pipeline
+               and T1 is executed.
+
+Arguments
+
+An argument is a simple value, denoted by one of the following.
+
+       - A boolean, string, character, integer, floating-point, imaginary
+         or complex constant in Go syntax. These behave like Go's untyped
+         constants, although raw strings may not span newlines.
+       - The keyword nil, representing an untyped Go nil.
+       - The character '.' (period):
+               .
+         The result is the value of dot.
+       - A variable name, which is a (possibly empty) alphanumeric string
+         preceded by a dollar sign, such as
+               $piOver2
+         or
+               $
+         The result is the value of the variable.
+         Variables are described below.
+       - The name of a field of the data, which must be a struct, preceded
+         by a period, such as
+               .Field
+         The result is the value of the field. Field invocations may be
+         chained:
+           .Field1.Field2
+         Fields can also be evaluated on variables, including chaining:
+           $x.Field1.Field2
+       - The name of a key of the data, which must be a map, preceded
+         by a period, such as
+               .Key
+         The result is the map element value indexed by the key.
+         Key invocations may be chained and combined with fields to any
+         depth:
+           .Field1.Key1.Field2.Key2
+         Although the key must be an alphanumeric identifier, unlike with
+         field names they do not need to start with an upper case letter.
+         Keys can also be evaluated on variables, including chaining:
+           $x.key1.key2
+       - The name of a niladic method of the data, preceded by a period,
+         such as
+               .Method
+         The result is the value of invoking the method with dot as the
+         receiver, dot.Method(). Such a method must have one return value (of
+         any type) or two return values, the second of which is an error.
+         If it has two and the returned error is non-nil, execution terminates
+         and an error is returned to the caller as the value of Execute.
+         Method invocations may be chained and combined with fields and keys
+         to any depth:
+           .Field1.Key1.Method1.Field2.Key2.Method2
+         Methods can also be evaluated on variables, including chaining:
+           $x.Method1.Field
+       - The name of a niladic function, such as
+               fun
+         The result is the value of invoking the function, fun(). The return
+         types and values behave as in methods. Functions and function
+         names are described below.
+       - A parenthesized instance of one the above, for grouping. The result
+         may be accessed by a field or map key invocation.
+               print (.F1 arg1) (.F2 arg2)
+               (.StructValuedMethod "arg").Field
+
+Arguments may evaluate to any type; if they are pointers the implementation
+automatically indirects to the base type when required.
+If an evaluation yields a function value, such as a function-valued
+field of a struct, the function is not invoked automatically, but it
+can be used as a truth value for an if action and the like. To invoke
+it, use the call function, defined below.
+
+A pipeline is a possibly chained sequence of "commands". A command is a simple
+value (argument) or a function or method call, possibly with multiple arguments:
+
+       Argument
+               The result is the value of evaluating the argument.
+       .Method [Argument...]
+               The method can be alone or the last element of a chain but,
+               unlike methods in the middle of a chain, it can take arguments.
+               The result is the value of calling the method with the
+               arguments:
+                       dot.Method(Argument1, etc.)
+       functionName [Argument...]
+               The result is the value of calling the function associated
+               with the name:
+                       function(Argument1, etc.)
+               Functions and function names are described below.
+
+Pipelines
+
+A pipeline may be "chained" by separating a sequence of commands with pipeline
+characters '|'. In a chained pipeline, the result of the each command is
+passed as the last argument of the following command. The output of the final
+command in the pipeline is the value of the pipeline.
+
+The output of a command will be either one value or two values, the second of
+which has type error. If that second value is present and evaluates to
+non-nil, execution terminates and the error is returned to the caller of
+Execute.
+
+Variables
+
+A pipeline inside an action may initialize a variable to capture the result.
+The initialization has syntax
+
+       $variable := pipeline
+
+where $variable is the name of the variable. An action that declares a
+variable produces no output.
+
+If a "range" action initializes a variable, the variable is set to the
+successive elements of the iteration.  Also, a "range" may declare two
+variables, separated by a comma:
+
+       range $index, $element := pipeline
+
+in which case $index and $element are set to the successive values of the
+array/slice index or map key and element, respectively.  Note that if there is
+only one variable, it is assigned the element; this is opposite to the
+convention in Go range clauses.
+
+A variable's scope extends to the "end" action of the control structure ("if",
+"with", or "range") in which it is declared, or to the end of the template if
+there is no such control structure.  A template invocation does not inherit
+variables from the point of its invocation.
+
+When execution begins, $ is set to the data argument passed to Execute, that is,
+to the starting value of dot.
+
+Examples
+
+Here are some example one-line templates demonstrating pipelines and variables.
+All produce the quoted word "output":
+
+       {{"\"output\""}}
+               A string constant.
+       {{`"output"`}}
+               A raw string constant.
+       {{printf "%q" "output"}}
+               A function call.
+       {{"output" | printf "%q"}}
+               A function call whose final argument comes from the previous
+               command.
+       {{printf "%q" (print "out" "put")}}
+               A parenthesized argument.
+       {{"put" | printf "%s%s" "out" | printf "%q"}}
+               A more elaborate call.
+       {{"output" | printf "%s" | printf "%q"}}
+               A longer chain.
+       {{with "output"}}{{printf "%q" .}}{{end}}
+               A with action using dot.
+       {{with $x := "output" | printf "%q"}}{{$x}}{{end}}
+               A with action that creates and uses a variable.
+       {{with $x := "output"}}{{printf "%q" $x}}{{end}}
+               A with action that uses the variable in another action.
+       {{with $x := "output"}}{{$x | printf "%q"}}{{end}}
+               The same, but pipelined.
+
+Functions
+
+During execution functions are found in two function maps: first in the
+template, then in the global function map. By default, no functions are defined
+in the template but the Funcs method can be used to add them.
+
+Predefined global functions are named as follows.
+
+       and
+               Returns the boolean AND of its arguments by returning the
+               first empty argument or the last argument, that is,
+               "and x y" behaves as "if x then y else x". All the
+               arguments are evaluated.
+       call
+               Returns the result of calling the first argument, which
+               must be a function, with the remaining arguments as parameters.
+               Thus "call .X.Y 1 2" is, in Go notation, dot.X.Y(1, 2) where
+               Y is a func-valued field, map entry, or the like.
+               The first argument must be the result of an evaluation
+               that yields a value of function type (as distinct from
+               a predefined function such as print). The function must
+               return either one or two result values, the second of which
+               is of type error. If the arguments don't match the function
+               or the returned error value is non-nil, execution stops.
+       html
+               Returns the escaped HTML equivalent of the textual
+               representation of its arguments.
+       index
+               Returns the result of indexing its first argument by the
+               following arguments. Thus "index x 1 2 3" is, in Go syntax,
+               x[1][2][3]. Each indexed item must be a map, slice, or array.
+       js
+               Returns the escaped JavaScript equivalent of the textual
+               representation of its arguments.
+       len
+               Returns the integer length of its argument.
+       not
+               Returns the boolean negation of its single argument.
+       or
+               Returns the boolean OR of its arguments by returning the
+               first non-empty argument or the last argument, that is,
+               "or x y" behaves as "if x then x else y". All the
+               arguments are evaluated.
+       print
+               An alias for fmt.Sprint
+       printf
+               An alias for fmt.Sprintf
+       println
+               An alias for fmt.Sprintln
+       urlquery
+               Returns the escaped value of the textual representation of
+               its arguments in a form suitable for embedding in a URL query.
+
+The boolean functions take any zero value to be false and a non-zero
+value to be true.
+
+There is also a set of binary comparison operators defined as
+functions:
+
+       eq
+               Returns the boolean truth of arg1 == arg2
+       ne
+               Returns the boolean truth of arg1 != arg2
+       lt
+               Returns the boolean truth of arg1 < arg2
+       le
+               Returns the boolean truth of arg1 <= arg2
+       gt
+               Returns the boolean truth of arg1 > arg2
+       ge
+               Returns the boolean truth of arg1 >= arg2
+
+For simpler multi-way equality tests, eq (only) accepts two or more
+arguments and compares the second and subsequent to the first,
+returning in effect
+
+       arg1==arg2 || arg1==arg3 || arg1==arg4 ...
+
+(Unlike with || in Go, however, eq is a function call and all the
+arguments will be evaluated.)
+
+The comparison functions work on basic types only (or named basic
+types, such as "type Celsius float32"). They implement the Go rules
+for comparison of values, except that size and exact type are
+ignored, so any integer value, signed or unsigned, may be compared
+with any other integer value. (The arithmetic value is compared,
+not the bit pattern, so all negative integers are less than all
+unsigned integers.) However, as usual, one may not compare an int
+with a float32 and so on.
+
+Associated templates
+
+Each template is named by a string specified when it is created. Also, each
+template is associated with zero or more other templates that it may invoke by
+name; such associations are transitive and form a name space of templates.
+
+A template may use a template invocation to instantiate another associated
+template; see the explanation of the "template" action above. The name must be
+that of a template associated with the template that contains the invocation.
+
+Nested template definitions
+
+When parsing a template, another template may be defined and associated with the
+template being parsed. Template definitions must appear at the top level of the
+template, much like global variables in a Go program.
+
+The syntax of such definitions is to surround each template declaration with a
+"define" and "end" action.
+
+The define action names the template being created by providing a string
+constant. Here is a simple example:
+
+       `{{define "T1"}}ONE{{end}}
+       {{define "T2"}}TWO{{end}}
+       {{define "T3"}}{{template "T1"}} {{template "T2"}}{{end}}
+       {{template "T3"}}`
+
+This defines two templates, T1 and T2, and a third T3 that invokes the other two
+when it is executed. Finally it invokes T3. If executed this template will
+produce the text
+
+       ONE TWO
+
+By construction, a template may reside in only one association. If it's
+necessary to have a template addressable from multiple associations, the
+template definition must be parsed multiple times to create distinct *Template
+values, or must be copied with the Clone or AddParseTree method.
+
+Parse may be called multiple times to assemble the various associated templates;
+see the ParseFiles and ParseGlob functions and methods for simple ways to parse
+related templates stored in files.
+
+A template may be executed directly or through ExecuteTemplate, which executes
+an associated template identified by name. To invoke our example above, we
+might write,
+
+       err := tmpl.Execute(os.Stdout, "no data needed")
+       if err != nil {
+               log.Fatalf("execution failed: %s", err)
+       }
+
+or to invoke a particular template explicitly by name,
+
+       err := tmpl.ExecuteTemplate(os.Stdout, "T2", "no data needed")
+       if err != nil {
+               log.Fatalf("execution failed: %s", err)
+       }
+
+*/
+package template
diff --git a/vendor/github.com/alecthomas/template/exec.go b/vendor/github.com/alecthomas/template/exec.go
new file mode 100644 (file)
index 0000000..c3078e5
--- /dev/null
@@ -0,0 +1,845 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+       "bytes"
+       "fmt"
+       "io"
+       "reflect"
+       "runtime"
+       "sort"
+       "strings"
+
+       "github.com/alecthomas/template/parse"
+)
+
+// state represents the state of an execution. It's not part of the
+// template so that multiple executions of the same template
+// can execute in parallel.
+type state struct {
+       tmpl *Template
+       wr   io.Writer
+       node parse.Node // current node, for errors
+       vars []variable // push-down stack of variable values.
+}
+
+// variable holds the dynamic value of a variable such as $, $x etc.
+type variable struct {
+       name  string
+       value reflect.Value
+}
+
+// push pushes a new variable on the stack.
+func (s *state) push(name string, value reflect.Value) {
+       s.vars = append(s.vars, variable{name, value})
+}
+
+// mark returns the length of the variable stack.
+func (s *state) mark() int {
+       return len(s.vars)
+}
+
+// pop pops the variable stack up to the mark.
+func (s *state) pop(mark int) {
+       s.vars = s.vars[0:mark]
+}
+
+// setVar overwrites the top-nth variable on the stack. Used by range iterations.
+func (s *state) setVar(n int, value reflect.Value) {
+       s.vars[len(s.vars)-n].value = value
+}
+
+// varValue returns the value of the named variable.
+func (s *state) varValue(name string) reflect.Value {
+       for i := s.mark() - 1; i >= 0; i-- {
+               if s.vars[i].name == name {
+                       return s.vars[i].value
+               }
+       }
+       s.errorf("undefined variable: %s", name)
+       return zero
+}
+
+var zero reflect.Value
+
+// at marks the state to be on node n, for error reporting.
+func (s *state) at(node parse.Node) {
+       s.node = node
+}
+
+// doublePercent returns the string with %'s replaced by %%, if necessary,
+// so it can be used safely inside a Printf format string.
+func doublePercent(str string) string {
+       if strings.Contains(str, "%") {
+               str = strings.Replace(str, "%", "%%", -1)
+       }
+       return str
+}
+
+// errorf formats the error and terminates processing.
+func (s *state) errorf(format string, args ...interface{}) {
+       name := doublePercent(s.tmpl.Name())
+       if s.node == nil {
+               format = fmt.Sprintf("template: %s: %s", name, format)
+       } else {
+               location, context := s.tmpl.ErrorContext(s.node)
+               format = fmt.Sprintf("template: %s: executing %q at <%s>: %s", location, name, doublePercent(context), format)
+       }
+       panic(fmt.Errorf(format, args...))
+}
+
+// errRecover is the handler that turns panics into returns from the top
+// level of Parse.
+func errRecover(errp *error) {
+       e := recover()
+       if e != nil {
+               switch err := e.(type) {
+               case runtime.Error:
+                       panic(e)
+               case error:
+                       *errp = err
+               default:
+                       panic(e)
+               }
+       }
+}
+
+// ExecuteTemplate applies the template associated with t that has the given name
+// to the specified data object and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
+       tmpl := t.tmpl[name]
+       if tmpl == nil {
+               return fmt.Errorf("template: no template %q associated with template %q", name, t.name)
+       }
+       return tmpl.Execute(wr, data)
+}
+
+// Execute applies a parsed template to the specified data object,
+// and writes the output to wr.
+// If an error occurs executing the template or writing its output,
+// execution stops, but partial results may already have been written to
+// the output writer.
+// A template may be executed safely in parallel.
+func (t *Template) Execute(wr io.Writer, data interface{}) (err error) {
+       defer errRecover(&err)
+       value := reflect.ValueOf(data)
+       state := &state{
+               tmpl: t,
+               wr:   wr,
+               vars: []variable{{"$", value}},
+       }
+       t.init()
+       if t.Tree == nil || t.Root == nil {
+               var b bytes.Buffer
+               for name, tmpl := range t.tmpl {
+                       if tmpl.Tree == nil || tmpl.Root == nil {
+                               continue
+                       }
+                       if b.Len() > 0 {
+                               b.WriteString(", ")
+                       }
+                       fmt.Fprintf(&b, "%q", name)
+               }
+               var s string
+               if b.Len() > 0 {
+                       s = "; defined templates are: " + b.String()
+               }
+               state.errorf("%q is an incomplete or empty template%s", t.Name(), s)
+       }
+       state.walk(value, t.Root)
+       return
+}
+
+// Walk functions step through the major pieces of the template structure,
+// generating output as they go.
+func (s *state) walk(dot reflect.Value, node parse.Node) {
+       s.at(node)
+       switch node := node.(type) {
+       case *parse.ActionNode:
+               // Do not pop variables so they persist until next end.
+               // Also, if the action declares variables, don't print the result.
+               val := s.evalPipeline(dot, node.Pipe)
+               if len(node.Pipe.Decl) == 0 {
+                       s.printValue(node, val)
+               }
+       case *parse.IfNode:
+               s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList)
+       case *parse.ListNode:
+               for _, node := range node.Nodes {
+                       s.walk(dot, node)
+               }
+       case *parse.RangeNode:
+               s.walkRange(dot, node)
+       case *parse.TemplateNode:
+               s.walkTemplate(dot, node)
+       case *parse.TextNode:
+               if _, err := s.wr.Write(node.Text); err != nil {
+                       s.errorf("%s", err)
+               }
+       case *parse.WithNode:
+               s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList)
+       default:
+               s.errorf("unknown node: %s", node)
+       }
+}
+
+// walkIfOrWith walks an 'if' or 'with' node. The two control structures
+// are identical in behavior except that 'with' sets dot.
+func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse.PipeNode, list, elseList *parse.ListNode) {
+       defer s.pop(s.mark())
+       val := s.evalPipeline(dot, pipe)
+       truth, ok := isTrue(val)
+       if !ok {
+               s.errorf("if/with can't use %v", val)
+       }
+       if truth {
+               if typ == parse.NodeWith {
+                       s.walk(val, list)
+               } else {
+                       s.walk(dot, list)
+               }
+       } else if elseList != nil {
+               s.walk(dot, elseList)
+       }
+}
+
+// isTrue reports whether the value is 'true', in the sense of not the zero of its type,
+// and whether the value has a meaningful truth value.
+func isTrue(val reflect.Value) (truth, ok bool) {
+       if !val.IsValid() {
+               // Something like var x interface{}, never set. It's a form of nil.
+               return false, true
+       }
+       switch val.Kind() {
+       case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+               truth = val.Len() > 0
+       case reflect.Bool:
+               truth = val.Bool()
+       case reflect.Complex64, reflect.Complex128:
+               truth = val.Complex() != 0
+       case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
+               truth = !val.IsNil()
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               truth = val.Int() != 0
+       case reflect.Float32, reflect.Float64:
+               truth = val.Float() != 0
+       case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+               truth = val.Uint() != 0
+       case reflect.Struct:
+               truth = true // Struct values are always true.
+       default:
+               return
+       }
+       return truth, true
+}
+
+func (s *state) walkRange(dot reflect.Value, r *parse.RangeNode) {
+       s.at(r)
+       defer s.pop(s.mark())
+       val, _ := indirect(s.evalPipeline(dot, r.Pipe))
+       // mark top of stack before any variables in the body are pushed.
+       mark := s.mark()
+       oneIteration := func(index, elem reflect.Value) {
+               // Set top var (lexically the second if there are two) to the element.
+               if len(r.Pipe.Decl) > 0 {
+                       s.setVar(1, elem)
+               }
+               // Set next var (lexically the first if there are two) to the index.
+               if len(r.Pipe.Decl) > 1 {
+                       s.setVar(2, index)
+               }
+               s.walk(elem, r.List)
+               s.pop(mark)
+       }
+       switch val.Kind() {
+       case reflect.Array, reflect.Slice:
+               if val.Len() == 0 {
+                       break
+               }
+               for i := 0; i < val.Len(); i++ {
+                       oneIteration(reflect.ValueOf(i), val.Index(i))
+               }
+               return
+       case reflect.Map:
+               if val.Len() == 0 {
+                       break
+               }
+               for _, key := range sortKeys(val.MapKeys()) {
+                       oneIteration(key, val.MapIndex(key))
+               }
+               return
+       case reflect.Chan:
+               if val.IsNil() {
+                       break
+               }
+               i := 0
+               for ; ; i++ {
+                       elem, ok := val.Recv()
+                       if !ok {
+                               break
+                       }
+                       oneIteration(reflect.ValueOf(i), elem)
+               }
+               if i == 0 {
+                       break
+               }
+               return
+       case reflect.Invalid:
+               break // An invalid value is likely a nil map, etc. and acts like an empty map.
+       default:
+               s.errorf("range can't iterate over %v", val)
+       }
+       if r.ElseList != nil {
+               s.walk(dot, r.ElseList)
+       }
+}
+
+func (s *state) walkTemplate(dot reflect.Value, t *parse.TemplateNode) {
+       s.at(t)
+       tmpl := s.tmpl.tmpl[t.Name]
+       if tmpl == nil {
+               s.errorf("template %q not defined", t.Name)
+       }
+       // Variables declared by the pipeline persist.
+       dot = s.evalPipeline(dot, t.Pipe)
+       newState := *s
+       newState.tmpl = tmpl
+       // No dynamic scoping: template invocations inherit no variables.
+       newState.vars = []variable{{"$", dot}}
+       newState.walk(dot, tmpl.Root)
+}
+
+// Eval functions evaluate pipelines, commands, and their elements and extract
+// values from the data structure by examining fields, calling methods, and so on.
+// The printing of those values happens only through walk functions.
+
+// evalPipeline returns the value acquired by evaluating a pipeline. If the
+// pipeline has a variable declaration, the variable will be pushed on the
+// stack. Callers should therefore pop the stack after they are finished
+// executing commands depending on the pipeline value.
+func (s *state) evalPipeline(dot reflect.Value, pipe *parse.PipeNode) (value reflect.Value) {
+       if pipe == nil {
+               return
+       }
+       s.at(pipe)
+       for _, cmd := range pipe.Cmds {
+               value = s.evalCommand(dot, cmd, value) // previous value is this one's final arg.
+               // If the object has type interface{}, dig down one level to the thing inside.
+               if value.Kind() == reflect.Interface && value.Type().NumMethod() == 0 {
+                       value = reflect.ValueOf(value.Interface()) // lovely!
+               }
+       }
+       for _, variable := range pipe.Decl {
+               s.push(variable.Ident[0], value)
+       }
+       return value
+}
+
+func (s *state) notAFunction(args []parse.Node, final reflect.Value) {
+       if len(args) > 1 || final.IsValid() {
+               s.errorf("can't give argument to non-function %s", args[0])
+       }
+}
+
+func (s *state) evalCommand(dot reflect.Value, cmd *parse.CommandNode, final reflect.Value) reflect.Value {
+       firstWord := cmd.Args[0]
+       switch n := firstWord.(type) {
+       case *parse.FieldNode:
+               return s.evalFieldNode(dot, n, cmd.Args, final)
+       case *parse.ChainNode:
+               return s.evalChainNode(dot, n, cmd.Args, final)
+       case *parse.IdentifierNode:
+               // Must be a function.
+               return s.evalFunction(dot, n, cmd, cmd.Args, final)
+       case *parse.PipeNode:
+               // Parenthesized pipeline. The arguments are all inside the pipeline; final is ignored.
+               return s.evalPipeline(dot, n)
+       case *parse.VariableNode:
+               return s.evalVariableNode(dot, n, cmd.Args, final)
+       }
+       s.at(firstWord)
+       s.notAFunction(cmd.Args, final)
+       switch word := firstWord.(type) {
+       case *parse.BoolNode:
+               return reflect.ValueOf(word.True)
+       case *parse.DotNode:
+               return dot
+       case *parse.NilNode:
+               s.errorf("nil is not a command")
+       case *parse.NumberNode:
+               return s.idealConstant(word)
+       case *parse.StringNode:
+               return reflect.ValueOf(word.Text)
+       }
+       s.errorf("can't evaluate command %q", firstWord)
+       panic("not reached")
+}
+
+// idealConstant is called to return the value of a number in a context where
+// we don't know the type. In that case, the syntax of the number tells us
+// its type, and we use Go rules to resolve.  Note there is no such thing as
+// a uint ideal constant in this situation - the value must be of int type.
+func (s *state) idealConstant(constant *parse.NumberNode) reflect.Value {
+       // These are ideal constants but we don't know the type
+       // and we have no context.  (If it was a method argument,
+       // we'd know what we need.) The syntax guides us to some extent.
+       s.at(constant)
+       switch {
+       case constant.IsComplex:
+               return reflect.ValueOf(constant.Complex128) // incontrovertible.
+       case constant.IsFloat && !isHexConstant(constant.Text) && strings.IndexAny(constant.Text, ".eE") >= 0:
+               return reflect.ValueOf(constant.Float64)
+       case constant.IsInt:
+               n := int(constant.Int64)
+               if int64(n) != constant.Int64 {
+                       s.errorf("%s overflows int", constant.Text)
+               }
+               return reflect.ValueOf(n)
+       case constant.IsUint:
+               s.errorf("%s overflows int", constant.Text)
+       }
+       return zero
+}
+
+func isHexConstant(s string) bool {
+       return len(s) > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')
+}
+
+func (s *state) evalFieldNode(dot reflect.Value, field *parse.FieldNode, args []parse.Node, final reflect.Value) reflect.Value {
+       s.at(field)
+       return s.evalFieldChain(dot, dot, field, field.Ident, args, final)
+}
+
+func (s *state) evalChainNode(dot reflect.Value, chain *parse.ChainNode, args []parse.Node, final reflect.Value) reflect.Value {
+       s.at(chain)
+       // (pipe).Field1.Field2 has pipe as .Node, fields as .Field. Eval the pipeline, then the fields.
+       pipe := s.evalArg(dot, nil, chain.Node)
+       if len(chain.Field) == 0 {
+               s.errorf("internal error: no fields in evalChainNode")
+       }
+       return s.evalFieldChain(dot, pipe, chain, chain.Field, args, final)
+}
+
+func (s *state) evalVariableNode(dot reflect.Value, variable *parse.VariableNode, args []parse.Node, final reflect.Value) reflect.Value {
+       // $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
+       s.at(variable)
+       value := s.varValue(variable.Ident[0])
+       if len(variable.Ident) == 1 {
+               s.notAFunction(args, final)
+               return value
+       }
+       return s.evalFieldChain(dot, value, variable, variable.Ident[1:], args, final)
+}
+
+// evalFieldChain evaluates .X.Y.Z possibly followed by arguments.
+// dot is the environment in which to evaluate arguments, while
+// receiver is the value being walked along the chain.
+func (s *state) evalFieldChain(dot, receiver reflect.Value, node parse.Node, ident []string, args []parse.Node, final reflect.Value) reflect.Value {
+       n := len(ident)
+       for i := 0; i < n-1; i++ {
+               receiver = s.evalField(dot, ident[i], node, nil, zero, receiver)
+       }
+       // Now if it's a method, it gets the arguments.
+       return s.evalField(dot, ident[n-1], node, args, final, receiver)
+}
+
+func (s *state) evalFunction(dot reflect.Value, node *parse.IdentifierNode, cmd parse.Node, args []parse.Node, final reflect.Value) reflect.Value {
+       s.at(node)
+       name := node.Ident
+       function, ok := findFunction(name, s.tmpl)
+       if !ok {
+               s.errorf("%q is not a defined function", name)
+       }
+       return s.evalCall(dot, function, cmd, name, args, final)
+}
+
+// evalField evaluates an expression like (.Field) or (.Field arg1 arg2).
+// The 'final' argument represents the return value from the preceding
+// value of the pipeline, if any.
+func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, args []parse.Node, final, receiver reflect.Value) reflect.Value {
+       if !receiver.IsValid() {
+               return zero
+       }
+       typ := receiver.Type()
+       receiver, _ = indirect(receiver)
+       // Unless it's an interface, need to get to a value of type *T to guarantee
+       // we see all methods of T and *T.
+       ptr := receiver
+       if ptr.Kind() != reflect.Interface && ptr.CanAddr() {
+               ptr = ptr.Addr()
+       }
+       if method := ptr.MethodByName(fieldName); method.IsValid() {
+               return s.evalCall(dot, method, node, fieldName, args, final)
+       }
+       hasArgs := len(args) > 1 || final.IsValid()
+       // It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil.
+       receiver, isNil := indirect(receiver)
+       if isNil {
+               s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
+       }
+       switch receiver.Kind() {
+       case reflect.Struct:
+               tField, ok := receiver.Type().FieldByName(fieldName)
+               if ok {
+                       field := receiver.FieldByIndex(tField.Index)
+                       if tField.PkgPath != "" { // field is unexported
+                               s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
+                       }
+                       // If it's a function, we must call it.
+                       if hasArgs {
+                               s.errorf("%s has arguments but cannot be invoked as function", fieldName)
+                       }
+                       return field
+               }
+               s.errorf("%s is not a field of struct type %s", fieldName, typ)
+       case reflect.Map:
+               // If it's a map, attempt to use the field name as a key.
+               nameVal := reflect.ValueOf(fieldName)
+               if nameVal.Type().AssignableTo(receiver.Type().Key()) {
+                       if hasArgs {
+                               s.errorf("%s is not a method but has arguments", fieldName)
+                       }
+                       return receiver.MapIndex(nameVal)
+               }
+       }
+       s.errorf("can't evaluate field %s in type %s", fieldName, typ)
+       panic("not reached")
+}
+
+var (
+       errorType       = reflect.TypeOf((*error)(nil)).Elem()
+       fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
+)
+
+// evalCall executes a function or method call. If it's a method, fun already has the receiver bound, so
+// it looks just like a function call.  The arg list, if non-nil, includes (in the manner of the shell), arg[0]
+// as the function itself.
+func (s *state) evalCall(dot, fun reflect.Value, node parse.Node, name string, args []parse.Node, final reflect.Value) reflect.Value {
+       if args != nil {
+               args = args[1:] // Zeroth arg is function name/node; not passed to function.
+       }
+       typ := fun.Type()
+       numIn := len(args)
+       if final.IsValid() {
+               numIn++
+       }
+       numFixed := len(args)
+       if typ.IsVariadic() {
+               numFixed = typ.NumIn() - 1 // last arg is the variadic one.
+               if numIn < numFixed {
+                       s.errorf("wrong number of args for %s: want at least %d got %d", name, typ.NumIn()-1, len(args))
+               }
+       } else if numIn < typ.NumIn()-1 || !typ.IsVariadic() && numIn != typ.NumIn() {
+               s.errorf("wrong number of args for %s: want %d got %d", name, typ.NumIn(), len(args))
+       }
+       if !goodFunc(typ) {
+               // TODO: This could still be a confusing error; maybe goodFunc should provide info.
+               s.errorf("can't call method/function %q with %d results", name, typ.NumOut())
+       }
+       // Build the arg list.
+       argv := make([]reflect.Value, numIn)
+       // Args must be evaluated. Fixed args first.
+       i := 0
+       for ; i < numFixed && i < len(args); i++ {
+               argv[i] = s.evalArg(dot, typ.In(i), args[i])
+       }
+       // Now the ... args.
+       if typ.IsVariadic() {
+               argType := typ.In(typ.NumIn() - 1).Elem() // Argument is a slice.
+               for ; i < len(args); i++ {
+                       argv[i] = s.evalArg(dot, argType, args[i])
+               }
+       }
+       // Add final value if necessary.
+       if final.IsValid() {
+               t := typ.In(typ.NumIn() - 1)
+               if typ.IsVariadic() {
+                       t = t.Elem()
+               }
+               argv[i] = s.validateType(final, t)
+       }
+       result := fun.Call(argv)
+       // If we have an error that is not nil, stop execution and return that error to the caller.
+       if len(result) == 2 && !result[1].IsNil() {
+               s.at(node)
+               s.errorf("error calling %s: %s", name, result[1].Interface().(error))
+       }
+       return result[0]
+}
+
+// canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
+func canBeNil(typ reflect.Type) bool {
+       switch typ.Kind() {
+       case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
+               return true
+       }
+       return false
+}
+
+// validateType guarantees that the value is valid and assignable to the type.
+func (s *state) validateType(value reflect.Value, typ reflect.Type) reflect.Value {
+       if !value.IsValid() {
+               if typ == nil || canBeNil(typ) {
+                       // An untyped nil interface{}. Accept as a proper nil value.
+                       return reflect.Zero(typ)
+               }
+               s.errorf("invalid value; expected %s", typ)
+       }
+       if typ != nil && !value.Type().AssignableTo(typ) {
+               if value.Kind() == reflect.Interface && !value.IsNil() {
+                       value = value.Elem()
+                       if value.Type().AssignableTo(typ) {
+                               return value
+                       }
+                       // fallthrough
+               }
+               // Does one dereference or indirection work? We could do more, as we
+               // do with method receivers, but that gets messy and method receivers
+               // are much more constrained, so it makes more sense there than here.
+               // Besides, one is almost always all you need.
+               switch {
+               case value.Kind() == reflect.Ptr && value.Type().Elem().AssignableTo(typ):
+                       value = value.Elem()
+                       if !value.IsValid() {
+                               s.errorf("dereference of nil pointer of type %s", typ)
+                       }
+               case reflect.PtrTo(value.Type()).AssignableTo(typ) && value.CanAddr():
+                       value = value.Addr()
+               default:
+                       s.errorf("wrong type for value; expected %s; got %s", typ, value.Type())
+               }
+       }
+       return value
+}
+
+func (s *state) evalArg(dot reflect.Value, typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       switch arg := n.(type) {
+       case *parse.DotNode:
+               return s.validateType(dot, typ)
+       case *parse.NilNode:
+               if canBeNil(typ) {
+                       return reflect.Zero(typ)
+               }
+               s.errorf("cannot assign nil to %s", typ)
+       case *parse.FieldNode:
+               return s.validateType(s.evalFieldNode(dot, arg, []parse.Node{n}, zero), typ)
+       case *parse.VariableNode:
+               return s.validateType(s.evalVariableNode(dot, arg, nil, zero), typ)
+       case *parse.PipeNode:
+               return s.validateType(s.evalPipeline(dot, arg), typ)
+       case *parse.IdentifierNode:
+               return s.evalFunction(dot, arg, arg, nil, zero)
+       case *parse.ChainNode:
+               return s.validateType(s.evalChainNode(dot, arg, nil, zero), typ)
+       }
+       switch typ.Kind() {
+       case reflect.Bool:
+               return s.evalBool(typ, n)
+       case reflect.Complex64, reflect.Complex128:
+               return s.evalComplex(typ, n)
+       case reflect.Float32, reflect.Float64:
+               return s.evalFloat(typ, n)
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               return s.evalInteger(typ, n)
+       case reflect.Interface:
+               if typ.NumMethod() == 0 {
+                       return s.evalEmptyInterface(dot, n)
+               }
+       case reflect.String:
+               return s.evalString(typ, n)
+       case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+               return s.evalUnsignedInteger(typ, n)
+       }
+       s.errorf("can't handle %s for arg of type %s", n, typ)
+       panic("not reached")
+}
+
+func (s *state) evalBool(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       if n, ok := n.(*parse.BoolNode); ok {
+               value := reflect.New(typ).Elem()
+               value.SetBool(n.True)
+               return value
+       }
+       s.errorf("expected bool; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalString(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       if n, ok := n.(*parse.StringNode); ok {
+               value := reflect.New(typ).Elem()
+               value.SetString(n.Text)
+               return value
+       }
+       s.errorf("expected string; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalInteger(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       if n, ok := n.(*parse.NumberNode); ok && n.IsInt {
+               value := reflect.New(typ).Elem()
+               value.SetInt(n.Int64)
+               return value
+       }
+       s.errorf("expected integer; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalUnsignedInteger(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       if n, ok := n.(*parse.NumberNode); ok && n.IsUint {
+               value := reflect.New(typ).Elem()
+               value.SetUint(n.Uint64)
+               return value
+       }
+       s.errorf("expected unsigned integer; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalFloat(typ reflect.Type, n parse.Node) reflect.Value {
+       s.at(n)
+       if n, ok := n.(*parse.NumberNode); ok && n.IsFloat {
+               value := reflect.New(typ).Elem()
+               value.SetFloat(n.Float64)
+               return value
+       }
+       s.errorf("expected float; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalComplex(typ reflect.Type, n parse.Node) reflect.Value {
+       if n, ok := n.(*parse.NumberNode); ok && n.IsComplex {
+               value := reflect.New(typ).Elem()
+               value.SetComplex(n.Complex128)
+               return value
+       }
+       s.errorf("expected complex; found %s", n)
+       panic("not reached")
+}
+
+func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Value {
+       s.at(n)
+       switch n := n.(type) {
+       case *parse.BoolNode:
+               return reflect.ValueOf(n.True)
+       case *parse.DotNode:
+               return dot
+       case *parse.FieldNode:
+               return s.evalFieldNode(dot, n, nil, zero)
+       case *parse.IdentifierNode:
+               return s.evalFunction(dot, n, n, nil, zero)
+       case *parse.NilNode:
+               // NilNode is handled in evalArg, the only place that calls here.
+               s.errorf("evalEmptyInterface: nil (can't happen)")
+       case *parse.NumberNode:
+               return s.idealConstant(n)
+       case *parse.StringNode:
+               return reflect.ValueOf(n.Text)
+       case *parse.VariableNode:
+               return s.evalVariableNode(dot, n, nil, zero)
+       case *parse.PipeNode:
+               return s.evalPipeline(dot, n)
+       }
+       s.errorf("can't handle assignment of %s to empty interface argument", n)
+       panic("not reached")
+}
+
+// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
+// We indirect through pointers and empty interfaces (only) because
+// non-empty interfaces have methods we might need.
+func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
+       for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
+               if v.IsNil() {
+                       return v, true
+               }
+               if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+                       break
+               }
+       }
+       return v, false
+}
+
+// printValue writes the textual representation of the value to the output of
+// the template.
+func (s *state) printValue(n parse.Node, v reflect.Value) {
+       s.at(n)
+       iface, ok := printableValue(v)
+       if !ok {
+               s.errorf("can't print %s of type %s", n, v.Type())
+       }
+       fmt.Fprint(s.wr, iface)
+}
+
+// printableValue returns the, possibly indirected, interface value inside v that
+// is best for a call to formatted printer.
+func printableValue(v reflect.Value) (interface{}, bool) {
+       if v.Kind() == reflect.Ptr {
+               v, _ = indirect(v) // fmt.Fprint handles nil.
+       }
+       if !v.IsValid() {
+               return "<no value>", true
+       }
+
+       if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
+               if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
+                       v = v.Addr()
+               } else {
+                       switch v.Kind() {
+                       case reflect.Chan, reflect.Func:
+                               return nil, false
+                       }
+               }
+       }
+       return v.Interface(), true
+}
+
+// Types to help sort the keys in a map for reproducible output.
+
+type rvs []reflect.Value
+
+func (x rvs) Len() int      { return len(x) }
+func (x rvs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
+type rvInts struct{ rvs }
+
+func (x rvInts) Less(i, j int) bool { return x.rvs[i].Int() < x.rvs[j].Int() }
+
+type rvUints struct{ rvs }
+
+func (x rvUints) Less(i, j int) bool { return x.rvs[i].Uint() < x.rvs[j].Uint() }
+
+type rvFloats struct{ rvs }
+
+func (x rvFloats) Less(i, j int) bool { return x.rvs[i].Float() < x.rvs[j].Float() }
+
+type rvStrings struct{ rvs }
+
+func (x rvStrings) Less(i, j int) bool { return x.rvs[i].String() < x.rvs[j].String() }
+
+// sortKeys sorts (if it can) the slice of reflect.Values, which is a slice of map keys.
+func sortKeys(v []reflect.Value) []reflect.Value {
+       if len(v) <= 1 {
+               return v
+       }
+       switch v[0].Kind() {
+       case reflect.Float32, reflect.Float64:
+               sort.Sort(rvFloats{v})
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               sort.Sort(rvInts{v})
+       case reflect.String:
+               sort.Sort(rvStrings{v})
+       case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+               sort.Sort(rvUints{v})
+       }
+       return v
+}
diff --git a/vendor/github.com/alecthomas/template/funcs.go b/vendor/github.com/alecthomas/template/funcs.go
new file mode 100644 (file)
index 0000000..39ee5ed
--- /dev/null
@@ -0,0 +1,598 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+       "bytes"
+       "errors"
+       "fmt"
+       "io"
+       "net/url"
+       "reflect"
+       "strings"
+       "unicode"
+       "unicode/utf8"
+)
+
+// FuncMap is the type of the map defining the mapping from names to functions.
+// Each function must have either a single return value, or two return values of
+// which the second has type error. In that case, if the second (error)
+// return value evaluates to non-nil during execution, execution terminates and
+// Execute returns that error.
+type FuncMap map[string]interface{}
+
+var builtins = FuncMap{
+       "and":      and,
+       "call":     call,
+       "html":     HTMLEscaper,
+       "index":    index,
+       "js":       JSEscaper,
+       "len":      length,
+       "not":      not,
+       "or":       or,
+       "print":    fmt.Sprint,
+       "printf":   fmt.Sprintf,
+       "println":  fmt.Sprintln,
+       "urlquery": URLQueryEscaper,
+
+       // Comparisons
+       "eq": eq, // ==
+       "ge": ge, // >=
+       "gt": gt, // >
+       "le": le, // <=
+       "lt": lt, // <
+       "ne": ne, // !=
+}
+
+var builtinFuncs = createValueFuncs(builtins)
+
+// createValueFuncs turns a FuncMap into a map[string]reflect.Value
+func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
+       m := make(map[string]reflect.Value)
+       addValueFuncs(m, funcMap)
+       return m
+}
+
+// addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
+func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
+       for name, fn := range in {
+               v := reflect.ValueOf(fn)
+               if v.Kind() != reflect.Func {
+                       panic("value for " + name + " not a function")
+               }
+               if !goodFunc(v.Type()) {
+                       panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
+               }
+               out[name] = v
+       }
+}
+
+// addFuncs adds to values the functions in funcs. It does no checking of the input -
+// call addValueFuncs first.
+func addFuncs(out, in FuncMap) {
+       for name, fn := range in {
+               out[name] = fn
+       }
+}
+
+// goodFunc checks that the function or method has the right result signature.
+func goodFunc(typ reflect.Type) bool {
+       // We allow functions with 1 result or 2 results where the second is an error.
+       switch {
+       case typ.NumOut() == 1:
+               return true
+       case typ.NumOut() == 2 && typ.Out(1) == errorType:
+               return true
+       }
+       return false
+}
+
+// findFunction looks for a function in the template, and global map.
+func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
+       if tmpl != nil && tmpl.common != nil {
+               if fn := tmpl.execFuncs[name]; fn.IsValid() {
+                       return fn, true
+               }
+       }
+       if fn := builtinFuncs[name]; fn.IsValid() {
+               return fn, true
+       }
+       return reflect.Value{}, false
+}
+
+// Indexing.
+
+// index returns the result of indexing its first argument by the following
+// arguments.  Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
+// indexed item must be a map, slice, or array.
+func index(item interface{}, indices ...interface{}) (interface{}, error) {
+       v := reflect.ValueOf(item)
+       for _, i := range indices {
+               index := reflect.ValueOf(i)
+               var isNil bool
+               if v, isNil = indirect(v); isNil {
+                       return nil, fmt.Errorf("index of nil pointer")
+               }
+               switch v.Kind() {
+               case reflect.Array, reflect.Slice, reflect.String:
+                       var x int64
+                       switch index.Kind() {
+                       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+                               x = index.Int()
+                       case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+                               x = int64(index.Uint())
+                       default:
+                               return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type())
+                       }
+                       if x < 0 || x >= int64(v.Len()) {
+                               return nil, fmt.Errorf("index out of range: %d", x)
+                       }
+                       v = v.Index(int(x))
+               case reflect.Map:
+                       if !index.IsValid() {
+                               index = reflect.Zero(v.Type().Key())
+                       }
+                       if !index.Type().AssignableTo(v.Type().Key()) {
+                               return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type())
+                       }
+                       if x := v.MapIndex(index); x.IsValid() {
+                               v = x
+                       } else {
+                               v = reflect.Zero(v.Type().Elem())
+                       }
+               default:
+                       return nil, fmt.Errorf("can't index item of type %s", v.Type())
+               }
+       }
+       return v.Interface(), nil
+}
+
+// Length
+
+// length returns the length of the item, with an error if it has no defined length.
+func length(item interface{}) (int, error) {
+       v, isNil := indirect(reflect.ValueOf(item))
+       if isNil {
+               return 0, fmt.Errorf("len of nil pointer")
+       }
+       switch v.Kind() {
+       case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
+               return v.Len(), nil
+       }
+       return 0, fmt.Errorf("len of type %s", v.Type())
+}
+
+// Function invocation
+
+// call returns the result of evaluating the first argument as a function.
+// The function must return 1 result, or 2 results, the second of which is an error.
+func call(fn interface{}, args ...interface{}) (interface{}, error) {
+       v := reflect.ValueOf(fn)
+       typ := v.Type()
+       if typ.Kind() != reflect.Func {
+               return nil, fmt.Errorf("non-function of type %s", typ)
+       }
+       if !goodFunc(typ) {
+               return nil, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
+       }
+       numIn := typ.NumIn()
+       var dddType reflect.Type
+       if typ.IsVariadic() {
+               if len(args) < numIn-1 {
+                       return nil, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
+               }
+               dddType = typ.In(numIn - 1).Elem()
+       } else {
+               if len(args) != numIn {
+                       return nil, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
+               }
+       }
+       argv := make([]reflect.Value, len(args))
+       for i, arg := range args {
+               value := reflect.ValueOf(arg)
+               // Compute the expected type. Clumsy because of variadics.
+               var argType reflect.Type
+               if !typ.IsVariadic() || i < numIn-1 {
+                       argType = typ.In(i)
+               } else {
+                       argType = dddType
+               }
+               if !value.IsValid() && canBeNil(argType) {
+                       value = reflect.Zero(argType)
+               }
+               if !value.Type().AssignableTo(argType) {
+                       return nil, fmt.Errorf("arg %d has type %s; should be %s", i, value.Type(), argType)
+               }
+               argv[i] = value
+       }
+       result := v.Call(argv)
+       if len(result) == 2 && !result[1].IsNil() {
+               return result[0].Interface(), result[1].Interface().(error)
+       }
+       return result[0].Interface(), nil
+}
+
+// Boolean logic.
+
+func truth(a interface{}) bool {
+       t, _ := isTrue(reflect.ValueOf(a))
+       return t
+}
+
+// and computes the Boolean AND of its arguments, returning
+// the first false argument it encounters, or the last argument.
+func and(arg0 interface{}, args ...interface{}) interface{} {
+       if !truth(arg0) {
+               return arg0
+       }
+       for i := range args {
+               arg0 = args[i]
+               if !truth(arg0) {
+                       break
+               }
+       }
+       return arg0
+}
+
+// or computes the Boolean OR of its arguments, returning
+// the first true argument it encounters, or the last argument.
+func or(arg0 interface{}, args ...interface{}) interface{} {
+       if truth(arg0) {
+               return arg0
+       }
+       for i := range args {
+               arg0 = args[i]
+               if truth(arg0) {
+                       break
+               }
+       }
+       return arg0
+}
+
+// not returns the Boolean negation of its argument.
+func not(arg interface{}) (truth bool) {
+       truth, _ = isTrue(reflect.ValueOf(arg))
+       return !truth
+}
+
+// Comparison.
+
+// TODO: Perhaps allow comparison between signed and unsigned integers.
+
+var (
+       errBadComparisonType = errors.New("invalid type for comparison")
+       errBadComparison     = errors.New("incompatible types for comparison")
+       errNoComparison      = errors.New("missing argument for comparison")
+)
+
+type kind int
+
+const (
+       invalidKind kind = iota
+       boolKind
+       complexKind
+       intKind
+       floatKind
+       integerKind
+       stringKind
+       uintKind
+)
+
+func basicKind(v reflect.Value) (kind, error) {
+       switch v.Kind() {
+       case reflect.Bool:
+               return boolKind, nil
+       case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+               return intKind, nil
+       case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+               return uintKind, nil
+       case reflect.Float32, reflect.Float64:
+               return floatKind, nil
+       case reflect.Complex64, reflect.Complex128:
+               return complexKind, nil
+       case reflect.String:
+               return stringKind, nil
+       }
+       return invalidKind, errBadComparisonType
+}
+
+// eq evaluates the comparison a == b || a == c || ...
+func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) {
+       v1 := reflect.ValueOf(arg1)
+       k1, err := basicKind(v1)
+       if err != nil {
+               return false, err
+       }
+       if len(arg2) == 0 {
+               return false, errNoComparison
+       }
+       for _, arg := range arg2 {
+               v2 := reflect.ValueOf(arg)
+               k2, err := basicKind(v2)
+               if err != nil {
+                       return false, err
+               }
+               truth := false
+               if k1 != k2 {
+                       // Special case: Can compare integer values regardless of type's sign.
+                       switch {
+                       case k1 == intKind && k2 == uintKind:
+                               truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
+                       case k1 == uintKind && k2 == intKind:
+                               truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
+                       default:
+                               return false, errBadComparison
+                       }
+               } else {
+                       switch k1 {
+                       case boolKind:
+                               truth = v1.Bool() == v2.Bool()
+                       case complexKind:
+                               truth = v1.Complex() == v2.Complex()
+                       case floatKind:
+                               truth = v1.Float() == v2.Float()
+                       case intKind:
+                               truth = v1.Int() == v2.Int()
+                       case stringKind:
+                               truth = v1.String() == v2.String()
+                       case uintKind:
+                               truth = v1.Uint() == v2.Uint()
+                       default:
+                               panic("invalid kind")
+                       }
+               }
+               if truth {
+                       return true, nil
+               }
+       }
+       return false, nil
+}
+
+// ne evaluates the comparison a != b.
+func ne(arg1, arg2 interface{}) (bool, error) {
+       // != is the inverse of ==.
+       equal, err := eq(arg1, arg2)
+       return !equal, err
+}
+
+// lt evaluates the comparison a < b.
+func lt(arg1, arg2 interface{}) (bool, error) {
+       v1 := reflect.ValueOf(arg1)
+       k1, err := basicKind(v1)
+       if err != nil {
+               return false, err
+       }
+       v2 := reflect.ValueOf(arg2)
+       k2, err := basicKind(v2)
+       if err != nil {
+               return false, err
+       }
+       truth := false
+       if k1 != k2 {
+               // Special case: Can compare integer values regardless of type's sign.
+               switch {
+               case k1 == intKind && k2 == uintKind:
+                       truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
+               case k1 == uintKind && k2 == intKind:
+                       truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
+               default:
+                       return false, errBadComparison
+               }
+       } else {
+               switch k1 {
+               case boolKind, complexKind:
+                       return false, errBadComparisonType
+               case floatKind:
+                       truth = v1.Float() < v2.Float()
+               case intKind:
+                       truth = v1.Int() < v2.Int()
+               case stringKind:
+                       truth = v1.String() < v2.String()
+               case uintKind:
+                       truth = v1.Uint() < v2.Uint()
+               default:
+                       panic("invalid kind")
+               }
+       }
+       return truth, nil
+}
+
+// le evaluates the comparison <= b.
+func le(arg1, arg2 interface{}) (bool, error) {
+       // <= is < or ==.
+       lessThan, err := lt(arg1, arg2)
+       if lessThan || err != nil {
+               return lessThan, err
+       }
+       return eq(arg1, arg2)
+}
+
+// gt evaluates the comparison a > b.
+func gt(arg1, arg2 interface{}) (bool, error) {
+       // > is the inverse of <=.
+       lessOrEqual, err := le(arg1, arg2)
+       if err != nil {
+               return false, err
+       }
+       return !lessOrEqual, nil
+}
+
+// ge evaluates the comparison a >= b.
+func ge(arg1, arg2 interface{}) (bool, error) {
+       // >= is the inverse of <.
+       lessThan, err := lt(arg1, arg2)
+       if err != nil {
+               return false, err
+       }
+       return !lessThan, nil
+}
+
+// HTML escaping.
+
+var (
+       htmlQuot = []byte("&#34;") // shorter than "&quot;"
+       htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
+       htmlAmp  = []byte("&amp;")
+       htmlLt   = []byte("&lt;")
+       htmlGt   = []byte("&gt;")
+)
+
+// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
+func HTMLEscape(w io.Writer, b []byte) {
+       last := 0
+       for i, c := range b {
+               var html []byte
+               switch c {
+               case '"':
+                       html = htmlQuot
+               case '\'':
+                       html = htmlApos
+               case '&':
+                       html = htmlAmp
+               case '<':
+                       html = htmlLt
+               case '>':
+                       html = htmlGt
+               default:
+                       continue
+               }
+               w.Write(b[last:i])
+               w.Write(html)
+               last = i + 1
+       }
+       w.Write(b[last:])
+}
+
+// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
+func HTMLEscapeString(s string) string {
+       // Avoid allocation if we can.
+       if strings.IndexAny(s, `'"&<>`) < 0 {
+               return s
+       }
+       var b bytes.Buffer
+       HTMLEscape(&b, []byte(s))
+       return b.String()
+}
+
+// HTMLEscaper returns the escaped HTML equivalent of the textual
+// representation of its arguments.
+func HTMLEscaper(args ...interface{}) string {
+       return HTMLEscapeString(evalArgs(args))
+}
+
+// JavaScript escaping.
+
+var (
+       jsLowUni = []byte(`\u00`)
+       hex      = []byte("0123456789ABCDEF")
+
+       jsBackslash = []byte(`\\`)
+       jsApos      = []byte(`\'`)
+       jsQuot      = []byte(`\"`)
+       jsLt        = []byte(`\x3C`)
+       jsGt        = []byte(`\x3E`)
+)
+
+// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
+func JSEscape(w io.Writer, b []byte) {
+       last := 0
+       for i := 0; i < len(b); i++ {
+               c := b[i]
+
+               if !jsIsSpecial(rune(c)) {
+                       // fast path: nothing to do
+                       continue
+               }
+               w.Write(b[last:i])
+
+               if c < utf8.RuneSelf {
+                       // Quotes, slashes and angle brackets get quoted.
+                       // Control characters get written as \u00XX.
+                       switch c {
+                       case '\\':
+                               w.Write(jsBackslash)
+                       case '\'':
+                               w.Write(jsApos)
+                       case '"':
+                               w.Write(jsQuot)
+                       case '<':
+                               w.Write(jsLt)
+                       case '>':
+                               w.Write(jsGt)
+                       default:
+                               w.Write(jsLowUni)
+                               t, b := c>>4, c&0x0f
+                               w.Write(hex[t : t+1])
+                               w.Write(hex[b : b+1])
+                       }
+               } else {
+                       // Unicode rune.
+                       r, size := utf8.DecodeRune(b[i:])
+                       if unicode.IsPrint(r) {
+                               w.Write(b[i : i+size])
+                       } else {
+                               fmt.Fprintf(w, "\\u%04X", r)
+                       }
+                       i += size - 1
+               }
+               last = i + 1
+       }
+       w.Write(b[last:])
+}
+
+// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
+func JSEscapeString(s string) string {
+       // Avoid allocation if we can.
+       if strings.IndexFunc(s, jsIsSpecial) < 0 {
+               return s
+       }
+       var b bytes.Buffer
+       JSEscape(&b, []byte(s))
+       return b.String()
+}
+
+func jsIsSpecial(r rune) bool {
+       switch r {
+       case '\\', '\'', '"', '<', '>':
+               return true
+       }
+       return r < ' ' || utf8.RuneSelf <= r
+}
+
+// JSEscaper returns the escaped JavaScript equivalent of the textual
+// representation of its arguments.
+func JSEscaper(args ...interface{}) string {
+       return JSEscapeString(evalArgs(args))
+}
+
+// URLQueryEscaper returns the escaped value of the textual representation of
+// its arguments in a form suitable for embedding in a URL query.
+func URLQueryEscaper(args ...interface{}) string {
+       return url.QueryEscape(evalArgs(args))
+}
+
+// evalArgs formats the list of arguments into a string. It is therefore equivalent to
+//     fmt.Sprint(args...)
+// except that each argument is indirected (if a pointer), as required,
+// using the same rules as the default string evaluation during template
+// execution.
+func evalArgs(args []interface{}) string {
+       ok := false
+       var s string
+       // Fast path for simple common case.
+       if len(args) == 1 {
+               s, ok = args[0].(string)
+       }
+       if !ok {
+               for i, arg := range args {
+                       a, ok := printableValue(reflect.ValueOf(arg))
+                       if ok {
+                               args[i] = a
+                       } // else left fmt do its thing
+               }
+               s = fmt.Sprint(args...)
+       }
+       return s
+}
diff --git a/vendor/github.com/alecthomas/template/helper.go b/vendor/github.com/alecthomas/template/helper.go
new file mode 100644 (file)
index 0000000..3636fb5
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Helper functions to make constructing templates easier.
+
+package template
+
+import (
+       "fmt"
+       "io/ioutil"
+       "path/filepath"
+)
+
+// Functions and methods to parse templates.
+
+// Must is a helper that wraps a call to a function returning (*Template, error)
+// and panics if the error is non-nil. It is intended for use in variable
+// initializations such as
+//     var t = template.Must(template.New("name").Parse("text"))
+func Must(t *Template, err error) *Template {
+       if err != nil {
+               panic(err)
+       }
+       return t
+}
+
+// ParseFiles creates a new Template and parses the template definitions from
+// the named files. The returned template's name will have the (base) name and
+// (parsed) contents of the first file. There must be at least one file.
+// If an error occurs, parsing stops and the returned *Template is nil.
+func ParseFiles(filenames ...string) (*Template, error) {
+       return parseFiles(nil, filenames...)
+}
+
+// ParseFiles parses the named files and associates the resulting templates with
+// t. If an error occurs, parsing stops and the returned template is nil;
+// otherwise it is t. There must be at least one file.
+func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
+       return parseFiles(t, filenames...)
+}
+
+// parseFiles is the helper for the method and function. If the argument
+// template is nil, it is created from the first file.
+func parseFiles(t *Template, filenames ...string) (*Template, error) {
+       if len(filenames) == 0 {
+               // Not really a problem, but be consistent.
+               return nil, fmt.Errorf("template: no files named in call to ParseFiles")
+       }
+       for _, filename := range filenames {
+               b, err := ioutil.ReadFile(filename)
+               if err != nil {
+                       return nil, err
+               }
+               s := string(b)
+               name := filepath.Base(filename)
+               // First template becomes return value if not already defined,
+               // and we use that one for subsequent New calls to associate
+               // all the templates together. Also, if this file has the same name
+               // as t, this file becomes the contents of t, so
+               //  t, err := New(name).Funcs(xxx).ParseFiles(name)
+               // works. Otherwise we create a new template associated with t.
+               var tmpl *Template
+               if t == nil {
+                       t = New(name)
+               }
+               if name == t.Name() {
+                       tmpl = t
+               } else {
+                       tmpl = t.New(name)
+               }
+               _, err = tmpl.Parse(s)
+               if err != nil {
+                       return nil, err
+               }
+       }
+       return t, nil
+}
+
+// ParseGlob creates a new Template and parses the template definitions from the
+// files identified by the pattern, which must match at least one file. The
+// returned template will have the (base) name and (parsed) contents of the
+// first file matched by the pattern. ParseGlob is equivalent to calling
+// ParseFiles with the list of files matched by the pattern.
+func ParseGlob(pattern string) (*Template, error) {
+       return parseGlob(nil, pattern)
+}
+
+// ParseGlob parses the template definitions in the files identified by the
+// pattern and associates the resulting templates with t. The pattern is
+// processed by filepath.Glob and must match at least one file. ParseGlob is
+// equivalent to calling t.ParseFiles with the list of files matched by the
+// pattern.
+func (t *Template) ParseGlob(pattern string) (*Template, error) {
+       return parseGlob(t, pattern)
+}
+
+// parseGlob is the implementation of the function and method ParseGlob.
+func parseGlob(t *Template, pattern string) (*Template, error) {
+       filenames, err := filepath.Glob(pattern)
+       if err != nil {
+               return nil, err
+       }
+       if len(filenames) == 0 {
+               return nil, fmt.Errorf("template: pattern matches no files: %#q", pattern)
+       }
+       return parseFiles(t, filenames...)
+}
diff --git a/vendor/github.com/alecthomas/template/parse/lex.go b/vendor/github.com/alecthomas/template/parse/lex.go
new file mode 100644 (file)
index 0000000..55f1c05
--- /dev/null
@@ -0,0 +1,556 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package parse
+
+import (
+       "fmt"
+       "strings"
+       "unicode"
+       "unicode/utf8"
+)
+
+// item represents a token or text string returned from the scanner.
+type item struct {
+       typ itemType // The type of this item.
+       pos Pos      // The starting position, in bytes, of this item in the input string.
+       val string   // The value of this item.
+}
+
+func (i item) String() string {
+       switch {
+       case i.typ == itemEOF:
+               return "EOF"
+       case i.typ == itemError:
+               return i.val
+       case i.typ > itemKeyword:
+               return fmt.Sprintf("<%s>", i.val)
+       case len(i.val) > 10:
+               return fmt.Sprintf("%.10q...", i.val)
+       }
+       return fmt.Sprintf("%q", i.val)
+}
+
+// itemType identifies the type of lex items.
+type itemType int
+
+const (
+       itemError        itemType = iota // error occurred; value is text of error
+       itemBool                         // boolean constant
+       itemChar                         // printable ASCII character; grab bag for comma etc.
+       itemCharConstant                 // character constant
+       itemComplex                      // complex constant (1+2i); imaginary is just a number
+       itemColonEquals                  // colon-equals (':=') introducing a declaration
+       itemEOF
+       itemField        // alphanumeric identifier starting with '.'
+       itemIdentifier   // alphanumeric identifier not starting with '.'
+       itemLeftDelim    // left action delimiter
+       itemLeftParen    // '(' inside action
+       itemNumber       // simple number, including imaginary
+       itemPipe         // pipe symbol
+       itemRawString    // raw quoted string (includes quotes)
+       itemRightDelim   // right action delimiter
+       itemElideNewline // elide newline after right delim
+       itemRightParen   // ')' inside action
+       itemSpace        // run of spaces separating arguments
+       itemString       // quoted string (includes quotes)
+       itemText         // plain text
+       itemVariable     // variable starting with '$', such as '$' or  '$1' or '$hello'
+       // Keywords appear after all the rest.
+       itemKeyword  // used only to delimit the keywords
+       itemDot      // the cursor, spelled '.'
+       itemDefine   // define keyword
+       itemElse     // else keyword
+       itemEnd      // end keyword
+       itemIf       // if keyword
+       itemNil      // the untyped nil constant, easiest to treat as a keyword
+       itemRange    // range keyword
+       itemTemplate // template keyword
+       itemWith     // with keyword
+)
+
+var key = map[string]itemType{
+       ".":        itemDot,
+       "define":   itemDefine,
+       "else":     itemElse,
+       "end":      itemEnd,
+       "if":       itemIf,
+       "range":    itemRange,
+       "nil":      itemNil,
+       "template": itemTemplate,
+       "with":     itemWith,
+}
+
+const eof = -1
+
+// stateFn represents the state of the scanner as a function that returns the next state.
+type stateFn func(*lexer) stateFn
+
+// lexer holds the state of the scanner.
+type lexer struct {
+       name       string    // the name of the input; used only for error reports
+       input      string    // the string being scanned
+       leftDelim  string    // start of action
+       rightDelim string    // end of action
+       state      stateFn   // the next lexing function to enter
+       pos        Pos       // current position in the input
+       start      Pos       // start position of this item
+       width      Pos       // width of last rune read from input
+       lastPos    Pos       // position of most recent item returned by nextItem
+       items      chan item // channel of scanned items
+       parenDepth int       // nesting depth of ( ) exprs
+}
+
+// next returns the next rune in the input.
+func (l *lexer) next() rune {
+       if int(l.pos) >= len(l.input) {
+               l.width = 0
+               return eof
+       }
+       r, w := utf8.DecodeRuneInString(l.input[l.pos:])
+       l.width = Pos(w)
+       l.pos += l.width
+       return r
+}
+
+// peek returns but does not consume the next rune in the input.
+func (l *lexer) peek() rune {
+       r := l.next()
+       l.backup()
+       return r
+}
+
+// backup steps back one rune. Can only be called once per call of next.
+func (l *lexer) backup() {
+       l.pos -= l.width
+}
+
+// emit passes an item back to the client.
+func (l *lexer) emit(t itemType) {
+       l.items <- item{t, l.start, l.input[l.start:l.pos]}
+       l.start = l.pos
+}
+
+// ignore skips over the pending input before this point.
+func (l *lexer) ignore() {
+       l.start = l.pos
+}
+
+// accept consumes the next rune if it's from the valid set.
+func (l *lexer) accept(valid string) bool {
+       if strings.IndexRune(valid, l.next()) >= 0 {
+               return true
+       }
+       l.backup()
+       return false
+}
+
+// acceptRun consumes a run of runes from the valid set.
+func (l *lexer) acceptRun(valid string) {
+       for strings.IndexRune(valid, l.next()) >= 0 {
+       }
+       l.backup()
+}
+
+// lineNumber reports which line we're on, based on the position of
+// the previous item returned by nextItem. Doing it this way
+// means we don't have to worry about peek double counting.
+func (l *lexer) lineNumber() int {
+       return 1 + strings.Count(l.input[:l.lastPos], "\n")
+}
+
+// errorf returns an error token and terminates the scan by passing
+// back a nil pointer that will be the next state, terminating l.nextItem.
+func (l *lexer) errorf(format string, args ...interface{}) stateFn {
+       l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
+       return nil
+}
+
+// nextItem returns the next item from the input.
+func (l *lexer) nextItem() item {
+       item := <-l.items
+       l.lastPos = item.pos
+       return item
+}
+
+// lex creates a new scanner for the input string.
+func lex(name, input, left, right string) *lexer {
+       if left == "" {
+               left = leftDelim
+       }
+       if right == "" {
+               right = rightDelim
+       }
+       l := &lexer{
+               name:       name,
+               input:      input,
+               leftDelim:  left,
+               rightDelim: right,
+               items:      make(chan item),
+       }
+       go l.run()
+       return l
+}
+
+// run runs the state machine for the lexer.
+func (l *lexer) run() {
+       for l.state = lexText; l.state != nil; {
+               l.state = l.state(l)
+       }
+}
+
+// state functions
+
+const (
+       leftDelim    = "{{"
+       rightDelim   = "}}"
+       leftComment  = "/*"
+       rightComment = "*/"
+)
+
+// lexText scans until an opening action delimiter, "{{".
+func lexText(l *lexer) stateFn {
+       for {
+               if strings.HasPrefix(l.input[l.pos:], l.leftDelim) {
+                       if l.pos > l.start {
+                               l.emit(itemText)
+                       }
+                       return lexLeftDelim
+               }
+               if l.next() == eof {
+                       break
+               }
+       }
+       // Correctly reached EOF.
+       if l.pos > l.start {
+               l.emit(itemText)
+       }
+       l.emit(itemEOF)
+       return nil
+}
+
+// lexLeftDelim scans the left delimiter, which is known to be present.
+func lexLeftDelim(l *lexer) stateFn {
+       l.pos += Pos(len(l.leftDelim))
+       if strings.HasPrefix(l.input[l.pos:], leftComment) {
+               return lexComment
+       }
+       l.emit(itemLeftDelim)
+       l.parenDepth = 0
+       return lexInsideAction
+}
+
+// lexComment scans a comment. The left comment marker is known to be present.
+func lexComment(l *lexer) stateFn {
+       l.pos += Pos(len(leftComment))
+       i := strings.Index(l.input[l.pos:], rightComment)
+       if i < 0 {
+               return l.errorf("unclosed comment")
+       }
+       l.pos += Pos(i + len(rightComment))
+       if !strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+               return l.errorf("comment ends before closing delimiter")
+
+       }
+       l.pos += Pos(len(l.rightDelim))
+       l.ignore()
+       return lexText
+}
+
+// lexRightDelim scans the right delimiter, which is known to be present.
+func lexRightDelim(l *lexer) stateFn {
+       l.pos += Pos(len(l.rightDelim))
+       l.emit(itemRightDelim)
+       if l.peek() == '\\' {
+               l.pos++
+               l.emit(itemElideNewline)
+       }
+       return lexText
+}
+
+// lexInsideAction scans the elements inside action delimiters.
+func lexInsideAction(l *lexer) stateFn {
+       // Either number, quoted string, or identifier.
+       // Spaces separate arguments; runs of spaces turn into itemSpace.
+       // Pipe symbols separate and are emitted.
+       if strings.HasPrefix(l.input[l.pos:], l.rightDelim+"\\") || strings.HasPrefix(l.input[l.pos:], l.rightDelim) {
+               if l.parenDepth == 0 {
+                       return lexRightDelim
+               }
+               return l.errorf("unclosed left paren")
+       }
+       switch r := l.next(); {
+       case r == eof || isEndOfLine(r):
+               return l.errorf("unclosed action")
+       case isSpace(r):
+               return lexSpace
+       case r == ':':
+               if l.next() != '=' {
+                       return l.errorf("expected :=")
+               }
+               l.emit(itemColonEquals)
+       case r == '|':
+               l.emit(itemPipe)
+       case r == '"':
+               return lexQuote
+       case r == '`':
+               return lexRawQuote
+       case r == '$':
+               return lexVariable
+       case r == '\'':
+               return lexChar
+       case r == '.':
+               // special look-ahead for ".field" so we don't break l.backup().
+               if l.pos < Pos(len(l.input)) {
+                       r := l.input[l.pos]
+                       if r < '0' || '9' < r {
+                               return lexField
+                       }
+               }
+               fallthrough // '.' can start a number.
+       case r == '+' || r == '-' || ('0' <= r && r <= '9'):
+               l.backup()
+               return lexNumber
+       case isAlphaNumeric(r):
+               l.backup()
+               return lexIdentifier
+       case r == '(':
+               l.emit(itemLeftParen)
+               l.parenDepth++
+               return lexInsideAction
+       case r == ')':
+               l.emit(itemRightParen)
+               l.parenDepth--
+               if l.parenDepth < 0 {
+                       return l.errorf("unexpected right paren %#U", r)
+               }
+               return lexInsideAction
+       case r <= unicode.MaxASCII && unicode.IsPrint(r):
+               l.emit(itemChar)
+               return lexInsideAction
+       default:
+               return l.errorf("unrecognized character in action: %#U", r)
+       }
+       return lexInsideAction
+}
+
+// lexSpace scans a run of space characters.
+// One space has already been seen.
+func lexSpace(l *lexer) stateFn {
+       for isSpace(l.peek()) {
+               l.next()
+       }
+       l.emit(itemSpace)
+       return lexInsideAction
+}
+
+// lexIdentifier scans an alphanumeric.
+func lexIdentifier(l *lexer) stateFn {
+Loop:
+       for {
+               switch r := l.next(); {
+               case isAlphaNumeric(r):
+                       // absorb.
+               default:
+                       l.backup()
+                       word := l.input[l.start:l.pos]
+                       if !l.atTerminator() {
+                               return l.errorf("bad character %#U", r)
+                       }
+                       switch {
+                       case key[word] > itemKeyword:
+                               l.emit(key[word])
+                       case word[0] == '.':
+                               l.emit(itemField)
+                       case word == "true", word == "false":
+                               l.emit(itemBool)
+                       default:
+                               l.emit(itemIdentifier)
+                       }
+                       break Loop
+               }
+       }
+       return lexInsideAction
+}
+
+// lexField scans a field: .Alphanumeric.
+// The . has been scanned.
+func lexField(l *lexer) stateFn {
+       return lexFieldOrVariable(l, itemField)
+}
+
+// lexVariable scans a Variable: $Alphanumeric.
+// The $ has been scanned.
+func lexVariable(l *lexer) stateFn {
+       if l.atTerminator() { // Nothing interesting follows -> "$".
+               l.emit(itemVariable)
+               return lexInsideAction
+       }
+       return lexFieldOrVariable(l, itemVariable)
+}
+
+// lexVariable scans a field or variable: [.$]Alphanumeric.
+// The . or $ has been scanned.
+func lexFieldOrVariable(l *lexer, typ itemType) stateFn {
+       if l.atTerminator() { // Nothing interesting follows -> "." or "$".
+               if typ == itemVariable {
+                       l.emit(itemVariable)
+               } else {
+                       l.emit(itemDot)
+               }
+               return lexInsideAction
+       }
+       var r rune
+       for {
+               r = l.next()
+               if !isAlphaNumeric(r) {
+                       l.backup()
+                       break
+               }
+       }
+       if !l.atTerminator() {
+               return l.errorf("bad character %#U", r)
+       }
+       l.emit(typ)
+       return lexInsideAction
+}
+
+// atTerminator reports whether the input is at valid termination character to
+// appear after an identifier. Breaks .X.Y into two pieces. Also catches cases
+// like "$x+2" not being acceptable without a space, in case we decide one
+// day to implement arithmetic.
+func (l *lexer) atTerminator() bool {
+       r := l.peek()
+       if isSpace(r) || isEndOfLine(r) {
+               return true
+       }
+       switch r {
+       case eof, '.', ',', '|', ':', ')', '(':
+               return true
+       }
+       // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
+       // succeed but should fail) but only in extremely rare cases caused by willfully
+       // bad choice of delimiter.
+       if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
+               return true
+       }
+       return false
+}
+
+// lexChar scans a character constant. The initial quote is already
+// scanned. Syntax checking is done by the parser.
+func lexChar(l *lexer) stateFn {
+Loop:
+       for {
+               switch l.next() {
+               case '\\':
+                       if r := l.next(); r != eof && r != '\n' {
+                               break
+                       }
+                       fallthrough
+               case eof, '\n':
+                       return l.errorf("unterminated character constant")
+               case '\'':
+                       break Loop
+               }
+       }
+       l.emit(itemCharConstant)
+       return lexInsideAction
+}
+
+// lexNumber scans a number: decimal, octal, hex, float, or imaginary. This
+// isn't a perfect number scanner - for instance it accepts "." and "0x0.2"
+// and "089" - but when it's wrong the input is invalid and the parser (via
+// strconv) will notice.
+func lexNumber(l *lexer) stateFn {
+       if !l.scanNumber() {
+               return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+       }
+       if sign := l.peek(); sign == '+' || sign == '-' {
+               // Complex: 1+2i. No spaces, must end in 'i'.
+               if !l.scanNumber() || l.input[l.pos-1] != 'i' {
+                       return l.errorf("bad number syntax: %q", l.input[l.start:l.pos])
+               }
+               l.emit(itemComplex)
+       } else {
+               l.emit(itemNumber)
+       }
+       return lexInsideAction
+}
+
+func (l *lexer) scanNumber() bool {
+       // Optional leading sign.
+       l.accept("+-")
+       // Is it hex?
+       digits := "0123456789"
+       if l.accept("0") && l.accept("xX") {
+               digits = "0123456789abcdefABCDEF"
+       }
+       l.acceptRun(digits)
+       if l.accept(".") {
+               l.acceptRun(digits)
+       }
+       if l.accept("eE") {
+               l.accept("+-")
+               l.acceptRun("0123456789")
+       }
+       // Is it imaginary?
+       l.accept("i")
+       // Next thing mustn't be alphanumeric.
+       if isAlphaNumeric(l.peek()) {
+               l.next()
+               return false
+       }
+       return true
+}
+
+// lexQuote scans a quoted string.
+func lexQuote(l *lexer) stateFn {
+Loop:
+       for {
+               switch l.next() {
+               case '\\':
+                       if r := l.next(); r != eof && r != '\n' {
+                               break
+                       }
+                       fallthrough
+               case eof, '\n':
+                       return l.errorf("unterminated quoted string")
+               case '"':
+                       break Loop
+               }
+       }
+       l.emit(itemString)
+       return lexInsideAction
+}
+
+// lexRawQuote scans a raw quoted string.
+func lexRawQuote(l *lexer) stateFn {
+Loop:
+       for {
+               switch l.next() {
+               case eof, '\n':
+                       return l.errorf("unterminated raw quoted string")
+               case '`':
+                       break Loop
+               }
+       }
+       l.emit(itemRawString)
+       return lexInsideAction
+}
+
+// isSpace reports whether r is a space character.
+func isSpace(r rune) bool {
+       return r == ' ' || r == '\t'
+}
+
+// isEndOfLine reports whether r is an end-of-line character.
+func isEndOfLine(r rune) bool {
+       return r == '\r' || r == '\n'
+}
+
+// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
+func isAlphaNumeric(r rune) bool {
+       return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
+}
diff --git a/vendor/github.com/alecthomas/template/parse/node.go b/vendor/github.com/alecthomas/template/parse/node.go
new file mode 100644 (file)
index 0000000..55c37f6
--- /dev/null
@@ -0,0 +1,834 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Parse nodes.
+
+package parse
+
+import (
+       "bytes"
+       "fmt"
+       "strconv"
+       "strings"
+)
+
+var textFormat = "%s" // Changed to "%q" in tests for better error messages.
+
+// A Node is an element in the parse tree. The interface is trivial.
+// The interface contains an unexported method so that only
+// types local to this package can satisfy it.
+type Node interface {
+       Type() NodeType
+       String() string
+       // Copy does a deep copy of the Node and all its components.
+       // To avoid type assertions, some XxxNodes also have specialized
+       // CopyXxx methods that return *XxxNode.
+       Copy() Node
+       Position() Pos // byte position of start of node in full original input string
+       // tree returns the containing *Tree.
+       // It is unexported so all implementations of Node are in this package.
+       tree() *Tree
+}
+
+// NodeType identifies the type of a parse tree node.
+type NodeType int
+
+// Pos represents a byte position in the original input text from which
+// this template was parsed.
+type Pos int
+
+func (p Pos) Position() Pos {
+       return p
+}
+
+// Type returns itself and provides an easy default implementation
+// for embedding in a Node. Embedded in all non-trivial Nodes.
+func (t NodeType) Type() NodeType {
+       return t
+}
+
+const (
+       NodeText       NodeType = iota // Plain text.
+       NodeAction                     // A non-control action such as a field evaluation.
+       NodeBool                       // A boolean constant.
+       NodeChain                      // A sequence of field accesses.
+       NodeCommand                    // An element of a pipeline.
+       NodeDot                        // The cursor, dot.
+       nodeElse                       // An else action. Not added to tree.
+       nodeEnd                        // An end action. Not added to tree.
+       NodeField                      // A field or method name.
+       NodeIdentifier                 // An identifier; always a function name.
+       NodeIf                         // An if action.
+       NodeList                       // A list of Nodes.
+       NodeNil                        // An untyped nil constant.
+       NodeNumber                     // A numerical constant.
+       NodePipe                       // A pipeline of commands.
+       NodeRange                      // A range action.
+       NodeString                     // A string constant.
+       NodeTemplate                   // A template invocation action.
+       NodeVariable                   // A $ variable.
+       NodeWith                       // A with action.
+)
+
+// Nodes.
+
+// ListNode holds a sequence of nodes.
+type ListNode struct {
+       NodeType
+       Pos
+       tr    *Tree
+       Nodes []Node // The element nodes in lexical order.
+}
+
+func (t *Tree) newList(pos Pos) *ListNode {
+       return &ListNode{tr: t, NodeType: NodeList, Pos: pos}
+}
+
+func (l *ListNode) append(n Node) {
+       l.Nodes = append(l.Nodes, n)
+}
+
+func (l *ListNode) tree() *Tree {
+       return l.tr
+}
+
+func (l *ListNode) String() string {
+       b := new(bytes.Buffer)
+       for _, n := range l.Nodes {
+               fmt.Fprint(b, n)
+       }
+       return b.String()
+}
+
+func (l *ListNode) CopyList() *ListNode {
+       if l == nil {
+               return l
+       }
+       n := l.tr.newList(l.Pos)
+       for _, elem := range l.Nodes {
+               n.append(elem.Copy())
+       }
+       return n
+}
+
+func (l *ListNode) Copy() Node {
+       return l.CopyList()
+}
+
+// TextNode holds plain text.
+type TextNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Text []byte // The text; may span newlines.
+}
+
+func (t *Tree) newText(pos Pos, text string) *TextNode {
+       return &TextNode{tr: t, NodeType: NodeText, Pos: pos, Text: []byte(text)}
+}
+
+func (t *TextNode) String() string {
+       return fmt.Sprintf(textFormat, t.Text)
+}
+
+func (t *TextNode) tree() *Tree {
+       return t.tr
+}
+
+func (t *TextNode) Copy() Node {
+       return &TextNode{tr: t.tr, NodeType: NodeText, Pos: t.Pos, Text: append([]byte{}, t.Text...)}
+}
+
+// PipeNode holds a pipeline with optional declaration
+type PipeNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Line int             // The line number in the input (deprecated; kept for compatibility)
+       Decl []*VariableNode // Variable declarations in lexical order.
+       Cmds []*CommandNode  // The commands in lexical order.
+}
+
+func (t *Tree) newPipeline(pos Pos, line int, decl []*VariableNode) *PipeNode {
+       return &PipeNode{tr: t, NodeType: NodePipe, Pos: pos, Line: line, Decl: decl}
+}
+
+func (p *PipeNode) append(command *CommandNode) {
+       p.Cmds = append(p.Cmds, command)
+}
+
+func (p *PipeNode) String() string {
+       s := ""
+       if len(p.Decl) > 0 {
+               for i, v := range p.Decl {
+                       if i > 0 {
+                               s += ", "
+                       }
+                       s += v.String()
+               }
+               s += " := "
+       }
+       for i, c := range p.Cmds {
+               if i > 0 {
+                       s += " | "
+               }
+               s += c.String()
+       }
+       return s
+}
+
+func (p *PipeNode) tree() *Tree {
+       return p.tr
+}
+
+func (p *PipeNode) CopyPipe() *PipeNode {
+       if p == nil {
+               return p
+       }
+       var decl []*VariableNode
+       for _, d := range p.Decl {
+               decl = append(decl, d.Copy().(*VariableNode))
+       }
+       n := p.tr.newPipeline(p.Pos, p.Line, decl)
+       for _, c := range p.Cmds {
+               n.append(c.Copy().(*CommandNode))
+       }
+       return n
+}
+
+func (p *PipeNode) Copy() Node {
+       return p.CopyPipe()
+}
+
+// ActionNode holds an action (something bounded by delimiters).
+// Control actions have their own nodes; ActionNode represents simple
+// ones such as field evaluations and parenthesized pipelines.
+type ActionNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Line int       // The line number in the input (deprecated; kept for compatibility)
+       Pipe *PipeNode // The pipeline in the action.
+}
+
+func (t *Tree) newAction(pos Pos, line int, pipe *PipeNode) *ActionNode {
+       return &ActionNode{tr: t, NodeType: NodeAction, Pos: pos, Line: line, Pipe: pipe}
+}
+
+func (a *ActionNode) String() string {
+       return fmt.Sprintf("{{%s}}", a.Pipe)
+
+}
+
+func (a *ActionNode) tree() *Tree {
+       return a.tr
+}
+
+func (a *ActionNode) Copy() Node {
+       return a.tr.newAction(a.Pos, a.Line, a.Pipe.CopyPipe())
+
+}
+
+// CommandNode holds a command (a pipeline inside an evaluating action).
+type CommandNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Args []Node // Arguments in lexical order: Identifier, field, or constant.
+}
+
+func (t *Tree) newCommand(pos Pos) *CommandNode {
+       return &CommandNode{tr: t, NodeType: NodeCommand, Pos: pos}
+}
+
+func (c *CommandNode) append(arg Node) {
+       c.Args = append(c.Args, arg)
+}
+
+func (c *CommandNode) String() string {
+       s := ""
+       for i, arg := range c.Args {
+               if i > 0 {
+                       s += " "
+               }
+               if arg, ok := arg.(*PipeNode); ok {
+                       s += "(" + arg.String() + ")"
+                       continue
+               }
+               s += arg.String()
+       }
+       return s
+}
+
+func (c *CommandNode) tree() *Tree {
+       return c.tr
+}
+
+func (c *CommandNode) Copy() Node {
+       if c == nil {
+               return c
+       }
+       n := c.tr.newCommand(c.Pos)
+       for _, c := range c.Args {
+               n.append(c.Copy())
+       }
+       return n
+}
+
+// IdentifierNode holds an identifier.
+type IdentifierNode struct {
+       NodeType
+       Pos
+       tr    *Tree
+       Ident string // The identifier's name.
+}
+
+// NewIdentifier returns a new IdentifierNode with the given identifier name.
+func NewIdentifier(ident string) *IdentifierNode {
+       return &IdentifierNode{NodeType: NodeIdentifier, Ident: ident}
+}
+
+// SetPos sets the position. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetPos(pos Pos) *IdentifierNode {
+       i.Pos = pos
+       return i
+}
+
+// SetTree sets the parent tree for the node. NewIdentifier is a public method so we can't modify its signature.
+// Chained for convenience.
+// TODO: fix one day?
+func (i *IdentifierNode) SetTree(t *Tree) *IdentifierNode {
+       i.tr = t
+       return i
+}
+
+func (i *IdentifierNode) String() string {
+       return i.Ident
+}
+
+func (i *IdentifierNode) tree() *Tree {
+       return i.tr
+}
+
+func (i *IdentifierNode) Copy() Node {
+       return NewIdentifier(i.Ident).SetTree(i.tr).SetPos(i.Pos)
+}
+
+// VariableNode holds a list of variable names, possibly with chained field
+// accesses. The dollar sign is part of the (first) name.
+type VariableNode struct {
+       NodeType
+       Pos
+       tr    *Tree
+       Ident []string // Variable name and fields in lexical order.
+}
+
+func (t *Tree) newVariable(pos Pos, ident string) *VariableNode {
+       return &VariableNode{tr: t, NodeType: NodeVariable, Pos: pos, Ident: strings.Split(ident, ".")}
+}
+
+func (v *VariableNode) String() string {
+       s := ""
+       for i, id := range v.Ident {
+               if i > 0 {
+                       s += "."
+               }
+               s += id
+       }
+       return s
+}
+
+func (v *VariableNode) tree() *Tree {
+       return v.tr
+}
+
+func (v *VariableNode) Copy() Node {
+       return &VariableNode{tr: v.tr, NodeType: NodeVariable, Pos: v.Pos, Ident: append([]string{}, v.Ident...)}
+}
+
+// DotNode holds the special identifier '.'.
+type DotNode struct {
+       NodeType
+       Pos
+       tr *Tree
+}
+
+func (t *Tree) newDot(pos Pos) *DotNode {
+       return &DotNode{tr: t, NodeType: NodeDot, Pos: pos}
+}
+
+func (d *DotNode) Type() NodeType {
+       // Override method on embedded NodeType for API compatibility.
+       // TODO: Not really a problem; could change API without effect but
+       // api tool complains.
+       return NodeDot
+}
+
+func (d *DotNode) String() string {
+       return "."
+}
+
+func (d *DotNode) tree() *Tree {
+       return d.tr
+}
+
+func (d *DotNode) Copy() Node {
+       return d.tr.newDot(d.Pos)
+}
+
+// NilNode holds the special identifier 'nil' representing an untyped nil constant.
+type NilNode struct {
+       NodeType
+       Pos
+       tr *Tree
+}
+
+func (t *Tree) newNil(pos Pos) *NilNode {
+       return &NilNode{tr: t, NodeType: NodeNil, Pos: pos}
+}
+
+func (n *NilNode) Type() NodeType {
+       // Override method on embedded NodeType for API compatibility.
+       // TODO: Not really a problem; could change API without effect but
+       // api tool complains.
+       return NodeNil
+}
+
+func (n *NilNode) String() string {
+       return "nil"
+}
+
+func (n *NilNode) tree() *Tree {
+       return n.tr
+}
+
+func (n *NilNode) Copy() Node {
+       return n.tr.newNil(n.Pos)
+}
+
+// FieldNode holds a field (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The period is dropped from each ident.
+type FieldNode struct {
+       NodeType
+       Pos
+       tr    *Tree
+       Ident []string // The identifiers in lexical order.
+}
+
+func (t *Tree) newField(pos Pos, ident string) *FieldNode {
+       return &FieldNode{tr: t, NodeType: NodeField, Pos: pos, Ident: strings.Split(ident[1:], ".")} // [1:] to drop leading period
+}
+
+func (f *FieldNode) String() string {
+       s := ""
+       for _, id := range f.Ident {
+               s += "." + id
+       }
+       return s
+}
+
+func (f *FieldNode) tree() *Tree {
+       return f.tr
+}
+
+func (f *FieldNode) Copy() Node {
+       return &FieldNode{tr: f.tr, NodeType: NodeField, Pos: f.Pos, Ident: append([]string{}, f.Ident...)}
+}
+
+// ChainNode holds a term followed by a chain of field accesses (identifier starting with '.').
+// The names may be chained ('.x.y').
+// The periods are dropped from each ident.
+type ChainNode struct {
+       NodeType
+       Pos
+       tr    *Tree
+       Node  Node
+       Field []string // The identifiers in lexical order.
+}
+
+func (t *Tree) newChain(pos Pos, node Node) *ChainNode {
+       return &ChainNode{tr: t, NodeType: NodeChain, Pos: pos, Node: node}
+}
+
+// Add adds the named field (which should start with a period) to the end of the chain.
+func (c *ChainNode) Add(field string) {
+       if len(field) == 0 || field[0] != '.' {
+               panic("no dot in field")
+       }
+       field = field[1:] // Remove leading dot.
+       if field == "" {
+               panic("empty field")
+       }
+       c.Field = append(c.Field, field)
+}
+
+func (c *ChainNode) String() string {
+       s := c.Node.String()
+       if _, ok := c.Node.(*PipeNode); ok {
+               s = "(" + s + ")"
+       }
+       for _, field := range c.Field {
+               s += "." + field
+       }
+       return s
+}
+
+func (c *ChainNode) tree() *Tree {
+       return c.tr
+}
+
+func (c *ChainNode) Copy() Node {
+       return &ChainNode{tr: c.tr, NodeType: NodeChain, Pos: c.Pos, Node: c.Node, Field: append([]string{}, c.Field...)}
+}
+
+// BoolNode holds a boolean constant.
+type BoolNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       True bool // The value of the boolean constant.
+}
+
+func (t *Tree) newBool(pos Pos, true bool) *BoolNode {
+       return &BoolNode{tr: t, NodeType: NodeBool, Pos: pos, True: true}
+}
+
+func (b *BoolNode) String() string {
+       if b.True {
+               return "true"
+       }
+       return "false"
+}
+
+func (b *BoolNode) tree() *Tree {
+       return b.tr
+}
+
+func (b *BoolNode) Copy() Node {
+       return b.tr.newBool(b.Pos, b.True)
+}
+
+// NumberNode holds a number: signed or unsigned integer, float, or complex.
+// The value is parsed and stored under all the types that can represent the value.
+// This simulates in a small amount of code the behavior of Go's ideal constants.
+type NumberNode struct {
+       NodeType
+       Pos
+       tr         *Tree
+       IsInt      bool       // Number has an integral value.
+       IsUint     bool       // Number has an unsigned integral value.
+       IsFloat    bool       // Number has a floating-point value.
+       IsComplex  bool       // Number is complex.
+       Int64      int64      // The signed integer value.
+       Uint64     uint64     // The unsigned integer value.
+       Float64    float64    // The floating-point value.
+       Complex128 complex128 // The complex value.
+       Text       string     // The original textual representation from the input.
+}
+
+func (t *Tree) newNumber(pos Pos, text string, typ itemType) (*NumberNode, error) {
+       n := &NumberNode{tr: t, NodeType: NodeNumber, Pos: pos, Text: text}
+       switch typ {
+       case itemCharConstant:
+               rune, _, tail, err := strconv.UnquoteChar(text[1:], text[0])
+               if err != nil {
+                       return nil, err
+               }
+               if tail != "'" {
+                       return nil, fmt.Errorf("malformed character constant: %s", text)
+               }
+               n.Int64 = int64(rune)
+               n.IsInt = true
+               n.Uint64 = uint64(rune)
+               n.IsUint = true
+               n.Float64 = float64(rune) // odd but those are the rules.
+               n.IsFloat = true
+               return n, nil
+       case itemComplex:
+               // fmt.Sscan can parse the pair, so let it do the work.
+               if _, err := fmt.Sscan(text, &n.Complex128); err != nil {
+                       return nil, err
+               }
+               n.IsComplex = true
+               n.simplifyComplex()
+               return n, nil
+       }
+       // Imaginary constants can only be complex unless they are zero.
+       if len(text) > 0 && text[len(text)-1] == 'i' {
+               f, err := strconv.ParseFloat(text[:len(text)-1], 64)
+               if err == nil {
+                       n.IsComplex = true
+                       n.Complex128 = complex(0, f)
+                       n.simplifyComplex()
+                       return n, nil
+               }
+       }
+       // Do integer test first so we get 0x123 etc.
+       u, err := strconv.ParseUint(text, 0, 64) // will fail for -0; fixed below.
+       if err == nil {
+               n.IsUint = true
+               n.Uint64 = u
+       }
+       i, err := strconv.ParseInt(text, 0, 64)
+       if err == nil {
+               n.IsInt = true
+               n.Int64 = i
+               if i == 0 {
+                       n.IsUint = true // in case of -0.
+                       n.Uint64 = u
+               }
+       }
+       // If an integer extraction succeeded, promote the float.
+       if n.IsInt {
+               n.IsFloat = true
+               n.Float64 = float64(n.Int64)
+       } else if n.IsUint {
+               n.IsFloat = true
+               n.Float64 = float64(n.Uint64)
+       } else {
+               f, err := strconv.ParseFloat(text, 64)
+               if err == nil {
+                       n.IsFloat = true
+                       n.Float64 = f
+                       // If a floating-point extraction succeeded, extract the int if needed.
+                       if !n.IsInt && float64(int64(f)) == f {
+                               n.IsInt = true
+                               n.Int64 = int64(f)
+                       }
+                       if !n.IsUint && float64(uint64(f)) == f {
+                               n.IsUint = true
+                               n.Uint64 = uint64(f)
+                       }
+               }
+       }
+       if !n.IsInt && !n.IsUint && !n.IsFloat {
+               return nil, fmt.Errorf("illegal number syntax: %q", text)
+       }
+       return n, nil
+}
+
+// simplifyComplex pulls out any other types that are represented by the complex number.
+// These all require that the imaginary part be zero.
+func (n *NumberNode) simplifyComplex() {
+       n.IsFloat = imag(n.Complex128) == 0
+       if n.IsFloat {
+               n.Float64 = real(n.Complex128)
+               n.IsInt = float64(int64(n.Float64)) == n.Float64
+               if n.IsInt {
+                       n.Int64 = int64(n.Float64)
+               }
+               n.IsUint = float64(uint64(n.Float64)) == n.Float64
+               if n.IsUint {
+                       n.Uint64 = uint64(n.Float64)
+               }
+       }
+}
+
+func (n *NumberNode) String() string {
+       return n.Text
+}
+
+func (n *NumberNode) tree() *Tree {
+       return n.tr
+}
+
+func (n *NumberNode) Copy() Node {
+       nn := new(NumberNode)
+       *nn = *n // Easy, fast, correct.
+       return nn
+}
+
+// StringNode holds a string constant. The value has been "unquoted".
+type StringNode struct {
+       NodeType
+       Pos
+       tr     *Tree
+       Quoted string // The original text of the string, with quotes.
+       Text   string // The string, after quote processing.
+}
+
+func (t *Tree) newString(pos Pos, orig, text string) *StringNode {
+       return &StringNode{tr: t, NodeType: NodeString, Pos: pos, Quoted: orig, Text: text}
+}
+
+func (s *StringNode) String() string {
+       return s.Quoted
+}
+
+func (s *StringNode) tree() *Tree {
+       return s.tr
+}
+
+func (s *StringNode) Copy() Node {
+       return s.tr.newString(s.Pos, s.Quoted, s.Text)
+}
+
+// endNode represents an {{end}} action.
+// It does not appear in the final parse tree.
+type endNode struct {
+       NodeType
+       Pos
+       tr *Tree
+}
+
+func (t *Tree) newEnd(pos Pos) *endNode {
+       return &endNode{tr: t, NodeType: nodeEnd, Pos: pos}
+}
+
+func (e *endNode) String() string {
+       return "{{end}}"
+}
+
+func (e *endNode) tree() *Tree {
+       return e.tr
+}
+
+func (e *endNode) Copy() Node {
+       return e.tr.newEnd(e.Pos)
+}
+
+// elseNode represents an {{else}} action. Does not appear in the final tree.
+type elseNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Line int // The line number in the input (deprecated; kept for compatibility)
+}
+
+func (t *Tree) newElse(pos Pos, line int) *elseNode {
+       return &elseNode{tr: t, NodeType: nodeElse, Pos: pos, Line: line}
+}
+
+func (e *elseNode) Type() NodeType {
+       return nodeElse
+}
+
+func (e *elseNode) String() string {
+       return "{{else}}"
+}
+
+func (e *elseNode) tree() *Tree {
+       return e.tr
+}
+
+func (e *elseNode) Copy() Node {
+       return e.tr.newElse(e.Pos, e.Line)
+}
+
+// BranchNode is the common representation of if, range, and with.
+type BranchNode struct {
+       NodeType
+       Pos
+       tr       *Tree
+       Line     int       // The line number in the input (deprecated; kept for compatibility)
+       Pipe     *PipeNode // The pipeline to be evaluated.
+       List     *ListNode // What to execute if the value is non-empty.
+       ElseList *ListNode // What to execute if the value is empty (nil if absent).
+}
+
+func (b *BranchNode) String() string {
+       name := ""
+       switch b.NodeType {
+       case NodeIf:
+               name = "if"
+       case NodeRange:
+               name = "range"
+       case NodeWith:
+               name = "with"
+       default:
+               panic("unknown branch type")
+       }
+       if b.ElseList != nil {
+               return fmt.Sprintf("{{%s %s}}%s{{else}}%s{{end}}", name, b.Pipe, b.List, b.ElseList)
+       }
+       return fmt.Sprintf("{{%s %s}}%s{{end}}", name, b.Pipe, b.List)
+}
+
+func (b *BranchNode) tree() *Tree {
+       return b.tr
+}
+
+func (b *BranchNode) Copy() Node {
+       switch b.NodeType {
+       case NodeIf:
+               return b.tr.newIf(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+       case NodeRange:
+               return b.tr.newRange(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+       case NodeWith:
+               return b.tr.newWith(b.Pos, b.Line, b.Pipe, b.List, b.ElseList)
+       default:
+               panic("unknown branch type")
+       }
+}
+
+// IfNode represents an {{if}} action and its commands.
+type IfNode struct {
+       BranchNode
+}
+
+func (t *Tree) newIf(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *IfNode {
+       return &IfNode{BranchNode{tr: t, NodeType: NodeIf, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (i *IfNode) Copy() Node {
+       return i.tr.newIf(i.Pos, i.Line, i.Pipe.CopyPipe(), i.List.CopyList(), i.ElseList.CopyList())
+}
+
+// RangeNode represents a {{range}} action and its commands.
+type RangeNode struct {
+       BranchNode
+}
+
+func (t *Tree) newRange(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *RangeNode {
+       return &RangeNode{BranchNode{tr: t, NodeType: NodeRange, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (r *RangeNode) Copy() Node {
+       return r.tr.newRange(r.Pos, r.Line, r.Pipe.CopyPipe(), r.List.CopyList(), r.ElseList.CopyList())
+}
+
+// WithNode represents a {{with}} action and its commands.
+type WithNode struct {
+       BranchNode
+}
+
+func (t *Tree) newWith(pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) *WithNode {
+       return &WithNode{BranchNode{tr: t, NodeType: NodeWith, Pos: pos, Line: line, Pipe: pipe, List: list, ElseList: elseList}}
+}
+
+func (w *WithNode) Copy() Node {
+       return w.tr.newWith(w.Pos, w.Line, w.Pipe.CopyPipe(), w.List.CopyList(), w.ElseList.CopyList())
+}
+
+// TemplateNode represents a {{template}} action.
+type TemplateNode struct {
+       NodeType
+       Pos
+       tr   *Tree
+       Line int       // The line number in the input (deprecated; kept for compatibility)
+       Name string    // The name of the template (unquoted).
+       Pipe *PipeNode // The command to evaluate as dot for the template.
+}
+
+func (t *Tree) newTemplate(pos Pos, line int, name string, pipe *PipeNode) *TemplateNode {
+       return &TemplateNode{tr: t, NodeType: NodeTemplate, Pos: pos, Line: line, Name: name, Pipe: pipe}
+}
+
+func (t *TemplateNode) String() string {
+       if t.Pipe == nil {
+               return fmt.Sprintf("{{template %q}}", t.Name)
+       }
+       return fmt.Sprintf("{{template %q %s}}", t.Name, t.Pipe)
+}
+
+func (t *TemplateNode) tree() *Tree {
+       return t.tr
+}
+
+func (t *TemplateNode) Copy() Node {
+       return t.tr.newTemplate(t.Pos, t.Line, t.Name, t.Pipe.CopyPipe())
+}
diff --git a/vendor/github.com/alecthomas/template/parse/parse.go b/vendor/github.com/alecthomas/template/parse/parse.go
new file mode 100644 (file)
index 0000000..0d77ade
--- /dev/null
@@ -0,0 +1,700 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package parse builds parse trees for templates as defined by text/template
+// and html/template. Clients should use those packages to construct templates
+// rather than this one, which provides shared internal data structures not
+// intended for general use.
+package parse
+
+import (
+       "bytes"
+       "fmt"
+       "runtime"
+       "strconv"
+       "strings"
+)
+
+// Tree is the representation of a single parsed template.
+type Tree struct {
+       Name      string    // name of the template represented by the tree.
+       ParseName string    // name of the top-level template during parsing, for error messages.
+       Root      *ListNode // top-level root of the tree.
+       text      string    // text parsed to create the template (or its parent)
+       // Parsing only; cleared after parse.
+       funcs     []map[string]interface{}
+       lex       *lexer
+       token     [3]item // three-token lookahead for parser.
+       peekCount int
+       vars      []string // variables defined at the moment.
+}
+
+// Copy returns a copy of the Tree. Any parsing state is discarded.
+func (t *Tree) Copy() *Tree {
+       if t == nil {
+               return nil
+       }
+       return &Tree{
+               Name:      t.Name,
+               ParseName: t.ParseName,
+               Root:      t.Root.CopyList(),
+               text:      t.text,
+       }
+}
+
+// Parse returns a map from template name to parse.Tree, created by parsing the
+// templates described in the argument string. The top-level template will be
+// given the specified name. If an error is encountered, parsing stops and an
+// empty map is returned with the error.
+func Parse(name, text, leftDelim, rightDelim string, funcs ...map[string]interface{}) (treeSet map[string]*Tree, err error) {
+       treeSet = make(map[string]*Tree)
+       t := New(name)
+       t.text = text
+       _, err = t.Parse(text, leftDelim, rightDelim, treeSet, funcs...)
+       return
+}
+
+// next returns the next token.
+func (t *Tree) next() item {
+       if t.peekCount > 0 {
+               t.peekCount--
+       } else {
+               t.token[0] = t.lex.nextItem()
+       }
+       return t.token[t.peekCount]
+}
+
+// backup backs the input stream up one token.
+func (t *Tree) backup() {
+       t.peekCount++
+}
+
+// backup2 backs the input stream up two tokens.
+// The zeroth token is already there.
+func (t *Tree) backup2(t1 item) {
+       t.token[1] = t1
+       t.peekCount = 2
+}
+
+// backup3 backs the input stream up three tokens
+// The zeroth token is already there.
+func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
+       t.token[1] = t1
+       t.token[2] = t2
+       t.peekCount = 3
+}
+
+// peek returns but does not consume the next token.
+func (t *Tree) peek() item {
+       if t.peekCount > 0 {
+               return t.token[t.peekCount-1]
+       }
+       t.peekCount = 1
+       t.token[0] = t.lex.nextItem()
+       return t.token[0]
+}
+
+// nextNonSpace returns the next non-space token.
+func (t *Tree) nextNonSpace() (token item) {
+       for {
+               token = t.next()
+               if token.typ != itemSpace {
+                       break
+               }
+       }
+       return token
+}
+
+// peekNonSpace returns but does not consume the next non-space token.
+func (t *Tree) peekNonSpace() (token item) {
+       for {
+               token = t.next()
+               if token.typ != itemSpace {
+                       break
+               }
+       }
+       t.backup()
+       return token
+}
+
+// Parsing.
+
+// New allocates a new parse tree with the given name.
+func New(name string, funcs ...map[string]interface{}) *Tree {
+       return &Tree{
+               Name:  name,
+               funcs: funcs,
+       }
+}
+
+// ErrorContext returns a textual representation of the location of the node in the input text.
+// The receiver is only used when the node does not have a pointer to the tree inside,
+// which can occur in old code.
+func (t *Tree) ErrorContext(n Node) (location, context string) {
+       pos := int(n.Position())
+       tree := n.tree()
+       if tree == nil {
+               tree = t
+       }
+       text := tree.text[:pos]
+       byteNum := strings.LastIndex(text, "\n")
+       if byteNum == -1 {
+               byteNum = pos // On first line.
+       } else {
+               byteNum++ // After the newline.
+               byteNum = pos - byteNum
+       }
+       lineNum := 1 + strings.Count(text, "\n")
+       context = n.String()
+       if len(context) > 20 {
+               context = fmt.Sprintf("%.20s...", context)
+       }
+       return fmt.Sprintf("%s:%d:%d", tree.ParseName, lineNum, byteNum), context
+}
+
+// errorf formats the error and terminates processing.
+func (t *Tree) errorf(format string, args ...interface{}) {
+       t.Root = nil
+       format = fmt.Sprintf("template: %s:%d: %s", t.ParseName, t.lex.lineNumber(), format)
+       panic(fmt.Errorf(format, args...))
+}
+
+// error terminates processing.
+func (t *Tree) error(err error) {
+       t.errorf("%s", err)
+}
+
+// expect consumes the next token and guarantees it has the required type.
+func (t *Tree) expect(expected itemType, context string) item {
+       token := t.nextNonSpace()
+       if token.typ != expected {
+               t.unexpected(token, context)
+       }
+       return token
+}
+
+// expectOneOf consumes the next token and guarantees it has one of the required types.
+func (t *Tree) expectOneOf(expected1, expected2 itemType, context string) item {
+       token := t.nextNonSpace()
+       if token.typ != expected1 && token.typ != expected2 {
+               t.unexpected(token, context)
+       }
+       return token
+}
+
+// unexpected complains about the token and terminates processing.
+func (t *Tree) unexpected(token item, context string) {
+       t.errorf("unexpected %s in %s", token, context)
+}
+
+// recover is the handler that turns panics into returns from the top level of Parse.
+func (t *Tree) recover(errp *error) {
+       e := recover()
+       if e != nil {
+               if _, ok := e.(runtime.Error); ok {
+                       panic(e)
+               }
+               if t != nil {
+                       t.stopParse()
+               }
+               *errp = e.(error)
+       }
+       return
+}
+
+// startParse initializes the parser, using the lexer.
+func (t *Tree) startParse(funcs []map[string]interface{}, lex *lexer) {
+       t.Root = nil
+       t.lex = lex
+       t.vars = []string{"$"}
+       t.funcs = funcs
+}
+
+// stopParse terminates parsing.
+func (t *Tree) stopParse() {
+       t.lex = nil
+       t.vars = nil
+       t.funcs = nil
+}
+
+// Parse parses the template definition string to construct a representation of
+// the template for execution. If either action delimiter string is empty, the
+// default ("{{" or "}}") is used. Embedded template definitions are added to
+// the treeSet map.
+func (t *Tree) Parse(text, leftDelim, rightDelim string, treeSet map[string]*Tree, funcs ...map[string]interface{}) (tree *Tree, err error) {
+       defer t.recover(&err)
+       t.ParseName = t.Name
+       t.startParse(funcs, lex(t.Name, text, leftDelim, rightDelim))
+       t.text = text
+       t.parse(treeSet)
+       t.add(treeSet)
+       t.stopParse()
+       return t, nil
+}
+
+// add adds tree to the treeSet.
+func (t *Tree) add(treeSet map[string]*Tree) {
+       tree := treeSet[t.Name]
+       if tree == nil || IsEmptyTree(tree.Root) {
+               treeSet[t.Name] = t
+               return
+       }
+       if !IsEmptyTree(t.Root) {
+               t.errorf("template: multiple definition of template %q", t.Name)
+       }
+}
+
+// IsEmptyTree reports whether this tree (node) is empty of everything but space.
+func IsEmptyTree(n Node) bool {
+       switch n := n.(type) {
+       case nil:
+               return true
+       case *ActionNode:
+       case *IfNode:
+       case *ListNode:
+               for _, node := range n.Nodes {
+                       if !IsEmptyTree(node) {
+                               return false
+                       }
+               }
+               return true
+       case *RangeNode:
+       case *TemplateNode:
+       case *TextNode:
+               return len(bytes.TrimSpace(n.Text)) == 0
+       case *WithNode:
+       default:
+               panic("unknown node: " + n.String())
+       }
+       return false
+}
+
+// parse is the top-level parser for a template, essentially the same
+// as itemList except it also parses {{define}} actions.
+// It runs to EOF.
+func (t *Tree) parse(treeSet map[string]*Tree) (next Node) {
+       t.Root = t.newList(t.peek().pos)
+       for t.peek().typ != itemEOF {
+               if t.peek().typ == itemLeftDelim {
+                       delim := t.next()
+                       if t.nextNonSpace().typ == itemDefine {
+                               newT := New("definition") // name will be updated once we know it.
+                               newT.text = t.text
+                               newT.ParseName = t.ParseName
+                               newT.startParse(t.funcs, t.lex)
+                               newT.parseDefinition(treeSet)
+                               continue
+                       }
+                       t.backup2(delim)
+               }
+               n := t.textOrAction()
+               if n.Type() == nodeEnd {
+                       t.errorf("unexpected %s", n)
+               }
+               t.Root.append(n)
+       }
+       return nil
+}
+
+// parseDefinition parses a {{define}} ...  {{end}} template definition and
+// installs the definition in the treeSet map.  The "define" keyword has already
+// been scanned.
+func (t *Tree) parseDefinition(treeSet map[string]*Tree) {
+       const context = "define clause"
+       name := t.expectOneOf(itemString, itemRawString, context)
+       var err error
+       t.Name, err = strconv.Unquote(name.val)
+       if err != nil {
+               t.error(err)
+       }
+       t.expect(itemRightDelim, context)
+       var end Node
+       t.Root, end = t.itemList()
+       if end.Type() != nodeEnd {
+               t.errorf("unexpected %s in %s", end, context)
+       }
+       t.add(treeSet)
+       t.stopParse()
+}
+
+// itemList:
+//     textOrAction*
+// Terminates at {{end}} or {{else}}, returned separately.
+func (t *Tree) itemList() (list *ListNode, next Node) {
+       list = t.newList(t.peekNonSpace().pos)
+       for t.peekNonSpace().typ != itemEOF {
+               n := t.textOrAction()
+               switch n.Type() {
+               case nodeEnd, nodeElse:
+                       return list, n
+               }
+               list.append(n)
+       }
+       t.errorf("unexpected EOF")
+       return
+}
+
+// textOrAction:
+//     text | action
+func (t *Tree) textOrAction() Node {
+       switch token := t.nextNonSpace(); token.typ {
+       case itemElideNewline:
+               return t.elideNewline()
+       case itemText:
+               return t.newText(token.pos, token.val)
+       case itemLeftDelim:
+               return t.action()
+       default:
+               t.unexpected(token, "input")
+       }
+       return nil
+}
+
+// elideNewline:
+// Remove newlines trailing rightDelim if \\ is present.
+func (t *Tree) elideNewline() Node {
+       token := t.peek()
+       if token.typ != itemText {
+               t.unexpected(token, "input")
+               return nil
+       }
+
+       t.next()
+       stripped := strings.TrimLeft(token.val, "\n\r")
+       diff := len(token.val) - len(stripped)
+       if diff > 0 {
+               // This is a bit nasty. We mutate the token in-place to remove
+               // preceding newlines.
+               token.pos += Pos(diff)
+               token.val = stripped
+       }
+       return t.newText(token.pos, token.val)
+}
+
+// Action:
+//     control
+//     command ("|" command)*
+// Left delim is past. Now get actions.
+// First word could be a keyword such as range.
+func (t *Tree) action() (n Node) {
+       switch token := t.nextNonSpace(); token.typ {
+       case itemElse:
+               return t.elseControl()
+       case itemEnd:
+               return t.endControl()
+       case itemIf:
+               return t.ifControl()
+       case itemRange:
+               return t.rangeControl()
+       case itemTemplate:
+               return t.templateControl()
+       case itemWith:
+               return t.withControl()
+       }
+       t.backup()
+       // Do not pop variables; they persist until "end".
+       return t.newAction(t.peek().pos, t.lex.lineNumber(), t.pipeline("command"))
+}
+
+// Pipeline:
+//     declarations? command ('|' command)*
+func (t *Tree) pipeline(context string) (pipe *PipeNode) {
+       var decl []*VariableNode
+       pos := t.peekNonSpace().pos
+       // Are there declarations?
+       for {
+               if v := t.peekNonSpace(); v.typ == itemVariable {
+                       t.next()
+                       // Since space is a token, we need 3-token look-ahead here in the worst case:
+                       // in "$x foo" we need to read "foo" (as opposed to ":=") to know that $x is an
+                       // argument variable rather than a declaration. So remember the token
+                       // adjacent to the variable so we can push it back if necessary.
+                       tokenAfterVariable := t.peek()
+                       if next := t.peekNonSpace(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
+                               t.nextNonSpace()
+                               variable := t.newVariable(v.pos, v.val)
+                               decl = append(decl, variable)
+                               t.vars = append(t.vars, v.val)
+                               if next.typ == itemChar && next.val == "," {
+                                       if context == "range" && len(decl) < 2 {
+                                               continue
+                                       }
+                                       t.errorf("too many declarations in %s", context)
+                               }
+                       } else if tokenAfterVariable.typ == itemSpace {
+                               t.backup3(v, tokenAfterVariable)
+                       } else {
+                               t.backup2(v)
+                       }
+               }
+               break
+       }
+       pipe = t.newPipeline(pos, t.lex.lineNumber(), decl)
+       for {
+               switch token := t.nextNonSpace(); token.typ {
+               case itemRightDelim, itemRightParen:
+                       if len(pipe.Cmds) == 0 {
+                               t.errorf("missing value for %s", context)
+                       }
+                       if token.typ == itemRightParen {
+                               t.backup()
+                       }
+                       return
+               case itemBool, itemCharConstant, itemComplex, itemDot, itemField, itemIdentifier,
+                       itemNumber, itemNil, itemRawString, itemString, itemVariable, itemLeftParen:
+                       t.backup()
+                       pipe.append(t.command())
+               default:
+                       t.unexpected(token, context)
+               }
+       }
+}
+
+func (t *Tree) parseControl(allowElseIf bool, context string) (pos Pos, line int, pipe *PipeNode, list, elseList *ListNode) {
+       defer t.popVars(len(t.vars))
+       line = t.lex.lineNumber()
+       pipe = t.pipeline(context)
+       var next Node
+       list, next = t.itemList()
+       switch next.Type() {
+       case nodeEnd: //done
+       case nodeElse:
+               if allowElseIf {
+                       // Special case for "else if". If the "else" is followed immediately by an "if",
+                       // the elseControl will have left the "if" token pending. Treat
+                       //      {{if a}}_{{else if b}}_{{end}}
+                       // as
+                       //      {{if a}}_{{else}}{{if b}}_{{end}}{{end}}.
+                       // To do this, parse the if as usual and stop at it {{end}}; the subsequent{{end}}
+                       // is assumed. This technique works even for long if-else-if chains.
+                       // TODO: Should we allow else-if in with and range?
+                       if t.peek().typ == itemIf {
+                               t.next() // Consume the "if" token.
+                               elseList = t.newList(next.Position())
+                               elseList.append(t.ifControl())
+                               // Do not consume the next item - only one {{end}} required.
+                               break
+                       }
+               }
+               elseList, next = t.itemList()
+               if next.Type() != nodeEnd {
+                       t.errorf("expected end; found %s", next)
+               }
+       }
+       return pipe.Position(), line, pipe, list, elseList
+}
+
+// If:
+//     {{if pipeline}} itemList {{end}}
+//     {{if pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) ifControl() Node {
+       return t.newIf(t.parseControl(true, "if"))
+}
+
+// Range:
+//     {{range pipeline}} itemList {{end}}
+//     {{range pipeline}} itemList {{else}} itemList {{end}}
+// Range keyword is past.
+func (t *Tree) rangeControl() Node {
+       return t.newRange(t.parseControl(false, "range"))
+}
+
+// With:
+//     {{with pipeline}} itemList {{end}}
+//     {{with pipeline}} itemList {{else}} itemList {{end}}
+// If keyword is past.
+func (t *Tree) withControl() Node {
+       return t.newWith(t.parseControl(false, "with"))
+}
+
+// End:
+//     {{end}}
+// End keyword is past.
+func (t *Tree) endControl() Node {
+       return t.newEnd(t.expect(itemRightDelim, "end").pos)
+}
+
+// Else:
+//     {{else}}
+// Else keyword is past.
+func (t *Tree) elseControl() Node {
+       // Special case for "else if".
+       peek := t.peekNonSpace()
+       if peek.typ == itemIf {
+               // We see "{{else if ... " but in effect rewrite it to {{else}}{{if ... ".
+               return t.newElse(peek.pos, t.lex.lineNumber())
+       }
+       return t.newElse(t.expect(itemRightDelim, "else").pos, t.lex.lineNumber())
+}
+
+// Template:
+//     {{template stringValue pipeline}}
+// Template keyword is past.  The name must be something that can evaluate
+// to a string.
+func (t *Tree) templateControl() Node {
+       var name string
+       token := t.nextNonSpace()
+       switch token.typ {
+       case itemString, itemRawString:
+               s, err := strconv.Unquote(token.val)
+               if err != nil {
+                       t.error(err)
+               }
+               name = s
+       default:
+               t.unexpected(token, "template invocation")
+       }
+       var pipe *PipeNode
+       if t.nextNonSpace().typ != itemRightDelim {
+               t.backup()
+               // Do not pop variables; they persist until "end".
+               pipe = t.pipeline("template")
+       }
+       return t.newTemplate(token.pos, t.lex.lineNumber(), name, pipe)
+}
+
+// command:
+//     operand (space operand)*
+// space-separated arguments up to a pipeline character or right delimiter.
+// we consume the pipe character but leave the right delim to terminate the action.
+func (t *Tree) command() *CommandNode {
+       cmd := t.newCommand(t.peekNonSpace().pos)
+       for {
+               t.peekNonSpace() // skip leading spaces.
+               operand := t.operand()
+               if operand != nil {
+                       cmd.append(operand)
+               }
+               switch token := t.next(); token.typ {
+               case itemSpace:
+                       continue
+               case itemError:
+                       t.errorf("%s", token.val)
+               case itemRightDelim, itemRightParen:
+                       t.backup()
+               case itemPipe:
+               default:
+                       t.errorf("unexpected %s in operand; missing space?", token)
+               }
+               break
+       }
+       if len(cmd.Args) == 0 {
+               t.errorf("empty command")
+       }
+       return cmd
+}
+
+// operand:
+//     term .Field*
+// An operand is a space-separated component of a command,
+// a term possibly followed by field accesses.
+// A nil return means the next item is not an operand.
+func (t *Tree) operand() Node {
+       node := t.term()
+       if node == nil {
+               return nil
+       }
+       if t.peek().typ == itemField {
+               chain := t.newChain(t.peek().pos, node)
+               for t.peek().typ == itemField {
+                       chain.Add(t.next().val)
+               }
+               // Compatibility with original API: If the term is of type NodeField
+               // or NodeVariable, just put more fields on the original.
+               // Otherwise, keep the Chain node.
+               // TODO: Switch to Chains always when we can.
+               switch node.Type() {
+               case NodeField:
+                       node = t.newField(chain.Position(), chain.String())
+               case NodeVariable:
+                       node = t.newVariable(chain.Position(), chain.String())
+               default:
+                       node = chain
+               }
+       }
+       return node
+}
+
+// term:
+//     literal (number, string, nil, boolean)
+//     function (identifier)
+//     .
+//     .Field
+//     $
+//     '(' pipeline ')'
+// A term is a simple "expression".
+// A nil return means the next item is not a term.
+func (t *Tree) term() Node {
+       switch token := t.nextNonSpace(); token.typ {
+       case itemError:
+               t.errorf("%s", token.val)
+       case itemIdentifier:
+               if !t.hasFunction(token.val) {
+                       t.errorf("function %q not defined", token.val)
+               }
+               return NewIdentifier(token.val).SetTree(t).SetPos(token.pos)
+       case itemDot:
+               return t.newDot(token.pos)
+       case itemNil:
+               return t.newNil(token.pos)
+       case itemVariable:
+               return t.useVar(token.pos, token.val)
+       case itemField:
+               return t.newField(token.pos, token.val)
+       case itemBool:
+               return t.newBool(token.pos, token.val == "true")
+       case itemCharConstant, itemComplex, itemNumber:
+               number, err := t.newNumber(token.pos, token.val, token.typ)
+               if err != nil {
+                       t.error(err)
+               }
+               return number
+       case itemLeftParen:
+               pipe := t.pipeline("parenthesized pipeline")
+               if token := t.next(); token.typ != itemRightParen {
+                       t.errorf("unclosed right paren: unexpected %s", token)
+               }
+               return pipe
+       case itemString, itemRawString:
+               s, err := strconv.Unquote(token.val)
+               if err != nil {
+                       t.error(err)
+               }
+               return t.newString(token.pos, token.val, s)
+       }
+       t.backup()
+       return nil
+}
+
+// hasFunction reports if a function name exists in the Tree's maps.
+func (t *Tree) hasFunction(name string) bool {
+       for _, funcMap := range t.funcs {
+               if funcMap == nil {
+                       continue
+               }
+               if funcMap[name] != nil {
+                       return true
+               }
+       }
+       return false
+}
+
+// popVars trims the variable list to the specified length
+func (t *Tree) popVars(n int) {
+       t.vars = t.vars[:n]
+}
+
+// useVar returns a node for a variable reference. It errors if the
+// variable is not defined.
+func (t *Tree) useVar(pos Pos, name string) Node {
+       v := t.newVariable(pos, name)
+       for _, varName := range t.vars {
+               if varName == v.Ident[0] {
+                       return v
+               }
+       }
+       t.errorf("undefined variable %q", v.Ident[0])
+       return nil
+}
diff --git a/vendor/github.com/alecthomas/template/template.go b/vendor/github.com/alecthomas/template/template.go
new file mode 100644 (file)
index 0000000..447ed2a
--- /dev/null
@@ -0,0 +1,218 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package template
+
+import (
+       "fmt"
+       "reflect"
+
+       "github.com/alecthomas/template/parse"
+)
+
+// common holds the information shared by related templates.
+type common struct {
+       tmpl map[string]*Template
+       // We use two maps, one for parsing and one for execution.
+       // This separation makes the API cleaner since it doesn't
+       // expose reflection to the client.
+       parseFuncs FuncMap
+       execFuncs  map[string]reflect.Value
+}
+
+// Template is the representation of a parsed template. The *parse.Tree
+// field is exported only for use by html/template and should be treated
+// as unexported by all other clients.
+type Template struct {
+       name string
+       *parse.Tree
+       *common
+       leftDelim  string
+       rightDelim string
+}
+
+// New allocates a new template with the given name.
+func New(name string) *Template {
+       return &Template{
+               name: name,
+       }
+}
+
+// Name returns the name of the template.
+func (t *Template) Name() string {
+       return t.name
+}
+
+// New allocates a new template associated with the given one and with the same
+// delimiters. The association, which is transitive, allows one template to
+// invoke another with a {{template}} action.
+func (t *Template) New(name string) *Template {
+       t.init()
+       return &Template{
+               name:       name,
+               common:     t.common,
+               leftDelim:  t.leftDelim,
+               rightDelim: t.rightDelim,
+       }
+}
+
+func (t *Template) init() {
+       if t.common == nil {
+               t.common = new(common)
+               t.tmpl = make(map[string]*Template)
+               t.parseFuncs = make(FuncMap)
+               t.execFuncs = make(map[string]reflect.Value)
+       }
+}
+
+// Clone returns a duplicate of the template, including all associated
+// templates. The actual representation is not copied, but the name space of
+// associated templates is, so further calls to Parse in the copy will add
+// templates to the copy but not to the original. Clone can be used to prepare
+// common templates and use them with variant definitions for other templates
+// by adding the variants after the clone is made.
+func (t *Template) Clone() (*Template, error) {
+       nt := t.copy(nil)
+       nt.init()
+       nt.tmpl[t.name] = nt
+       for k, v := range t.tmpl {
+               if k == t.name { // Already installed.
+                       continue
+               }
+               // The associated templates share nt's common structure.
+               tmpl := v.copy(nt.common)
+               nt.tmpl[k] = tmpl
+       }
+       for k, v := range t.parseFuncs {
+               nt.parseFuncs[k] = v
+       }
+       for k, v := range t.execFuncs {
+               nt.execFuncs[k] = v
+       }
+       return nt, nil
+}
+
+// copy returns a shallow copy of t, with common set to the argument.
+func (t *Template) copy(c *common) *Template {
+       nt := New(t.name)
+       nt.Tree = t.Tree
+       nt.common = c
+       nt.leftDelim = t.leftDelim
+       nt.rightDelim = t.rightDelim
+       return nt
+}
+
+// AddParseTree creates a new template with the name and parse tree
+// and associates it with t.
+func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
+       if t.common != nil && t.tmpl[name] != nil {
+               return nil, fmt.Errorf("template: redefinition of template %q", name)
+       }
+       nt := t.New(name)
+       nt.Tree = tree
+       t.tmpl[name] = nt
+       return nt, nil
+}
+
+// Templates returns a slice of the templates associated with t, including t
+// itself.
+func (t *Template) Templates() []*Template {
+       if t.common == nil {
+               return nil
+       }
+       // Return a slice so we don't expose the map.
+       m := make([]*Template, 0, len(t.tmpl))
+       for _, v := range t.tmpl {
+               m = append(m, v)
+       }
+       return m
+}
+
+// Delims sets the action delimiters to the specified strings, to be used in
+// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
+// definitions will inherit the settings. An empty delimiter stands for the
+// corresponding default: {{ or }}.
+// The return value is the template, so calls can be chained.
+func (t *Template) Delims(left, right string) *Template {
+       t.leftDelim = left
+       t.rightDelim = right
+       return t
+}
+
+// Funcs adds the elements of the argument map to the template's function map.
+// It panics if a value in the map is not a function with appropriate return
+// type. However, it is legal to overwrite elements of the map. The return
+// value is the template, so calls can be chained.
+func (t *Template) Funcs(funcMap FuncMap) *Template {
+       t.init()
+       addValueFuncs(t.execFuncs, funcMap)
+       addFuncs(t.parseFuncs, funcMap)
+       return t
+}
+
+// Lookup returns the template with the given name that is associated with t,
+// or nil if there is no such template.
+func (t *Template) Lookup(name string) *Template {
+       if t.common == nil {
+               return nil
+       }
+       return t.tmpl[name]
+}
+
+// Parse parses a string into a template. Nested template definitions will be
+// associated with the top-level template t. Parse may be called multiple times
+// to parse definitions of templates to associate with t. It is an error if a
+// resulting template is non-empty (contains content other than template
+// definitions) and would replace a non-empty template with the same name.
+// (In multiple calls to Parse with the same receiver template, only one call
+// can contain text other than space, comments, and template definitions.)
+func (t *Template) Parse(text string) (*Template, error) {
+       t.init()
+       trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)
+       if err != nil {
+               return nil, err
+       }
+       // Add the newly parsed trees, including the one for t, into our common structure.
+       for name, tree := range trees {
+               // If the name we parsed is the name of this template, overwrite this template.
+               // The associate method checks it's not a redefinition.
+               tmpl := t
+               if name != t.name {
+                       tmpl = t.New(name)
+               }
+               // Even if t == tmpl, we need to install it in the common.tmpl map.
+               if replace, err := t.associate(tmpl, tree); err != nil {
+                       return nil, err
+               } else if replace {
+                       tmpl.Tree = tree
+               }
+               tmpl.leftDelim = t.leftDelim
+               tmpl.rightDelim = t.rightDelim
+       }
+       return t, nil
+}
+
+// associate installs the new template into the group of templates associated
+// with t. It is an error to reuse a name except to overwrite an empty
+// template. The two are already known to share the common structure.
+// The boolean return value reports wither to store this tree as t.Tree.
+func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) {
+       if new.common != t.common {
+               panic("internal error: associate not common")
+       }
+       name := new.name
+       if old := t.tmpl[name]; old != nil {
+               oldIsEmpty := parse.IsEmptyTree(old.Root)
+               newIsEmpty := parse.IsEmptyTree(tree.Root)
+               if newIsEmpty {
+                       // Whether old is empty or not, new is empty; no reason to replace old.
+                       return false, nil
+               }
+               if !oldIsEmpty {
+                       return false, fmt.Errorf("template: redefinition of template %q", name)
+               }
+       }
+       t.tmpl[name] = new
+       return true, nil
+}
diff --git a/vendor/github.com/alecthomas/units/COPYING b/vendor/github.com/alecthomas/units/COPYING
new file mode 100644 (file)
index 0000000..2993ec0
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (C) 2014 Alec Thomas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/alecthomas/units/README.md b/vendor/github.com/alecthomas/units/README.md
new file mode 100644 (file)
index 0000000..bee884e
--- /dev/null
@@ -0,0 +1,11 @@
+# Units - Helpful unit multipliers and functions for Go
+
+The goal of this package is to have functionality similar to the [time](http://golang.org/pkg/time/) package.
+
+It allows for code like this:
+
+```go
+n, err := ParseBase2Bytes("1KB")
+// n == 1024
+n = units.Mebibyte * 512
+```
diff --git a/vendor/github.com/alecthomas/units/bytes.go b/vendor/github.com/alecthomas/units/bytes.go
new file mode 100644 (file)
index 0000000..eaadeb8
--- /dev/null
@@ -0,0 +1,83 @@
+package units
+
+// Base2Bytes is the old non-SI power-of-2 byte scale (1024 bytes in a kilobyte,
+// etc.).
+type Base2Bytes int64
+
+// Base-2 byte units.
+const (
+       Kibibyte Base2Bytes = 1024
+       KiB                 = Kibibyte
+       Mebibyte            = Kibibyte * 1024
+       MiB                 = Mebibyte
+       Gibibyte            = Mebibyte * 1024
+       GiB                 = Gibibyte
+       Tebibyte            = Gibibyte * 1024
+       TiB                 = Tebibyte
+       Pebibyte            = Tebibyte * 1024
+       PiB                 = Pebibyte
+       Exbibyte            = Pebibyte * 1024
+       EiB                 = Exbibyte
+)
+
+var (
+       bytesUnitMap    = MakeUnitMap("iB", "B", 1024)
+       oldBytesUnitMap = MakeUnitMap("B", "B", 1024)
+)
+
+// ParseBase2Bytes supports both iB and B in base-2 multipliers. That is, KB
+// and KiB are both 1024.
+func ParseBase2Bytes(s string) (Base2Bytes, error) {
+       n, err := ParseUnit(s, bytesUnitMap)
+       if err != nil {
+               n, err = ParseUnit(s, oldBytesUnitMap)
+       }
+       return Base2Bytes(n), err
+}
+
+func (b Base2Bytes) String() string {
+       return ToString(int64(b), 1024, "iB", "B")
+}
+
+var (
+       metricBytesUnitMap = MakeUnitMap("B", "B", 1000)
+)
+
+// MetricBytes are SI byte units (1000 bytes in a kilobyte).
+type MetricBytes SI
+
+// SI base-10 byte units.
+const (
+       Kilobyte MetricBytes = 1000
+       KB                   = Kilobyte
+       Megabyte             = Kilobyte * 1000
+       MB                   = Megabyte
+       Gigabyte             = Megabyte * 1000
+       GB                   = Gigabyte
+       Terabyte             = Gigabyte * 1000
+       TB                   = Terabyte
+       Petabyte             = Terabyte * 1000
+       PB                   = Petabyte
+       Exabyte              = Petabyte * 1000
+       EB                   = Exabyte
+)
+
+// ParseMetricBytes parses base-10 metric byte units. That is, KB is 1000 bytes.
+func ParseMetricBytes(s string) (MetricBytes, error) {
+       n, err := ParseUnit(s, metricBytesUnitMap)
+       return MetricBytes(n), err
+}
+
+func (m MetricBytes) String() string {
+       return ToString(int64(m), 1000, "B", "B")
+}
+
+// ParseStrictBytes supports both iB and B suffixes for base 2 and metric,
+// respectively. That is, KiB represents 1024 and KB represents 1000.
+func ParseStrictBytes(s string) (int64, error) {
+       n, err := ParseUnit(s, bytesUnitMap)
+       if err != nil {
+               n, err = ParseUnit(s, metricBytesUnitMap)
+       }
+       return int64(n), err
+}
diff --git a/vendor/github.com/alecthomas/units/doc.go b/vendor/github.com/alecthomas/units/doc.go
new file mode 100644 (file)
index 0000000..156ae38
--- /dev/null
@@ -0,0 +1,13 @@
+// Package units provides helpful unit multipliers and functions for Go.
+//
+// The goal of this package is to have functionality similar to the time [1] package.
+//
+//
+// [1] http://golang.org/pkg/time/
+//
+// It allows for code like this:
+//
+//     n, err := ParseBase2Bytes("1KB")
+//     // n == 1024
+//     n = units.Mebibyte * 512
+package units
diff --git a/vendor/github.com/alecthomas/units/si.go b/vendor/github.com/alecthomas/units/si.go
new file mode 100644 (file)
index 0000000..8234a9d
--- /dev/null
@@ -0,0 +1,26 @@
+package units
+
+// SI units.
+type SI int64
+
+// SI unit multiples.
+const (
+       Kilo SI = 1000
+       Mega    = Kilo * 1000
+       Giga    = Mega * 1000
+       Tera    = Giga * 1000
+       Peta    = Tera * 1000
+       Exa     = Peta * 1000
+)
+
+func MakeUnitMap(suffix, shortSuffix string, scale int64) map[string]float64 {
+       return map[string]float64{
+               shortSuffix:  1,
+               "K" + suffix: float64(scale),
+               "M" + suffix: float64(scale * scale),
+               "G" + suffix: float64(scale * scale * scale),
+               "T" + suffix: float64(scale * scale * scale * scale),
+               "P" + suffix: float64(scale * scale * scale * scale * scale),
+               "E" + suffix: float64(scale * scale * scale * scale * scale * scale),
+       }
+}
diff --git a/vendor/github.com/alecthomas/units/util.go b/vendor/github.com/alecthomas/units/util.go
new file mode 100644 (file)
index 0000000..6527e92
--- /dev/null
@@ -0,0 +1,138 @@
+package units
+
+import (
+       "errors"
+       "fmt"
+       "strings"
+)
+
+var (
+       siUnits = []string{"", "K", "M", "G", "T", "P", "E"}
+)
+
+func ToString(n int64, scale int64, suffix, baseSuffix string) string {
+       mn := len(siUnits)
+       out := make([]string, mn)
+       for i, m := range siUnits {
+               if n%scale != 0 || i == 0 && n == 0 {
+                       s := suffix
+                       if i == 0 {
+                               s = baseSuffix
+                       }
+                       out[mn-1-i] = fmt.Sprintf("%d%s%s", n%scale, m, s)
+               }
+               n /= scale
+               if n == 0 {
+                       break
+               }
+       }
+       return strings.Join(out, "")
+}
+
+// Below code ripped straight from http://golang.org/src/pkg/time/format.go?s=33392:33438#L1123
+var errLeadingInt = errors.New("units: bad [0-9]*") // never printed
+
+// leadingInt consumes the leading [0-9]* from s.
+func leadingInt(s string) (x int64, rem string, err error) {
+       i := 0
+       for ; i < len(s); i++ {
+               c := s[i]
+               if c < '0' || c > '9' {
+                       break
+               }
+               if x >= (1<<63-10)/10 {
+                       // overflow
+                       return 0, "", errLeadingInt
+               }
+               x = x*10 + int64(c) - '0'
+       }
+       return x, s[i:], nil
+}
+
+func ParseUnit(s string, unitMap map[string]float64) (int64, error) {
+       // [-+]?([0-9]*(\.[0-9]*)?[a-z]+)+
+       orig := s
+       f := float64(0)
+       neg := false
+
+       // Consume [-+]?
+       if s != "" {
+               c := s[0]
+               if c == '-' || c == '+' {
+                       neg = c == '-'
+                       s = s[1:]
+               }
+       }
+       // Special case: if all that is left is "0", this is zero.
+       if s == "0" {
+               return 0, nil
+       }
+       if s == "" {
+               return 0, errors.New("units: invalid " + orig)
+       }
+       for s != "" {
+               g := float64(0) // this element of the sequence
+
+               var x int64
+               var err error
+
+               // The next character must be [0-9.]
+               if !(s[0] == '.' || ('0' <= s[0] && s[0] <= '9')) {
+                       return 0, errors.New("units: invalid " + orig)
+               }
+               // Consume [0-9]*
+               pl := len(s)
+               x, s, err = leadingInt(s)
+               if err != nil {
+                       return 0, errors.New("units: invalid " + orig)
+               }
+               g = float64(x)
+               pre := pl != len(s) // whether we consumed anything before a period
+
+               // Consume (\.[0-9]*)?
+               post := false
+               if s != "" && s[0] == '.' {
+                       s = s[1:]
+                       pl := len(s)
+                       x, s, err = leadingInt(s)
+                       if err != nil {
+                               return 0, errors.New("units: invalid " + orig)
+                       }
+                       scale := 1.0
+                       for n := pl - len(s); n > 0; n-- {
+                               scale *= 10
+                       }
+                       g += float64(x) / scale
+                       post = pl != len(s)
+               }
+               if !pre && !post {
+                       // no digits (e.g. ".s" or "-.s")
+                       return 0, errors.New("units: invalid " + orig)
+               }
+
+               // Consume unit.
+               i := 0
+               for ; i < len(s); i++ {
+                       c := s[i]
+                       if c == '.' || ('0' <= c && c <= '9') {
+                               break
+                       }
+               }
+               u := s[:i]
+               s = s[i:]
+               unit, ok := unitMap[u]
+               if !ok {
+                       return 0, errors.New("units: unknown unit " + u + " in " + orig)
+               }
+
+               f += g * unit
+       }
+
+       if neg {
+               f = -f
+       }
+       if f < float64(-1<<63) || f > float64(1<<63-1) {
+               return 0, errors.New("units: overflow parsing unit")
+       }
+       return int64(f), nil
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/COPYING b/vendor/gopkg.in/alecthomas/kingpin.v2/COPYING
new file mode 100644 (file)
index 0000000..2993ec0
--- /dev/null
@@ -0,0 +1,19 @@
+Copyright (C) 2014 Alec Thomas
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/README.md b/vendor/gopkg.in/alecthomas/kingpin.v2/README.md
new file mode 100644 (file)
index 0000000..49542d3
--- /dev/null
@@ -0,0 +1,674 @@
+# Kingpin - A Go (golang) command line and flag parser
+[![](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)
+
+
+
+<!-- MarkdownTOC -->
+
+- [Overview](#overview)
+- [Features](#features)
+- [User-visible changes between v1 and v2](#user-visible-changes-between-v1-and-v2)
+  - [Flags can be used at any point after their definition.](#flags-can-be-used-at-any-point-after-their-definition)
+  - [Short flags can be combined with their parameters](#short-flags-can-be-combined-with-their-parameters)
+- [API changes between v1 and v2](#api-changes-between-v1-and-v2)
+- [Versions](#versions)
+  - [V2 is the current stable version](#v2-is-the-current-stable-version)
+  - [V1 is the OLD stable version](#v1-is-the-old-stable-version)
+- [Change History](#change-history)
+- [Examples](#examples)
+  - [Simple Example](#simple-example)
+  - [Complex Example](#complex-example)
+- [Reference Documentation](#reference-documentation)
+  - [Displaying errors and usage information](#displaying-errors-and-usage-information)
+  - [Sub-commands](#sub-commands)
+  - [Custom Parsers](#custom-parsers)
+  - [Repeatable flags](#repeatable-flags)
+  - [Boolean Values](#boolean-values)
+  - [Default Values](#default-values)
+  - [Place-holders in Help](#place-holders-in-help)
+  - [Consuming all remaining arguments](#consuming-all-remaining-arguments)
+  - [Bash/ZSH Shell Completion](#bashzsh-shell-completion)
+  - [Supporting -h for help](#supporting--h-for-help)
+  - [Custom help](#custom-help)
+
+<!-- /MarkdownTOC -->
+
+## Overview
+
+Kingpin is a [fluent-style](http://en.wikipedia.org/wiki/Fluent_interface),
+type-safe command-line parser. It supports flags, nested commands, and
+positional arguments.
+
+Install it with:
+
+    $ go get gopkg.in/alecthomas/kingpin.v2
+
+It looks like this:
+
+```go
+var (
+  verbose = kingpin.Flag("verbose", "Verbose mode.").Short('v').Bool()
+  name    = kingpin.Arg("name", "Name of user.").Required().String()
+)
+
+func main() {
+  kingpin.Parse()
+  fmt.Printf("%v, %s\n", *verbose, *name)
+}
+```
+
+More [examples](https://github.com/alecthomas/kingpin/tree/master/_examples) are available.
+
+Second to parsing, providing the user with useful help is probably the most
+important thing a command-line parser does. Kingpin tries to provide detailed
+contextual help if `--help` is encountered at any point in the command line
+(excluding after `--`).
+
+## Features
+
+- Help output that isn't as ugly as sin.
+- Fully [customisable help](#custom-help), via Go templates.
+- Parsed, type-safe flags (`kingpin.Flag("f", "help").Int()`)
+- Parsed, type-safe positional arguments (`kingpin.Arg("a", "help").Int()`).
+- Parsed, type-safe, arbitrarily deep commands (`kingpin.Command("c", "help")`).
+- Support for required flags and required positional arguments (`kingpin.Flag("f", "").Required().Int()`).
+- Support for arbitrarily nested default commands (`command.Default()`).
+- Callbacks per command, flag and argument (`kingpin.Command("c", "").Action(myAction)`).
+- POSIX-style short flag combining (`-a -b` -> `-ab`).
+- Short-flag+parameter combining (`-a parm` -> `-aparm`).
+- Read command-line from files (`@<file>`).
+- Automatically generate man pages (`--help-man`).
+
+## User-visible changes between v1 and v2
+
+### Flags can be used at any point after their definition.
+
+Flags can be specified at any point after their definition, not just
+*immediately after their associated command*. From the chat example below, the
+following used to be required:
+
+```
+$ chat --server=chat.server.com:8080 post --image=~/Downloads/owls.jpg pics
+```
+
+But the following will now work:
+
+```
+$ chat post --server=chat.server.com:8080 --image=~/Downloads/owls.jpg pics
+```
+
+### Short flags can be combined with their parameters
+
+Previously, if a short flag was used, any argument to that flag would have to
+be separated by a space. That is no longer the case.
+
+## API changes between v1 and v2
+
+- `ParseWithFileExpansion()` is gone. The new parser directly supports expanding `@<file>`.
+- Added `FatalUsage()` and `FatalUsageContext()` for displaying an error + usage and terminating.
+- `Dispatch()` renamed to `Action()`.
+- Added `ParseContext()` for parsing a command line into its intermediate context form without executing.
+- Added `Terminate()` function to override the termination function.
+- Added `UsageForContextWithTemplate()` for printing usage via a custom template.
+- Added `UsageTemplate()` for overriding the default template to use. Two templates are included:
+    1. `DefaultUsageTemplate` - default template.
+    2. `CompactUsageTemplate` - compact command template for larger applications.
+
+## Versions
+
+Kingpin uses [gopkg.in](https://gopkg.in/alecthomas/kingpin) for versioning.
+
+The 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.
+
+### [V2](https://gopkg.in/alecthomas/kingpin.v2) is the current stable version
+
+Installation:
+
+```sh
+$ go get gopkg.in/alecthomas/kingpin.v2
+```
+
+### [V1](https://gopkg.in/alecthomas/kingpin.v1) is the OLD stable version
+
+Installation:
+
+```sh
+$ go get gopkg.in/alecthomas/kingpin.v1
+```
+
+## Change History
+
+- *2015-09-19* -- Stable v2.1.0 release.
+    - Added `command.Default()` to specify a default command to use if no other
+      command matches. This allows for convenient user shortcuts.
+    - Exposed `HelpFlag` and `VersionFlag` for further customisation.
+    - `Action()` and `PreAction()` added and both now support an arbitrary
+      number of callbacks.
+    - `kingpin.SeparateOptionalFlagsUsageTemplate`.
+    - `--help-long` and `--help-man` (hidden by default) flags.
+    - Flags are "interspersed" by default, but can be disabled with `app.Interspersed(false)`.
+    - Added flags for all simple builtin types (int8, uint16, etc.) and slice variants.
+    - Use `app.Writer(os.Writer)` to specify the default writer for all output functions.
+    - Dropped `os.Writer` prefix from all printf-like functions.
+
+- *2015-05-22* -- Stable v2.0.0 release.
+    - Initial stable release of v2.0.0.
+    - Fully supports interspersed flags, commands and arguments.
+    - Flags can be present at any point after their logical definition.
+    - Application.Parse() terminates if commands are present and a command is not parsed.
+    - Dispatch() -> Action().
+    - Actions are dispatched after all values are populated.
+    - Override termination function (defaults to os.Exit).
+    - Override output stream (defaults to os.Stderr).
+    - Templatised usage help, with default and compact templates.
+    - Make error/usage functions more consistent.
+    - Support argument expansion from files by default (with @<file>).
+    - Fully public data model is available via .Model().
+    - Parser has been completely refactored.
+    - Parsing and execution has been split into distinct stages.
+    - Use `go generate` to generate repeated flags.
+    - Support combined short-flag+argument: -fARG.
+
+- *2015-01-23* -- Stable v1.3.4 release.
+    - Support "--" for separating flags from positional arguments.
+    - Support loading flags from files (ParseWithFileExpansion()). Use @FILE as an argument.
+    - Add post-app and post-cmd validation hooks. This allows arbitrary validation to be added.
+    - A bunch of improvements to help usage and formatting.
+    - Support arbitrarily nested sub-commands.
+
+- *2014-07-08* -- Stable v1.2.0 release.
+    - Pass any value through to `Strings()` when final argument.
+      Allows for values that look like flags to be processed.
+    - Allow `--help` to be used with commands.
+    - Support `Hidden()` flags.
+    - Parser for [units.Base2Bytes](https://github.com/alecthomas/units)
+      type. Allows for flags like `--ram=512MB` or `--ram=1GB`.
+    - Add an `Enum()` value, allowing only one of a set of values
+      to be selected. eg. `Flag(...).Enum("debug", "info", "warning")`.
+
+- *2014-06-27* -- Stable v1.1.0 release.
+    - Bug fixes.
+    - Always return an error (rather than panicing) when misconfigured.
+    - `OpenFile(flag, perm)` value type added, for finer control over opening files.
+    - Significantly improved usage formatting.
+
+- *2014-06-19* -- Stable v1.0.0 release.
+    - Support [cumulative positional](#consuming-all-remaining-arguments) arguments.
+    - Return error rather than panic when there are fatal errors not caught by
+      the type system. eg. when a default value is invalid.
+    - Use gokpg.in.
+
+- *2014-06-10* -- Place-holder streamlining.
+    - Renamed `MetaVar` to `PlaceHolder`.
+    - Removed `MetaVarFromDefault`. Kingpin now uses [heuristics](#place-holders-in-help)
+      to determine what to display.
+
+## Examples
+
+### Simple Example
+
+Kingpin can be used for simple flag+arg applications like so:
+
+```
+$ ping --help
+usage: ping [<flags>] <ip> [<count>]
+
+Flags:
+  --debug            Enable debug mode.
+  --help             Show help.
+  -t, --timeout=5s   Timeout waiting for ping.
+
+Args:
+  <ip>        IP address to ping.
+  [<count>]   Number of packets to send
+$ ping 1.2.3.4 5
+Would ping: 1.2.3.4 with timeout 5s and count 0
+```
+
+From the following source:
+
+```go
+package main
+
+import (
+  "fmt"
+
+  "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+  debug   = kingpin.Flag("debug", "Enable debug mode.").Bool()
+  timeout = kingpin.Flag("timeout", "Timeout waiting for ping.").Default("5s").OverrideDefaultFromEnvar("PING_TIMEOUT").Short('t').Duration()
+  ip      = kingpin.Arg("ip", "IP address to ping.").Required().IP()
+  count   = kingpin.Arg("count", "Number of packets to send").Int()
+)
+
+func main() {
+  kingpin.Version("0.0.1")
+  kingpin.Parse()
+  fmt.Printf("Would ping: %s with timeout %s and count %d\n", *ip, *timeout, *count)
+}
+```
+
+### Complex Example
+
+Kingpin can also produce complex command-line applications with global flags,
+subcommands, and per-subcommand flags, like this:
+
+```
+$ chat --help
+usage: chat [<flags>] <command> [<flags>] [<args> ...]
+
+A command-line chat application.
+
+Flags:
+  --help              Show help.
+  --debug             Enable debug mode.
+  --server=127.0.0.1  Server address.
+
+Commands:
+  help [<command>]
+    Show help for a command.
+
+  register <nick> <name>
+    Register a new user.
+
+  post [<flags>] <channel> [<text>]
+    Post a message to a channel.
+
+$ chat help post
+usage: chat [<flags>] post [<flags>] <channel> [<text>]
+
+Post a message to a channel.
+
+Flags:
+  --image=IMAGE  Image to post.
+
+Args:
+  <channel>  Channel to post to.
+  [<text>]   Text to post.
+
+$ chat post --image=~/Downloads/owls.jpg pics
+...
+```
+
+From this code:
+
+```go
+package main
+
+import (
+  "os"
+  "strings"
+  "gopkg.in/alecthomas/kingpin.v2"
+)
+
+var (
+  app      = kingpin.New("chat", "A command-line chat application.")
+  debug    = app.Flag("debug", "Enable debug mode.").Bool()
+  serverIP = app.Flag("server", "Server address.").Default("127.0.0.1").IP()
+
+  register     = app.Command("register", "Register a new user.")
+  registerNick = register.Arg("nick", "Nickname for user.").Required().String()
+  registerName = register.Arg("name", "Name of user.").Required().String()
+
+  post        = app.Command("post", "Post a message to a channel.")
+  postImage   = post.Flag("image", "Image to post.").File()
+  postChannel = post.Arg("channel", "Channel to post to.").Required().String()
+  postText    = post.Arg("text", "Text to post.").Strings()
+)
+
+func main() {
+  switch kingpin.MustParse(app.Parse(os.Args[1:])) {
+  // Register user
+  case register.FullCommand():
+    println(*registerNick)
+
+  // Post message
+  case post.FullCommand():
+    if *postImage != nil {
+    }
+    text := strings.Join(*postText, " ")
+    println("Post:", text)
+  }
+}
+```
+
+## Reference Documentation
+
+### Displaying errors and usage information
+
+Kingpin exports a set of functions to provide consistent errors and usage
+information to the user.
+
+Error messages look something like this:
+
+    <app>: error: <message>
+
+The functions on `Application` are:
+
+Function | Purpose
+---------|--------------
+`Errorf(format, args)` | Display a printf formatted error to the user.
+`Fatalf(format, args)` | As with Errorf, but also call the termination handler.
+`FatalUsage(format, args)` | As with Fatalf, but also print contextual usage information.
+`FatalUsageContext(context, format, args)` | As with Fatalf, but also print contextual usage information from a `ParseContext`.
+`FatalIfError(err, format, args)` | Conditionally print an error prefixed with format+args, then call the termination handler
+
+There are equivalent global functions in the kingpin namespace for the default
+`kingpin.CommandLine` instance.
+
+### Sub-commands
+
+Kingpin supports nested sub-commands, with separate flag and positional
+arguments per sub-command. Note that positional arguments may only occur after
+sub-commands.
+
+For example:
+
+```go
+var (
+  deleteCommand     = kingpin.Command("delete", "Delete an object.")
+  deleteUserCommand = deleteCommand.Command("user", "Delete a user.")
+  deleteUserUIDFlag = deleteUserCommand.Flag("uid", "Delete user by UID rather than username.")
+  deleteUserUsername = deleteUserCommand.Arg("username", "Username to delete.")
+  deletePostCommand = deleteCommand.Command("post", "Delete a post.")
+)
+
+func main() {
+  switch kingpin.Parse() {
+  case "delete user":
+  case "delete post":
+  }
+}
+```
+
+### Custom Parsers
+
+Kingpin supports both flag and positional argument parsers for converting to
+Go types. For example, some included parsers are `Int()`, `Float()`,
+`Duration()` and `ExistingFile()` (see [parsers.go](./parsers.go) for a complete list of included parsers).
+
+Parsers conform to Go's [`flag.Value`](http://godoc.org/flag#Value)
+interface, so any existing implementations will work.
+
+For example, a parser for accumulating HTTP header values might look like this:
+
+```go
+type HTTPHeaderValue http.Header
+
+func (h *HTTPHeaderValue) Set(value string) error {
+  parts := strings.SplitN(value, ":", 2)
+  if len(parts) != 2 {
+    return fmt.Errorf("expected HEADER:VALUE got '%s'", value)
+  }
+  (*http.Header)(h).Add(parts[0], parts[1])
+  return nil
+}
+
+func (h *HTTPHeaderValue) String() string {
+  return ""
+}
+```
+
+As a convenience, I would recommend something like this:
+
+```go
+func HTTPHeader(s Settings) (target *http.Header) {
+  target = &http.Header{}
+  s.SetValue((*HTTPHeaderValue)(target))
+  return
+}
+```
+
+You would use it like so:
+
+```go
+headers = HTTPHeader(kingpin.Flag("header", "Add a HTTP header to the request.").Short('H'))
+```
+
+### Repeatable flags
+
+Depending on the `Value` they hold, some flags may be repeated. The
+`IsCumulative() bool` function on `Value` tells if it's safe to call `Set()`
+multiple times or if an error should be raised if several values are passed.
+
+The built-in `Value`s returning slices and maps, as well as `Counter` are
+examples of `Value`s that make a flag repeatable.
+
+### Boolean values
+
+Boolean values are uniquely managed by Kingpin. Each boolean flag will have a negative complement:
+`--<name>` and `--no-<name>`.
+
+### Default Values
+
+The default value is the zero value for a type. This can be overridden with
+the `Default(value...)` function on flags and arguments. This function accepts
+one or several strings, which are parsed by the value itself, so they *must*
+be compliant with the format expected.
+
+### Place-holders in Help
+
+The place-holder value for a flag is the value used in the help to describe
+the value of a non-boolean flag.
+
+The value provided to PlaceHolder() is used if provided, then the value
+provided by Default() if provided, then finally the capitalised flag name is
+used.
+
+Here are some examples of flags with various permutations:
+
+    --name=NAME           // Flag(...).String()
+    --name="Harry"        // Flag(...).Default("Harry").String()
+    --name=FULL-NAME      // flag(...).PlaceHolder("FULL-NAME").Default("Harry").String()
+
+### Consuming all remaining arguments
+
+A common command-line idiom is to use all remaining arguments for some
+purpose. eg. The following command accepts an arbitrary number of
+IP addresses as positional arguments:
+
+    ./cmd ping 10.1.1.1 192.168.1.1
+
+Such arguments are similar to [repeatable flags](#repeatable-flags), but for
+arguments. Therefore they use the same `IsCumulative() bool` function on the
+underlying `Value`, so the built-in `Value`s for which the `Set()` function
+can be called several times will consume multiple arguments.
+
+To implement the above example with a custom `Value`, we might do something
+like this:
+
+```go
+type ipList []net.IP
+
+func (i *ipList) Set(value string) error {
+  if ip := net.ParseIP(value); ip == nil {
+    return fmt.Errorf("'%s' is not an IP address", value)
+  } else {
+    *i = append(*i, ip)
+    return nil
+  }
+}
+
+func (i *ipList) String() string {
+  return ""
+}
+
+func (i *ipList) IsCumulative() bool {
+  return true
+}
+
+func IPList(s Settings) (target *[]net.IP) {
+  target = new([]net.IP)
+  s.SetValue((*ipList)(target))
+  return
+}
+```
+
+And use it like so:
+
+```go
+ips := IPList(kingpin.Arg("ips", "IP addresses to ping."))
+```
+
+### Bash/ZSH Shell Completion
+
+By default, all flags and commands/subcommands generate completions 
+internally.
+
+Out of the box, CLI tools using kingpin should be able to take advantage 
+of completion hinting for flags and commands. By specifying 
+`--completion-bash` as the first argument, your CLI tool will show 
+possible subcommands. By ending your argv with `--`, hints for flags 
+will be shown.
+
+To allow your end users to take advantage you must package a 
+`/etc/bash_completion.d` script with your distribution (or the equivalent 
+for your target platform/shell). An alternative is to instruct your end 
+user to source a script from their `bash_profile` (or equivalent).
+
+Fortunately Kingpin makes it easy to generate or source a script for use
+with end users shells. `./yourtool --completion-script-bash` and 
+`./yourtool --completion-script-zsh` will generate these scripts for you.
+
+**Installation by Package**
+
+For the best user experience, you should bundle your pre-created 
+completion script with your CLI tool and install it inside 
+`/etc/bash_completion.d` (or equivalent). A good suggestion is to add 
+this as an automated step to your build pipeline, in the implementation 
+is improved for bug fixed.
+
+**Installation by `bash_profile`**
+
+Alternatively, instruct your users to add an additional statement to 
+their `bash_profile` (or equivalent):
+
+```
+eval "$(your-cli-tool --completion-script-bash)"
+```
+
+Or for ZSH
+
+```
+eval "$(your-cli-tool --completion-script-zsh)"
+```
+
+#### Additional API
+To provide more flexibility, a completion option API has been
+exposed for flags to allow user defined completion options, to extend
+completions further than just EnumVar/Enum. 
+
+
+**Provide Static Options**
+
+When using an `Enum` or `EnumVar`, users are limited to only the options 
+given. Maybe we wish to hint possible options to the user, but also 
+allow them to provide their own custom option. `HintOptions` gives
+this functionality to flags.
+
+```
+app := kingpin.New("completion", "My application with bash completion.")
+app.Flag("port", "Provide a port to connect to").
+    Required().
+    HintOptions("80", "443", "8080").
+    IntVar(&c.port)
+```
+
+**Provide Dynamic Options**
+Consider the case that you needed to read a local database or a file to 
+provide suggestions. You can dynamically generate the options
+
+```
+func listHosts(args []string) []string {
+  // Provide a dynamic list of hosts from a hosts file or otherwise
+  // for bash completion. In this example we simply return static slice.
+
+  // You could use this functionality to reach into a hosts file to provide
+  // completion for a list of known hosts.
+  return []string{"sshhost.example", "webhost.example", "ftphost.example"}
+}
+
+app := kingpin.New("completion", "My application with bash completion.")
+app.Flag("flag-1", "").HintAction(listHosts).String()
+```
+
+**EnumVar/Enum**
+When using `Enum` or `EnumVar`, any provided options will be automatically
+used for bash autocompletion. However, if you wish to provide a subset or 
+different options, you can use `HintOptions` or `HintAction` which will override
+the default completion options for `Enum`/`EnumVar`.
+
+
+**Examples**
+You can see an in depth example of the completion API within 
+`examples/completion/main.go`
+
+
+### Supporting -h for help
+
+`kingpin.CommandLine.HelpFlag.Short('h')`
+
+### Custom help
+
+Kingpin v2 supports templatised help using the text/template library (actually, [a fork](https://github.com/alecthomas/template)).
+
+You can specify the template to use with the [Application.UsageTemplate()](http://godoc.org/gopkg.in/alecthomas/kingpin.v2#Application.UsageTemplate) function.
+
+There are four included templates: `kingpin.DefaultUsageTemplate` is the default,
+`kingpin.CompactUsageTemplate` provides a more compact representation for more complex command-line structures,
+`kingpin.SeparateOptionalFlagsUsageTemplate` looks like the default template, but splits required
+and optional command flags into separate lists, and `kingpin.ManPageTemplate` is used to generate man pages.
+
+See 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.
+
+#### Default help template
+
+```
+$ go run ./examples/curl/curl.go --help
+usage: curl [<flags>] <command> [<args> ...]
+
+An example implementation of curl.
+
+Flags:
+  --help            Show help.
+  -t, --timeout=5s  Set connection timeout.
+  -H, --headers=HEADER=VALUE
+                    Add HTTP headers to the request.
+
+Commands:
+  help [<command>...]
+    Show help.
+
+  get url <url>
+    Retrieve a URL.
+
+  get file <file>
+    Retrieve a file.
+
+  post [<flags>] <url>
+    POST a resource.
+```
+
+#### Compact help template
+
+```
+$ go run ./examples/curl/curl.go --help
+usage: curl [<flags>] <command> [<args> ...]
+
+An example implementation of curl.
+
+Flags:
+  --help            Show help.
+  -t, --timeout=5s  Set connection timeout.
+  -H, --headers=HEADER=VALUE
+                    Add HTTP headers to the request.
+
+Commands:
+  help [<command>...]
+  get [<flags>]
+    url <url>
+    file <file>
+  post [<flags>] <url>
+```
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/actions.go b/vendor/gopkg.in/alecthomas/kingpin.v2/actions.go
new file mode 100644 (file)
index 0000000..72d6cbd
--- /dev/null
@@ -0,0 +1,42 @@
+package kingpin
+
+// Action callback executed at various stages after all values are populated.
+// The application, commands, arguments and flags all have corresponding
+// actions.
+type Action func(*ParseContext) error
+
+type actionMixin struct {
+       actions    []Action
+       preActions []Action
+}
+
+type actionApplier interface {
+       applyActions(*ParseContext) error
+       applyPreActions(*ParseContext) error
+}
+
+func (a *actionMixin) addAction(action Action) {
+       a.actions = append(a.actions, action)
+}
+
+func (a *actionMixin) addPreAction(action Action) {
+       a.preActions = append(a.preActions, action)
+}
+
+func (a *actionMixin) applyActions(context *ParseContext) error {
+       for _, action := range a.actions {
+               if err := action(context); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func (a *actionMixin) applyPreActions(context *ParseContext) error {
+       for _, preAction := range a.preActions {
+               if err := preAction(context); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/app.go b/vendor/gopkg.in/alecthomas/kingpin.v2/app.go
new file mode 100644 (file)
index 0000000..a5e8b80
--- /dev/null
@@ -0,0 +1,685 @@
+package kingpin
+
+import (
+       "fmt"
+       "io"
+       "os"
+       "regexp"
+       "strings"
+)
+
+var (
+       ErrCommandNotSpecified = fmt.Errorf("command not specified")
+)
+
+var (
+       envarTransformRegexp = regexp.MustCompile(`[^a-zA-Z0-9_]+`)
+)
+
+type ApplicationValidator func(*Application) error
+
+// An Application contains the definitions of flags, arguments and commands
+// for an application.
+type Application struct {
+       cmdMixin
+       initialized bool
+
+       Name string
+       Help string
+
+       author         string
+       version        string
+       errorWriter    io.Writer // Destination for errors.
+       usageWriter    io.Writer // Destination for usage
+       usageTemplate  string
+       validator      ApplicationValidator
+       terminate      func(status int) // See Terminate()
+       noInterspersed bool             // can flags be interspersed with args (or must they come first)
+       defaultEnvars  bool
+       completion     bool
+
+       // Help flag. Exposed for user customisation.
+       HelpFlag *FlagClause
+       // Help command. Exposed for user customisation. May be nil.
+       HelpCommand *CmdClause
+       // Version flag. Exposed for user customisation. May be nil.
+       VersionFlag *FlagClause
+}
+
+// New creates a new Kingpin application instance.
+func New(name, help string) *Application {
+       a := &Application{
+               Name:          name,
+               Help:          help,
+               errorWriter:   os.Stderr, // Left for backwards compatibility purposes.
+               usageWriter:   os.Stderr,
+               usageTemplate: DefaultUsageTemplate,
+               terminate:     os.Exit,
+       }
+       a.flagGroup = newFlagGroup()
+       a.argGroup = newArgGroup()
+       a.cmdGroup = newCmdGroup(a)
+       a.HelpFlag = a.Flag("help", "Show context-sensitive help (also try --help-long and --help-man).")
+       a.HelpFlag.Bool()
+       a.Flag("help-long", "Generate long help.").Hidden().PreAction(a.generateLongHelp).Bool()
+       a.Flag("help-man", "Generate a man page.").Hidden().PreAction(a.generateManPage).Bool()
+       a.Flag("completion-bash", "Output possible completions for the given args.").Hidden().BoolVar(&a.completion)
+       a.Flag("completion-script-bash", "Generate completion script for bash.").Hidden().PreAction(a.generateBashCompletionScript).Bool()
+       a.Flag("completion-script-zsh", "Generate completion script for ZSH.").Hidden().PreAction(a.generateZSHCompletionScript).Bool()
+
+       return a
+}
+
+func (a *Application) generateLongHelp(c *ParseContext) error {
+       a.Writer(os.Stdout)
+       if err := a.UsageForContextWithTemplate(c, 2, LongHelpTemplate); err != nil {
+               return err
+       }
+       a.terminate(0)
+       return nil
+}
+
+func (a *Application) generateManPage(c *ParseContext) error {
+       a.Writer(os.Stdout)
+       if err := a.UsageForContextWithTemplate(c, 2, ManPageTemplate); err != nil {
+               return err
+       }
+       a.terminate(0)
+       return nil
+}
+
+func (a *Application) generateBashCompletionScript(c *ParseContext) error {
+       a.Writer(os.Stdout)
+       if err := a.UsageForContextWithTemplate(c, 2, BashCompletionTemplate); err != nil {
+               return err
+       }
+       a.terminate(0)
+       return nil
+}
+
+func (a *Application) generateZSHCompletionScript(c *ParseContext) error {
+       a.Writer(os.Stdout)
+       if err := a.UsageForContextWithTemplate(c, 2, ZshCompletionTemplate); err != nil {
+               return err
+       }
+       a.terminate(0)
+       return nil
+}
+
+// DefaultEnvars configures all flags (that do not already have an associated
+// envar) to use a default environment variable in the form "<app>_<flag>".
+//
+// For example, if the application is named "foo" and a flag is named "bar-
+// waz" the environment variable: "FOO_BAR_WAZ".
+func (a *Application) DefaultEnvars() *Application {
+       a.defaultEnvars = true
+       return a
+}
+
+// Terminate specifies the termination handler. Defaults to os.Exit(status).
+// If nil is passed, a no-op function will be used.
+func (a *Application) Terminate(terminate func(int)) *Application {
+       if terminate == nil {
+               terminate = func(int) {}
+       }
+       a.terminate = terminate
+       return a
+}
+
+// Writer specifies the writer to use for usage and errors. Defaults to os.Stderr.
+// DEPRECATED: See ErrorWriter and UsageWriter.
+func (a *Application) Writer(w io.Writer) *Application {
+       a.errorWriter = w
+       a.usageWriter = w
+       return a
+}
+
+// ErrorWriter sets the io.Writer to use for errors.
+func (a *Application) ErrorWriter(w io.Writer) *Application {
+       a.errorWriter = w
+       return a
+}
+
+// UsageWriter sets the io.Writer to use for errors.
+func (a *Application) UsageWriter(w io.Writer) *Application {
+       a.usageWriter = w
+       return a
+}
+
+// UsageTemplate specifies the text template to use when displaying usage
+// information. The default is UsageTemplate.
+func (a *Application) UsageTemplate(template string) *Application {
+       a.usageTemplate = template
+       return a
+}
+
+// Validate sets a validation function to run when parsing.
+func (a *Application) Validate(validator ApplicationValidator) *Application {
+       a.validator = validator
+       return a
+}
+
+// ParseContext parses the given command line and returns the fully populated
+// ParseContext.
+func (a *Application) ParseContext(args []string) (*ParseContext, error) {
+       return a.parseContext(false, args)
+}
+
+func (a *Application) parseContext(ignoreDefault bool, args []string) (*ParseContext, error) {
+       if err := a.init(); err != nil {
+               return nil, err
+       }
+       context := tokenize(args, ignoreDefault)
+       err := parse(context, a)
+       return context, err
+}
+
+// Parse parses command-line arguments. It returns the selected command and an
+// error. The selected command will be a space separated subcommand, if
+// subcommands have been configured.
+//
+// This will populate all flag and argument values, call all callbacks, and so
+// on.
+func (a *Application) Parse(args []string) (command string, err error) {
+
+       context, parseErr := a.ParseContext(args)
+       selected := []string{}
+       var setValuesErr error
+
+       if context == nil {
+               // Since we do not throw error immediately, there could be a case
+               // where a context returns nil. Protect against that.
+               return "", parseErr
+       }
+
+       if err = a.setDefaults(context); err != nil {
+               return "", err
+       }
+
+       selected, setValuesErr = a.setValues(context)
+
+       if err = a.applyPreActions(context, !a.completion); err != nil {
+               return "", err
+       }
+
+       if a.completion {
+               a.generateBashCompletion(context)
+               a.terminate(0)
+       } else {
+               if parseErr != nil {
+                       return "", parseErr
+               }
+
+               a.maybeHelp(context)
+               if !context.EOL() {
+                       return "", fmt.Errorf("unexpected argument '%s'", context.Peek())
+               }
+
+               if setValuesErr != nil {
+                       return "", setValuesErr
+               }
+
+               command, err = a.execute(context, selected)
+               if err == ErrCommandNotSpecified {
+                       a.writeUsage(context, nil)
+               }
+       }
+       return command, err
+}
+
+func (a *Application) writeUsage(context *ParseContext, err error) {
+       if err != nil {
+               a.Errorf("%s", err)
+       }
+       if err := a.UsageForContext(context); err != nil {
+               panic(err)
+       }
+       if err != nil {
+               a.terminate(1)
+       } else {
+               a.terminate(0)
+       }
+}
+
+func (a *Application) maybeHelp(context *ParseContext) {
+       for _, element := range context.Elements {
+               if flag, ok := element.Clause.(*FlagClause); ok && flag == a.HelpFlag {
+                       // Re-parse the command-line ignoring defaults, so that help works correctly.
+                       context, _ = a.parseContext(true, context.rawArgs)
+                       a.writeUsage(context, nil)
+               }
+       }
+}
+
+// Version adds a --version flag for displaying the application version.
+func (a *Application) Version(version string) *Application {
+       a.version = version
+       a.VersionFlag = a.Flag("version", "Show application version.").PreAction(func(*ParseContext) error {
+               fmt.Fprintln(a.usageWriter, version)
+               a.terminate(0)
+               return nil
+       })
+       a.VersionFlag.Bool()
+       return a
+}
+
+// Author sets the author output by some help templates.
+func (a *Application) Author(author string) *Application {
+       a.author = author
+       return a
+}
+
+// Action callback to call when all values are populated and parsing is
+// complete, but before any command, flag or argument actions.
+//
+// All Action() callbacks are called in the order they are encountered on the
+// command line.
+func (a *Application) Action(action Action) *Application {
+       a.addAction(action)
+       return a
+}
+
+// Action called after parsing completes but before validation and execution.
+func (a *Application) PreAction(action Action) *Application {
+       a.addPreAction(action)
+       return a
+}
+
+// Command adds a new top-level command.
+func (a *Application) Command(name, help string) *CmdClause {
+       return a.addCommand(name, help)
+}
+
+// Interspersed control if flags can be interspersed with positional arguments
+//
+// true (the default) means that they can, false means that all the flags must appear before the first positional arguments.
+func (a *Application) Interspersed(interspersed bool) *Application {
+       a.noInterspersed = !interspersed
+       return a
+}
+
+func (a *Application) defaultEnvarPrefix() string {
+       if a.defaultEnvars {
+               return a.Name
+       }
+       return ""
+}
+
+func (a *Application) init() error {
+       if a.initialized {
+               return nil
+       }
+       if a.cmdGroup.have() && a.argGroup.have() {
+               return fmt.Errorf("can't mix top-level Arg()s with Command()s")
+       }
+
+       // If we have subcommands, add a help command at the top-level.
+       if a.cmdGroup.have() {
+               var command []string
+               a.HelpCommand = a.Command("help", "Show help.").PreAction(func(context *ParseContext) error {
+                       a.Usage(command)
+                       a.terminate(0)
+                       return nil
+               })
+               a.HelpCommand.Arg("command", "Show help on command.").StringsVar(&command)
+               // Make help first command.
+               l := len(a.commandOrder)
+               a.commandOrder = append(a.commandOrder[l-1:l], a.commandOrder[:l-1]...)
+       }
+
+       if err := a.flagGroup.init(a.defaultEnvarPrefix()); err != nil {
+               return err
+       }
+       if err := a.cmdGroup.init(); err != nil {
+               return err
+       }
+       if err := a.argGroup.init(); err != nil {
+               return err
+       }
+       for _, cmd := range a.commands {
+               if err := cmd.init(); err != nil {
+                       return err
+               }
+       }
+       flagGroups := []*flagGroup{a.flagGroup}
+       for _, cmd := range a.commandOrder {
+               if err := checkDuplicateFlags(cmd, flagGroups); err != nil {
+                       return err
+               }
+       }
+       a.initialized = true
+       return nil
+}
+
+// Recursively check commands for duplicate flags.
+func checkDuplicateFlags(current *CmdClause, flagGroups []*flagGroup) error {
+       // Check for duplicates.
+       for _, flags := range flagGroups {
+               for _, flag := range current.flagOrder {
+                       if flag.shorthand != 0 {
+                               if _, ok := flags.short[string(flag.shorthand)]; ok {
+                                       return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
+                               }
+                       }
+                       if _, ok := flags.long[flag.name]; ok {
+                               return fmt.Errorf("duplicate long flag --%s", flag.name)
+                       }
+               }
+       }
+       flagGroups = append(flagGroups, current.flagGroup)
+       // Check subcommands.
+       for _, subcmd := range current.commandOrder {
+               if err := checkDuplicateFlags(subcmd, flagGroups); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+func (a *Application) execute(context *ParseContext, selected []string) (string, error) {
+       var err error
+
+       if err = a.validateRequired(context); err != nil {
+               return "", err
+       }
+
+       if err = a.applyValidators(context); err != nil {
+               return "", err
+       }
+
+       if err = a.applyActions(context); err != nil {
+               return "", err
+       }
+
+       command := strings.Join(selected, " ")
+       if command == "" && a.cmdGroup.have() {
+               return "", ErrCommandNotSpecified
+       }
+       return command, err
+}
+
+func (a *Application) setDefaults(context *ParseContext) error {
+       flagElements := map[string]*ParseElement{}
+       for _, element := range context.Elements {
+               if flag, ok := element.Clause.(*FlagClause); ok {
+                       flagElements[flag.name] = element
+               }
+       }
+
+       argElements := map[string]*ParseElement{}
+       for _, element := range context.Elements {
+               if arg, ok := element.Clause.(*ArgClause); ok {
+                       argElements[arg.name] = element
+               }
+       }
+
+       // Check required flags and set defaults.
+       for _, flag := range context.flags.long {
+               if flagElements[flag.name] == nil {
+                       if err := flag.setDefault(); err != nil {
+                               return err
+                       }
+               }
+       }
+
+       for _, arg := range context.arguments.args {
+               if argElements[arg.name] == nil {
+                       if err := arg.setDefault(); err != nil {
+                               return err
+                       }
+               }
+       }
+
+       return nil
+}
+
+func (a *Application) validateRequired(context *ParseContext) error {
+       flagElements := map[string]*ParseElement{}
+       for _, element := range context.Elements {
+               if flag, ok := element.Clause.(*FlagClause); ok {
+                       flagElements[flag.name] = element
+               }
+       }
+
+       argElements := map[string]*ParseElement{}
+       for _, element := range context.Elements {
+               if arg, ok := element.Clause.(*ArgClause); ok {
+                       argElements[arg.name] = element
+               }
+       }
+
+       // Check required flags and set defaults.
+       for _, flag := range context.flags.long {
+               if flagElements[flag.name] == nil {
+                       // Check required flags were provided.
+                       if flag.needsValue() {
+                               return fmt.Errorf("required flag --%s not provided", flag.name)
+                       }
+               }
+       }
+
+       for _, arg := range context.arguments.args {
+               if argElements[arg.name] == nil {
+                       if arg.needsValue() {
+                               return fmt.Errorf("required argument '%s' not provided", arg.name)
+                       }
+               }
+       }
+       return nil
+}
+
+func (a *Application) setValues(context *ParseContext) (selected []string, err error) {
+       // Set all arg and flag values.
+       var (
+               lastCmd *CmdClause
+               flagSet = map[string]struct{}{}
+       )
+       for _, element := range context.Elements {
+               switch clause := element.Clause.(type) {
+               case *FlagClause:
+                       if _, ok := flagSet[clause.name]; ok {
+                               if v, ok := clause.value.(repeatableFlag); !ok || !v.IsCumulative() {
+                                       return nil, fmt.Errorf("flag '%s' cannot be repeated", clause.name)
+                               }
+                       }
+                       if err = clause.value.Set(*element.Value); err != nil {
+                               return
+                       }
+                       flagSet[clause.name] = struct{}{}
+
+               case *ArgClause:
+                       if err = clause.value.Set(*element.Value); err != nil {
+                               return
+                       }
+
+               case *CmdClause:
+                       if clause.validator != nil {
+                               if err = clause.validator(clause); err != nil {
+                                       return
+                               }
+                       }
+                       selected = append(selected, clause.name)
+                       lastCmd = clause
+               }
+       }
+
+       if lastCmd != nil && len(lastCmd.commands) > 0 {
+               return nil, fmt.Errorf("must select a subcommand of '%s'", lastCmd.FullCommand())
+       }
+
+       return
+}
+
+func (a *Application) applyValidators(context *ParseContext) (err error) {
+       // Call command validation functions.
+       for _, element := range context.Elements {
+               if cmd, ok := element.Clause.(*CmdClause); ok && cmd.validator != nil {
+                       if err = cmd.validator(cmd); err != nil {
+                               return err
+                       }
+               }
+       }
+
+       if a.validator != nil {
+               err = a.validator(a)
+       }
+       return err
+}
+
+func (a *Application) applyPreActions(context *ParseContext, dispatch bool) error {
+       if err := a.actionMixin.applyPreActions(context); err != nil {
+               return err
+       }
+       // Dispatch to actions.
+       if dispatch {
+               for _, element := range context.Elements {
+                       if applier, ok := element.Clause.(actionApplier); ok {
+                               if err := applier.applyPreActions(context); err != nil {
+                                       return err
+                               }
+                       }
+               }
+       }
+
+       return nil
+}
+
+func (a *Application) applyActions(context *ParseContext) error {
+       if err := a.actionMixin.applyActions(context); err != nil {
+               return err
+       }
+       // Dispatch to actions.
+       for _, element := range context.Elements {
+               if applier, ok := element.Clause.(actionApplier); ok {
+                       if err := applier.applyActions(context); err != nil {
+                               return err
+                       }
+               }
+       }
+       return nil
+}
+
+// Errorf prints an error message to w in the format "<appname>: error: <message>".
+func (a *Application) Errorf(format string, args ...interface{}) {
+       fmt.Fprintf(a.errorWriter, a.Name+": error: "+format+"\n", args...)
+}
+
+// Fatalf writes a formatted error to w then terminates with exit status 1.
+func (a *Application) Fatalf(format string, args ...interface{}) {
+       a.Errorf(format, args...)
+       a.terminate(1)
+}
+
+// FatalUsage prints an error message followed by usage information, then
+// exits with a non-zero status.
+func (a *Application) FatalUsage(format string, args ...interface{}) {
+       a.Errorf(format, args...)
+       // Force usage to go to error output.
+       a.usageWriter = a.errorWriter
+       a.Usage([]string{})
+       a.terminate(1)
+}
+
+// FatalUsageContext writes a printf formatted error message to w, then usage
+// information for the given ParseContext, before exiting.
+func (a *Application) FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
+       a.Errorf(format, args...)
+       if err := a.UsageForContext(context); err != nil {
+               panic(err)
+       }
+       a.terminate(1)
+}
+
+// FatalIfError prints an error and exits if err is not nil. The error is printed
+// with the given formatted string, if any.
+func (a *Application) FatalIfError(err error, format string, args ...interface{}) {
+       if err != nil {
+               prefix := ""
+               if format != "" {
+                       prefix = fmt.Sprintf(format, args...) + ": "
+               }
+               a.Errorf(prefix+"%s", err)
+               a.terminate(1)
+       }
+}
+
+func (a *Application) completionOptions(context *ParseContext) []string {
+       args := context.rawArgs
+
+       var (
+               currArg string
+               prevArg string
+               target  cmdMixin
+       )
+
+       numArgs := len(args)
+       if numArgs > 1 {
+               args = args[1:]
+               currArg = args[len(args)-1]
+       }
+       if numArgs > 2 {
+               prevArg = args[len(args)-2]
+       }
+
+       target = a.cmdMixin
+       if context.SelectedCommand != nil {
+               // A subcommand was in use. We will use it as the target
+               target = context.SelectedCommand.cmdMixin
+       }
+
+       if (currArg != "" && strings.HasPrefix(currArg, "--")) || strings.HasPrefix(prevArg, "--") {
+               // Perform completion for A flag. The last/current argument started with "-"
+               var (
+                       flagName  string // The name of a flag if given (could be half complete)
+                       flagValue string // The value assigned to a flag (if given) (could be half complete)
+               )
+
+               if strings.HasPrefix(prevArg, "--") && !strings.HasPrefix(currArg, "--") {
+                       // Matches:     ./myApp --flag value
+                       // Wont Match:  ./myApp --flag --
+                       flagName = prevArg[2:] // Strip the "--"
+                       flagValue = currArg
+               } else if strings.HasPrefix(currArg, "--") {
+                       // Matches:     ./myApp --flag --
+                       // Matches:             ./myApp --flag somevalue --
+                       // Matches:     ./myApp --
+                       flagName = currArg[2:] // Strip the "--"
+               }
+
+               options, flagMatched, valueMatched := target.FlagCompletion(flagName, flagValue)
+               if valueMatched {
+                       // Value Matched. Show cmdCompletions
+                       return target.CmdCompletion(context)
+               }
+
+               // Add top level flags if we're not at the top level and no match was found.
+               if context.SelectedCommand != nil && !flagMatched {
+                       topOptions, topFlagMatched, topValueMatched := a.FlagCompletion(flagName, flagValue)
+                       if topValueMatched {
+                               // Value Matched. Back to cmdCompletions
+                               return target.CmdCompletion(context)
+                       }
+
+                       if topFlagMatched {
+                               // Top level had a flag which matched the input. Return it's options.
+                               options = topOptions
+                       } else {
+                               // Add top level flags
+                               options = append(options, topOptions...)
+                       }
+               }
+               return options
+       }
+
+       // Perform completion for sub commands and arguments.
+       return target.CmdCompletion(context)
+}
+
+func (a *Application) generateBashCompletion(context *ParseContext) {
+       options := a.completionOptions(context)
+       fmt.Printf("%s", strings.Join(options, "\n"))
+}
+
+func envarTransform(name string) string {
+       return strings.ToUpper(envarTransformRegexp.ReplaceAllString(name, "_"))
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/args.go b/vendor/gopkg.in/alecthomas/kingpin.v2/args.go
new file mode 100644 (file)
index 0000000..3400694
--- /dev/null
@@ -0,0 +1,184 @@
+package kingpin
+
+import (
+       "fmt"
+)
+
+type argGroup struct {
+       args []*ArgClause
+}
+
+func newArgGroup() *argGroup {
+       return &argGroup{}
+}
+
+func (a *argGroup) have() bool {
+       return len(a.args) > 0
+}
+
+// GetArg gets an argument definition.
+//
+// This allows existing arguments to be modified after definition but before parsing. Useful for
+// modular applications.
+func (a *argGroup) GetArg(name string) *ArgClause {
+       for _, arg := range a.args {
+               if arg.name == name {
+                       return arg
+               }
+       }
+       return nil
+}
+
+func (a *argGroup) Arg(name, help string) *ArgClause {
+       arg := newArg(name, help)
+       a.args = append(a.args, arg)
+       return arg
+}
+
+func (a *argGroup) init() error {
+       required := 0
+       seen := map[string]struct{}{}
+       previousArgMustBeLast := false
+       for i, arg := range a.args {
+               if previousArgMustBeLast {
+                       return fmt.Errorf("Args() can't be followed by another argument '%s'", arg.name)
+               }
+               if arg.consumesRemainder() {
+                       previousArgMustBeLast = true
+               }
+               if _, ok := seen[arg.name]; ok {
+                       return fmt.Errorf("duplicate argument '%s'", arg.name)
+               }
+               seen[arg.name] = struct{}{}
+               if arg.required && required != i {
+                       return fmt.Errorf("required arguments found after non-required")
+               }
+               if arg.required {
+                       required++
+               }
+               if err := arg.init(); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+type ArgClause struct {
+       actionMixin
+       parserMixin
+       completionsMixin
+       envarMixin
+       name          string
+       help          string
+       defaultValues []string
+       required      bool
+}
+
+func newArg(name, help string) *ArgClause {
+       a := &ArgClause{
+               name: name,
+               help: help,
+       }
+       return a
+}
+
+func (a *ArgClause) setDefault() error {
+       if a.HasEnvarValue() {
+               if v, ok := a.value.(remainderArg); !ok || !v.IsCumulative() {
+                       // Use the value as-is
+                       return a.value.Set(a.GetEnvarValue())
+               }
+               for _, value := range a.GetSplitEnvarValue() {
+                       if err := a.value.Set(value); err != nil {
+                               return err
+                       }
+               }
+               return nil
+       }
+
+       if len(a.defaultValues) > 0 {
+               for _, defaultValue := range a.defaultValues {
+                       if err := a.value.Set(defaultValue); err != nil {
+                               return err
+                       }
+               }
+               return nil
+       }
+
+       return nil
+}
+
+func (a *ArgClause) needsValue() bool {
+       haveDefault := len(a.defaultValues) > 0
+       return a.required && !(haveDefault || a.HasEnvarValue())
+}
+
+func (a *ArgClause) consumesRemainder() bool {
+       if r, ok := a.value.(remainderArg); ok {
+               return r.IsCumulative()
+       }
+       return false
+}
+
+// Required arguments must be input by the user. They can not have a Default() value provided.
+func (a *ArgClause) Required() *ArgClause {
+       a.required = true
+       return a
+}
+
+// Default values for this argument. They *must* be parseable by the value of the argument.
+func (a *ArgClause) Default(values ...string) *ArgClause {
+       a.defaultValues = values
+       return a
+}
+
+// Envar overrides the default value(s) for a flag from an environment variable,
+// if it is set. Several default values can be provided by using new lines to
+// separate them.
+func (a *ArgClause) Envar(name string) *ArgClause {
+       a.envar = name
+       a.noEnvar = false
+       return a
+}
+
+// NoEnvar forces environment variable defaults to be disabled for this flag.
+// Most useful in conjunction with app.DefaultEnvars().
+func (a *ArgClause) NoEnvar() *ArgClause {
+       a.envar = ""
+       a.noEnvar = true
+       return a
+}
+
+func (a *ArgClause) Action(action Action) *ArgClause {
+       a.addAction(action)
+       return a
+}
+
+func (a *ArgClause) PreAction(action Action) *ArgClause {
+       a.addPreAction(action)
+       return a
+}
+
+// HintAction registers a HintAction (function) for the arg to provide completions
+func (a *ArgClause) HintAction(action HintAction) *ArgClause {
+       a.addHintAction(action)
+       return a
+}
+
+// HintOptions registers any number of options for the flag to provide completions
+func (a *ArgClause) HintOptions(options ...string) *ArgClause {
+       a.addHintAction(func() []string {
+               return options
+       })
+       return a
+}
+
+func (a *ArgClause) init() error {
+       if a.required && len(a.defaultValues) > 0 {
+               return fmt.Errorf("required argument '%s' with unusable default value", a.name)
+       }
+       if a.value == nil {
+               return fmt.Errorf("no parser defined for arg '%s'", a.name)
+       }
+       return nil
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go b/vendor/gopkg.in/alecthomas/kingpin.v2/cmd.go
new file mode 100644 (file)
index 0000000..0473b87
--- /dev/null
@@ -0,0 +1,274 @@
+package kingpin
+
+import (
+       "fmt"
+       "strings"
+)
+
+type cmdMixin struct {
+       *flagGroup
+       *argGroup
+       *cmdGroup
+       actionMixin
+}
+
+// CmdCompletion returns completion options for arguments, if that's where
+// parsing left off, or commands if there aren't any unsatisfied args.
+func (c *cmdMixin) CmdCompletion(context *ParseContext) []string {
+       var options []string
+
+       // Count args already satisfied - we won't complete those, and add any
+       // default commands' alternatives, since they weren't listed explicitly
+       // and the user may want to explicitly list something else.
+       argsSatisfied := 0
+       for _, el := range context.Elements {
+               switch clause := el.Clause.(type) {
+               case *ArgClause:
+                       if el.Value != nil && *el.Value != "" {
+                               argsSatisfied++
+                       }
+               case *CmdClause:
+                       options = append(options, clause.completionAlts...)
+               default:
+               }
+       }
+
+       if argsSatisfied < len(c.argGroup.args) {
+               // Since not all args have been satisfied, show options for the current one
+               options = append(options, c.argGroup.args[argsSatisfied].resolveCompletions()...)
+       } else {
+               // If all args are satisfied, then go back to completing commands
+               for _, cmd := range c.cmdGroup.commandOrder {
+                       if !cmd.hidden {
+                               options = append(options, cmd.name)
+                       }
+               }
+       }
+
+       return options
+}
+
+func (c *cmdMixin) FlagCompletion(flagName string, flagValue string) (choices []string, flagMatch bool, optionMatch bool) {
+       // Check if flagName matches a known flag.
+       // If it does, show the options for the flag
+       // Otherwise, show all flags
+
+       options := []string{}
+
+       for _, flag := range c.flagGroup.flagOrder {
+               // Loop through each flag and determine if a match exists
+               if flag.name == flagName {
+                       // User typed entire flag. Need to look for flag options.
+                       options = flag.resolveCompletions()
+                       if len(options) == 0 {
+                               // No Options to Choose From, Assume Match.
+                               return options, true, true
+                       }
+
+                       // Loop options to find if the user specified value matches
+                       isPrefix := false
+                       matched := false
+
+                       for _, opt := range options {
+                               if flagValue == opt {
+                                       matched = true
+                               } else if strings.HasPrefix(opt, flagValue) {
+                                       isPrefix = true
+                               }
+                       }
+
+                       // Matched Flag Directly
+                       // Flag Value Not Prefixed, and Matched Directly
+                       return options, true, !isPrefix && matched
+               }
+
+               if !flag.hidden {
+                       options = append(options, "--"+flag.name)
+               }
+       }
+       // No Flag directly matched.
+       return options, false, false
+
+}
+
+type cmdGroup struct {
+       app          *Application
+       parent       *CmdClause
+       commands     map[string]*CmdClause
+       commandOrder []*CmdClause
+}
+
+func (c *cmdGroup) defaultSubcommand() *CmdClause {
+       for _, cmd := range c.commandOrder {
+               if cmd.isDefault {
+                       return cmd
+               }
+       }
+       return nil
+}
+
+func (c *cmdGroup) cmdNames() []string {
+       names := make([]string, 0, len(c.commandOrder))
+       for _, cmd := range c.commandOrder {
+               names = append(names, cmd.name)
+       }
+       return names
+}
+
+// GetArg gets a command definition.
+//
+// This allows existing commands to be modified after definition but before parsing. Useful for
+// modular applications.
+func (c *cmdGroup) GetCommand(name string) *CmdClause {
+       return c.commands[name]
+}
+
+func newCmdGroup(app *Application) *cmdGroup {
+       return &cmdGroup{
+               app:      app,
+               commands: make(map[string]*CmdClause),
+       }
+}
+
+func (c *cmdGroup) flattenedCommands() (out []*CmdClause) {
+       for _, cmd := range c.commandOrder {
+               if len(cmd.commands) == 0 {
+                       out = append(out, cmd)
+               }
+               out = append(out, cmd.flattenedCommands()...)
+       }
+       return
+}
+
+func (c *cmdGroup) addCommand(name, help string) *CmdClause {
+       cmd := newCommand(c.app, name, help)
+       c.commands[name] = cmd
+       c.commandOrder = append(c.commandOrder, cmd)
+       return cmd
+}
+
+func (c *cmdGroup) init() error {
+       seen := map[string]bool{}
+       if c.defaultSubcommand() != nil && !c.have() {
+               return fmt.Errorf("default subcommand %q provided but no subcommands defined", c.defaultSubcommand().name)
+       }
+       defaults := []string{}
+       for _, cmd := range c.commandOrder {
+               if cmd.isDefault {
+                       defaults = append(defaults, cmd.name)
+               }
+               if seen[cmd.name] {
+                       return fmt.Errorf("duplicate command %q", cmd.name)
+               }
+               seen[cmd.name] = true
+               for _, alias := range cmd.aliases {
+                       if seen[alias] {
+                               return fmt.Errorf("alias duplicates existing command %q", alias)
+                       }
+                       c.commands[alias] = cmd
+               }
+               if err := cmd.init(); err != nil {
+                       return err
+               }
+       }
+       if len(defaults) > 1 {
+               return fmt.Errorf("more than one default subcommand exists: %s", strings.Join(defaults, ", "))
+       }
+       return nil
+}
+
+func (c *cmdGroup) have() bool {
+       return len(c.commands) > 0
+}
+
+type CmdClauseValidator func(*CmdClause) error
+
+// A CmdClause is a single top-level command. It encapsulates a set of flags
+// and either subcommands or positional arguments.
+type CmdClause struct {
+       cmdMixin
+       app            *Application
+       name           string
+       aliases        []string
+       help           string
+       isDefault      bool
+       validator      CmdClauseValidator
+       hidden         bool
+       completionAlts []string
+}
+
+func newCommand(app *Application, name, help string) *CmdClause {
+       c := &CmdClause{
+               app:  app,
+               name: name,
+               help: help,
+       }
+       c.flagGroup = newFlagGroup()
+       c.argGroup = newArgGroup()
+       c.cmdGroup = newCmdGroup(app)
+       return c
+}
+
+// Add an Alias for this command.
+func (c *CmdClause) Alias(name string) *CmdClause {
+       c.aliases = append(c.aliases, name)
+       return c
+}
+
+// Validate sets a validation function to run when parsing.
+func (c *CmdClause) Validate(validator CmdClauseValidator) *CmdClause {
+       c.validator = validator
+       return c
+}
+
+func (c *CmdClause) FullCommand() string {
+       out := []string{c.name}
+       for p := c.parent; p != nil; p = p.parent {
+               out = append([]string{p.name}, out...)
+       }
+       return strings.Join(out, " ")
+}
+
+// Command adds a new sub-command.
+func (c *CmdClause) Command(name, help string) *CmdClause {
+       cmd := c.addCommand(name, help)
+       cmd.parent = c
+       return cmd
+}
+
+// Default makes this command the default if commands don't match.
+func (c *CmdClause) Default() *CmdClause {
+       c.isDefault = true
+       return c
+}
+
+func (c *CmdClause) Action(action Action) *CmdClause {
+       c.addAction(action)
+       return c
+}
+
+func (c *CmdClause) PreAction(action Action) *CmdClause {
+       c.addPreAction(action)
+       return c
+}
+
+func (c *CmdClause) init() error {
+       if err := c.flagGroup.init(c.app.defaultEnvarPrefix()); err != nil {
+               return err
+       }
+       if c.argGroup.have() && c.cmdGroup.have() {
+               return fmt.Errorf("can't mix Arg()s with Command()s")
+       }
+       if err := c.argGroup.init(); err != nil {
+               return err
+       }
+       if err := c.cmdGroup.init(); err != nil {
+               return err
+       }
+       return nil
+}
+
+func (c *CmdClause) Hidden() *CmdClause {
+       c.hidden = true
+       return c
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/completions.go b/vendor/gopkg.in/alecthomas/kingpin.v2/completions.go
new file mode 100644 (file)
index 0000000..6e7b409
--- /dev/null
@@ -0,0 +1,33 @@
+package kingpin
+
+// HintAction is a function type who is expected to return a slice of possible
+// command line arguments.
+type HintAction func() []string
+type completionsMixin struct {
+       hintActions        []HintAction
+       builtinHintActions []HintAction
+}
+
+func (a *completionsMixin) addHintAction(action HintAction) {
+       a.hintActions = append(a.hintActions, action)
+}
+
+// Allow adding of HintActions which are added internally, ie, EnumVar
+func (a *completionsMixin) addHintActionBuiltin(action HintAction) {
+       a.builtinHintActions = append(a.builtinHintActions, action)
+}
+
+func (a *completionsMixin) resolveCompletions() []string {
+       var hints []string
+
+       options := a.builtinHintActions
+       if len(a.hintActions) > 0 {
+               // User specified their own hintActions. Use those instead.
+               options = a.hintActions
+       }
+
+       for _, hintAction := range options {
+               hints = append(hints, hintAction()...)
+       }
+       return hints
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/doc.go b/vendor/gopkg.in/alecthomas/kingpin.v2/doc.go
new file mode 100644 (file)
index 0000000..cb951a8
--- /dev/null
@@ -0,0 +1,68 @@
+// Package kingpin provides command line interfaces like this:
+//
+//     $ chat
+//     usage: chat [<flags>] <command> [<flags>] [<args> ...]
+//
+//     Flags:
+//       --debug              enable debug mode
+//       --help               Show help.
+//       --server=127.0.0.1   server address
+//
+//     Commands:
+//       help <command>
+//         Show help for a command.
+//
+//       post [<flags>] <channel>
+//         Post a message to a channel.
+//
+//       register <nick> <name>
+//         Register a new user.
+//
+//     $ chat help post
+//     usage: chat [<flags>] post [<flags>] <channel> [<text>]
+//
+//     Post a message to a channel.
+//
+//     Flags:
+//       --image=IMAGE   image to post
+//
+//     Args:
+//       <channel>   channel to post to
+//       [<text>]    text to post
+//     $ chat post --image=~/Downloads/owls.jpg pics
+//
+// From code like this:
+//
+//     package main
+//
+//     import "gopkg.in/alecthomas/kingpin.v2"
+//
+//     var (
+//       debug    = kingpin.Flag("debug", "enable debug mode").Default("false").Bool()
+//       serverIP = kingpin.Flag("server", "server address").Default("127.0.0.1").IP()
+//
+//       register     = kingpin.Command("register", "Register a new user.")
+//       registerNick = register.Arg("nick", "nickname for user").Required().String()
+//       registerName = register.Arg("name", "name of user").Required().String()
+//
+//       post        = kingpin.Command("post", "Post a message to a channel.")
+//       postImage   = post.Flag("image", "image to post").ExistingFile()
+//       postChannel = post.Arg("channel", "channel to post to").Required().String()
+//       postText    = post.Arg("text", "text to post").String()
+//     )
+//
+//     func main() {
+//       switch kingpin.Parse() {
+//       // Register user
+//       case "register":
+//         println(*registerNick)
+//
+//       // Post message
+//       case "post":
+//         if *postImage != nil {
+//         }
+//         if *postText != "" {
+//         }
+//       }
+//     }
+package 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 (file)
index 0000000..c01a27d
--- /dev/null
@@ -0,0 +1,45 @@
+package kingpin
+
+import (
+       "os"
+       "regexp"
+)
+
+var (
+       envVarValuesSeparator = "\r?\n"
+       envVarValuesTrimmer   = regexp.MustCompile(envVarValuesSeparator + "$")
+       envVarValuesSplitter  = regexp.MustCompile(envVarValuesSeparator)
+)
+
+type envarMixin struct {
+       envar   string
+       noEnvar bool
+}
+
+func (e *envarMixin) HasEnvarValue() bool {
+       return e.GetEnvarValue() != ""
+}
+
+func (e *envarMixin) GetEnvarValue() string {
+       if e.noEnvar || e.envar == "" {
+               return ""
+       }
+       return os.Getenv(e.envar)
+}
+
+func (e *envarMixin) GetSplitEnvarValue() []string {
+       values := make([]string, 0)
+
+       envarValue := e.GetEnvarValue()
+       if envarValue == "" {
+               return values
+       }
+
+       // Split by new line to extract multiple values, if any.
+       trimmed := envVarValuesTrimmer.ReplaceAllString(envarValue, "")
+       for _, value := range envVarValuesSplitter.Split(trimmed, -1) {
+               values = append(values, value)
+       }
+
+       return values
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/flags.go b/vendor/gopkg.in/alecthomas/kingpin.v2/flags.go
new file mode 100644 (file)
index 0000000..8f33721
--- /dev/null
@@ -0,0 +1,308 @@
+package kingpin
+
+import (
+       "fmt"
+       "strings"
+)
+
+type flagGroup struct {
+       short     map[string]*FlagClause
+       long      map[string]*FlagClause
+       flagOrder []*FlagClause
+}
+
+func newFlagGroup() *flagGroup {
+       return &flagGroup{
+               short: map[string]*FlagClause{},
+               long:  map[string]*FlagClause{},
+       }
+}
+
+// GetFlag gets a flag definition.
+//
+// This allows existing flags to be modified after definition but before parsing. Useful for
+// modular applications.
+func (f *flagGroup) GetFlag(name string) *FlagClause {
+       return f.long[name]
+}
+
+// Flag defines a new flag with the given long name and help.
+func (f *flagGroup) Flag(name, help string) *FlagClause {
+       flag := newFlag(name, help)
+       f.long[name] = flag
+       f.flagOrder = append(f.flagOrder, flag)
+       return flag
+}
+
+func (f *flagGroup) init(defaultEnvarPrefix string) error {
+       if err := f.checkDuplicates(); err != nil {
+               return err
+       }
+       for _, flag := range f.long {
+               if defaultEnvarPrefix != "" && !flag.noEnvar && flag.envar == "" {
+                       flag.envar = envarTransform(defaultEnvarPrefix + "_" + flag.name)
+               }
+               if err := flag.init(); err != nil {
+                       return err
+               }
+               if flag.shorthand != 0 {
+                       f.short[string(flag.shorthand)] = flag
+               }
+       }
+       return nil
+}
+
+func (f *flagGroup) checkDuplicates() error {
+       seenShort := map[rune]bool{}
+       seenLong := map[string]bool{}
+       for _, flag := range f.flagOrder {
+               if flag.shorthand != 0 {
+                       if _, ok := seenShort[flag.shorthand]; ok {
+                               return fmt.Errorf("duplicate short flag -%c", flag.shorthand)
+                       }
+                       seenShort[flag.shorthand] = true
+               }
+               if _, ok := seenLong[flag.name]; ok {
+                       return fmt.Errorf("duplicate long flag --%s", flag.name)
+               }
+               seenLong[flag.name] = true
+       }
+       return nil
+}
+
+func (f *flagGroup) parse(context *ParseContext) (*FlagClause, error) {
+       var token *Token
+
+loop:
+       for {
+               token = context.Peek()
+               switch token.Type {
+               case TokenEOL:
+                       break loop
+
+               case TokenLong, TokenShort:
+                       flagToken := token
+                       defaultValue := ""
+                       var flag *FlagClause
+                       var ok bool
+                       invert := false
+
+                       name := token.Value
+                       if token.Type == TokenLong {
+                               flag, ok = f.long[name]
+                               if !ok {
+                                       if strings.HasPrefix(name, "no-") {
+                                               name = name[3:]
+                                               invert = true
+                                       }
+                                       flag, ok = f.long[name]
+                               }
+                               if !ok {
+                                       return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
+                               }
+                       } else {
+                               flag, ok = f.short[name]
+                               if !ok {
+                                       return nil, fmt.Errorf("unknown short flag '%s'", flagToken)
+                               }
+                       }
+
+                       context.Next()
+
+                       fb, ok := flag.value.(boolFlag)
+                       if ok && fb.IsBoolFlag() {
+                               if invert {
+                                       defaultValue = "false"
+                               } else {
+                                       defaultValue = "true"
+                               }
+                       } else {
+                               if invert {
+                                       context.Push(token)
+                                       return nil, fmt.Errorf("unknown long flag '%s'", flagToken)
+                               }
+                               token = context.Peek()
+                               if token.Type != TokenArg {
+                                       context.Push(token)
+                                       return nil, fmt.Errorf("expected argument for flag '%s'", flagToken)
+                               }
+                               context.Next()
+                               defaultValue = token.Value
+                       }
+
+                       context.matchedFlag(flag, defaultValue)
+                       return flag, nil
+
+               default:
+                       break loop
+               }
+       }
+       return nil, nil
+}
+
+// FlagClause is a fluid interface used to build flags.
+type FlagClause struct {
+       parserMixin
+       actionMixin
+       completionsMixin
+       envarMixin
+       name          string
+       shorthand     rune
+       help          string
+       defaultValues []string
+       placeholder   string
+       hidden        bool
+}
+
+func newFlag(name, help string) *FlagClause {
+       f := &FlagClause{
+               name: name,
+               help: help,
+       }
+       return f
+}
+
+func (f *FlagClause) setDefault() error {
+       if f.HasEnvarValue() {
+               if v, ok := f.value.(repeatableFlag); !ok || !v.IsCumulative() {
+                       // Use the value as-is
+                       return f.value.Set(f.GetEnvarValue())
+               } else {
+                       for _, value := range f.GetSplitEnvarValue() {
+                               if err := f.value.Set(value); err != nil {
+                                       return err
+                               }
+                       }
+                       return nil
+               }
+       }
+
+       if len(f.defaultValues) > 0 {
+               for _, defaultValue := range f.defaultValues {
+                       if err := f.value.Set(defaultValue); err != nil {
+                               return err
+                       }
+               }
+               return nil
+       }
+
+       return nil
+}
+
+func (f *FlagClause) needsValue() bool {
+       haveDefault := len(f.defaultValues) > 0
+       return f.required && !(haveDefault || f.HasEnvarValue())
+}
+
+func (f *FlagClause) init() error {
+       if f.required && len(f.defaultValues) > 0 {
+               return fmt.Errorf("required flag '--%s' with default value that will never be used", f.name)
+       }
+       if f.value == nil {
+               return fmt.Errorf("no type defined for --%s (eg. .String())", f.name)
+       }
+       if v, ok := f.value.(repeatableFlag); (!ok || !v.IsCumulative()) && len(f.defaultValues) > 1 {
+               return fmt.Errorf("invalid default for '--%s', expecting single value", f.name)
+       }
+       return nil
+}
+
+// Dispatch to the given function after the flag is parsed and validated.
+func (f *FlagClause) Action(action Action) *FlagClause {
+       f.addAction(action)
+       return f
+}
+
+func (f *FlagClause) PreAction(action Action) *FlagClause {
+       f.addPreAction(action)
+       return f
+}
+
+// HintAction registers a HintAction (function) for the flag to provide completions
+func (a *FlagClause) HintAction(action HintAction) *FlagClause {
+       a.addHintAction(action)
+       return a
+}
+
+// HintOptions registers any number of options for the flag to provide completions
+func (a *FlagClause) HintOptions(options ...string) *FlagClause {
+       a.addHintAction(func() []string {
+               return options
+       })
+       return a
+}
+
+func (a *FlagClause) EnumVar(target *string, options ...string) {
+       a.parserMixin.EnumVar(target, options...)
+       a.addHintActionBuiltin(func() []string {
+               return options
+       })
+}
+
+func (a *FlagClause) Enum(options ...string) (target *string) {
+       a.addHintActionBuiltin(func() []string {
+               return options
+       })
+       return a.parserMixin.Enum(options...)
+}
+
+// Default values for this flag. They *must* be parseable by the value of the flag.
+func (f *FlagClause) Default(values ...string) *FlagClause {
+       f.defaultValues = values
+       return f
+}
+
+// DEPRECATED: Use Envar(name) instead.
+func (f *FlagClause) OverrideDefaultFromEnvar(envar string) *FlagClause {
+       return f.Envar(envar)
+}
+
+// Envar overrides the default value(s) for a flag from an environment variable,
+// if it is set. Several default values can be provided by using new lines to
+// separate them.
+func (f *FlagClause) Envar(name string) *FlagClause {
+       f.envar = name
+       f.noEnvar = false
+       return f
+}
+
+// NoEnvar forces environment variable defaults to be disabled for this flag.
+// Most useful in conjunction with app.DefaultEnvars().
+func (f *FlagClause) NoEnvar() *FlagClause {
+       f.envar = ""
+       f.noEnvar = true
+       return f
+}
+
+// PlaceHolder sets the place-holder string used for flag values in the help. The
+// default behaviour is to use the value provided by Default() if provided,
+// then fall back on the capitalized flag name.
+func (f *FlagClause) PlaceHolder(placeholder string) *FlagClause {
+       f.placeholder = placeholder
+       return f
+}
+
+// Hidden hides a flag from usage but still allows it to be used.
+func (f *FlagClause) Hidden() *FlagClause {
+       f.hidden = true
+       return f
+}
+
+// Required makes the flag required. You can not provide a Default() value to a Required() flag.
+func (f *FlagClause) Required() *FlagClause {
+       f.required = true
+       return f
+}
+
+// Short sets the short flag name.
+func (f *FlagClause) Short(name rune) *FlagClause {
+       f.shorthand = name
+       return f
+}
+
+// Bool makes this flag a boolean flag.
+func (f *FlagClause) Bool() (target *bool) {
+       target = new(bool)
+       f.SetValue(newBoolValue(target))
+       return
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/global.go b/vendor/gopkg.in/alecthomas/kingpin.v2/global.go
new file mode 100644 (file)
index 0000000..10a2913
--- /dev/null
@@ -0,0 +1,94 @@
+package kingpin
+
+import (
+       "os"
+       "path/filepath"
+)
+
+var (
+       // CommandLine is the default Kingpin parser.
+       CommandLine = New(filepath.Base(os.Args[0]), "")
+       // Global help flag. Exposed for user customisation.
+       HelpFlag = CommandLine.HelpFlag
+       // Top-level help command. Exposed for user customisation. May be nil.
+       HelpCommand = CommandLine.HelpCommand
+       // Global version flag. Exposed for user customisation. May be nil.
+       VersionFlag = CommandLine.VersionFlag
+)
+
+// Command adds a new command to the default parser.
+func Command(name, help string) *CmdClause {
+       return CommandLine.Command(name, help)
+}
+
+// Flag adds a new flag to the default parser.
+func Flag(name, help string) *FlagClause {
+       return CommandLine.Flag(name, help)
+}
+
+// Arg adds a new argument to the top-level of the default parser.
+func Arg(name, help string) *ArgClause {
+       return CommandLine.Arg(name, help)
+}
+
+// Parse and return the selected command. Will call the termination handler if
+// an error is encountered.
+func Parse() string {
+       selected := MustParse(CommandLine.Parse(os.Args[1:]))
+       if selected == "" && CommandLine.cmdGroup.have() {
+               Usage()
+               CommandLine.terminate(0)
+       }
+       return selected
+}
+
+// Errorf prints an error message to stderr.
+func Errorf(format string, args ...interface{}) {
+       CommandLine.Errorf(format, args...)
+}
+
+// Fatalf prints an error message to stderr and exits.
+func Fatalf(format string, args ...interface{}) {
+       CommandLine.Fatalf(format, args...)
+}
+
+// FatalIfError prints an error and exits if err is not nil. The error is printed
+// with the given prefix.
+func FatalIfError(err error, format string, args ...interface{}) {
+       CommandLine.FatalIfError(err, format, args...)
+}
+
+// FatalUsage prints an error message followed by usage information, then
+// exits with a non-zero status.
+func FatalUsage(format string, args ...interface{}) {
+       CommandLine.FatalUsage(format, args...)
+}
+
+// FatalUsageContext writes a printf formatted error message to stderr, then
+// usage information for the given ParseContext, before exiting.
+func FatalUsageContext(context *ParseContext, format string, args ...interface{}) {
+       CommandLine.FatalUsageContext(context, format, args...)
+}
+
+// Usage prints usage to stderr.
+func Usage() {
+       CommandLine.Usage(os.Args[1:])
+}
+
+// Set global usage template to use (defaults to DefaultUsageTemplate).
+func UsageTemplate(template string) *Application {
+       return CommandLine.UsageTemplate(template)
+}
+
+// MustParse can be used with app.Parse(args) to exit with an error if parsing fails.
+func MustParse(command string, err error) string {
+       if err != nil {
+               Fatalf("%s, try --help", err)
+       }
+       return command
+}
+
+// Version adds a flag for displaying the application version number.
+func Version(version string) *Application {
+       return CommandLine.Version(version)
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go b/vendor/gopkg.in/alecthomas/kingpin.v2/guesswidth.go
new file mode 100644 (file)
index 0000000..a269531
--- /dev/null
@@ -0,0 +1,9 @@
+// +build appengine !linux,!freebsd,!darwin,!dragonfly,!netbsd,!openbsd
+
+package kingpin
+
+import "io"
+
+func guessWidth(w io.Writer) int {
+       return 80
+}
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 (file)
index 0000000..ad8163f
--- /dev/null
@@ -0,0 +1,38 @@
+// +build !appengine,linux freebsd darwin dragonfly netbsd openbsd
+
+package kingpin
+
+import (
+       "io"
+       "os"
+       "strconv"
+       "syscall"
+       "unsafe"
+)
+
+func guessWidth(w io.Writer) int {
+       // check if COLUMNS env is set to comply with
+       // http://pubs.opengroup.org/onlinepubs/009604499/basedefs/xbd_chap08.html
+       colsStr := os.Getenv("COLUMNS")
+       if colsStr != "" {
+               if cols, err := strconv.Atoi(colsStr); err == nil {
+                       return cols
+               }
+       }
+
+       if t, ok := w.(*os.File); ok {
+               fd := t.Fd()
+               var dimensions [4]uint16
+
+               if _, _, err := syscall.Syscall6(
+                       syscall.SYS_IOCTL,
+                       uintptr(fd),
+                       uintptr(syscall.TIOCGWINSZ),
+                       uintptr(unsafe.Pointer(&dimensions)),
+                       0, 0, 0,
+               ); err == 0 {
+                       return int(dimensions[1])
+               }
+       }
+       return 80
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/model.go b/vendor/gopkg.in/alecthomas/kingpin.v2/model.go
new file mode 100644 (file)
index 0000000..a4ee83b
--- /dev/null
@@ -0,0 +1,227 @@
+package kingpin
+
+import (
+       "fmt"
+       "strconv"
+       "strings"
+)
+
+// Data model for Kingpin command-line structure.
+
+type FlagGroupModel struct {
+       Flags []*FlagModel
+}
+
+func (f *FlagGroupModel) FlagSummary() string {
+       out := []string{}
+       count := 0
+       for _, flag := range f.Flags {
+               if flag.Name != "help" {
+                       count++
+               }
+               if flag.Required {
+                       if flag.IsBoolFlag() {
+                               out = append(out, fmt.Sprintf("--[no-]%s", flag.Name))
+                       } else {
+                               out = append(out, fmt.Sprintf("--%s=%s", flag.Name, flag.FormatPlaceHolder()))
+                       }
+               }
+       }
+       if count != len(out) {
+               out = append(out, "[<flags>]")
+       }
+       return strings.Join(out, " ")
+}
+
+type FlagModel struct {
+       Name        string
+       Help        string
+       Short       rune
+       Default     []string
+       Envar       string
+       PlaceHolder string
+       Required    bool
+       Hidden      bool
+       Value       Value
+}
+
+func (f *FlagModel) String() string {
+       return f.Value.String()
+}
+
+func (f *FlagModel) IsBoolFlag() bool {
+       if fl, ok := f.Value.(boolFlag); ok {
+               return fl.IsBoolFlag()
+       }
+       return false
+}
+
+func (f *FlagModel) FormatPlaceHolder() string {
+       if f.PlaceHolder != "" {
+               return f.PlaceHolder
+       }
+       if len(f.Default) > 0 {
+               ellipsis := ""
+               if len(f.Default) > 1 {
+                       ellipsis = "..."
+               }
+               if _, ok := f.Value.(*stringValue); ok {
+                       return strconv.Quote(f.Default[0]) + ellipsis
+               }
+               return f.Default[0] + ellipsis
+       }
+       return strings.ToUpper(f.Name)
+}
+
+type ArgGroupModel struct {
+       Args []*ArgModel
+}
+
+func (a *ArgGroupModel) ArgSummary() string {
+       depth := 0
+       out := []string{}
+       for _, arg := range a.Args {
+               h := "<" + arg.Name + ">"
+               if !arg.Required {
+                       h = "[" + h
+                       depth++
+               }
+               out = append(out, h)
+       }
+       out[len(out)-1] = out[len(out)-1] + strings.Repeat("]", depth)
+       return strings.Join(out, " ")
+}
+
+type ArgModel struct {
+       Name     string
+       Help     string
+       Default  []string
+       Envar    string
+       Required bool
+       Value    Value
+}
+
+func (a *ArgModel) String() string {
+       return a.Value.String()
+}
+
+type CmdGroupModel struct {
+       Commands []*CmdModel
+}
+
+func (c *CmdGroupModel) FlattenedCommands() (out []*CmdModel) {
+       for _, cmd := range c.Commands {
+               if len(cmd.Commands) == 0 {
+                       out = append(out, cmd)
+               }
+               out = append(out, cmd.FlattenedCommands()...)
+       }
+       return
+}
+
+type CmdModel struct {
+       Name        string
+       Aliases     []string
+       Help        string
+       FullCommand string
+       Depth       int
+       Hidden      bool
+       Default     bool
+       *FlagGroupModel
+       *ArgGroupModel
+       *CmdGroupModel
+}
+
+func (c *CmdModel) String() string {
+       return c.FullCommand
+}
+
+type ApplicationModel struct {
+       Name    string
+       Help    string
+       Version string
+       Author  string
+       *ArgGroupModel
+       *CmdGroupModel
+       *FlagGroupModel
+}
+
+func (a *Application) Model() *ApplicationModel {
+       return &ApplicationModel{
+               Name:           a.Name,
+               Help:           a.Help,
+               Version:        a.version,
+               Author:         a.author,
+               FlagGroupModel: a.flagGroup.Model(),
+               ArgGroupModel:  a.argGroup.Model(),
+               CmdGroupModel:  a.cmdGroup.Model(),
+       }
+}
+
+func (a *argGroup) Model() *ArgGroupModel {
+       m := &ArgGroupModel{}
+       for _, arg := range a.args {
+               m.Args = append(m.Args, arg.Model())
+       }
+       return m
+}
+
+func (a *ArgClause) Model() *ArgModel {
+       return &ArgModel{
+               Name:     a.name,
+               Help:     a.help,
+               Default:  a.defaultValues,
+               Envar:    a.envar,
+               Required: a.required,
+               Value:    a.value,
+       }
+}
+
+func (f *flagGroup) Model() *FlagGroupModel {
+       m := &FlagGroupModel{}
+       for _, fl := range f.flagOrder {
+               m.Flags = append(m.Flags, fl.Model())
+       }
+       return m
+}
+
+func (f *FlagClause) Model() *FlagModel {
+       return &FlagModel{
+               Name:        f.name,
+               Help:        f.help,
+               Short:       rune(f.shorthand),
+               Default:     f.defaultValues,
+               Envar:       f.envar,
+               PlaceHolder: f.placeholder,
+               Required:    f.required,
+               Hidden:      f.hidden,
+               Value:       f.value,
+       }
+}
+
+func (c *cmdGroup) Model() *CmdGroupModel {
+       m := &CmdGroupModel{}
+       for _, cm := range c.commandOrder {
+               m.Commands = append(m.Commands, cm.Model())
+       }
+       return m
+}
+
+func (c *CmdClause) Model() *CmdModel {
+       depth := 0
+       for i := c; i != nil; i = i.parent {
+               depth++
+       }
+       return &CmdModel{
+               Name:           c.name,
+               Aliases:        c.aliases,
+               Help:           c.help,
+               Depth:          depth,
+               Hidden:         c.hidden,
+               Default:        c.isDefault,
+               FullCommand:    c.FullCommand(),
+               FlagGroupModel: c.flagGroup.Model(),
+               ArgGroupModel:  c.argGroup.Model(),
+               CmdGroupModel:  c.cmdGroup.Model(),
+       }
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/parser.go b/vendor/gopkg.in/alecthomas/kingpin.v2/parser.go
new file mode 100644 (file)
index 0000000..80e1f0b
--- /dev/null
@@ -0,0 +1,384 @@
+package kingpin
+
+import (
+       "bufio"
+       "fmt"
+       "os"
+       "strings"
+       "unicode/utf8"
+)
+
+type TokenType int
+
+// Token types.
+const (
+       TokenShort TokenType = iota
+       TokenLong
+       TokenArg
+       TokenError
+       TokenEOL
+)
+
+func (t TokenType) String() string {
+       switch t {
+       case TokenShort:
+               return "short flag"
+       case TokenLong:
+               return "long flag"
+       case TokenArg:
+               return "argument"
+       case TokenError:
+               return "error"
+       case TokenEOL:
+               return "<EOL>"
+       }
+       return "?"
+}
+
+var (
+       TokenEOLMarker = Token{-1, TokenEOL, ""}
+)
+
+type Token struct {
+       Index int
+       Type  TokenType
+       Value string
+}
+
+func (t *Token) Equal(o *Token) bool {
+       return t.Index == o.Index
+}
+
+func (t *Token) IsFlag() bool {
+       return t.Type == TokenShort || t.Type == TokenLong
+}
+
+func (t *Token) IsEOF() bool {
+       return t.Type == TokenEOL
+}
+
+func (t *Token) String() string {
+       switch t.Type {
+       case TokenShort:
+               return "-" + t.Value
+       case TokenLong:
+               return "--" + t.Value
+       case TokenArg:
+               return t.Value
+       case TokenError:
+               return "error: " + t.Value
+       case TokenEOL:
+               return "<EOL>"
+       default:
+               panic("unhandled type")
+       }
+}
+
+// A union of possible elements in a parse stack.
+type ParseElement struct {
+       // Clause is either *CmdClause, *ArgClause or *FlagClause.
+       Clause interface{}
+       // Value is corresponding value for an ArgClause or FlagClause (if any).
+       Value *string
+}
+
+// ParseContext holds the current context of the parser. When passed to
+// Action() callbacks Elements will be fully populated with *FlagClause,
+// *ArgClause and *CmdClause values and their corresponding arguments (if
+// any).
+type ParseContext struct {
+       SelectedCommand *CmdClause
+       ignoreDefault   bool
+       argsOnly        bool
+       peek            []*Token
+       argi            int // Index of current command-line arg we're processing.
+       args            []string
+       rawArgs         []string
+       flags           *flagGroup
+       arguments       *argGroup
+       argumenti       int // Cursor into arguments
+       // Flags, arguments and commands encountered and collected during parse.
+       Elements []*ParseElement
+}
+
+func (p *ParseContext) nextArg() *ArgClause {
+       if p.argumenti >= len(p.arguments.args) {
+               return nil
+       }
+       arg := p.arguments.args[p.argumenti]
+       if !arg.consumesRemainder() {
+               p.argumenti++
+       }
+       return arg
+}
+
+func (p *ParseContext) next() {
+       p.argi++
+       p.args = p.args[1:]
+}
+
+// HasTrailingArgs returns true if there are unparsed command-line arguments.
+// This can occur if the parser can not match remaining arguments.
+func (p *ParseContext) HasTrailingArgs() bool {
+       return len(p.args) > 0
+}
+
+func tokenize(args []string, ignoreDefault bool) *ParseContext {
+       return &ParseContext{
+               ignoreDefault: ignoreDefault,
+               args:          args,
+               rawArgs:       args,
+               flags:         newFlagGroup(),
+               arguments:     newArgGroup(),
+       }
+}
+
+func (p *ParseContext) mergeFlags(flags *flagGroup) {
+       for _, flag := range flags.flagOrder {
+               if flag.shorthand != 0 {
+                       p.flags.short[string(flag.shorthand)] = flag
+               }
+               p.flags.long[flag.name] = flag
+               p.flags.flagOrder = append(p.flags.flagOrder, flag)
+       }
+}
+
+func (p *ParseContext) mergeArgs(args *argGroup) {
+       for _, arg := range args.args {
+               p.arguments.args = append(p.arguments.args, arg)
+       }
+}
+
+func (p *ParseContext) EOL() bool {
+       return p.Peek().Type == TokenEOL
+}
+
+// Next token in the parse context.
+func (p *ParseContext) Next() *Token {
+       if len(p.peek) > 0 {
+               return p.pop()
+       }
+
+       // End of tokens.
+       if len(p.args) == 0 {
+               return &Token{Index: p.argi, Type: TokenEOL}
+       }
+
+       arg := p.args[0]
+       p.next()
+
+       if p.argsOnly {
+               return &Token{p.argi, TokenArg, arg}
+       }
+
+       // All remaining args are passed directly.
+       if arg == "--" {
+               p.argsOnly = true
+               return p.Next()
+       }
+
+       if strings.HasPrefix(arg, "--") {
+               parts := strings.SplitN(arg[2:], "=", 2)
+               token := &Token{p.argi, TokenLong, parts[0]}
+               if len(parts) == 2 {
+                       p.Push(&Token{p.argi, TokenArg, parts[1]})
+               }
+               return token
+       }
+
+       if strings.HasPrefix(arg, "-") {
+               if len(arg) == 1 {
+                       return &Token{Index: p.argi, Type: TokenShort}
+               }
+               shortRune, size := utf8.DecodeRuneInString(arg[1:])
+               short := string(shortRune)
+               flag, ok := p.flags.short[short]
+               // Not a known short flag, we'll just return it anyway.
+               if !ok {
+               } else if fb, ok := flag.value.(boolFlag); ok && fb.IsBoolFlag() {
+                       // Bool short flag.
+               } else {
+                       // Short flag with combined argument: -fARG
+                       token := &Token{p.argi, TokenShort, short}
+                       if len(arg) > size+1 {
+                               p.Push(&Token{p.argi, TokenArg, arg[size+1:]})
+                       }
+                       return token
+               }
+
+               if len(arg) > size+1 {
+                       p.args = append([]string{"-" + arg[size+1:]}, p.args...)
+               }
+               return &Token{p.argi, TokenShort, short}
+       } else if strings.HasPrefix(arg, "@") {
+               expanded, err := ExpandArgsFromFile(arg[1:])
+               if err != nil {
+                       return &Token{p.argi, TokenError, err.Error()}
+               }
+               if len(p.args) == 0 {
+                       p.args = append(p.args, expanded...)
+               } else if p.argi >= len(p.args) {
+                       p.args = append(p.args[:p.argi-1], expanded...)
+               } else {
+                       p.args = append(p.args[:p.argi-1], append(expanded, p.args[p.argi+1:]...)...)
+               }
+               return p.Next()
+       }
+
+       return &Token{p.argi, TokenArg, arg}
+}
+
+func (p *ParseContext) Peek() *Token {
+       if len(p.peek) == 0 {
+               return p.Push(p.Next())
+       }
+       return p.peek[len(p.peek)-1]
+}
+
+func (p *ParseContext) Push(token *Token) *Token {
+       p.peek = append(p.peek, token)
+       return token
+}
+
+func (p *ParseContext) pop() *Token {
+       end := len(p.peek) - 1
+       token := p.peek[end]
+       p.peek = p.peek[0:end]
+       return token
+}
+
+func (p *ParseContext) String() string {
+       return p.SelectedCommand.FullCommand()
+}
+
+func (p *ParseContext) matchedFlag(flag *FlagClause, value string) {
+       p.Elements = append(p.Elements, &ParseElement{Clause: flag, Value: &value})
+}
+
+func (p *ParseContext) matchedArg(arg *ArgClause, value string) {
+       p.Elements = append(p.Elements, &ParseElement{Clause: arg, Value: &value})
+}
+
+func (p *ParseContext) matchedCmd(cmd *CmdClause) {
+       p.Elements = append(p.Elements, &ParseElement{Clause: cmd})
+       p.mergeFlags(cmd.flagGroup)
+       p.mergeArgs(cmd.argGroup)
+       p.SelectedCommand = cmd
+}
+
+// Expand arguments from a file. Lines starting with # will be treated as comments.
+func ExpandArgsFromFile(filename string) (out []string, err error) {
+       r, err := os.Open(filename)
+       if err != nil {
+               return nil, err
+       }
+       defer r.Close()
+       scanner := bufio.NewScanner(r)
+       for scanner.Scan() {
+               line := scanner.Text()
+               if strings.HasPrefix(line, "#") {
+                       continue
+               }
+               out = append(out, line)
+       }
+       err = scanner.Err()
+       return
+}
+
+func parse(context *ParseContext, app *Application) (err error) {
+       context.mergeFlags(app.flagGroup)
+       context.mergeArgs(app.argGroup)
+
+       cmds := app.cmdGroup
+       ignoreDefault := context.ignoreDefault
+
+loop:
+       for !context.EOL() {
+               token := context.Peek()
+
+               switch token.Type {
+               case TokenLong, TokenShort:
+                       if flag, err := context.flags.parse(context); err != nil {
+                               if !ignoreDefault {
+                                       if cmd := cmds.defaultSubcommand(); cmd != nil {
+                                               cmd.completionAlts = cmds.cmdNames()
+                                               context.matchedCmd(cmd)
+                                               cmds = cmd.cmdGroup
+                                               break
+                                       }
+                               }
+                               return err
+                       } else if flag == HelpFlag {
+                               ignoreDefault = true
+                       }
+
+               case TokenArg:
+                       if cmds.have() {
+                               selectedDefault := false
+                               cmd, ok := cmds.commands[token.String()]
+                               if !ok {
+                                       if !ignoreDefault {
+                                               if cmd = cmds.defaultSubcommand(); cmd != nil {
+                                                       cmd.completionAlts = cmds.cmdNames()
+                                                       selectedDefault = true
+                                               }
+                                       }
+                                       if cmd == nil {
+                                               return fmt.Errorf("expected command but got %q", token)
+                                       }
+                               }
+                               if cmd == HelpCommand {
+                                       ignoreDefault = true
+                               }
+                               cmd.completionAlts = nil
+                               context.matchedCmd(cmd)
+                               cmds = cmd.cmdGroup
+                               if !selectedDefault {
+                                       context.Next()
+                               }
+                       } else if context.arguments.have() {
+                               if app.noInterspersed {
+                                       // no more flags
+                                       context.argsOnly = true
+                               }
+                               arg := context.nextArg()
+                               if arg == nil {
+                                       break loop
+                               }
+                               context.matchedArg(arg, token.String())
+                               context.Next()
+                       } else {
+                               break loop
+                       }
+
+               case TokenEOL:
+                       break loop
+               }
+       }
+
+       // Move to innermost default command.
+       for !ignoreDefault {
+               if cmd := cmds.defaultSubcommand(); cmd != nil {
+                       cmd.completionAlts = cmds.cmdNames()
+                       context.matchedCmd(cmd)
+                       cmds = cmd.cmdGroup
+               } else {
+                       break
+               }
+       }
+
+       if !context.EOL() {
+               return fmt.Errorf("unexpected %s", context.Peek())
+       }
+
+       // Set defaults for all remaining args.
+       for arg := context.nextArg(); arg != nil && !arg.consumesRemainder(); arg = context.nextArg() {
+               for _, defaultValue := range arg.defaultValues {
+                       if err := arg.value.Set(defaultValue); err != nil {
+                               return fmt.Errorf("invalid default value '%s' for argument '%s'", defaultValue, arg.name)
+                       }
+               }
+       }
+
+       return
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go b/vendor/gopkg.in/alecthomas/kingpin.v2/parsers.go
new file mode 100644 (file)
index 0000000..d9ad57e
--- /dev/null
@@ -0,0 +1,212 @@
+package kingpin
+
+import (
+       "net"
+       "net/url"
+       "os"
+       "time"
+
+       "github.com/alecthomas/units"
+)
+
+type Settings interface {
+       SetValue(value Value)
+}
+
+type parserMixin struct {
+       value    Value
+       required bool
+}
+
+func (p *parserMixin) SetValue(value Value) {
+       p.value = value
+}
+
+// StringMap provides key=value parsing into a map.
+func (p *parserMixin) StringMap() (target *map[string]string) {
+       target = &(map[string]string{})
+       p.StringMapVar(target)
+       return
+}
+
+// Duration sets the parser to a time.Duration parser.
+func (p *parserMixin) Duration() (target *time.Duration) {
+       target = new(time.Duration)
+       p.DurationVar(target)
+       return
+}
+
+// Bytes parses numeric byte units. eg. 1.5KB
+func (p *parserMixin) Bytes() (target *units.Base2Bytes) {
+       target = new(units.Base2Bytes)
+       p.BytesVar(target)
+       return
+}
+
+// IP sets the parser to a net.IP parser.
+func (p *parserMixin) IP() (target *net.IP) {
+       target = new(net.IP)
+       p.IPVar(target)
+       return
+}
+
+// TCP (host:port) address.
+func (p *parserMixin) TCP() (target **net.TCPAddr) {
+       target = new(*net.TCPAddr)
+       p.TCPVar(target)
+       return
+}
+
+// TCPVar (host:port) address.
+func (p *parserMixin) TCPVar(target **net.TCPAddr) {
+       p.SetValue(newTCPAddrValue(target))
+}
+
+// ExistingFile sets the parser to one that requires and returns an existing file.
+func (p *parserMixin) ExistingFile() (target *string) {
+       target = new(string)
+       p.ExistingFileVar(target)
+       return
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingDir() (target *string) {
+       target = new(string)
+       p.ExistingDirVar(target)
+       return
+}
+
+// ExistingFileOrDir sets the parser to one that requires and returns an existing file OR directory.
+func (p *parserMixin) ExistingFileOrDir() (target *string) {
+       target = new(string)
+       p.ExistingFileOrDirVar(target)
+       return
+}
+
+// File returns an os.File against an existing file.
+func (p *parserMixin) File() (target **os.File) {
+       target = new(*os.File)
+       p.FileVar(target)
+       return
+}
+
+// File attempts to open a File with os.OpenFile(flag, perm).
+func (p *parserMixin) OpenFile(flag int, perm os.FileMode) (target **os.File) {
+       target = new(*os.File)
+       p.OpenFileVar(target, flag, perm)
+       return
+}
+
+// URL provides a valid, parsed url.URL.
+func (p *parserMixin) URL() (target **url.URL) {
+       target = new(*url.URL)
+       p.URLVar(target)
+       return
+}
+
+// StringMap provides key=value parsing into a map.
+func (p *parserMixin) StringMapVar(target *map[string]string) {
+       p.SetValue(newStringMapValue(target))
+}
+
+// Float sets the parser to a float64 parser.
+func (p *parserMixin) Float() (target *float64) {
+       return p.Float64()
+}
+
+// Float sets the parser to a float64 parser.
+func (p *parserMixin) FloatVar(target *float64) {
+       p.Float64Var(target)
+}
+
+// Duration sets the parser to a time.Duration parser.
+func (p *parserMixin) DurationVar(target *time.Duration) {
+       p.SetValue(newDurationValue(target))
+}
+
+// BytesVar parses numeric byte units. eg. 1.5KB
+func (p *parserMixin) BytesVar(target *units.Base2Bytes) {
+       p.SetValue(newBytesValue(target))
+}
+
+// IP sets the parser to a net.IP parser.
+func (p *parserMixin) IPVar(target *net.IP) {
+       p.SetValue(newIPValue(target))
+}
+
+// ExistingFile sets the parser to one that requires and returns an existing file.
+func (p *parserMixin) ExistingFileVar(target *string) {
+       p.SetValue(newExistingFileValue(target))
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingDirVar(target *string) {
+       p.SetValue(newExistingDirValue(target))
+}
+
+// ExistingDir sets the parser to one that requires and returns an existing directory.
+func (p *parserMixin) ExistingFileOrDirVar(target *string) {
+       p.SetValue(newExistingFileOrDirValue(target))
+}
+
+// FileVar opens an existing file.
+func (p *parserMixin) FileVar(target **os.File) {
+       p.SetValue(newFileValue(target, os.O_RDONLY, 0))
+}
+
+// OpenFileVar calls os.OpenFile(flag, perm)
+func (p *parserMixin) OpenFileVar(target **os.File, flag int, perm os.FileMode) {
+       p.SetValue(newFileValue(target, flag, perm))
+}
+
+// URL provides a valid, parsed url.URL.
+func (p *parserMixin) URLVar(target **url.URL) {
+       p.SetValue(newURLValue(target))
+}
+
+// URLList provides a parsed list of url.URL values.
+func (p *parserMixin) URLList() (target *[]*url.URL) {
+       target = new([]*url.URL)
+       p.URLListVar(target)
+       return
+}
+
+// URLListVar provides a parsed list of url.URL values.
+func (p *parserMixin) URLListVar(target *[]*url.URL) {
+       p.SetValue(newURLListValue(target))
+}
+
+// Enum allows a value from a set of options.
+func (p *parserMixin) Enum(options ...string) (target *string) {
+       target = new(string)
+       p.EnumVar(target, options...)
+       return
+}
+
+// EnumVar allows a value from a set of options.
+func (p *parserMixin) EnumVar(target *string, options ...string) {
+       p.SetValue(newEnumFlag(target, options...))
+}
+
+// Enums allows a set of values from a set of options.
+func (p *parserMixin) Enums(options ...string) (target *[]string) {
+       target = new([]string)
+       p.EnumsVar(target, options...)
+       return
+}
+
+// EnumVar allows a value from a set of options.
+func (p *parserMixin) EnumsVar(target *[]string, options ...string) {
+       p.SetValue(newEnumsFlag(target, options...))
+}
+
+// A Counter increments a number each time it is encountered.
+func (p *parserMixin) Counter() (target *int) {
+       target = new(int)
+       p.CounterVar(target)
+       return
+}
+
+func (p *parserMixin) CounterVar(target *int) {
+       p.SetValue(newCounterValue(target))
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/templates.go b/vendor/gopkg.in/alecthomas/kingpin.v2/templates.go
new file mode 100644 (file)
index 0000000..97b5c9f
--- /dev/null
@@ -0,0 +1,262 @@
+package kingpin
+
+// Default usage template.
+var DefaultUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+{{if len .Context.SelectedCommand.Commands}}\
+Subcommands:
+{{template "FormatCommands" .Context.SelectedCommand}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+// Usage template where command's optional flags are listed separately
+var SeparateOptionalFlagsUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+  {{.FullCommand}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+
+{{if .Context.Flags|RequiredFlags}}\
+Required flags:
+{{.Context.Flags|RequiredFlags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if  .Context.Flags|OptionalFlags}}\
+Optional flags:
+{{.Context.Flags|OptionalFlags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+Subcommands:
+{{if .Context.SelectedCommand.Commands}}\
+{{template "FormatCommands" .Context.SelectedCommand}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+// Usage template with compactly formatted commands.
+var CompactUsageTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommandList"}}\
+{{range .}}\
+{{if not .Hidden}}\
+{{.Depth|Indent}}{{.Name}}{{if .Default}}*{{end}}{{template "FormatCommand" .}}
+{{end}}\
+{{template "FormatCommandList" .Commands}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+{{if .Context.SelectedCommand}}\
+usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
+{{else}}\
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{end}}\
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.SelectedCommand}}\
+{{if .Context.SelectedCommand.Commands}}\
+Commands:
+  {{.Context.SelectedCommand}}
+{{template "FormatCommandList" .Context.SelectedCommand.Commands}}
+{{end}}\
+{{else if .App.Commands}}\
+Commands:
+{{template "FormatCommandList" .App.Commands}}
+{{end}}\
+`
+
+var ManPageTemplate = `{{define "FormatFlags"}}\
+{{range .Flags}}\
+{{if not .Hidden}}\
+.TP
+\fB{{if .Short}}-{{.Short|Char}}, {{end}}--{{.Name}}{{if not .IsBoolFlag}}={{.FormatPlaceHolder}}{{end}}\\fR
+{{.Help}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}{{if .Default}}*{{end}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+.SS
+\fB{{.FullCommand}}{{template "FormatCommand" .}}\\fR
+.PP
+{{.Help}}
+{{template "FormatFlags" .}}\
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}\\fR
+{{end}}\
+
+.TH {{.App.Name}} 1 {{.App.Version}} "{{.App.Author}}"
+.SH "NAME"
+{{.App.Name}}
+.SH "SYNOPSIS"
+.TP
+\fB{{.App.Name}}{{template "FormatUsage" .App}}
+.SH "DESCRIPTION"
+{{.App.Help}}
+.SH "OPTIONS"
+{{template "FormatFlags" .App}}\
+{{if .App.Commands}}\
+.SH "COMMANDS"
+{{template "FormatCommands" .App}}\
+{{end}}\
+`
+
+// Default usage template.
+var LongHelpTemplate = `{{define "FormatCommand"}}\
+{{if .FlagSummary}} {{.FlagSummary}}{{end}}\
+{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end}}\
+{{end}}\
+
+{{define "FormatCommands"}}\
+{{range .FlattenedCommands}}\
+{{if not .Hidden}}\
+  {{.FullCommand}}{{template "FormatCommand" .}}
+{{.Help|Wrap 4}}
+{{with .Flags|FlagsToTwoColumns}}{{FormatTwoColumnsWithIndent . 4 2}}{{end}}
+{{end}}\
+{{end}}\
+{{end}}\
+
+{{define "FormatUsage"}}\
+{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
+{{if .Help}}
+{{.Help|Wrap 0}}\
+{{end}}\
+
+{{end}}\
+
+usage: {{.App.Name}}{{template "FormatUsage" .App}}
+{{if .Context.Flags}}\
+Flags:
+{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .Context.Args}}\
+Args:
+{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
+{{end}}\
+{{if .App.Commands}}\
+Commands:
+{{template "FormatCommands" .App}}
+{{end}}\
+`
+
+var BashCompletionTemplate = `
+_{{.App.Name}}_bash_autocomplete() {
+    local cur prev opts base
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
+    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+    return 0
+}
+complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
+
+`
+
+var ZshCompletionTemplate = `
+#compdef {{.App.Name}}
+autoload -U compinit && compinit
+autoload -U bashcompinit && bashcompinit
+
+_{{.App.Name}}_bash_autocomplete() {
+    local cur prev opts base
+    COMPREPLY=()
+    cur="${COMP_WORDS[COMP_CWORD]}"
+    opts=$( ${COMP_WORDS[0]} --completion-bash ${COMP_WORDS[@]:1:$COMP_CWORD} )
+    COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+    return 0
+}
+complete -F _{{.App.Name}}_bash_autocomplete {{.App.Name}}
+`
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/usage.go b/vendor/gopkg.in/alecthomas/kingpin.v2/usage.go
new file mode 100644 (file)
index 0000000..44af6f6
--- /dev/null
@@ -0,0 +1,211 @@
+package kingpin
+
+import (
+       "bytes"
+       "fmt"
+       "go/doc"
+       "io"
+       "strings"
+
+       "github.com/alecthomas/template"
+)
+
+var (
+       preIndent = "  "
+)
+
+func formatTwoColumns(w io.Writer, indent, padding, width int, rows [][2]string) {
+       // Find size of first column.
+       s := 0
+       for _, row := range rows {
+               if c := len(row[0]); c > s && c < 30 {
+                       s = c
+               }
+       }
+
+       indentStr := strings.Repeat(" ", indent)
+       offsetStr := strings.Repeat(" ", s+padding)
+
+       for _, row := range rows {
+               buf := bytes.NewBuffer(nil)
+               doc.ToText(buf, row[1], "", preIndent, width-s-padding-indent)
+               lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n")
+               fmt.Fprintf(w, "%s%-*s%*s", indentStr, s, row[0], padding, "")
+               if len(row[0]) >= 30 {
+                       fmt.Fprintf(w, "\n%s%s", indentStr, offsetStr)
+               }
+               fmt.Fprintf(w, "%s\n", lines[0])
+               for _, line := range lines[1:] {
+                       fmt.Fprintf(w, "%s%s%s\n", indentStr, offsetStr, line)
+               }
+       }
+}
+
+// Usage writes application usage to w. It parses args to determine
+// appropriate help context, such as which command to show help for.
+func (a *Application) Usage(args []string) {
+       context, err := a.parseContext(true, args)
+       a.FatalIfError(err, "")
+       if err := a.UsageForContextWithTemplate(context, 2, a.usageTemplate); err != nil {
+               panic(err)
+       }
+}
+
+func formatAppUsage(app *ApplicationModel) string {
+       s := []string{app.Name}
+       if len(app.Flags) > 0 {
+               s = append(s, app.FlagSummary())
+       }
+       if len(app.Args) > 0 {
+               s = append(s, app.ArgSummary())
+       }
+       return strings.Join(s, " ")
+}
+
+func formatCmdUsage(app *ApplicationModel, cmd *CmdModel) string {
+       s := []string{app.Name, cmd.String()}
+       if len(app.Flags) > 0 {
+               s = append(s, app.FlagSummary())
+       }
+       if len(app.Args) > 0 {
+               s = append(s, app.ArgSummary())
+       }
+       return strings.Join(s, " ")
+}
+
+func formatFlag(haveShort bool, flag *FlagModel) string {
+       flagString := ""
+       if flag.Short != 0 {
+               flagString += fmt.Sprintf("-%c, --%s", flag.Short, flag.Name)
+       } else {
+               if haveShort {
+                       flagString += fmt.Sprintf("    --%s", flag.Name)
+               } else {
+                       flagString += fmt.Sprintf("--%s", flag.Name)
+               }
+       }
+       if !flag.IsBoolFlag() {
+               flagString += fmt.Sprintf("=%s", flag.FormatPlaceHolder())
+       }
+       if v, ok := flag.Value.(repeatableFlag); ok && v.IsCumulative() {
+               flagString += " ..."
+       }
+       return flagString
+}
+
+type templateParseContext struct {
+       SelectedCommand *CmdModel
+       *FlagGroupModel
+       *ArgGroupModel
+}
+
+type templateContext struct {
+       App     *ApplicationModel
+       Width   int
+       Context *templateParseContext
+}
+
+// UsageForContext displays usage information from a ParseContext (obtained from
+// Application.ParseContext() or Action(f) callbacks).
+func (a *Application) UsageForContext(context *ParseContext) error {
+       return a.UsageForContextWithTemplate(context, 2, a.usageTemplate)
+}
+
+// UsageForContextWithTemplate is the base usage function. You generally don't need to use this.
+func (a *Application) UsageForContextWithTemplate(context *ParseContext, indent int, tmpl string) error {
+       width := guessWidth(a.usageWriter)
+       funcs := template.FuncMap{
+               "Indent": func(level int) string {
+                       return strings.Repeat(" ", level*indent)
+               },
+               "Wrap": func(indent int, s string) string {
+                       buf := bytes.NewBuffer(nil)
+                       indentText := strings.Repeat(" ", indent)
+                       doc.ToText(buf, s, indentText, "  "+indentText, width-indent)
+                       return buf.String()
+               },
+               "FormatFlag": formatFlag,
+               "FlagsToTwoColumns": func(f []*FlagModel) [][2]string {
+                       rows := [][2]string{}
+                       haveShort := false
+                       for _, flag := range f {
+                               if flag.Short != 0 {
+                                       haveShort = true
+                                       break
+                               }
+                       }
+                       for _, flag := range f {
+                               if !flag.Hidden {
+                                       rows = append(rows, [2]string{formatFlag(haveShort, flag), flag.Help})
+                               }
+                       }
+                       return rows
+               },
+               "RequiredFlags": func(f []*FlagModel) []*FlagModel {
+                       requiredFlags := []*FlagModel{}
+                       for _, flag := range f {
+                               if flag.Required {
+                                       requiredFlags = append(requiredFlags, flag)
+                               }
+                       }
+                       return requiredFlags
+               },
+               "OptionalFlags": func(f []*FlagModel) []*FlagModel {
+                       optionalFlags := []*FlagModel{}
+                       for _, flag := range f {
+                               if !flag.Required {
+                                       optionalFlags = append(optionalFlags, flag)
+                               }
+                       }
+                       return optionalFlags
+               },
+               "ArgsToTwoColumns": func(a []*ArgModel) [][2]string {
+                       rows := [][2]string{}
+                       for _, arg := range a {
+                               s := "<" + arg.Name + ">"
+                               if !arg.Required {
+                                       s = "[" + s + "]"
+                               }
+                               rows = append(rows, [2]string{s, arg.Help})
+                       }
+                       return rows
+               },
+               "FormatTwoColumns": func(rows [][2]string) string {
+                       buf := bytes.NewBuffer(nil)
+                       formatTwoColumns(buf, indent, indent, width, rows)
+                       return buf.String()
+               },
+               "FormatTwoColumnsWithIndent": func(rows [][2]string, indent, padding int) string {
+                       buf := bytes.NewBuffer(nil)
+                       formatTwoColumns(buf, indent, padding, width, rows)
+                       return buf.String()
+               },
+               "FormatAppUsage":     formatAppUsage,
+               "FormatCommandUsage": formatCmdUsage,
+               "IsCumulative": func(value Value) bool {
+                       r, ok := value.(remainderArg)
+                       return ok && r.IsCumulative()
+               },
+               "Char": func(c rune) string {
+                       return string(c)
+               },
+       }
+       t, err := template.New("usage").Funcs(funcs).Parse(tmpl)
+       if err != nil {
+               return err
+       }
+       var selectedCommand *CmdModel
+       if context.SelectedCommand != nil {
+               selectedCommand = context.SelectedCommand.Model()
+       }
+       ctx := templateContext{
+               App:   a.Model(),
+               Width: width,
+               Context: &templateParseContext{
+                       SelectedCommand: selectedCommand,
+                       FlagGroupModel:  context.flags.Model(),
+                       ArgGroupModel:   context.arguments.Model(),
+               },
+       }
+       return t.Execute(a.usageWriter, ctx)
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/values.go b/vendor/gopkg.in/alecthomas/kingpin.v2/values.go
new file mode 100644 (file)
index 0000000..7ee9a3b
--- /dev/null
@@ -0,0 +1,470 @@
+package kingpin
+
+//go:generate go run ./cmd/genvalues/main.go
+
+import (
+       "fmt"
+       "net"
+       "net/url"
+       "os"
+       "reflect"
+       "regexp"
+       "strings"
+       "time"
+
+       "github.com/alecthomas/units"
+)
+
+// NOTE: Most of the base type values were lifted from:
+// http://golang.org/src/pkg/flag/flag.go?s=20146:20222
+
+// Value is the interface to the dynamic value stored in a flag.
+// (The default value is represented as a string.)
+//
+// If a Value has an IsBoolFlag() bool method returning true, the command-line
+// parser makes --name equivalent to -name=true rather than using the next
+// command-line argument, and adds a --no-name counterpart for negating the
+// flag.
+type Value interface {
+       String() string
+       Set(string) error
+}
+
+// Getter is an interface that allows the contents of a Value to be retrieved.
+// It wraps the Value interface, rather than being part of it, because it
+// appeared after Go 1 and its compatibility rules. All Value types provided
+// by this package satisfy the Getter interface.
+type Getter interface {
+       Value
+       Get() interface{}
+}
+
+// Optional interface to indicate boolean flags that don't accept a value, and
+// implicitly have a --no-<x> negation counterpart.
+type boolFlag interface {
+       Value
+       IsBoolFlag() bool
+}
+
+// Optional interface for arguments that cumulatively consume all remaining
+// input.
+type remainderArg interface {
+       Value
+       IsCumulative() bool
+}
+
+// Optional interface for flags that can be repeated.
+type repeatableFlag interface {
+       Value
+       IsCumulative() bool
+}
+
+type accumulator struct {
+       element func(value interface{}) Value
+       typ     reflect.Type
+       slice   reflect.Value
+}
+
+// Use reflection to accumulate values into a slice.
+//
+// target := []string{}
+// newAccumulator(&target, func (value interface{}) Value {
+//   return newStringValue(value.(*string))
+// })
+func newAccumulator(slice interface{}, element func(value interface{}) Value) *accumulator {
+       typ := reflect.TypeOf(slice)
+       if typ.Kind() != reflect.Ptr || typ.Elem().Kind() != reflect.Slice {
+               panic("expected a pointer to a slice")
+       }
+       return &accumulator{
+               element: element,
+               typ:     typ.Elem().Elem(),
+               slice:   reflect.ValueOf(slice),
+       }
+}
+
+func (a *accumulator) String() string {
+       out := []string{}
+       s := a.slice.Elem()
+       for i := 0; i < s.Len(); i++ {
+               out = append(out, a.element(s.Index(i).Addr().Interface()).String())
+       }
+       return strings.Join(out, ",")
+}
+
+func (a *accumulator) Set(value string) error {
+       e := reflect.New(a.typ)
+       if err := a.element(e.Interface()).Set(value); err != nil {
+               return err
+       }
+       slice := reflect.Append(a.slice.Elem(), e.Elem())
+       a.slice.Elem().Set(slice)
+       return nil
+}
+
+func (a *accumulator) Get() interface{} {
+       return a.slice.Interface()
+}
+
+func (a *accumulator) IsCumulative() bool {
+       return true
+}
+
+func (b *boolValue) IsBoolFlag() bool { return true }
+
+// -- time.Duration Value
+type durationValue time.Duration
+
+func newDurationValue(p *time.Duration) *durationValue {
+       return (*durationValue)(p)
+}
+
+func (d *durationValue) Set(s string) error {
+       v, err := time.ParseDuration(s)
+       *d = durationValue(v)
+       return err
+}
+
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
+
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
+
+// -- map[string]string Value
+type stringMapValue map[string]string
+
+func newStringMapValue(p *map[string]string) *stringMapValue {
+       return (*stringMapValue)(p)
+}
+
+var stringMapRegex = regexp.MustCompile("[:=]")
+
+func (s *stringMapValue) Set(value string) error {
+       parts := stringMapRegex.Split(value, 2)
+       if len(parts) != 2 {
+               return fmt.Errorf("expected KEY=VALUE got '%s'", value)
+       }
+       (*s)[parts[0]] = parts[1]
+       return nil
+}
+
+func (s *stringMapValue) Get() interface{} {
+       return (map[string]string)(*s)
+}
+
+func (s *stringMapValue) String() string {
+       return fmt.Sprintf("%s", map[string]string(*s))
+}
+
+func (s *stringMapValue) IsCumulative() bool {
+       return true
+}
+
+// -- net.IP Value
+type ipValue net.IP
+
+func newIPValue(p *net.IP) *ipValue {
+       return (*ipValue)(p)
+}
+
+func (i *ipValue) Set(value string) error {
+       if ip := net.ParseIP(value); ip == nil {
+               return fmt.Errorf("'%s' is not an IP address", value)
+       } else {
+               *i = *(*ipValue)(&ip)
+               return nil
+       }
+}
+
+func (i *ipValue) Get() interface{} {
+       return (net.IP)(*i)
+}
+
+func (i *ipValue) String() string {
+       return (*net.IP)(i).String()
+}
+
+// -- *net.TCPAddr Value
+type tcpAddrValue struct {
+       addr **net.TCPAddr
+}
+
+func newTCPAddrValue(p **net.TCPAddr) *tcpAddrValue {
+       return &tcpAddrValue{p}
+}
+
+func (i *tcpAddrValue) Set(value string) error {
+       if addr, err := net.ResolveTCPAddr("tcp", value); err != nil {
+               return fmt.Errorf("'%s' is not a valid TCP address: %s", value, err)
+       } else {
+               *i.addr = addr
+               return nil
+       }
+}
+
+func (t *tcpAddrValue) Get() interface{} {
+       return (*net.TCPAddr)(*t.addr)
+}
+
+func (i *tcpAddrValue) String() string {
+       return (*i.addr).String()
+}
+
+// -- existingFile Value
+
+type fileStatValue struct {
+       path      *string
+       predicate func(os.FileInfo) error
+}
+
+func newFileStatValue(p *string, predicate func(os.FileInfo) error) *fileStatValue {
+       return &fileStatValue{
+               path:      p,
+               predicate: predicate,
+       }
+}
+
+func (e *fileStatValue) Set(value string) error {
+       if s, err := os.Stat(value); os.IsNotExist(err) {
+               return fmt.Errorf("path '%s' does not exist", value)
+       } else if err != nil {
+               return err
+       } else if err := e.predicate(s); err != nil {
+               return err
+       }
+       *e.path = value
+       return nil
+}
+
+func (f *fileStatValue) Get() interface{} {
+       return (string)(*f.path)
+}
+
+func (e *fileStatValue) String() string {
+       return *e.path
+}
+
+// -- os.File value
+
+type fileValue struct {
+       f    **os.File
+       flag int
+       perm os.FileMode
+}
+
+func newFileValue(p **os.File, flag int, perm os.FileMode) *fileValue {
+       return &fileValue{p, flag, perm}
+}
+
+func (f *fileValue) Set(value string) error {
+       if fd, err := os.OpenFile(value, f.flag, f.perm); err != nil {
+               return err
+       } else {
+               *f.f = fd
+               return nil
+       }
+}
+
+func (f *fileValue) Get() interface{} {
+       return (*os.File)(*f.f)
+}
+
+func (f *fileValue) String() string {
+       if *f.f == nil {
+               return "<nil>"
+       }
+       return (*f.f).Name()
+}
+
+// -- url.URL Value
+type urlValue struct {
+       u **url.URL
+}
+
+func newURLValue(p **url.URL) *urlValue {
+       return &urlValue{p}
+}
+
+func (u *urlValue) Set(value string) error {
+       if url, err := url.Parse(value); err != nil {
+               return fmt.Errorf("invalid URL: %s", err)
+       } else {
+               *u.u = url
+               return nil
+       }
+}
+
+func (u *urlValue) Get() interface{} {
+       return (*url.URL)(*u.u)
+}
+
+func (u *urlValue) String() string {
+       if *u.u == nil {
+               return "<nil>"
+       }
+       return (*u.u).String()
+}
+
+// -- []*url.URL Value
+type urlListValue []*url.URL
+
+func newURLListValue(p *[]*url.URL) *urlListValue {
+       return (*urlListValue)(p)
+}
+
+func (u *urlListValue) Set(value string) error {
+       if url, err := url.Parse(value); err != nil {
+               return fmt.Errorf("invalid URL: %s", err)
+       } else {
+               *u = append(*u, url)
+               return nil
+       }
+}
+
+func (u *urlListValue) Get() interface{} {
+       return ([]*url.URL)(*u)
+}
+
+func (u *urlListValue) String() string {
+       out := []string{}
+       for _, url := range *u {
+               out = append(out, url.String())
+       }
+       return strings.Join(out, ",")
+}
+
+func (u *urlListValue) IsCumulative() bool {
+       return true
+}
+
+// A flag whose value must be in a set of options.
+type enumValue struct {
+       value   *string
+       options []string
+}
+
+func newEnumFlag(target *string, options ...string) *enumValue {
+       return &enumValue{
+               value:   target,
+               options: options,
+       }
+}
+
+func (a *enumValue) String() string {
+       return *a.value
+}
+
+func (a *enumValue) Set(value string) error {
+       for _, v := range a.options {
+               if v == value {
+                       *a.value = value
+                       return nil
+               }
+       }
+       return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(a.options, ","), value)
+}
+
+func (e *enumValue) Get() interface{} {
+       return (string)(*e.value)
+}
+
+// -- []string Enum Value
+type enumsValue struct {
+       value   *[]string
+       options []string
+}
+
+func newEnumsFlag(target *[]string, options ...string) *enumsValue {
+       return &enumsValue{
+               value:   target,
+               options: options,
+       }
+}
+
+func (s *enumsValue) Set(value string) error {
+       for _, v := range s.options {
+               if v == value {
+                       *s.value = append(*s.value, value)
+                       return nil
+               }
+       }
+       return fmt.Errorf("enum value must be one of %s, got '%s'", strings.Join(s.options, ","), value)
+}
+
+func (e *enumsValue) Get() interface{} {
+       return ([]string)(*e.value)
+}
+
+func (s *enumsValue) String() string {
+       return strings.Join(*s.value, ",")
+}
+
+func (s *enumsValue) IsCumulative() bool {
+       return true
+}
+
+// -- units.Base2Bytes Value
+type bytesValue units.Base2Bytes
+
+func newBytesValue(p *units.Base2Bytes) *bytesValue {
+       return (*bytesValue)(p)
+}
+
+func (d *bytesValue) Set(s string) error {
+       v, err := units.ParseBase2Bytes(s)
+       *d = bytesValue(v)
+       return err
+}
+
+func (d *bytesValue) Get() interface{} { return units.Base2Bytes(*d) }
+
+func (d *bytesValue) String() string { return (*units.Base2Bytes)(d).String() }
+
+func newExistingFileValue(target *string) *fileStatValue {
+       return newFileStatValue(target, func(s os.FileInfo) error {
+               if s.IsDir() {
+                       return fmt.Errorf("'%s' is a directory", s.Name())
+               }
+               return nil
+       })
+}
+
+func newExistingDirValue(target *string) *fileStatValue {
+       return newFileStatValue(target, func(s os.FileInfo) error {
+               if !s.IsDir() {
+                       return fmt.Errorf("'%s' is a file", s.Name())
+               }
+               return nil
+       })
+}
+
+func newExistingFileOrDirValue(target *string) *fileStatValue {
+       return newFileStatValue(target, func(s os.FileInfo) error { return nil })
+}
+
+type counterValue int
+
+func newCounterValue(n *int) *counterValue {
+       return (*counterValue)(n)
+}
+
+func (c *counterValue) Set(s string) error {
+       *c++
+       return nil
+}
+
+func (c *counterValue) Get() interface{}   { return (int)(*c) }
+func (c *counterValue) IsBoolFlag() bool   { return true }
+func (c *counterValue) String() string     { return fmt.Sprintf("%d", *c) }
+func (c *counterValue) IsCumulative() bool { return true }
+
+func resolveHost(value string) (net.IP, error) {
+       if ip := net.ParseIP(value); ip != nil {
+               return ip, nil
+       } else {
+               if addr, err := net.ResolveIPAddr("ip", value); err != nil {
+                       return nil, err
+               } else {
+                       return addr.IP, nil
+               }
+       }
+}
diff --git a/vendor/gopkg.in/alecthomas/kingpin.v2/values.json b/vendor/gopkg.in/alecthomas/kingpin.v2/values.json
new file mode 100644 (file)
index 0000000..23c6744
--- /dev/null
@@ -0,0 +1,25 @@
+[
+  {"type": "bool", "parser": "strconv.ParseBool(s)"},
+  {"type": "string", "parser": "s, error(nil)", "format": "string(*f.v)", "plural": "Strings"},
+  {"type": "uint", "parser": "strconv.ParseUint(s, 0, 64)", "plural": "Uints"},
+  {"type": "uint8", "parser": "strconv.ParseUint(s, 0, 8)"},
+  {"type": "uint16", "parser": "strconv.ParseUint(s, 0, 16)"},
+  {"type": "uint32", "parser": "strconv.ParseUint(s, 0, 32)"},
+  {"type": "uint64", "parser": "strconv.ParseUint(s, 0, 64)"},
+  {"type": "int", "parser": "strconv.ParseFloat(s, 64)", "plural": "Ints"},
+  {"type": "int8", "parser": "strconv.ParseInt(s, 0, 8)"},
+  {"type": "int16", "parser": "strconv.ParseInt(s, 0, 16)"},
+  {"type": "int32", "parser": "strconv.ParseInt(s, 0, 32)"},
+  {"type": "int64", "parser": "strconv.ParseInt(s, 0, 64)"},
+  {"type": "float64", "parser": "strconv.ParseFloat(s, 64)"},
+  {"type": "float32", "parser": "strconv.ParseFloat(s, 32)"},
+  {"name": "Duration", "type": "time.Duration", "no_value_parser": true},
+  {"name": "IP", "type": "net.IP", "no_value_parser": true},
+  {"name": "TCPAddr", "Type": "*net.TCPAddr", "plural": "TCPList", "no_value_parser": true},
+  {"name": "ExistingFile", "Type": "string", "plural": "ExistingFiles", "no_value_parser": true},
+  {"name": "ExistingDir", "Type": "string", "plural": "ExistingDirs", "no_value_parser": true},
+  {"name": "ExistingFileOrDir", "Type": "string", "plural": "ExistingFilesOrDirs", "no_value_parser": true},
+  {"name": "Regexp", "Type": "*regexp.Regexp", "parser": "regexp.Compile(s)"},
+  {"name": "ResolvedIP", "Type": "net.IP", "parser": "resolveHost(s)", "help": "Resolve a hostname or IP to an IP."},
+  {"name": "HexBytes", "Type": "[]byte", "parser": "hex.DecodeString(s)", "help": "Bytes as a hex string."}
+]
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 (file)
index 0000000..602cfc9
--- /dev/null
@@ -0,0 +1,821 @@
+package kingpin
+
+import (
+       "encoding/hex"
+       "fmt"
+       "net"
+       "regexp"
+       "strconv"
+       "time"
+)
+
+// This file is autogenerated by "go generate .". Do not modify.
+
+// -- bool Value
+type boolValue struct{ v *bool }
+
+func newBoolValue(p *bool) *boolValue {
+       return &boolValue{p}
+}
+
+func (f *boolValue) Set(s string) error {
+       v, err := strconv.ParseBool(s)
+       if err == nil {
+               *f.v = (bool)(v)
+       }
+       return err
+}
+
+func (f *boolValue) Get() interface{} { return (bool)(*f.v) }
+
+func (f *boolValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Bool parses the next command-line value as bool.
+func (p *parserMixin) Bool() (target *bool) {
+       target = new(bool)
+       p.BoolVar(target)
+       return
+}
+
+func (p *parserMixin) BoolVar(target *bool) {
+       p.SetValue(newBoolValue(target))
+}
+
+// BoolList accumulates bool values into a slice.
+func (p *parserMixin) BoolList() (target *[]bool) {
+       target = new([]bool)
+       p.BoolListVar(target)
+       return
+}
+
+func (p *parserMixin) BoolListVar(target *[]bool) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newBoolValue(v.(*bool))
+       }))
+}
+
+// -- string Value
+type stringValue struct{ v *string }
+
+func newStringValue(p *string) *stringValue {
+       return &stringValue{p}
+}
+
+func (f *stringValue) Set(s string) error {
+       v, err := s, error(nil)
+       if err == nil {
+               *f.v = (string)(v)
+       }
+       return err
+}
+
+func (f *stringValue) Get() interface{} { return (string)(*f.v) }
+
+func (f *stringValue) String() string { return string(*f.v) }
+
+// String parses the next command-line value as string.
+func (p *parserMixin) String() (target *string) {
+       target = new(string)
+       p.StringVar(target)
+       return
+}
+
+func (p *parserMixin) StringVar(target *string) {
+       p.SetValue(newStringValue(target))
+}
+
+// Strings accumulates string values into a slice.
+func (p *parserMixin) Strings() (target *[]string) {
+       target = new([]string)
+       p.StringsVar(target)
+       return
+}
+
+func (p *parserMixin) StringsVar(target *[]string) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newStringValue(v.(*string))
+       }))
+}
+
+// -- uint Value
+type uintValue struct{ v *uint }
+
+func newUintValue(p *uint) *uintValue {
+       return &uintValue{p}
+}
+
+func (f *uintValue) Set(s string) error {
+       v, err := strconv.ParseUint(s, 0, 64)
+       if err == nil {
+               *f.v = (uint)(v)
+       }
+       return err
+}
+
+func (f *uintValue) Get() interface{} { return (uint)(*f.v) }
+
+func (f *uintValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Uint parses the next command-line value as uint.
+func (p *parserMixin) Uint() (target *uint) {
+       target = new(uint)
+       p.UintVar(target)
+       return
+}
+
+func (p *parserMixin) UintVar(target *uint) {
+       p.SetValue(newUintValue(target))
+}
+
+// Uints accumulates uint values into a slice.
+func (p *parserMixin) Uints() (target *[]uint) {
+       target = new([]uint)
+       p.UintsVar(target)
+       return
+}
+
+func (p *parserMixin) UintsVar(target *[]uint) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newUintValue(v.(*uint))
+       }))
+}
+
+// -- uint8 Value
+type uint8Value struct{ v *uint8 }
+
+func newUint8Value(p *uint8) *uint8Value {
+       return &uint8Value{p}
+}
+
+func (f *uint8Value) Set(s string) error {
+       v, err := strconv.ParseUint(s, 0, 8)
+       if err == nil {
+               *f.v = (uint8)(v)
+       }
+       return err
+}
+
+func (f *uint8Value) Get() interface{} { return (uint8)(*f.v) }
+
+func (f *uint8Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Uint8 parses the next command-line value as uint8.
+func (p *parserMixin) Uint8() (target *uint8) {
+       target = new(uint8)
+       p.Uint8Var(target)
+       return
+}
+
+func (p *parserMixin) Uint8Var(target *uint8) {
+       p.SetValue(newUint8Value(target))
+}
+
+// Uint8List accumulates uint8 values into a slice.
+func (p *parserMixin) Uint8List() (target *[]uint8) {
+       target = new([]uint8)
+       p.Uint8ListVar(target)
+       return
+}
+
+func (p *parserMixin) Uint8ListVar(target *[]uint8) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newUint8Value(v.(*uint8))
+       }))
+}
+
+// -- uint16 Value
+type uint16Value struct{ v *uint16 }
+
+func newUint16Value(p *uint16) *uint16Value {
+       return &uint16Value{p}
+}
+
+func (f *uint16Value) Set(s string) error {
+       v, err := strconv.ParseUint(s, 0, 16)
+       if err == nil {
+               *f.v = (uint16)(v)
+       }
+       return err
+}
+
+func (f *uint16Value) Get() interface{} { return (uint16)(*f.v) }
+
+func (f *uint16Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Uint16 parses the next command-line value as uint16.
+func (p *parserMixin) Uint16() (target *uint16) {
+       target = new(uint16)
+       p.Uint16Var(target)
+       return
+}
+
+func (p *parserMixin) Uint16Var(target *uint16) {
+       p.SetValue(newUint16Value(target))
+}
+
+// Uint16List accumulates uint16 values into a slice.
+func (p *parserMixin) Uint16List() (target *[]uint16) {
+       target = new([]uint16)
+       p.Uint16ListVar(target)
+       return
+}
+
+func (p *parserMixin) Uint16ListVar(target *[]uint16) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newUint16Value(v.(*uint16))
+       }))
+}
+
+// -- uint32 Value
+type uint32Value struct{ v *uint32 }
+
+func newUint32Value(p *uint32) *uint32Value {
+       return &uint32Value{p}
+}
+
+func (f *uint32Value) Set(s string) error {
+       v, err := strconv.ParseUint(s, 0, 32)
+       if err == nil {
+               *f.v = (uint32)(v)
+       }
+       return err
+}
+
+func (f *uint32Value) Get() interface{} { return (uint32)(*f.v) }
+
+func (f *uint32Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Uint32 parses the next command-line value as uint32.
+func (p *parserMixin) Uint32() (target *uint32) {
+       target = new(uint32)
+       p.Uint32Var(target)
+       return
+}
+
+func (p *parserMixin) Uint32Var(target *uint32) {
+       p.SetValue(newUint32Value(target))
+}
+
+// Uint32List accumulates uint32 values into a slice.
+func (p *parserMixin) Uint32List() (target *[]uint32) {
+       target = new([]uint32)
+       p.Uint32ListVar(target)
+       return
+}
+
+func (p *parserMixin) Uint32ListVar(target *[]uint32) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newUint32Value(v.(*uint32))
+       }))
+}
+
+// -- uint64 Value
+type uint64Value struct{ v *uint64 }
+
+func newUint64Value(p *uint64) *uint64Value {
+       return &uint64Value{p}
+}
+
+func (f *uint64Value) Set(s string) error {
+       v, err := strconv.ParseUint(s, 0, 64)
+       if err == nil {
+               *f.v = (uint64)(v)
+       }
+       return err
+}
+
+func (f *uint64Value) Get() interface{} { return (uint64)(*f.v) }
+
+func (f *uint64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Uint64 parses the next command-line value as uint64.
+func (p *parserMixin) Uint64() (target *uint64) {
+       target = new(uint64)
+       p.Uint64Var(target)
+       return
+}
+
+func (p *parserMixin) Uint64Var(target *uint64) {
+       p.SetValue(newUint64Value(target))
+}
+
+// Uint64List accumulates uint64 values into a slice.
+func (p *parserMixin) Uint64List() (target *[]uint64) {
+       target = new([]uint64)
+       p.Uint64ListVar(target)
+       return
+}
+
+func (p *parserMixin) Uint64ListVar(target *[]uint64) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newUint64Value(v.(*uint64))
+       }))
+}
+
+// -- int Value
+type intValue struct{ v *int }
+
+func newIntValue(p *int) *intValue {
+       return &intValue{p}
+}
+
+func (f *intValue) Set(s string) error {
+       v, err := strconv.ParseFloat(s, 64)
+       if err == nil {
+               *f.v = (int)(v)
+       }
+       return err
+}
+
+func (f *intValue) Get() interface{} { return (int)(*f.v) }
+
+func (f *intValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Int parses the next command-line value as int.
+func (p *parserMixin) Int() (target *int) {
+       target = new(int)
+       p.IntVar(target)
+       return
+}
+
+func (p *parserMixin) IntVar(target *int) {
+       p.SetValue(newIntValue(target))
+}
+
+// Ints accumulates int values into a slice.
+func (p *parserMixin) Ints() (target *[]int) {
+       target = new([]int)
+       p.IntsVar(target)
+       return
+}
+
+func (p *parserMixin) IntsVar(target *[]int) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newIntValue(v.(*int))
+       }))
+}
+
+// -- int8 Value
+type int8Value struct{ v *int8 }
+
+func newInt8Value(p *int8) *int8Value {
+       return &int8Value{p}
+}
+
+func (f *int8Value) Set(s string) error {
+       v, err := strconv.ParseInt(s, 0, 8)
+       if err == nil {
+               *f.v = (int8)(v)
+       }
+       return err
+}
+
+func (f *int8Value) Get() interface{} { return (int8)(*f.v) }
+
+func (f *int8Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Int8 parses the next command-line value as int8.
+func (p *parserMixin) Int8() (target *int8) {
+       target = new(int8)
+       p.Int8Var(target)
+       return
+}
+
+func (p *parserMixin) Int8Var(target *int8) {
+       p.SetValue(newInt8Value(target))
+}
+
+// Int8List accumulates int8 values into a slice.
+func (p *parserMixin) Int8List() (target *[]int8) {
+       target = new([]int8)
+       p.Int8ListVar(target)
+       return
+}
+
+func (p *parserMixin) Int8ListVar(target *[]int8) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newInt8Value(v.(*int8))
+       }))
+}
+
+// -- int16 Value
+type int16Value struct{ v *int16 }
+
+func newInt16Value(p *int16) *int16Value {
+       return &int16Value{p}
+}
+
+func (f *int16Value) Set(s string) error {
+       v, err := strconv.ParseInt(s, 0, 16)
+       if err == nil {
+               *f.v = (int16)(v)
+       }
+       return err
+}
+
+func (f *int16Value) Get() interface{} { return (int16)(*f.v) }
+
+func (f *int16Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Int16 parses the next command-line value as int16.
+func (p *parserMixin) Int16() (target *int16) {
+       target = new(int16)
+       p.Int16Var(target)
+       return
+}
+
+func (p *parserMixin) Int16Var(target *int16) {
+       p.SetValue(newInt16Value(target))
+}
+
+// Int16List accumulates int16 values into a slice.
+func (p *parserMixin) Int16List() (target *[]int16) {
+       target = new([]int16)
+       p.Int16ListVar(target)
+       return
+}
+
+func (p *parserMixin) Int16ListVar(target *[]int16) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newInt16Value(v.(*int16))
+       }))
+}
+
+// -- int32 Value
+type int32Value struct{ v *int32 }
+
+func newInt32Value(p *int32) *int32Value {
+       return &int32Value{p}
+}
+
+func (f *int32Value) Set(s string) error {
+       v, err := strconv.ParseInt(s, 0, 32)
+       if err == nil {
+               *f.v = (int32)(v)
+       }
+       return err
+}
+
+func (f *int32Value) Get() interface{} { return (int32)(*f.v) }
+
+func (f *int32Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Int32 parses the next command-line value as int32.
+func (p *parserMixin) Int32() (target *int32) {
+       target = new(int32)
+       p.Int32Var(target)
+       return
+}
+
+func (p *parserMixin) Int32Var(target *int32) {
+       p.SetValue(newInt32Value(target))
+}
+
+// Int32List accumulates int32 values into a slice.
+func (p *parserMixin) Int32List() (target *[]int32) {
+       target = new([]int32)
+       p.Int32ListVar(target)
+       return
+}
+
+func (p *parserMixin) Int32ListVar(target *[]int32) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newInt32Value(v.(*int32))
+       }))
+}
+
+// -- int64 Value
+type int64Value struct{ v *int64 }
+
+func newInt64Value(p *int64) *int64Value {
+       return &int64Value{p}
+}
+
+func (f *int64Value) Set(s string) error {
+       v, err := strconv.ParseInt(s, 0, 64)
+       if err == nil {
+               *f.v = (int64)(v)
+       }
+       return err
+}
+
+func (f *int64Value) Get() interface{} { return (int64)(*f.v) }
+
+func (f *int64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Int64 parses the next command-line value as int64.
+func (p *parserMixin) Int64() (target *int64) {
+       target = new(int64)
+       p.Int64Var(target)
+       return
+}
+
+func (p *parserMixin) Int64Var(target *int64) {
+       p.SetValue(newInt64Value(target))
+}
+
+// Int64List accumulates int64 values into a slice.
+func (p *parserMixin) Int64List() (target *[]int64) {
+       target = new([]int64)
+       p.Int64ListVar(target)
+       return
+}
+
+func (p *parserMixin) Int64ListVar(target *[]int64) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newInt64Value(v.(*int64))
+       }))
+}
+
+// -- float64 Value
+type float64Value struct{ v *float64 }
+
+func newFloat64Value(p *float64) *float64Value {
+       return &float64Value{p}
+}
+
+func (f *float64Value) Set(s string) error {
+       v, err := strconv.ParseFloat(s, 64)
+       if err == nil {
+               *f.v = (float64)(v)
+       }
+       return err
+}
+
+func (f *float64Value) Get() interface{} { return (float64)(*f.v) }
+
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Float64 parses the next command-line value as float64.
+func (p *parserMixin) Float64() (target *float64) {
+       target = new(float64)
+       p.Float64Var(target)
+       return
+}
+
+func (p *parserMixin) Float64Var(target *float64) {
+       p.SetValue(newFloat64Value(target))
+}
+
+// Float64List accumulates float64 values into a slice.
+func (p *parserMixin) Float64List() (target *[]float64) {
+       target = new([]float64)
+       p.Float64ListVar(target)
+       return
+}
+
+func (p *parserMixin) Float64ListVar(target *[]float64) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newFloat64Value(v.(*float64))
+       }))
+}
+
+// -- float32 Value
+type float32Value struct{ v *float32 }
+
+func newFloat32Value(p *float32) *float32Value {
+       return &float32Value{p}
+}
+
+func (f *float32Value) Set(s string) error {
+       v, err := strconv.ParseFloat(s, 32)
+       if err == nil {
+               *f.v = (float32)(v)
+       }
+       return err
+}
+
+func (f *float32Value) Get() interface{} { return (float32)(*f.v) }
+
+func (f *float32Value) String() string { return fmt.Sprintf("%v", *f) }
+
+// Float32 parses the next command-line value as float32.
+func (p *parserMixin) Float32() (target *float32) {
+       target = new(float32)
+       p.Float32Var(target)
+       return
+}
+
+func (p *parserMixin) Float32Var(target *float32) {
+       p.SetValue(newFloat32Value(target))
+}
+
+// Float32List accumulates float32 values into a slice.
+func (p *parserMixin) Float32List() (target *[]float32) {
+       target = new([]float32)
+       p.Float32ListVar(target)
+       return
+}
+
+func (p *parserMixin) Float32ListVar(target *[]float32) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newFloat32Value(v.(*float32))
+       }))
+}
+
+// DurationList accumulates time.Duration values into a slice.
+func (p *parserMixin) DurationList() (target *[]time.Duration) {
+       target = new([]time.Duration)
+       p.DurationListVar(target)
+       return
+}
+
+func (p *parserMixin) DurationListVar(target *[]time.Duration) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newDurationValue(v.(*time.Duration))
+       }))
+}
+
+// IPList accumulates net.IP values into a slice.
+func (p *parserMixin) IPList() (target *[]net.IP) {
+       target = new([]net.IP)
+       p.IPListVar(target)
+       return
+}
+
+func (p *parserMixin) IPListVar(target *[]net.IP) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newIPValue(v.(*net.IP))
+       }))
+}
+
+// TCPList accumulates *net.TCPAddr values into a slice.
+func (p *parserMixin) TCPList() (target *[]*net.TCPAddr) {
+       target = new([]*net.TCPAddr)
+       p.TCPListVar(target)
+       return
+}
+
+func (p *parserMixin) TCPListVar(target *[]*net.TCPAddr) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newTCPAddrValue(v.(**net.TCPAddr))
+       }))
+}
+
+// ExistingFiles accumulates string values into a slice.
+func (p *parserMixin) ExistingFiles() (target *[]string) {
+       target = new([]string)
+       p.ExistingFilesVar(target)
+       return
+}
+
+func (p *parserMixin) ExistingFilesVar(target *[]string) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newExistingFileValue(v.(*string))
+       }))
+}
+
+// ExistingDirs accumulates string values into a slice.
+func (p *parserMixin) ExistingDirs() (target *[]string) {
+       target = new([]string)
+       p.ExistingDirsVar(target)
+       return
+}
+
+func (p *parserMixin) ExistingDirsVar(target *[]string) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newExistingDirValue(v.(*string))
+       }))
+}
+
+// ExistingFilesOrDirs accumulates string values into a slice.
+func (p *parserMixin) ExistingFilesOrDirs() (target *[]string) {
+       target = new([]string)
+       p.ExistingFilesOrDirsVar(target)
+       return
+}
+
+func (p *parserMixin) ExistingFilesOrDirsVar(target *[]string) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newExistingFileOrDirValue(v.(*string))
+       }))
+}
+
+// -- *regexp.Regexp Value
+type regexpValue struct{ v **regexp.Regexp }
+
+func newRegexpValue(p **regexp.Regexp) *regexpValue {
+       return &regexpValue{p}
+}
+
+func (f *regexpValue) Set(s string) error {
+       v, err := regexp.Compile(s)
+       if err == nil {
+               *f.v = (*regexp.Regexp)(v)
+       }
+       return err
+}
+
+func (f *regexpValue) Get() interface{} { return (*regexp.Regexp)(*f.v) }
+
+func (f *regexpValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Regexp parses the next command-line value as *regexp.Regexp.
+func (p *parserMixin) Regexp() (target **regexp.Regexp) {
+       target = new(*regexp.Regexp)
+       p.RegexpVar(target)
+       return
+}
+
+func (p *parserMixin) RegexpVar(target **regexp.Regexp) {
+       p.SetValue(newRegexpValue(target))
+}
+
+// RegexpList accumulates *regexp.Regexp values into a slice.
+func (p *parserMixin) RegexpList() (target *[]*regexp.Regexp) {
+       target = new([]*regexp.Regexp)
+       p.RegexpListVar(target)
+       return
+}
+
+func (p *parserMixin) RegexpListVar(target *[]*regexp.Regexp) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newRegexpValue(v.(**regexp.Regexp))
+       }))
+}
+
+// -- net.IP Value
+type resolvedIPValue struct{ v *net.IP }
+
+func newResolvedIPValue(p *net.IP) *resolvedIPValue {
+       return &resolvedIPValue{p}
+}
+
+func (f *resolvedIPValue) Set(s string) error {
+       v, err := resolveHost(s)
+       if err == nil {
+               *f.v = (net.IP)(v)
+       }
+       return err
+}
+
+func (f *resolvedIPValue) Get() interface{} { return (net.IP)(*f.v) }
+
+func (f *resolvedIPValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Resolve a hostname or IP to an IP.
+func (p *parserMixin) ResolvedIP() (target *net.IP) {
+       target = new(net.IP)
+       p.ResolvedIPVar(target)
+       return
+}
+
+func (p *parserMixin) ResolvedIPVar(target *net.IP) {
+       p.SetValue(newResolvedIPValue(target))
+}
+
+// ResolvedIPList accumulates net.IP values into a slice.
+func (p *parserMixin) ResolvedIPList() (target *[]net.IP) {
+       target = new([]net.IP)
+       p.ResolvedIPListVar(target)
+       return
+}
+
+func (p *parserMixin) ResolvedIPListVar(target *[]net.IP) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newResolvedIPValue(v.(*net.IP))
+       }))
+}
+
+// -- []byte Value
+type hexBytesValue struct{ v *[]byte }
+
+func newHexBytesValue(p *[]byte) *hexBytesValue {
+       return &hexBytesValue{p}
+}
+
+func (f *hexBytesValue) Set(s string) error {
+       v, err := hex.DecodeString(s)
+       if err == nil {
+               *f.v = ([]byte)(v)
+       }
+       return err
+}
+
+func (f *hexBytesValue) Get() interface{} { return ([]byte)(*f.v) }
+
+func (f *hexBytesValue) String() string { return fmt.Sprintf("%v", *f) }
+
+// Bytes as a hex string.
+func (p *parserMixin) HexBytes() (target *[]byte) {
+       target = new([]byte)
+       p.HexBytesVar(target)
+       return
+}
+
+func (p *parserMixin) HexBytesVar(target *[]byte) {
+       p.SetValue(newHexBytesValue(target))
+}
+
+// HexBytesList accumulates []byte values into a slice.
+func (p *parserMixin) HexBytesList() (target *[][]byte) {
+       target = new([][]byte)
+       p.HexBytesListVar(target)
+       return
+}
+
+func (p *parserMixin) HexBytesListVar(target *[][]byte) {
+       p.SetValue(newAccumulator(target, func(v interface{}) Value {
+               return newHexBytesValue(v.(*[]byte))
+       }))
+}
index ab3806387922bcfec4f2a8b956ffcaa2729ee144..01784b9597aa5946199e51056095b7f29c077ec3 100644 (file)
                        "revision": "4b6ea7319e214d98c938f12692336f7ca9348d6b",
                        "revisionTime": "2016-03-17T14:11:10Z"
                },
+               {
+                       "checksumSHA1": "KmjnydoAbofMieIWm+it5OWERaM=",
+                       "path": "github.com/alecthomas/template",
+                       "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
+                       "revisionTime": "2016-04-05T07:15:01Z"
+               },
+               {
+                       "checksumSHA1": "3wt0pTXXeS+S93unwhGoLIyGX/Q=",
+                       "path": "github.com/alecthomas/template/parse",
+                       "revision": "a0175ee3bccc567396460bf5acd36800cb10c49c",
+                       "revisionTime": "2016-04-05T07:15:01Z"
+               },
+               {
+                       "checksumSHA1": "fCc3grA7vIxfBru7R3SqjcW+oLI=",
+                       "path": "github.com/alecthomas/units",
+                       "revision": "2efee857e7cfd4f3d0138cc3cbb1b4966962b93a",
+                       "revisionTime": "2015-10-22T06:55:26Z"
+               },
                {
                        "checksumSHA1": "4QnLdmB1kG3N+KlDd1N+G9TWAGQ=",
                        "path": "github.com/beorn7/perks/quantile",
                        "revision": "cfdf022e86b4ecfb646e1efbd7db175dd623a8fa",
                        "revisionTime": "2017-06-28T09:51:01Z"
                },
+               {
+                       "checksumSHA1": "ZvPW/nSYs/UeoZejaV2ZSm9+2Do=",
+                       "path": "gopkg.in/alecthomas/kingpin.v2",
+                       "revision": "7f0871f2e17818990e4eed73f9b5c2f429501228",
+                       "revisionTime": "2017-03-28T23:38:35Z"
+               },
                {
                        "checksumSHA1": "+OgOXBoiQ+X+C2dsAeiOHwBIEH0=",
                        "path": "gopkg.in/yaml.v2",