Browse Source

vendor: Add github.com/AudriusButkevicius/cli

Jakob Borg 9 years ago
parent
commit
9fdaa637a8

+ 21 - 0
vendor/github.com/AudriusButkevicius/cli/LICENSE

@@ -0,0 +1,21 @@
+Copyright (C) 2013 Jeremy Saenz
+All Rights Reserved.
+
+MIT LICENSE
+
+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.

+ 256 - 0
vendor/github.com/AudriusButkevicius/cli/app.go

@@ -0,0 +1,256 @@
+package cli
+
+import (
+	"fmt"
+	"io/ioutil"
+	"os"
+	"time"
+)
+
+// App is the main structure of a cli application. It is recomended that
+// and app be created with the cli.NewApp() function
+type App struct {
+	// The name of the program. Defaults to os.Args[0]
+	Name string
+	// Description of the program.
+	Usage string
+	// Version of the program
+	Version string
+	// List of commands to execute
+	Commands []Command
+	// List of flags to parse
+	Flags []Flag
+	// Boolean to enable bash completion commands
+	EnableBashCompletion bool
+	// Boolean to hide built-in help command
+	HideHelp bool
+	// An action to execute when the bash-completion flag is set
+	BashComplete func(context *Context)
+	// An action to execute before any subcommands are run, but after the context is ready
+	// If a non-nil error is returned, no subcommands are run
+	Before func(context *Context) error
+	// The action to execute when no subcommands are specified
+	Action func(context *Context)
+	// Execute this function if the proper command cannot be found
+	CommandNotFound func(context *Context, command string)
+	// Compilation date
+	Compiled time.Time
+	// Author
+	Author string
+	// Author e-mail
+	Email string
+	// Command argument requirements
+	Requires *Requires
+}
+
+// Tries to find out when this binary was compiled.
+// Returns the current time if it fails to find it.
+func compileTime() time.Time {
+	info, err := os.Stat(os.Args[0])
+	if err != nil {
+		return time.Now()
+	}
+	return info.ModTime()
+}
+
+// Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
+func NewApp() *App {
+	return &App{
+		Name:         os.Args[0],
+		Usage:        "A new cli application",
+		Version:      "0.0.0",
+		BashComplete: DefaultAppComplete,
+		Action:       helpCommand.Action,
+		Compiled:     compileTime(),
+	}
+}
+
+// Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
+func (a *App) Run(arguments []string) error {
+	// append help to commands
+	if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+		a.Commands = append(a.Commands, helpCommand)
+		a.appendFlag(HelpFlag)
+	}
+
+	//append version/help flags
+	if a.EnableBashCompletion {
+		a.appendFlag(BashCompletionFlag)
+	}
+	a.appendFlag(VersionFlag)
+
+	// parse flags
+	set := flagSet(a.Name, a.Flags)
+	set.SetOutput(ioutil.Discard)
+	err := set.Parse(arguments[1:])
+	nerr := normalizeFlags(a.Flags, set)
+	if nerr != nil {
+		fmt.Println(nerr)
+		context := NewContext(a, set, set)
+		ShowAppHelp(context)
+		fmt.Println("")
+		return nerr
+	}
+	context := NewContext(a, set, set)
+
+	if err != nil {
+		fmt.Printf("Incorrect Usage.\n\n")
+		ShowAppHelp(context)
+		fmt.Println("")
+		return err
+	}
+
+	if checkCompletions(context) {
+		return nil
+	}
+
+	if checkHelp(context) {
+		return nil
+	}
+
+	if checkVersion(context) {
+		return nil
+	}
+
+	if err := context.Satisfies(a.Requires); err != nil {
+		return err
+	}
+
+	if a.Before != nil {
+		err := a.Before(context)
+		if err != nil {
+			return err
+		}
+	}
+
+	args := context.Args()
+	if args.Present() {
+		name := args.First()
+		c := a.Command(name)
+		if c != nil {
+			return c.Run(context)
+		}
+	}
+
+	// Run default Action
+	a.Action(context)
+	return nil
+}
+
+// Another entry point to the cli app, takes care of passing arguments and error handling
+func (a *App) RunAndExitOnError() {
+	if err := a.Run(os.Args); err != nil {
+		os.Stderr.WriteString(fmt.Sprintln(err))
+		os.Exit(1)
+	}
+}
+
+// Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
+func (a *App) RunAsSubcommand(ctx *Context) error {
+	// append help to commands
+	if len(a.Commands) > 0 {
+		if a.Command(helpCommand.Name) == nil && !a.HideHelp {
+			a.Commands = append(a.Commands, helpCommand)
+			a.appendFlag(HelpFlag)
+		}
+	}
+
+	// append flags
+	if a.EnableBashCompletion {
+		a.appendFlag(BashCompletionFlag)
+	}
+
+	// parse flags
+	set := flagSet(a.Name, a.Flags)
+	set.SetOutput(ioutil.Discard)
+	err := set.Parse(ctx.Args().Tail())
+	nerr := normalizeFlags(a.Flags, set)
+	context := NewContext(a, set, ctx.globalSet)
+
+	if nerr != nil {
+		fmt.Println(nerr)
+		if len(a.Commands) > 0 {
+			ShowSubcommandHelp(context)
+		} else {
+			ShowCommandHelp(ctx, context.Args().First())
+		}
+		fmt.Println("")
+		return nerr
+	}
+
+	if err != nil {
+		fmt.Printf("Incorrect Usage.\n\n")
+		ShowSubcommandHelp(context)
+		return err
+	}
+
+	if checkCompletions(context) {
+		return nil
+	}
+
+	if len(a.Commands) > 0 {
+		if checkSubcommandHelp(context) {
+			return nil
+		}
+	} else {
+		if checkCommandHelp(ctx, context.Args().First()) {
+			return nil
+		}
+	}
+
+	if err := context.Satisfies(a.Requires); err != nil {
+		return err
+	}
+
+	if a.Before != nil {
+		err := a.Before(context)
+		if err != nil {
+			return err
+		}
+	}
+
+	args := context.Args()
+	if args.Present() {
+		name := args.First()
+		c := a.Command(name)
+		if c != nil {
+			return c.Run(context)
+		}
+	}
+
+	// Run default Action
+	if len(a.Commands) > 0 {
+		a.Action(context)
+	} else {
+		a.Action(ctx)
+	}
+
+	return nil
+}
+
+// Returns the named command on App. Returns nil if the command does not exist
+func (a *App) Command(name string) *Command {
+	for _, c := range a.Commands {
+		if c.HasName(name) {
+			return &c
+		}
+	}
+
+	return nil
+}
+
+func (a *App) hasFlag(flag Flag) bool {
+	for _, f := range a.Flags {
+		if flag == f {
+			return true
+		}
+	}
+
+	return false
+}
+
+func (a *App) appendFlag(flag Flag) {
+	if !a.hasFlag(flag) {
+		a.Flags = append(a.Flags, flag)
+	}
+}

+ 19 - 0
vendor/github.com/AudriusButkevicius/cli/cli.go

@@ -0,0 +1,19 @@
+// Package cli provides a minimal framework for creating and organizing command line
+// Go applications. cli is designed to be easy to understand and write, the most simple
+// cli application can be written as follows:
+//   func main() {
+//     cli.NewApp().Run(os.Args)
+//   }
+//
+// Of course this application does not do much, so let's make this an actual application:
+//   func main() {
+//     app := cli.NewApp()
+//     app.Name = "greet"
+//     app.Usage = "say a greeting"
+//     app.Action = func(c *cli.Context) {
+//       println("Greetings")
+//     }
+//
+//     app.Run(os.Args)
+//   }
+package cli

+ 148 - 0
vendor/github.com/AudriusButkevicius/cli/command.go

@@ -0,0 +1,148 @@
+package cli
+
+import (
+	"fmt"
+	"io/ioutil"
+	"strings"
+)
+
+// Command is a subcommand for a cli.App.
+type Command struct {
+	// The name of the command
+	Name string
+	// short name of the command. Typically one character
+	ShortName string
+	// A short description of the usage of this command
+	Usage string
+	// A longer explanation of how the command works
+	Description string
+	// The function to call when checking for bash command completions
+	BashComplete func(context *Context)
+	// An action to execute before any sub-subcommands are run, but after the context is ready
+	// If a non-nil error is returned, no sub-subcommands are run
+	Before func(context *Context) error
+	// The function to call when this command is invoked
+	Action func(context *Context)
+	// List of child commands
+	Subcommands []Command
+	// List of flags to parse
+	Flags []Flag
+	// Treat all flags as normal arguments if true
+	SkipFlagParsing bool
+	// Boolean to hide built-in help command
+	HideHelp bool
+	// Command argument requirements
+	Requires *Requires
+}
+
+// Invokes the command given the context, parses ctx.Args() to generate command-specific flags
+func (c Command) Run(ctx *Context) error {
+
+	if len(c.Subcommands) > 0 || c.Before != nil {
+		return c.startApp(ctx)
+	}
+
+	if !c.HideHelp {
+		// append help to flags
+		c.Flags = append(
+			c.Flags,
+			HelpFlag,
+		)
+	}
+
+	if ctx.App.EnableBashCompletion {
+		c.Flags = append(c.Flags, BashCompletionFlag)
+	}
+
+	set := flagSet(c.Name, c.Flags)
+	set.SetOutput(ioutil.Discard)
+
+	firstFlagIndex := -1
+	for index, arg := range ctx.Args() {
+		if strings.HasPrefix(arg, "-") {
+			firstFlagIndex = index
+			break
+		}
+	}
+
+	var err error
+	if firstFlagIndex > -1 && !c.SkipFlagParsing {
+		args := ctx.Args()
+		regularArgs := args[1:firstFlagIndex]
+		flagArgs := args[firstFlagIndex:]
+		err = set.Parse(append(flagArgs, regularArgs...))
+	} else {
+		err = set.Parse(ctx.Args().Tail())
+	}
+
+	if err != nil {
+		fmt.Printf("Incorrect Usage.\n\n")
+		ShowCommandHelp(ctx, c.Name)
+		fmt.Println("")
+		return err
+	}
+
+	nerr := normalizeFlags(c.Flags, set)
+	if nerr != nil {
+		fmt.Println(nerr)
+		fmt.Println("")
+		ShowCommandHelp(ctx, c.Name)
+		fmt.Println("")
+		return nerr
+	}
+	context := NewContext(ctx.App, set, ctx.globalSet)
+
+	if checkCommandCompletions(context, c.Name) {
+		return nil
+	}
+
+	if checkCommandHelp(context, c.Name) {
+		return nil
+	}
+
+	if err := context.Satisfies(c.Requires); err != nil {
+		return err
+	}
+
+	context.Command = c
+	c.Action(context)
+	return nil
+}
+
+// Returns true if Command.Name or Command.ShortName matches given name
+func (c Command) HasName(name string) bool {
+	return c.Name == name || c.ShortName == name
+}
+
+func (c Command) startApp(ctx *Context) error {
+	app := NewApp()
+
+	// set the name and usage
+	app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
+	if c.Description != "" {
+		app.Usage = c.Description
+	} else {
+		app.Usage = c.Usage
+	}
+
+	// set the flags and commands
+	app.Commands = c.Subcommands
+	app.Flags = c.Flags
+	app.HideHelp = c.HideHelp
+
+	// bash completion
+	app.EnableBashCompletion = ctx.App.EnableBashCompletion
+	if c.BashComplete != nil {
+		app.BashComplete = c.BashComplete
+	}
+
+	// set the actions
+	app.Before = c.Before
+	if c.Action != nil {
+		app.Action = c.Action
+	} else {
+		app.Action = helpSubcommand.Action
+	}
+
+	return app.RunAsSubcommand(ctx)
+}

+ 345 - 0
vendor/github.com/AudriusButkevicius/cli/context.go

@@ -0,0 +1,345 @@
+package cli
+
+import (
+	"errors"
+	"flag"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+// Context is a type that is passed through to
+// each Handler action in a cli application. Context
+// can be used to retrieve context-specific Args and
+// parsed command-line options.
+type Context struct {
+	App       *App
+	Command   Command
+	flagSet   *flag.FlagSet
+	globalSet *flag.FlagSet
+	setFlags  map[string]bool
+}
+
+type Requires []string
+
+// Creates a new context. For use in when invoking an App or Command action.
+func NewContext(app *App, set *flag.FlagSet, globalSet *flag.FlagSet) *Context {
+	return &Context{App: app, flagSet: set, globalSet: globalSet}
+}
+
+// Looks up the value of a local int flag, returns 0 if no int flag exists
+func (c *Context) Int(name string) int {
+	return lookupInt(name, c.flagSet)
+}
+
+// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
+func (c *Context) Float64(name string) float64 {
+	return lookupFloat64(name, c.flagSet)
+}
+
+// Looks up the value of a local bool flag, returns false if no bool flag exists
+func (c *Context) Bool(name string) bool {
+	return lookupBool(name, c.flagSet)
+}
+
+// Looks up the value of a local boolT flag, returns false if no bool flag exists
+func (c *Context) BoolT(name string) bool {
+	return lookupBoolT(name, c.flagSet)
+}
+
+// Looks up the value of a local string flag, returns "" if no string flag exists
+func (c *Context) String(name string) string {
+	return lookupString(name, c.flagSet)
+}
+
+// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
+func (c *Context) StringSlice(name string) []string {
+	return lookupStringSlice(name, c.flagSet)
+}
+
+// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
+func (c *Context) IntSlice(name string) []int {
+	return lookupIntSlice(name, c.flagSet)
+}
+
+// Looks up the value of a local generic flag, returns nil if no generic flag exists
+func (c *Context) Generic(name string) interface{} {
+	return lookupGeneric(name, c.flagSet)
+}
+
+// Looks up the value of a global int flag, returns 0 if no int flag exists
+func (c *Context) GlobalInt(name string) int {
+	return lookupInt(name, c.globalSet)
+}
+
+// Looks up the value of a global bool flag, returns false if no bool flag exists
+func (c *Context) GlobalBool(name string) bool {
+	return lookupBool(name, c.globalSet)
+}
+
+// Looks up the value of a global string flag, returns "" if no string flag exists
+func (c *Context) GlobalString(name string) string {
+	return lookupString(name, c.globalSet)
+}
+
+// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
+func (c *Context) GlobalStringSlice(name string) []string {
+	return lookupStringSlice(name, c.globalSet)
+}
+
+// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
+func (c *Context) GlobalIntSlice(name string) []int {
+	return lookupIntSlice(name, c.globalSet)
+}
+
+// Looks up the value of a global generic flag, returns nil if no generic flag exists
+func (c *Context) GlobalGeneric(name string) interface{} {
+	return lookupGeneric(name, c.globalSet)
+}
+
+// Determines if the flag was actually set exists
+func (c *Context) IsSet(name string) bool {
+	if c.setFlags == nil {
+		c.setFlags = make(map[string]bool)
+		c.flagSet.Visit(func(f *flag.Flag) {
+			c.setFlags[f.Name] = true
+		})
+	}
+	return c.setFlags[name] == true
+}
+
+type Args []string
+
+// Returns the command line arguments associated with the context.
+func (c *Context) Args() Args {
+	args := Args(c.flagSet.Args())
+	return args
+}
+
+// Returns an error if the context arguments do not satisfy the given requirements
+func (c *Context) Satisfies(req *Requires) error {
+	if req != nil {
+		optional := 0
+		unlimited := false
+		clean_args := []string{}
+		for _, arg := range *req {
+			if strings.Contains(arg, "...") {
+				unlimited = true
+				arg = strings.Replace(arg, "...", "", -1) + "..."
+			}
+			if strings.Contains(arg, "?") {
+				optional++
+				arg = "[" + strings.Replace(arg, "?", "", -1) + "]"
+			} else {
+				arg = "<" + arg + ">"
+			}
+			clean_args = append(clean_args, arg)
+		}
+		exactly, nomore, atleast := 0, 0, 0
+		if optional == 0 && !unlimited {
+			exactly = len(*req)
+		} else {
+			atleast = len(*req) - optional
+			if !unlimited {
+				nomore = len(*req)
+			}
+		}
+
+		argc := len(c.Args())
+		err := ""
+
+		if atleast > 0 || nomore > 0 {
+			if atleast > argc {
+				err = fmtRequiresError("atleast", atleast)
+			} else if nomore > 0 && argc > nomore {
+				err = fmtRequiresError("no more than", nomore)
+			}
+		} else if argc != exactly {
+			err = fmtRequiresError("exactly", exactly)
+		}
+		if err != "" {
+			if len(clean_args) > 0 {
+				err += ": " + strings.Join(clean_args, " ")
+			}
+			return fmt.Errorf(err)
+		}
+	}
+	return nil
+}
+
+// Returns the nth argument, or else a blank string
+func (a Args) Get(n int) string {
+	if len(a) > n {
+		return a[n]
+	}
+	return ""
+}
+
+// Returns the first argument, or else a blank string
+func (a Args) First() string {
+	return a.Get(0)
+}
+
+// Return the rest of the arguments (not the first one)
+// or else an empty string slice
+func (a Args) Tail() []string {
+	if len(a) >= 2 {
+		return []string(a)[1:]
+	}
+	return []string{}
+}
+
+// Checks if there are any arguments present
+func (a Args) Present() bool {
+	return len(a) != 0
+}
+
+// Swaps arguments at the given indexes
+func (a Args) Swap(from, to int) error {
+	if from >= len(a) || to >= len(a) {
+		return errors.New("index out of range")
+	}
+	a[from], a[to] = a[to], a[from]
+	return nil
+}
+
+// Formats the requirement error
+func fmtRequiresError(str string, count int) string {
+	switch count {
+	case 0:
+		return "Command requires no arguments"
+	case 1:
+		return fmt.Sprintf("Command requires %s 1 argument", str)
+	}
+	return fmt.Sprintf("Command requires %s %d arguments", str, count)
+}
+
+func lookupInt(name string, set *flag.FlagSet) int {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.Atoi(f.Value.String())
+		if err != nil {
+			return 0
+		}
+		return val
+	}
+
+	return 0
+}
+
+func lookupFloat64(name string, set *flag.FlagSet) float64 {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseFloat(f.Value.String(), 64)
+		if err != nil {
+			return 0
+		}
+		return val
+	}
+
+	return 0
+}
+
+func lookupString(name string, set *flag.FlagSet) string {
+	f := set.Lookup(name)
+	if f != nil {
+		return f.Value.String()
+	}
+
+	return ""
+}
+
+func lookupStringSlice(name string, set *flag.FlagSet) []string {
+	f := set.Lookup(name)
+	if f != nil {
+		return (f.Value.(*StringSlice)).Value()
+
+	}
+
+	return nil
+}
+
+func lookupIntSlice(name string, set *flag.FlagSet) []int {
+	f := set.Lookup(name)
+	if f != nil {
+		return (f.Value.(*IntSlice)).Value()
+
+	}
+
+	return nil
+}
+
+func lookupGeneric(name string, set *flag.FlagSet) interface{} {
+	f := set.Lookup(name)
+	if f != nil {
+		return f.Value
+	}
+	return nil
+}
+
+func lookupBool(name string, set *flag.FlagSet) bool {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseBool(f.Value.String())
+		if err != nil {
+			return false
+		}
+		return val
+	}
+
+	return false
+}
+
+func lookupBoolT(name string, set *flag.FlagSet) bool {
+	f := set.Lookup(name)
+	if f != nil {
+		val, err := strconv.ParseBool(f.Value.String())
+		if err != nil {
+			return true
+		}
+		return val
+	}
+
+	return false
+}
+
+func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
+	switch ff.Value.(type) {
+	case *StringSlice:
+	default:
+		set.Set(name, ff.Value.String())
+	}
+}
+
+func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
+	visited := make(map[string]bool)
+	set.Visit(func(f *flag.Flag) {
+		visited[f.Name] = true
+	})
+	for _, f := range flags {
+		parts := strings.Split(f.getName(), ",")
+		if len(parts) == 1 {
+			continue
+		}
+		var ff *flag.Flag
+		for _, name := range parts {
+			name = strings.Trim(name, " ")
+			if visited[name] {
+				if ff != nil {
+					return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
+				}
+				ff = set.Lookup(name)
+			}
+		}
+		if ff == nil {
+			continue
+		}
+		for _, name := range parts {
+			name = strings.Trim(name, " ")
+			if !visited[name] {
+				copyFlag(name, ff, set)
+			}
+		}
+	}
+	return nil
+}

+ 379 - 0
vendor/github.com/AudriusButkevicius/cli/flag.go

@@ -0,0 +1,379 @@
+package cli
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"strconv"
+	"strings"
+)
+
+// This flag enables bash-completion for all commands and subcommands
+var BashCompletionFlag = BoolFlag{
+	Name: "generate-bash-completion",
+}
+
+// This flag prints the version for the application
+var VersionFlag = BoolFlag{
+	Name:  "version, v",
+	Usage: "print the version",
+}
+
+// This flag prints the help for all commands and subcommands
+var HelpFlag = BoolFlag{
+	Name:  "help, h",
+	Usage: "show help",
+}
+
+// Flag is a common interface related to parsing flags in cli.
+// For more advanced flag parsing techniques, it is recomended that
+// this interface be implemented.
+type Flag interface {
+	fmt.Stringer
+	// Apply Flag settings to the given flag set
+	Apply(*flag.FlagSet)
+	getName() string
+}
+
+func flagSet(name string, flags []Flag) *flag.FlagSet {
+	set := flag.NewFlagSet(name, flag.ContinueOnError)
+
+	for _, f := range flags {
+		f.Apply(set)
+	}
+	return set
+}
+
+func eachName(longName string, fn func(string)) {
+	parts := strings.Split(longName, ",")
+	for _, name := range parts {
+		name = strings.Trim(name, " ")
+		fn(name)
+	}
+}
+
+// Generic is a generic parseable type identified by a specific flag
+type Generic interface {
+	Set(value string) error
+	String() string
+}
+
+// GenericFlag is the flag type for types implementing Generic
+type GenericFlag struct {
+	Name   string
+	Value  Generic
+	Usage  string
+	EnvVar string
+}
+
+func (f GenericFlag) String() string {
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s %v\t`%v` %s", prefixFor(f.Name), f.Name, f.Value, "-"+f.Name+" option -"+f.Name+" option", f.Usage))
+}
+
+func (f GenericFlag) Apply(set *flag.FlagSet) {
+	val := f.Value
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			val.Set(envVal)
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+func (f GenericFlag) getName() string {
+	return f.Name
+}
+
+type StringSlice []string
+
+func (f *StringSlice) Set(value string) error {
+	*f = append(*f, value)
+	return nil
+}
+
+func (f *StringSlice) String() string {
+	return fmt.Sprintf("%s", *f)
+}
+
+func (f *StringSlice) Value() []string {
+	return *f
+}
+
+type StringSliceFlag struct {
+	Name   string
+	Value  *StringSlice
+	Usage  string
+	EnvVar string
+}
+
+func (f StringSliceFlag) String() string {
+	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
+	pref := prefixFor(firstName)
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
+}
+
+func (f StringSliceFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			newVal := &StringSlice{}
+			for _, s := range strings.Split(envVal, ",") {
+				newVal.Set(s)
+			}
+			f.Value = newVal
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+func (f StringSliceFlag) getName() string {
+	return f.Name
+}
+
+type IntSlice []int
+
+func (f *IntSlice) Set(value string) error {
+
+	tmp, err := strconv.Atoi(value)
+	if err != nil {
+		return err
+	} else {
+		*f = append(*f, tmp)
+	}
+	return nil
+}
+
+func (f *IntSlice) String() string {
+	return fmt.Sprintf("%d", *f)
+}
+
+func (f *IntSlice) Value() []int {
+	return *f
+}
+
+type IntSliceFlag struct {
+	Name   string
+	Value  *IntSlice
+	Usage  string
+	EnvVar string
+}
+
+func (f IntSliceFlag) String() string {
+	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
+	pref := prefixFor(firstName)
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
+}
+
+func (f IntSliceFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			newVal := &IntSlice{}
+			for _, s := range strings.Split(envVal, ",") {
+				err := newVal.Set(s)
+				if err != nil {
+					fmt.Fprintf(os.Stderr, err.Error())
+				}
+			}
+			f.Value = newVal
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Var(f.Value, name, f.Usage)
+	})
+}
+
+func (f IntSliceFlag) getName() string {
+	return f.Name
+}
+
+type BoolFlag struct {
+	Name   string
+	Usage  string
+	EnvVar string
+}
+
+func (f BoolFlag) String() string {
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
+}
+
+func (f BoolFlag) Apply(set *flag.FlagSet) {
+	val := false
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			envValBool, err := strconv.ParseBool(envVal)
+			if err == nil {
+				val = envValBool
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Bool(name, val, f.Usage)
+	})
+}
+
+func (f BoolFlag) getName() string {
+	return f.Name
+}
+
+type BoolTFlag struct {
+	Name   string
+	Usage  string
+	EnvVar string
+}
+
+func (f BoolTFlag) String() string {
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
+}
+
+func (f BoolTFlag) Apply(set *flag.FlagSet) {
+	val := true
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			envValBool, err := strconv.ParseBool(envVal)
+			if err == nil {
+				val = envValBool
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Bool(name, val, f.Usage)
+	})
+}
+
+func (f BoolTFlag) getName() string {
+	return f.Name
+}
+
+type StringFlag struct {
+	Name   string
+	Value  string
+	Usage  string
+	EnvVar string
+}
+
+func (f StringFlag) String() string {
+	var fmtString string
+	fmtString = "%s %v\t%v"
+
+	if len(f.Value) > 0 {
+		fmtString = "%s '%v'\t%v"
+	} else {
+		fmtString = "%s %v\t%v"
+	}
+
+	return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage))
+}
+
+func (f StringFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			f.Value = envVal
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.String(name, f.Value, f.Usage)
+	})
+}
+
+func (f StringFlag) getName() string {
+	return f.Name
+}
+
+type IntFlag struct {
+	Name   string
+	Value  int
+	Usage  string
+	EnvVar string
+}
+
+func (f IntFlag) String() string {
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage))
+}
+
+func (f IntFlag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			envValInt, err := strconv.ParseUint(envVal, 10, 64)
+			if err == nil {
+				f.Value = int(envValInt)
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Int(name, f.Value, f.Usage)
+	})
+}
+
+func (f IntFlag) getName() string {
+	return f.Name
+}
+
+type Float64Flag struct {
+	Name   string
+	Value  float64
+	Usage  string
+	EnvVar string
+}
+
+func (f Float64Flag) String() string {
+	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage))
+}
+
+func (f Float64Flag) Apply(set *flag.FlagSet) {
+	if f.EnvVar != "" {
+		if envVal := os.Getenv(f.EnvVar); envVal != "" {
+			envValFloat, err := strconv.ParseFloat(envVal, 10)
+			if err == nil {
+				f.Value = float64(envValFloat)
+			}
+		}
+	}
+
+	eachName(f.Name, func(name string) {
+		set.Float64(name, f.Value, f.Usage)
+	})
+}
+
+func (f Float64Flag) getName() string {
+	return f.Name
+}
+
+func prefixFor(name string) (prefix string) {
+	if len(name) == 1 {
+		prefix = "-"
+	} else {
+		prefix = "--"
+	}
+
+	return
+}
+
+func prefixedNames(fullName string) (prefixed string) {
+	parts := strings.Split(fullName, ",")
+	for i, name := range parts {
+		name = strings.Trim(name, " ")
+		prefixed += prefixFor(name) + name
+		if i < len(parts)-1 {
+			prefixed += ", "
+		}
+	}
+	return
+}
+
+func withEnvHint(envVar, str string) string {
+	envText := ""
+	if envVar != "" {
+		envText = fmt.Sprintf(" [$%s]", envVar)
+	}
+	return str + envText
+}

+ 217 - 0
vendor/github.com/AudriusButkevicius/cli/help.go

@@ -0,0 +1,217 @@
+package cli
+
+import (
+	"fmt"
+	"os"
+	"text/tabwriter"
+	"text/template"
+)
+
+// The text template for the Default help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var AppHelpTemplate = `NAME:
+   {{.Name}} - {{.Usage}}
+
+USAGE:
+   {{.Name}} {{if .Flags}}[global options] {{end}}command{{if .Flags}} [command options]{{end}} [arguments...]
+
+VERSION:
+   {{.Version}}{{if or .Author .Email}}
+
+AUTHOR:{{if .Author}}
+  {{.Author}}{{if .Email}} - <{{.Email}}>{{end}}{{else}}
+  {{.Email}}{{end}}{{end}}
+
+COMMANDS:
+   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
+   {{end}}{{if .Flags}}
+GLOBAL OPTIONS:
+   {{range .Flags}}{{.}}
+   {{end}}{{end}}
+`
+
+// The text template for the command help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var CommandHelpTemplate = `NAME:
+   {{.Name}} - {{.Usage}}
+
+USAGE:
+   command {{.Name}}{{if .Flags}} [command options]{{end}} [arguments...]{{if .Description}}
+
+DESCRIPTION:
+   {{.Description}}{{end}}{{if .Flags}}
+
+OPTIONS:
+   {{range .Flags}}{{.}}
+   {{end}}{{ end }}
+`
+
+// The text template for the subcommand help topic.
+// cli.go uses text/template to render templates. You can
+// render custom help text by setting this variable.
+var SubcommandHelpTemplate = `NAME:
+   {{.Name}} - {{.Usage}}
+
+USAGE:
+   {{.Name}} command{{if .Flags}} [command options]{{end}} [arguments...]
+
+COMMANDS:
+   {{range .Commands}}{{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}
+   {{end}}{{if .Flags}}
+OPTIONS:
+   {{range .Flags}}{{.}}
+   {{end}}{{end}}
+`
+
+var helpCommand = Command{
+	Name:      "help",
+	ShortName: "h",
+	Usage:     "Shows a list of commands or help for one command",
+	Action: func(c *Context) {
+		args := c.Args()
+		if args.Present() {
+			ShowCommandHelp(c, args.First())
+		} else {
+			ShowAppHelp(c)
+		}
+	},
+}
+
+var helpSubcommand = Command{
+	Name:      "help",
+	ShortName: "h",
+	Usage:     "Shows a list of commands or help for one command",
+	Action: func(c *Context) {
+		args := c.Args()
+		if args.Present() {
+			ShowCommandHelp(c, args.First())
+		} else {
+			ShowSubcommandHelp(c)
+		}
+	},
+}
+
+// Prints help for the App
+var HelpPrinter = printHelp
+
+func ShowAppHelp(c *Context) {
+	HelpPrinter(AppHelpTemplate, c.App)
+}
+
+// Prints the list of subcommands as the default app completion method
+func DefaultAppComplete(c *Context) {
+	for _, command := range c.App.Commands {
+		fmt.Println(command.Name)
+		if command.ShortName != "" {
+			fmt.Println(command.ShortName)
+		}
+	}
+}
+
+// Prints help for the given command
+func ShowCommandHelp(c *Context, command string) {
+	for _, c := range c.App.Commands {
+		if c.HasName(command) {
+			HelpPrinter(CommandHelpTemplate, c)
+			return
+		}
+	}
+
+	if c.App.CommandNotFound != nil {
+		c.App.CommandNotFound(c, command)
+	} else {
+		fmt.Printf("No help topic for '%v'\n", command)
+	}
+}
+
+// Prints help for the given subcommand
+func ShowSubcommandHelp(c *Context) {
+	HelpPrinter(SubcommandHelpTemplate, c.App)
+}
+
+// Prints the version number of the App
+func ShowVersion(c *Context) {
+	fmt.Printf("%v version %v\n", c.App.Name, c.App.Version)
+}
+
+// Prints the lists of commands within a given context
+func ShowCompletions(c *Context) {
+	a := c.App
+	if a != nil && a.BashComplete != nil {
+		a.BashComplete(c)
+	}
+}
+
+// Prints the custom completions for a given command
+func ShowCommandCompletions(ctx *Context, command string) {
+	c := ctx.App.Command(command)
+	if c != nil && c.BashComplete != nil {
+		c.BashComplete(ctx)
+	}
+}
+
+func printHelp(templ string, data interface{}) {
+	w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', 0)
+	t := template.Must(template.New("help").Parse(templ))
+	err := t.Execute(w, data)
+	if err != nil {
+		panic(err)
+	}
+	w.Flush()
+}
+
+func checkVersion(c *Context) bool {
+	if c.GlobalBool("version") {
+		ShowVersion(c)
+		return true
+	}
+
+	return false
+}
+
+func checkHelp(c *Context) bool {
+	if c.GlobalBool("h") || c.GlobalBool("help") {
+		ShowAppHelp(c)
+		return true
+	}
+
+	return false
+}
+
+func checkCommandHelp(c *Context, name string) bool {
+	if c.Bool("h") || c.Bool("help") {
+		ShowCommandHelp(c, name)
+		return true
+	}
+
+	return false
+}
+
+func checkSubcommandHelp(c *Context) bool {
+	if c.GlobalBool("h") || c.GlobalBool("help") {
+		ShowSubcommandHelp(c)
+		return true
+	}
+
+	return false
+}
+
+func checkCompletions(c *Context) bool {
+	if c.GlobalBool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
+		ShowCompletions(c)
+		return true
+	}
+
+	return false
+}
+
+func checkCommandCompletions(c *Context, name string) bool {
+	if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
+		ShowCommandCompletions(c, name)
+		return true
+	}
+
+	return false
+}

+ 8 - 0
vendor/manifest

@@ -1,6 +1,14 @@
 {
 	"version": 0,
 	"dependencies": [
+		{
+			"importpath": "github.com/AudriusButkevicius/cli",
+			"repository": "https://github.com/AudriusButkevicius/cli",
+			"vcs": "git",
+			"revision": "7f561c78b5a4aad858d9fd550c92b5da6d55efbb",
+			"branch": "master",
+			"notests": true
+		},
 		{
 			"importpath": "github.com/AudriusButkevicius/go-nat-pmp",
 			"repository": "https://github.com/AudriusButkevicius/go-nat-pmp",