mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-21 23:01:03 +00:00
Merge pull request #38 from mcintyre94/migrate-to-flaggy
Migrate to flaggy
This commit is contained in:
commit
9c95c34825
11 changed files with 2094 additions and 14 deletions
9
Gopkg.lock
generated
9
Gopkg.lock
generated
|
|
@ -113,6 +113,14 @@
|
|||
revision = "7c29201646fa3de8506f701213473dd407f19646"
|
||||
version = "v0.3.7"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:9cf73012dbe62f96cd8cdd210a1123a360401967a4530284dcd2990888747e3d"
|
||||
name = "github.com/integrii/flaggy"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "07ea7eb774047dab1bdcc7cad0f825fa419df47d"
|
||||
version = "1.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:7b2ab5c6de135d57d3a594b53068e2712da4d376b2f78097dec7b46d18deaa78"
|
||||
|
|
@ -319,6 +327,7 @@
|
|||
"github.com/fatih/color",
|
||||
"github.com/go-errors/errors",
|
||||
"github.com/imdario/mergo",
|
||||
"github.com/integrii/flaggy",
|
||||
"github.com/jesseduffield/asciigraph",
|
||||
"github.com/jesseduffield/gocui",
|
||||
"github.com/jesseduffield/rollrus",
|
||||
|
|
|
|||
29
main.go
29
main.go
|
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
|
@ -10,6 +9,7 @@ import (
|
|||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/integrii/flaggy"
|
||||
"github.com/jesseduffield/lazydocker/pkg/app"
|
||||
"github.com/jesseduffield/lazydocker/pkg/config"
|
||||
"github.com/jesseduffield/yaml"
|
||||
|
|
@ -21,29 +21,30 @@ var (
|
|||
date string
|
||||
buildSource = "unknown"
|
||||
|
||||
configFlag = flag.Bool("config", false, "Print the current default config")
|
||||
debuggingFlag = flag.Bool("debug", false, "a boolean")
|
||||
versionFlag = flag.Bool("v", false, "Print the current version")
|
||||
configFlag = false
|
||||
debuggingFlag = false
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *versionFlag {
|
||||
fmt.Printf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if *configFlag {
|
||||
flaggy.SetName("lazydocker")
|
||||
flaggy.SetDescription("The lazier way to manage everything docker")
|
||||
flaggy.DefaultParser.AdditionalHelpPrepend = "https://github.com/jesseduffield/lazydocker"
|
||||
|
||||
flaggy.Bool(&configFlag, "c", "config", "Print the current default config")
|
||||
flaggy.Bool(&debuggingFlag, "d", "debug", "a boolean")
|
||||
flaggy.SetVersion(fmt.Sprintf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH))
|
||||
|
||||
flaggy.Parse()
|
||||
|
||||
if configFlag {
|
||||
var buf bytes.Buffer
|
||||
yaml.NewEncoder(&buf).Encode(config.GetDefaultConfig())
|
||||
fmt.Printf("%v\n", buf.String())
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// for now we're always in debug mode so we're not passing *debuggingFlag
|
||||
*debuggingFlag = true
|
||||
|
||||
appConfig, err := config.NewAppConfig("lazydocker", version, commit, date, buildSource, *debuggingFlag)
|
||||
appConfig, err := config.NewAppConfig("lazydocker", version, commit, date, buildSource, debuggingFlag)
|
||||
if err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
|
|
|
|||
24
vendor/github.com/integrii/flaggy/LICENSE
generated
vendored
Normal file
24
vendor/github.com/integrii/flaggy/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
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 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.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
29
vendor/github.com/integrii/flaggy/argumentParser.go
generated
vendored
Normal file
29
vendor/github.com/integrii/flaggy/argumentParser.go
generated
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
package flaggy
|
||||
|
||||
// setValueForParsers sets the value for a specified key in the
|
||||
// specified parsers (which normally include a Parser and Subcommand).
|
||||
// The return values represent the key being set, and any errors
|
||||
// returned when setting the key, such as failures to convert the string
|
||||
// into the appropriate flag value. We stop assigning values as soon
|
||||
// as we find a parser that accepts it.
|
||||
func setValueForParsers(key string, value string, parsers ...ArgumentParser) (bool, error) {
|
||||
|
||||
var valueWasSet bool
|
||||
|
||||
for _, p := range parsers {
|
||||
valueWasSet, err := p.SetValueForKey(key, value)
|
||||
if err != nil {
|
||||
return valueWasSet, err
|
||||
}
|
||||
if valueWasSet {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return valueWasSet, nil
|
||||
}
|
||||
|
||||
// ArgumentParser represents a parser or subcommand
|
||||
type ArgumentParser interface {
|
||||
SetValueForKey(key string, value string) (bool, error)
|
||||
}
|
||||
622
vendor/github.com/integrii/flaggy/flag.go
generated
vendored
Normal file
622
vendor/github.com/integrii/flaggy/flag.go
generated
vendored
Normal file
|
|
@ -0,0 +1,622 @@
|
|||
package flaggy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Flag holds the base methods for all flag types
|
||||
type Flag struct {
|
||||
ShortName string
|
||||
LongName string
|
||||
Description string
|
||||
rawValue string // the value as a string before being parsed
|
||||
Hidden bool // indicates this flag should be hidden from help and suggestions
|
||||
AssignmentVar interface{}
|
||||
defaultValue string // the value (as a string), that was set by default before any parsing and assignment
|
||||
parsed bool // indicates that this flag has already been parsed
|
||||
}
|
||||
|
||||
// HasName indicates that this flag's short or long name matches the
|
||||
// supplied name string
|
||||
func (f *Flag) HasName(name string) bool {
|
||||
name = strings.TrimSpace(name)
|
||||
if f.ShortName == name || f.LongName == name {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// identifyAndAssignValue identifies the type of the incoming value
|
||||
// and assigns it to the AssignmentVar pointer's target value. If
|
||||
// the value is a type that needs parsing, that is performed as well.
|
||||
func (f *Flag) identifyAndAssignValue(value string) error {
|
||||
|
||||
var err error
|
||||
|
||||
// Only parse this flag default value once. This keeps us from
|
||||
// overwriting the default value in help output
|
||||
if !f.parsed {
|
||||
f.parsed = true
|
||||
// parse the default value as a string and remember it for help output
|
||||
f.defaultValue, err = f.returnAssignmentVarValueAsString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
debugPrint("attempting to assign value", value, "to flag", f.LongName)
|
||||
f.rawValue = value // remember the raw value
|
||||
|
||||
// depending on the type of the assignment variable, we convert the
|
||||
// incoming string and assign it. We only use pointers to variables
|
||||
// in flagy. No returning vars by value.
|
||||
switch f.AssignmentVar.(type) {
|
||||
case *string:
|
||||
v, _ := (f.AssignmentVar).(*string)
|
||||
*v = value
|
||||
case *[]string:
|
||||
v := f.AssignmentVar.(*[]string)
|
||||
splitString := strings.Split(value, ",")
|
||||
new := append(*v, splitString...)
|
||||
*v = new
|
||||
case *bool:
|
||||
v, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a, _ := (f.AssignmentVar).(*bool)
|
||||
*a = v
|
||||
case *[]bool:
|
||||
// parse the incoming bool
|
||||
b, err := strconv.ParseBool(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// cast the assignment var
|
||||
existing := f.AssignmentVar.(*[]bool)
|
||||
// deref the assignment var and append to it
|
||||
v := append(*existing, b)
|
||||
// pointer the new value and assign it
|
||||
a, _ := (f.AssignmentVar).(*[]bool)
|
||||
*a = v
|
||||
case *time.Duration:
|
||||
v, err := time.ParseDuration(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a, _ := (f.AssignmentVar).(*time.Duration)
|
||||
*a = v
|
||||
case *[]time.Duration:
|
||||
t, err := time.ParseDuration(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]time.Duration)
|
||||
// deref the assignment var and append to it
|
||||
v := append(*existing, t)
|
||||
// pointer the new value and assign it
|
||||
a, _ := (f.AssignmentVar).(*[]time.Duration)
|
||||
*a = v
|
||||
case *float32:
|
||||
v, err := strconv.ParseFloat(value, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
float := float32(v)
|
||||
a, _ := (f.AssignmentVar).(*float32)
|
||||
*a = float
|
||||
case *[]float32:
|
||||
v, err := strconv.ParseFloat(value, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
float := float32(v)
|
||||
existing := f.AssignmentVar.(*[]float32)
|
||||
new := append(*existing, float)
|
||||
*existing = new
|
||||
case *float64:
|
||||
v, err := strconv.ParseFloat(value, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a, _ := (f.AssignmentVar).(*float64)
|
||||
*a = v
|
||||
case *[]float64:
|
||||
v, err := strconv.ParseFloat(value, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]float64)
|
||||
new := append(*existing, v)
|
||||
|
||||
*existing = new
|
||||
case *int:
|
||||
v, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e := f.AssignmentVar.(*int)
|
||||
*e = v
|
||||
case *[]int:
|
||||
v, err := strconv.Atoi(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]int)
|
||||
new := append(*existing, v)
|
||||
*existing = new
|
||||
case *uint:
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*uint)
|
||||
*existing = uint(v)
|
||||
case *[]uint:
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]uint)
|
||||
new := append(*existing, uint(v))
|
||||
*existing = new
|
||||
case *uint64:
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*uint64)
|
||||
*existing = v
|
||||
case *[]uint64:
|
||||
v, err := strconv.ParseUint(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]uint64)
|
||||
new := append(*existing, v)
|
||||
*existing = new
|
||||
case *uint32:
|
||||
v, err := strconv.ParseUint(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*uint32)
|
||||
*existing = uint32(v)
|
||||
case *[]uint32:
|
||||
v, err := strconv.ParseUint(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]uint32)
|
||||
new := append(*existing, uint32(v))
|
||||
*existing = new
|
||||
case *uint16:
|
||||
v, err := strconv.ParseUint(value, 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val := uint16(v)
|
||||
existing := f.AssignmentVar.(*uint16)
|
||||
*existing = val
|
||||
case *[]uint16:
|
||||
v, err := strconv.ParseUint(value, 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]uint16)
|
||||
new := append(*existing, uint16(v))
|
||||
*existing = new
|
||||
case *uint8:
|
||||
v, err := strconv.ParseUint(value, 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val := uint8(v)
|
||||
existing := f.AssignmentVar.(*uint8)
|
||||
*existing = val
|
||||
case *[]uint8:
|
||||
var newSlice []uint8
|
||||
|
||||
v, err := strconv.ParseUint(value, 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newV := uint8(v)
|
||||
existing := f.AssignmentVar.(*[]uint8)
|
||||
newSlice = append(*existing, newV)
|
||||
*existing = newSlice
|
||||
case *int64:
|
||||
v, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*int64)
|
||||
*existing = v
|
||||
case *[]int64:
|
||||
v, err := strconv.ParseInt(value, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingSlice := f.AssignmentVar.(*[]int64)
|
||||
newSlice := append(*existingSlice, v)
|
||||
*existingSlice = newSlice
|
||||
case *int32:
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
converted := int32(v)
|
||||
existing := f.AssignmentVar.(*int32)
|
||||
*existing = converted
|
||||
case *[]int32:
|
||||
v, err := strconv.ParseInt(value, 10, 32)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingSlice := f.AssignmentVar.(*[]int32)
|
||||
newSlice := append(*existingSlice, int32(v))
|
||||
*existingSlice = newSlice
|
||||
case *int16:
|
||||
v, err := strconv.ParseInt(value, 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
converted := int16(v)
|
||||
existing := f.AssignmentVar.(*int16)
|
||||
*existing = converted
|
||||
case *[]int16:
|
||||
v, err := strconv.ParseInt(value, 10, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingSlice := f.AssignmentVar.(*[]int16)
|
||||
newSlice := append(*existingSlice, int16(v))
|
||||
*existingSlice = newSlice
|
||||
case *int8:
|
||||
v, err := strconv.ParseInt(value, 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
converted := int8(v)
|
||||
existing := f.AssignmentVar.(*int8)
|
||||
*existing = converted
|
||||
case *[]int8:
|
||||
v, err := strconv.ParseInt(value, 10, 8)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existingSlice := f.AssignmentVar.(*[]int8)
|
||||
newSlice := append(*existingSlice, int8(v))
|
||||
*existingSlice = newSlice
|
||||
case *net.IP:
|
||||
v := net.ParseIP(value)
|
||||
existing := f.AssignmentVar.(*net.IP)
|
||||
*existing = v
|
||||
case *[]net.IP:
|
||||
v := net.ParseIP(value)
|
||||
existing := f.AssignmentVar.(*[]net.IP)
|
||||
new := append(*existing, v)
|
||||
*existing = new
|
||||
case *net.HardwareAddr:
|
||||
v, err := net.ParseMAC(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*net.HardwareAddr)
|
||||
*existing = v
|
||||
case *[]net.HardwareAddr:
|
||||
v, err := net.ParseMAC(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := f.AssignmentVar.(*[]net.HardwareAddr)
|
||||
new := append(*existing, v)
|
||||
*existing = new
|
||||
case *net.IPMask:
|
||||
v := net.IPMask(net.ParseIP(value).To4())
|
||||
existing := f.AssignmentVar.(*net.IPMask)
|
||||
*existing = v
|
||||
case *[]net.IPMask:
|
||||
v := net.IPMask(net.ParseIP(value).To4())
|
||||
existing := f.AssignmentVar.(*[]net.IPMask)
|
||||
new := append(*existing, v)
|
||||
*existing = new
|
||||
default:
|
||||
return errors.New("Unknown flag assignmentVar supplied in flag " + f.LongName + " " + f.ShortName)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
const argIsPositional = "positional" // subcommand or positional value
|
||||
const argIsFlagWithSpace = "flagWithSpace" // -f path or --file path
|
||||
const argIsFlagWithValue = "flagWithValue" // -f=path or --file=path
|
||||
const argIsFinal = "final" // the final argument only '--'
|
||||
|
||||
// determineArgType determines if the specified arg is a flag with space
|
||||
// separated value, a flag with a connected value, or neither (positional)
|
||||
func determineArgType(arg string) string {
|
||||
|
||||
// if the arg is --, then its the final arg
|
||||
if arg == "--" {
|
||||
return argIsFinal
|
||||
}
|
||||
|
||||
// if it has the prefix --, then its a long flag
|
||||
if strings.HasPrefix(arg, "--") {
|
||||
// if it contains an equals, it is a joined value
|
||||
if strings.Contains(arg, "=") {
|
||||
return argIsFlagWithValue
|
||||
}
|
||||
return argIsFlagWithSpace
|
||||
}
|
||||
|
||||
// if it has the prefix -, then its a short flag
|
||||
if strings.HasPrefix(arg, "-") {
|
||||
// if it contains an equals, it is a joined value
|
||||
if strings.Contains(arg, "=") {
|
||||
return argIsFlagWithValue
|
||||
}
|
||||
return argIsFlagWithSpace
|
||||
}
|
||||
|
||||
return argIsPositional
|
||||
}
|
||||
|
||||
// parseArgWithValue parses a key=value concatenated argument into a key and
|
||||
// value
|
||||
func parseArgWithValue(arg string) (key string, value string) {
|
||||
|
||||
// remove up to two minuses from start of flag
|
||||
arg = strings.TrimPrefix(arg, "-")
|
||||
arg = strings.TrimPrefix(arg, "-")
|
||||
|
||||
// debugPrint("parseArgWithValue parsing", arg)
|
||||
|
||||
// break at the equals
|
||||
args := strings.SplitN(arg, "=", 2)
|
||||
|
||||
// if its a bool arg, with no explicit value, we return a blank
|
||||
if len(args) == 1 {
|
||||
return args[0], ""
|
||||
}
|
||||
|
||||
// if its a key and value pair, we return those
|
||||
if len(args) == 2 {
|
||||
// debugPrint("parseArgWithValue parsed", args[0], args[1])
|
||||
return args[0], args[1]
|
||||
}
|
||||
|
||||
fmt.Println("Warning: attempted to parseArgWithValue but did not have correct parameter count.", arg, "->", args)
|
||||
return "", ""
|
||||
}
|
||||
|
||||
// parseFlagToName parses a flag with space value down to a key name:
|
||||
// --path -> path
|
||||
// -p -> p
|
||||
func parseFlagToName(arg string) string {
|
||||
// remove minus from start
|
||||
arg = strings.TrimLeft(arg, "-")
|
||||
arg = strings.TrimLeft(arg, "-")
|
||||
return arg
|
||||
}
|
||||
|
||||
// flagIsBool determines if the flag is a bool within the specified parser
|
||||
// and subcommand's context
|
||||
func flagIsBool(sc *Subcommand, p *Parser, key string) bool {
|
||||
for _, f := range append(sc.Flags, p.Flags...) {
|
||||
if f.HasName(key) {
|
||||
_, isBool := f.AssignmentVar.(*bool)
|
||||
_, isBoolSlice := f.AssignmentVar.(*[]bool)
|
||||
if isBool || isBoolSlice {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// by default, the answer is false
|
||||
return false
|
||||
}
|
||||
|
||||
// returnAssignmentVarValueAsString returns the value of the flag's
|
||||
// assignment variable as a string. This is used to display the
|
||||
// default value of flags before they are assigned (like when help is output).
|
||||
func (f *Flag) returnAssignmentVarValueAsString() (string, error) {
|
||||
|
||||
debugPrint("returning current value of assignment var of flag", f.LongName)
|
||||
|
||||
var err error
|
||||
|
||||
// depending on the type of the assignment variable, we convert the
|
||||
// incoming string and assign it. We only use pointers to variables
|
||||
// in flagy. No returning vars by value.
|
||||
switch f.AssignmentVar.(type) {
|
||||
case *string:
|
||||
v, _ := (f.AssignmentVar).(*string)
|
||||
return *v, err
|
||||
case *[]string:
|
||||
v := f.AssignmentVar.(*[]string)
|
||||
return strings.Join(*v, ","), err
|
||||
case *bool:
|
||||
a, _ := (f.AssignmentVar).(*bool)
|
||||
return strconv.FormatBool(*a), err
|
||||
case *[]bool:
|
||||
value := f.AssignmentVar.(*[]bool)
|
||||
var ss []string
|
||||
for _, b := range *value {
|
||||
ss = append(ss, strconv.FormatBool(b))
|
||||
}
|
||||
return strings.Join(ss, ","), err
|
||||
case *time.Duration:
|
||||
a := f.AssignmentVar.(*time.Duration)
|
||||
return (*a).String(), err
|
||||
case *[]time.Duration:
|
||||
tds := f.AssignmentVar.(*[]time.Duration)
|
||||
var asSlice []string
|
||||
for _, td := range *tds {
|
||||
asSlice = append(asSlice, td.String())
|
||||
}
|
||||
return strings.Join(asSlice, ","), err
|
||||
case *float32:
|
||||
a := f.AssignmentVar.(*float32)
|
||||
return strconv.FormatFloat(float64(*a), 'f', 2, 32), err
|
||||
case *[]float32:
|
||||
v := f.AssignmentVar.(*[]float32)
|
||||
var strSlice []string
|
||||
for _, f := range *v {
|
||||
formatted := strconv.FormatFloat(float64(f), 'f', 2, 32)
|
||||
strSlice = append(strSlice, formatted)
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
case *float64:
|
||||
a := f.AssignmentVar.(*float64)
|
||||
return strconv.FormatFloat(float64(*a), 'f', 2, 64), err
|
||||
case *[]float64:
|
||||
v := f.AssignmentVar.(*[]float64)
|
||||
var strSlice []string
|
||||
for _, f := range *v {
|
||||
formatted := strconv.FormatFloat(float64(f), 'f', 2, 64)
|
||||
strSlice = append(strSlice, formatted)
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
case *int:
|
||||
a := f.AssignmentVar.(*int)
|
||||
return strconv.Itoa(*a), err
|
||||
case *[]int:
|
||||
val := f.AssignmentVar.(*[]int)
|
||||
var strSlice []string
|
||||
for _, i := range *val {
|
||||
str := strconv.Itoa(i)
|
||||
strSlice = append(strSlice, str)
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
case *uint:
|
||||
v := f.AssignmentVar.(*uint)
|
||||
return strconv.FormatUint(uint64(*v), 10), err
|
||||
case *[]uint:
|
||||
values := f.AssignmentVar.(*[]uint)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *uint64:
|
||||
v := f.AssignmentVar.(*uint64)
|
||||
return strconv.FormatUint(*v, 10), err
|
||||
case *[]uint64:
|
||||
values := f.AssignmentVar.(*[]uint64)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatUint(i, 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *uint32:
|
||||
v := f.AssignmentVar.(*uint32)
|
||||
return strconv.FormatUint(uint64(*v), 10), err
|
||||
case *[]uint32:
|
||||
values := f.AssignmentVar.(*[]uint32)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *uint16:
|
||||
v := f.AssignmentVar.(*uint16)
|
||||
return strconv.FormatUint(uint64(*v), 10), err
|
||||
case *[]uint16:
|
||||
values := f.AssignmentVar.(*[]uint16)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *uint8:
|
||||
v := f.AssignmentVar.(*uint8)
|
||||
return strconv.FormatUint(uint64(*v), 10), err
|
||||
case *[]uint8:
|
||||
values := f.AssignmentVar.(*[]uint8)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatUint(uint64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *int64:
|
||||
v := f.AssignmentVar.(*int64)
|
||||
return strconv.FormatInt(int64(*v), 10), err
|
||||
case *[]int64:
|
||||
values := f.AssignmentVar.(*[]int64)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatInt(i, 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *int32:
|
||||
v := f.AssignmentVar.(*int32)
|
||||
return strconv.FormatInt(int64(*v), 10), err
|
||||
case *[]int32:
|
||||
values := f.AssignmentVar.(*[]int32)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatInt(int64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *int16:
|
||||
v := f.AssignmentVar.(*int16)
|
||||
return strconv.FormatInt(int64(*v), 10), err
|
||||
case *[]int16:
|
||||
values := f.AssignmentVar.(*[]int16)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatInt(int64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *int8:
|
||||
v := f.AssignmentVar.(*int8)
|
||||
return strconv.FormatInt(int64(*v), 10), err
|
||||
case *[]int8:
|
||||
values := f.AssignmentVar.(*[]int8)
|
||||
var strVars []string
|
||||
for _, i := range *values {
|
||||
strVars = append(strVars, strconv.FormatInt(int64(i), 10))
|
||||
}
|
||||
return strings.Join(strVars, ","), err
|
||||
case *net.IP:
|
||||
val := f.AssignmentVar.(*net.IP)
|
||||
return val.String(), err
|
||||
case *[]net.IP:
|
||||
val := f.AssignmentVar.(*[]net.IP)
|
||||
var strSlice []string
|
||||
for _, ip := range *val {
|
||||
strSlice = append(strSlice, ip.String())
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
case *net.HardwareAddr:
|
||||
val := f.AssignmentVar.(*net.HardwareAddr)
|
||||
return val.String(), err
|
||||
case *[]net.HardwareAddr:
|
||||
val := f.AssignmentVar.(*[]net.HardwareAddr)
|
||||
var strSlice []string
|
||||
for _, mac := range *val {
|
||||
strSlice = append(strSlice, mac.String())
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
case *net.IPMask:
|
||||
val := f.AssignmentVar.(*net.IPMask)
|
||||
return val.String(), err
|
||||
case *[]net.IPMask:
|
||||
val := f.AssignmentVar.(*[]net.IPMask)
|
||||
var strSlice []string
|
||||
for _, m := range *val {
|
||||
strSlice = append(strSlice, m.String())
|
||||
}
|
||||
return strings.Join(strSlice, ","), err
|
||||
default:
|
||||
return "", errors.New("Unknown flag assignmentVar found in flag " + f.LongName + " " + f.ShortName + ". Type not supported: " + reflect.TypeOf(f.AssignmentVar).String())
|
||||
}
|
||||
}
|
||||
23
vendor/github.com/integrii/flaggy/help.go
generated
vendored
Normal file
23
vendor/github.com/integrii/flaggy/help.go
generated
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package flaggy
|
||||
|
||||
// defaultHelpTemplate is the help template used by default
|
||||
// {{if (or (or (gt (len .StringFlags) 0) (gt (len .IntFlags) 0)) (gt (len .BoolFlags) 0))}}
|
||||
// {{if (or (gt (len .StringFlags) 0) (gt (len .BoolFlags) 0))}}
|
||||
const defaultHelpTemplate = `{{.CommandName}}{{if .Description}} - {{.Description}}{{end}}{{if .PrependMessage}}
|
||||
{{.PrependMessage}}{{end}}
|
||||
{{if .UsageString}}
|
||||
Usage:
|
||||
{{.UsageString}}{{end}}{{if .Positionals}}
|
||||
|
||||
Positional Variables: {{range .Positionals}}
|
||||
{{.Name}}{{if .Required}} (Required){{end}}{{if .Description}} - {{.Description}}{{end}}{{if .DefaultValue}} (default: {{.DefaultValue}}){{end}}{{end}}{{end}}{{if .Subcommands}}
|
||||
|
||||
Subcommands: {{range .Subcommands}}
|
||||
{{.LongName}}{{if .ShortName}} ({{.ShortName}}){{end}}{{if .Position}}{{if gt .Position 1}} (position {{.Position}}){{end}}{{end}}{{if .Description}} - {{.Description}}{{end}}{{end}}
|
||||
{{end}}{{if (gt (len .Flags) 0)}}
|
||||
Flags: {{if .Flags}}{{range .Flags}}
|
||||
{{if .ShortName}}-{{.ShortName}} {{else}} {{end}}{{if .LongName}}--{{.LongName}} {{end}}{{if .Description}} {{.Description}}{{if .DefaultValue}} (default: {{.DefaultValue}}){{end}}{{end}}{{end}}{{end}}
|
||||
{{end}}{{if .AppendMessage}}{{.AppendMessage}}
|
||||
{{end}}{{if .Message}}
|
||||
{{.Message}}{{end}}
|
||||
`
|
||||
215
vendor/github.com/integrii/flaggy/helpValues.go
generated
vendored
Normal file
215
vendor/github.com/integrii/flaggy/helpValues.go
generated
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
package flaggy
|
||||
|
||||
// Help represents the values needed to render a Help page
|
||||
type Help struct {
|
||||
Subcommands []HelpSubcommand
|
||||
Positionals []HelpPositional
|
||||
Flags []HelpFlag
|
||||
UsageString string
|
||||
CommandName string
|
||||
PrependMessage string
|
||||
AppendMessage string
|
||||
Message string
|
||||
Description string
|
||||
}
|
||||
|
||||
// HelpSubcommand is used to template subcommand Help output
|
||||
type HelpSubcommand struct {
|
||||
ShortName string
|
||||
LongName string
|
||||
Description string
|
||||
Position int
|
||||
}
|
||||
|
||||
// HelpPositional is used to template positional Help output
|
||||
type HelpPositional struct {
|
||||
Name string
|
||||
Description string
|
||||
Required bool
|
||||
Position int
|
||||
DefaultValue string
|
||||
}
|
||||
|
||||
// HelpFlag is used to template string flag Help output
|
||||
type HelpFlag struct {
|
||||
ShortName string
|
||||
LongName string
|
||||
Description string
|
||||
DefaultValue string
|
||||
}
|
||||
|
||||
// ExtractValues extracts Help template values from a subcommand and its parent
|
||||
// parser. The parser is required in order to detect default flag settings
|
||||
// for help and version outut.
|
||||
func (h *Help) ExtractValues(p *Parser, message string) {
|
||||
|
||||
// accept message string for output
|
||||
h.Message = message
|
||||
|
||||
// extract Help values from the current subcommand in context
|
||||
// prependMessage string
|
||||
h.PrependMessage = p.subcommandContext.AdditionalHelpPrepend
|
||||
// appendMessage string
|
||||
h.AppendMessage = p.subcommandContext.AdditionalHelpAppend
|
||||
// command name
|
||||
h.CommandName = p.subcommandContext.Name
|
||||
// description
|
||||
h.Description = p.subcommandContext.Description
|
||||
|
||||
// subcommands []HelpSubcommand
|
||||
for _, cmd := range p.subcommandContext.Subcommands {
|
||||
if cmd.Hidden {
|
||||
continue
|
||||
}
|
||||
newHelpSubcommand := HelpSubcommand{
|
||||
ShortName: cmd.ShortName,
|
||||
LongName: cmd.Name,
|
||||
Description: cmd.Description,
|
||||
Position: cmd.Position,
|
||||
}
|
||||
h.Subcommands = append(h.Subcommands, newHelpSubcommand)
|
||||
}
|
||||
|
||||
// parse positional flags into help output structs
|
||||
for _, pos := range p.subcommandContext.PositionalFlags {
|
||||
if pos.Hidden {
|
||||
continue
|
||||
}
|
||||
newHelpPositional := HelpPositional{
|
||||
Name: pos.Name,
|
||||
Position: pos.Position,
|
||||
Description: pos.Description,
|
||||
Required: pos.Required,
|
||||
DefaultValue: pos.defaultValue,
|
||||
}
|
||||
h.Positionals = append(h.Positionals, newHelpPositional)
|
||||
}
|
||||
|
||||
// if the built-in version flag is enabled, then add it as a help flag
|
||||
if p.ShowVersionWithVersionFlag {
|
||||
defaultVersionFlag := HelpFlag{
|
||||
ShortName: "",
|
||||
LongName: versionFlagLongName,
|
||||
Description: "Displays the program version string.",
|
||||
DefaultValue: "",
|
||||
}
|
||||
h.Flags = append(h.Flags, defaultVersionFlag)
|
||||
}
|
||||
|
||||
// if the built-in help flag exists, then add it as a help flag
|
||||
if p.ShowHelpWithHFlag {
|
||||
defaultHelpFlag := HelpFlag{
|
||||
ShortName: helpFlagShortName,
|
||||
LongName: helpFlagLongName,
|
||||
Description: "Displays help with available flag, subcommand, and positional value parameters.",
|
||||
DefaultValue: "",
|
||||
}
|
||||
h.Flags = append(h.Flags, defaultHelpFlag)
|
||||
}
|
||||
|
||||
// go through every flag in the subcommand and add it to help output
|
||||
h.parseFlagsToHelpFlags(p.subcommandContext.Flags)
|
||||
|
||||
// go through every flag in the parent parser and add it to help output
|
||||
h.parseFlagsToHelpFlags(p.Flags)
|
||||
|
||||
// formulate the usage string
|
||||
// first, we capture all the command and positional names by position
|
||||
commandsByPosition := make(map[int]string)
|
||||
for _, pos := range p.subcommandContext.PositionalFlags {
|
||||
if pos.Hidden {
|
||||
continue
|
||||
}
|
||||
if len(commandsByPosition[pos.Position]) > 0 {
|
||||
commandsByPosition[pos.Position] = commandsByPosition[pos.Position] + "|" + pos.Name
|
||||
} else {
|
||||
commandsByPosition[pos.Position] = pos.Name
|
||||
}
|
||||
}
|
||||
for _, cmd := range p.subcommandContext.Subcommands {
|
||||
if cmd.Hidden {
|
||||
continue
|
||||
}
|
||||
if len(commandsByPosition[cmd.Position]) > 0 {
|
||||
commandsByPosition[cmd.Position] = commandsByPosition[cmd.Position] + "|" + cmd.Name
|
||||
} else {
|
||||
commandsByPosition[cmd.Position] = cmd.Name
|
||||
}
|
||||
}
|
||||
|
||||
// find the highest position count in the map
|
||||
var highestPosition int
|
||||
for i := range commandsByPosition {
|
||||
if i > highestPosition {
|
||||
highestPosition = i
|
||||
}
|
||||
}
|
||||
|
||||
// only have a usage string if there are positional items
|
||||
var usageString string
|
||||
if highestPosition > 0 {
|
||||
// find each positional value and make our final string
|
||||
usageString = p.subcommandContext.Name
|
||||
for i := 1; i <= highestPosition; i++ {
|
||||
if len(commandsByPosition[i]) > 0 {
|
||||
usageString = usageString + " [" + commandsByPosition[i] + "]"
|
||||
} else {
|
||||
// dont keep listing after the first position without any properties
|
||||
// it will be impossible to reach anything beyond here anyway
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h.UsageString = usageString
|
||||
|
||||
}
|
||||
|
||||
// parseFlagsToHelpFlags parses the specified slice of flags into
|
||||
// help flags on the the calling help command
|
||||
func (h *Help) parseFlagsToHelpFlags(flags []*Flag) {
|
||||
for _, f := range flags {
|
||||
if f.Hidden {
|
||||
continue
|
||||
}
|
||||
|
||||
// determine the default value based on the assignment variable
|
||||
defaultValue := f.defaultValue
|
||||
|
||||
// dont show nils
|
||||
if defaultValue == "<nil>" {
|
||||
defaultValue = ""
|
||||
}
|
||||
|
||||
// for bools, dont show a default of false
|
||||
_, isBool := f.AssignmentVar.(*bool)
|
||||
if isBool {
|
||||
b := f.AssignmentVar.(*bool)
|
||||
if *b == false {
|
||||
defaultValue = ""
|
||||
}
|
||||
}
|
||||
|
||||
newHelpFlag := HelpFlag{
|
||||
ShortName: f.ShortName,
|
||||
LongName: f.LongName,
|
||||
Description: f.Description,
|
||||
DefaultValue: defaultValue,
|
||||
}
|
||||
|
||||
h.AddFlagToHelp(newHelpFlag)
|
||||
}
|
||||
}
|
||||
|
||||
// AddFlagToHelp adds a flag to help output if it does not exist
|
||||
func (h *Help) AddFlagToHelp(f HelpFlag) {
|
||||
for _, existingFlag := range h.Flags {
|
||||
if len(existingFlag.ShortName) > 0 && existingFlag.ShortName == f.ShortName {
|
||||
return
|
||||
}
|
||||
if len(existingFlag.LongName) > 0 && existingFlag.LongName == f.LongName {
|
||||
return
|
||||
}
|
||||
}
|
||||
h.Flags = append(h.Flags, f)
|
||||
}
|
||||
341
vendor/github.com/integrii/flaggy/main.go
generated
vendored
Normal file
341
vendor/github.com/integrii/flaggy/main.go
generated
vendored
Normal file
|
|
@ -0,0 +1,341 @@
|
|||
// Package flaggy is a input flag parsing package that supports recursive
|
||||
// subcommands, positional values, and any-position flags without
|
||||
// unnecessary complexeties.
|
||||
//
|
||||
// For a getting started tutorial and full feature list, check out the
|
||||
// readme at https://github.com/integrii/flaggy.
|
||||
package flaggy // import "github.com/integrii/flaggy"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// strings used for builtin help and version flags both short and long
|
||||
const versionFlagLongName = "version"
|
||||
const helpFlagLongName = "help"
|
||||
const helpFlagShortName = "h"
|
||||
|
||||
// defaultVersion is applied to parsers when they are created
|
||||
const defaultVersion = "0.0.0"
|
||||
|
||||
// DebugMode indicates that debug output should be enabled
|
||||
var DebugMode bool
|
||||
|
||||
// DefaultHelpTemplate is the help template that will be used
|
||||
// for newly created subcommands and commands
|
||||
var DefaultHelpTemplate = defaultHelpTemplate
|
||||
|
||||
// DefaultParser is the default parser that is used with the package-level public
|
||||
// functions
|
||||
var DefaultParser *Parser
|
||||
|
||||
// TrailingArguments holds trailing arguments in the main parser after parsing
|
||||
// has been run.
|
||||
var TrailingArguments []string
|
||||
|
||||
func init() {
|
||||
|
||||
// set the default help template
|
||||
// allow usage like flaggy.StringVar by enabling a default Parser
|
||||
ResetParser()
|
||||
}
|
||||
|
||||
// ResetParser resets the default parser to a fresh instance. Uses the
|
||||
// name of the binary executing as the program name by default.
|
||||
func ResetParser() {
|
||||
if len(os.Args) > 0 {
|
||||
chunks := strings.Split(os.Args[0], "/")
|
||||
DefaultParser = NewParser(chunks[len(chunks)-1])
|
||||
} else {
|
||||
DefaultParser = NewParser("default")
|
||||
}
|
||||
}
|
||||
|
||||
// Parse parses flags as requested in the default package parser
|
||||
func Parse() {
|
||||
err := DefaultParser.Parse()
|
||||
TrailingArguments = DefaultParser.TrailingArguments
|
||||
if err != nil {
|
||||
log.Panicln("Error from argument parser:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// ParseArgs parses the passed args as if they were the arguments to the
|
||||
// running binary. Targets the default main parser for the package.
|
||||
func ParseArgs(args []string) {
|
||||
err := DefaultParser.ParseArgs(args)
|
||||
TrailingArguments = DefaultParser.TrailingArguments
|
||||
if err != nil {
|
||||
log.Panicln("Error from argument parser:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// String adds a new string flag
|
||||
func String(assignmentVar *string, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// StringSlice adds a new slice of strings flag
|
||||
// Specify the flag multiple times to fill the slice
|
||||
func StringSlice(assignmentVar *[]string, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Bool adds a new bool flag
|
||||
func Bool(assignmentVar *bool, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// BoolSlice adds a new slice of bools flag
|
||||
// Specify the flag multiple times to fill the slice
|
||||
func BoolSlice(assignmentVar *[]bool, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// ByteSlice adds a new slice of bytes flag
|
||||
// Specify the flag multiple times to fill the slice. Takes hex as input.
|
||||
func ByteSlice(assignmentVar *[]byte, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Duration adds a new time.Duration flag.
|
||||
// Input format is described in time.ParseDuration().
|
||||
// Example values: 1h, 1h50m, 32s
|
||||
func Duration(assignmentVar *time.Duration, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// DurationSlice adds a new time.Duration flag.
|
||||
// Input format is described in time.ParseDuration().
|
||||
// Example values: 1h, 1h50m, 32s
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func DurationSlice(assignmentVar *[]time.Duration, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float32 adds a new float32 flag.
|
||||
func Float32(assignmentVar *float32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float32Slice adds a new float32 flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Float32Slice(assignmentVar *[]float32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float64 adds a new float64 flag.
|
||||
func Float64(assignmentVar *float64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float64Slice adds a new float64 flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Float64Slice(assignmentVar *[]float64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int adds a new int flag
|
||||
func Int(assignmentVar *int, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IntSlice adds a new int slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func IntSlice(assignmentVar *[]int, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt adds a new uint flag
|
||||
func UInt(assignmentVar *uint, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UIntSlice adds a new uint slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func UIntSlice(assignmentVar *[]uint, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt64 adds a new uint64 flag
|
||||
func UInt64(assignmentVar *uint64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt64Slice adds a new uint64 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func UInt64Slice(assignmentVar *[]uint64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt32 adds a new uint32 flag
|
||||
func UInt32(assignmentVar *uint32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt32Slice adds a new uint32 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func UInt32Slice(assignmentVar *[]uint32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt16 adds a new uint16 flag
|
||||
func UInt16(assignmentVar *uint16, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt16Slice adds a new uint16 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func UInt16Slice(assignmentVar *[]uint16, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt8 adds a new uint8 flag
|
||||
func UInt8(assignmentVar *uint8, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt8Slice adds a new uint8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func UInt8Slice(assignmentVar *[]uint8, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int64 adds a new int64 flag
|
||||
func Int64(assignmentVar *int64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int64Slice adds a new int64 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Int64Slice(assignmentVar *[]int64, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int32 adds a new int32 flag
|
||||
func Int32(assignmentVar *int32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int32Slice adds a new int32 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Int32Slice(assignmentVar *[]int32, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int16 adds a new int16 flag
|
||||
func Int16(assignmentVar *int16, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int16Slice adds a new int16 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Int16Slice(assignmentVar *[]int16, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int8 adds a new int8 flag
|
||||
func Int8(assignmentVar *int8, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int8Slice adds a new int8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func Int8Slice(assignmentVar *[]int8, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IP adds a new net.IP flag.
|
||||
func IP(assignmentVar *net.IP, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPSlice adds a new int8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func IPSlice(assignmentVar *[]net.IP, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// HardwareAddr adds a new net.HardwareAddr flag.
|
||||
func HardwareAddr(assignmentVar *net.HardwareAddr, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// HardwareAddrSlice adds a new net.HardwareAddr slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func HardwareAddrSlice(assignmentVar *[]net.HardwareAddr, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPMask adds a new net.IPMask flag. IPv4 Only.
|
||||
func IPMask(assignmentVar *net.IPMask, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPMaskSlice adds a new net.HardwareAddr slice flag. IPv4 only.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func IPMaskSlice(assignmentVar *[]net.IPMask, shortName string, longName string, description string) {
|
||||
DefaultParser.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// AttachSubcommand adds a subcommand for parsing
|
||||
func AttachSubcommand(subcommand *Subcommand, relativePosition int) {
|
||||
DefaultParser.AttachSubcommand(subcommand, relativePosition)
|
||||
}
|
||||
|
||||
// ShowHelp shows parser help
|
||||
func ShowHelp(message string) {
|
||||
DefaultParser.ShowHelpWithMessage(message)
|
||||
}
|
||||
|
||||
// SetDescription sets the description of the default package command parser
|
||||
func SetDescription(description string) {
|
||||
DefaultParser.Description = description
|
||||
}
|
||||
|
||||
// SetVersion sets the version of the default package command parser
|
||||
func SetVersion(version string) {
|
||||
DefaultParser.Version = version
|
||||
}
|
||||
|
||||
// SetName sets the name of the default package command parser
|
||||
func SetName(name string) {
|
||||
DefaultParser.Name = name
|
||||
}
|
||||
|
||||
// ShowHelpAndExit shows parser help and exits with status code 2
|
||||
func ShowHelpAndExit(message string) {
|
||||
ShowHelp(message)
|
||||
exitOrPanic(2)
|
||||
}
|
||||
|
||||
// PanicInsteadOfExit is used when running tests
|
||||
var PanicInsteadOfExit bool
|
||||
|
||||
// exitOrPanic panics instead of calling os.Exit so that tests can catch
|
||||
// more failures
|
||||
func exitOrPanic(code int) {
|
||||
if PanicInsteadOfExit {
|
||||
panic("Panic instead of exit with code: " + strconv.Itoa(code))
|
||||
}
|
||||
os.Exit(code)
|
||||
}
|
||||
|
||||
// AddPositionalValue adds a positional value to the main parser at the global
|
||||
// context
|
||||
func AddPositionalValue(assignmentVar *string, name string, relativePosition int, required bool, description string) {
|
||||
DefaultParser.AddPositionalValue(assignmentVar, name, relativePosition, required, description)
|
||||
}
|
||||
|
||||
// debugPrint prints if debugging is enabled
|
||||
func debugPrint(i ...interface{}) {
|
||||
if DebugMode {
|
||||
fmt.Println(i...)
|
||||
}
|
||||
}
|
||||
111
vendor/github.com/integrii/flaggy/parser.go
generated
vendored
Normal file
111
vendor/github.com/integrii/flaggy/parser.go
generated
vendored
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package flaggy
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"text/template"
|
||||
)
|
||||
|
||||
// Parser represents the set of vars and subcommands we are expecting
|
||||
// from our input args, and the parser than handles them all.
|
||||
type Parser struct {
|
||||
Subcommand
|
||||
Version string // the optional version of the parser.
|
||||
ShowHelpWithHFlag bool // display help when -h or --help passed
|
||||
ShowVersionWithVersionFlag bool // display the version when --version passed
|
||||
ShowHelpOnUnexpected bool // display help when an unexpected flag is passed
|
||||
TrailingArguments []string // everything after a -- is placed here
|
||||
HelpTemplate *template.Template // template for Help output
|
||||
trailingArgumentsExtracted bool // indicates that trailing args have been parsed and should not be appended again
|
||||
parsed bool // indicates this parser has parsed
|
||||
subcommandContext *Subcommand // points to the most specific subcommand being used
|
||||
}
|
||||
|
||||
// NewParser creates a new ArgumentParser ready to parse inputs
|
||||
func NewParser(name string) *Parser {
|
||||
// this can not be done inline because of struct embedding
|
||||
p := &Parser{}
|
||||
p.Name = name
|
||||
p.Version = defaultVersion
|
||||
p.ShowHelpOnUnexpected = true
|
||||
p.ShowHelpWithHFlag = true
|
||||
p.ShowVersionWithVersionFlag = true
|
||||
p.SetHelpTemplate(DefaultHelpTemplate)
|
||||
p.subcommandContext = &Subcommand{}
|
||||
return p
|
||||
}
|
||||
|
||||
// ParseArgs parses as if the passed args were the os.Args, but without the
|
||||
// binary at the 0 position in the array. An error is returned if there
|
||||
// is a low level issue converting flags to their proper type. No error
|
||||
// is returned for invalid arguments or missing require subcommands.
|
||||
func (p *Parser) ParseArgs(args []string) error {
|
||||
if p.parsed {
|
||||
return errors.New("Parser.Parse() called twice on parser with name: " + " " + p.Name + " " + p.ShortName)
|
||||
}
|
||||
p.parsed = true
|
||||
// debugPrint("Kicking off parsing with args:", args)
|
||||
return p.parse(p, args, 0)
|
||||
}
|
||||
|
||||
// ShowVersionAndExit shows the version of this parser
|
||||
func (p *Parser) ShowVersionAndExit() {
|
||||
fmt.Println("Version:", p.Version)
|
||||
exitOrPanic(0)
|
||||
}
|
||||
|
||||
// SetHelpTemplate sets the go template this parser will use when rendering
|
||||
// Help.
|
||||
func (p *Parser) SetHelpTemplate(tmpl string) error {
|
||||
var err error
|
||||
p.HelpTemplate = template.New(helpFlagLongName)
|
||||
p.HelpTemplate, err = p.HelpTemplate.Parse(tmpl)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse calculates all flags and subcommands
|
||||
func (p *Parser) Parse() error {
|
||||
|
||||
err := p.ParseArgs(os.Args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// ShowHelp shows Help without an error message
|
||||
func (p *Parser) ShowHelp() {
|
||||
debugPrint("showing help for", p.subcommandContext.Name)
|
||||
p.ShowHelpWithMessage("")
|
||||
}
|
||||
|
||||
// ShowHelpAndExit shows parser help and exits with status code 2
|
||||
func (p *Parser) ShowHelpAndExit(message string) {
|
||||
p.ShowHelpWithMessage(message)
|
||||
exitOrPanic(2)
|
||||
}
|
||||
|
||||
// ShowHelpWithMessage shows the Help for this parser with an optional string error
|
||||
// message as a header. The supplied subcommand will be the context of Help
|
||||
// displayed to the user.
|
||||
func (p *Parser) ShowHelpWithMessage(message string) {
|
||||
|
||||
// create a new Help values template and extract values into it
|
||||
help := Help{}
|
||||
help.ExtractValues(p, message)
|
||||
err := p.HelpTemplate.Execute(os.Stderr, help)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "Error rendering Help template:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Disable show version with --version. It is enabled by default.
|
||||
func (p *Parser) DisableShowVersionWithVersion() {
|
||||
p.ShowVersionWithVersionFlag = false
|
||||
}
|
||||
14
vendor/github.com/integrii/flaggy/positionalValue.go
generated
vendored
Normal file
14
vendor/github.com/integrii/flaggy/positionalValue.go
generated
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
package flaggy
|
||||
|
||||
// PositionalValue represents a value which is determined by its position
|
||||
// relative to where a subcommand was detected.
|
||||
type PositionalValue struct {
|
||||
Name string // used in documentation only
|
||||
Description string
|
||||
AssignmentVar *string // the var that will get this variable
|
||||
Position int // the position, not including switches, of this variable
|
||||
Required bool // this subcommand must always be specified
|
||||
Found bool // was this positional found during parsing?
|
||||
Hidden bool // indicates this positional value should be hidden from help
|
||||
defaultValue string // used for help output
|
||||
}
|
||||
691
vendor/github.com/integrii/flaggy/subCommand.go
generated
vendored
Normal file
691
vendor/github.com/integrii/flaggy/subCommand.go
generated
vendored
Normal file
|
|
@ -0,0 +1,691 @@
|
|||
package flaggy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Subcommand represents a subcommand which contains a set of child
|
||||
// subcommands along with a set of flags relevant to it. Parsing
|
||||
// runs until a subcommand is detected by matching its name and
|
||||
// position. Once a matching subcommand is found, the next set
|
||||
// of parsing occurs within that matched subcommand.
|
||||
type Subcommand struct {
|
||||
Name string
|
||||
ShortName string
|
||||
Description string
|
||||
Position int // the position of this subcommand, not including flags
|
||||
Subcommands []*Subcommand
|
||||
Flags []*Flag
|
||||
PositionalFlags []*PositionalValue
|
||||
AdditionalHelpPrepend string // additional prepended message when Help is displayed
|
||||
AdditionalHelpAppend string // additional appended message when Help is displayed
|
||||
Used bool // indicates this subcommand was found and parsed
|
||||
Hidden bool // indicates this subcommand should be hidden from help
|
||||
}
|
||||
|
||||
// NewSubcommand creates a new subcommand that can have flags or PositionalFlags
|
||||
// added to it. The position starts with 1, not 0
|
||||
func NewSubcommand(name string) *Subcommand {
|
||||
newSC := &Subcommand{
|
||||
Name: name,
|
||||
}
|
||||
return newSC
|
||||
}
|
||||
|
||||
// parseAllFlagsFromArgs parses the non-positional flags such as -f or -v=value
|
||||
// out of the supplied args and returns the positional items in order.
|
||||
func (sc *Subcommand) parseAllFlagsFromArgs(p *Parser, args []string) ([]string, bool, error) {
|
||||
|
||||
var err error
|
||||
var positionalOnlyArguments []string
|
||||
var helpRequested bool // indicates the user has supplied -h and we
|
||||
// should render help if we are the last subcommand
|
||||
|
||||
// indicates we should skip the next argument, like when parsing a flag
|
||||
// that separates key and value by space
|
||||
var skipNext bool
|
||||
|
||||
// endArgfound indicates that a -- was found and everything
|
||||
// remaining should be added to the trailing arguments slices
|
||||
var endArgFound bool
|
||||
|
||||
// find all the normal flags (not positional) and parse them out
|
||||
for i, a := range args {
|
||||
|
||||
debugPrint("parsing arg", 1, a)
|
||||
|
||||
// evaluate if there is a following arg to avoid panics
|
||||
var nextArgExists bool
|
||||
var nextArg string
|
||||
if len(args)-1 >= i+1 {
|
||||
nextArgExists = true
|
||||
nextArg = args[i+1]
|
||||
}
|
||||
|
||||
// if end arg -- has been found, just add everything to TrailingArguments
|
||||
if endArgFound {
|
||||
if !p.trailingArgumentsExtracted {
|
||||
p.TrailingArguments = append(p.TrailingArguments, a)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// skip this run if specified
|
||||
if skipNext {
|
||||
skipNext = false
|
||||
debugPrint("skipping flag because it is an arg:", a)
|
||||
continue
|
||||
}
|
||||
|
||||
// parse the flag into its name for consideration without dashes
|
||||
flagName := parseFlagToName(a)
|
||||
|
||||
// if the flag being passed is version or v and the option to display
|
||||
// version with version flags, then display version
|
||||
if p.ShowVersionWithVersionFlag {
|
||||
if flagName == versionFlagLongName {
|
||||
p.ShowVersionAndExit()
|
||||
}
|
||||
}
|
||||
|
||||
// if the show Help on h flag option is set, then show Help when h or Help
|
||||
// is passed as an option
|
||||
if p.ShowHelpWithHFlag {
|
||||
if flagName == helpFlagShortName || flagName == helpFlagLongName {
|
||||
// Ensure this is the last subcommand passed so we give the correct
|
||||
// help output
|
||||
helpRequested = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// determine what kind of flag this is
|
||||
argType := determineArgType(a)
|
||||
|
||||
// strip flags from arg
|
||||
// debugPrint("Parsing flag named", a, "of type", argType)
|
||||
|
||||
// depending on the flag type, parse the key and value out, then apply it
|
||||
switch argType {
|
||||
case argIsFinal:
|
||||
// debugPrint("Arg", i, "is final:", a)
|
||||
endArgFound = true
|
||||
case argIsPositional:
|
||||
// debugPrint("Arg is positional or subcommand:", a)
|
||||
// this positional argument into a slice of their own, so that
|
||||
// we can determine if its a subcommand or positional value later
|
||||
positionalOnlyArguments = append(positionalOnlyArguments, a)
|
||||
case argIsFlagWithSpace:
|
||||
a = parseFlagToName(a)
|
||||
// debugPrint("Arg", i, "is flag with space:", a)
|
||||
// parse next arg as value to this flag and apply to subcommand flags
|
||||
// if the flag is a bool flag, then we check for a following positional
|
||||
// and skip it if necessary
|
||||
if flagIsBool(sc, p, a) {
|
||||
debugPrint(sc.Name, "bool flag", a, "next var is:", nextArg)
|
||||
_, err = setValueForParsers(a, "true", p, sc)
|
||||
|
||||
// if an error occurs, just return it and quit parsing
|
||||
if err != nil {
|
||||
return []string{}, false, err
|
||||
}
|
||||
// by default, we just assign the next argument to the value and continue
|
||||
continue
|
||||
}
|
||||
|
||||
skipNext = true
|
||||
debugPrint(sc.Name, "NOT bool flag", a)
|
||||
|
||||
// if the next arg was not found, then show a Help message
|
||||
if !nextArgExists {
|
||||
p.ShowHelpWithMessage("Expected a following arg for flag " + a + ", but it did not exist.")
|
||||
exitOrPanic(2)
|
||||
}
|
||||
_, err = setValueForParsers(a, nextArg, p, sc)
|
||||
if err != nil {
|
||||
return []string{}, false, err
|
||||
}
|
||||
case argIsFlagWithValue:
|
||||
// debugPrint("Arg", i, "is flag with value:", a)
|
||||
a = parseFlagToName(a)
|
||||
// parse flag into key and value and apply to subcommand flags
|
||||
key, val := parseArgWithValue(a)
|
||||
_, err = setValueForParsers(key, val, p, sc)
|
||||
if err != nil {
|
||||
return []string{}, false, err
|
||||
}
|
||||
// if this flag type was found and not set, and the parser is set to show
|
||||
// Help when an unknown flag is found, then show Help and exit.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return positionalOnlyArguments, helpRequested, nil
|
||||
}
|
||||
|
||||
// Parse causes the argument parser to parse based on the supplied []string.
|
||||
// depth specifies the non-flag subcommand positional depth
|
||||
func (sc *Subcommand) parse(p *Parser, args []string, depth int) error {
|
||||
|
||||
debugPrint("- Parsing subcommand", sc.Name, "with depth of", depth, "and args", args)
|
||||
|
||||
// if a command is parsed, its used
|
||||
sc.Used = true
|
||||
|
||||
// as subcommands are used, they become the context of the parser. This helps
|
||||
// us understand how to display help based on which subcommand is being used
|
||||
p.subcommandContext = sc
|
||||
|
||||
// ensure that help and version flags are not used if the parser has the
|
||||
// built-in help and version flags enabled
|
||||
if p.ShowHelpWithHFlag {
|
||||
sc.ensureNoConflictWithBuiltinHelp()
|
||||
}
|
||||
if p.ShowVersionWithVersionFlag {
|
||||
sc.ensureNoConflictWithBuiltinVersion()
|
||||
}
|
||||
|
||||
// Parse the normal flags out of the argument list and retain the positionals.
|
||||
// Apply the flags to the parent parser and the current subcommand context.
|
||||
// ./command -f -z subcommand someVar -b becomes ./command subcommand somevar
|
||||
positionalOnlyArguments, helpRequested, err := sc.parseAllFlagsFromArgs(p, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// indicate that trailing arguments have been extracted, so that they aren't
|
||||
// appended a second time
|
||||
p.trailingArgumentsExtracted = true
|
||||
|
||||
// loop over positional values and look for their matching positional
|
||||
// parameter, or their positional command. If neither are found, then
|
||||
// we throw an error
|
||||
var parsedArgCount int
|
||||
for pos, v := range positionalOnlyArguments {
|
||||
|
||||
// the first relative positional argument will be human natural at position 1
|
||||
// but offset for the depth of relative commands being parsed for currently.
|
||||
relativeDepth := pos - depth + 1
|
||||
// debugPrint("Parsing positional only position", relativeDepth, "with value", v)
|
||||
|
||||
if relativeDepth < 1 {
|
||||
// debugPrint(sc.Name, "skipped value:", v)
|
||||
continue
|
||||
}
|
||||
parsedArgCount++
|
||||
|
||||
// determine subcommands and parse them by positional value and name
|
||||
for _, cmd := range sc.Subcommands {
|
||||
// debugPrint("Subcommand being compared", relativeDepth, "==", cmd.Position, "and", v, "==", cmd.Name, "==", cmd.ShortName)
|
||||
if relativeDepth == cmd.Position && (v == cmd.Name || v == cmd.ShortName) {
|
||||
debugPrint("Decending into positional subcommand", cmd.Name, "at relativeDepth", relativeDepth, "and absolute depth", depth+1)
|
||||
return cmd.parse(p, args, depth+parsedArgCount) // continue recursive positional parsing
|
||||
}
|
||||
}
|
||||
|
||||
// determine positional args and parse them by positional value and name
|
||||
var foundPositional bool
|
||||
for _, val := range sc.PositionalFlags {
|
||||
if relativeDepth == val.Position {
|
||||
debugPrint("Found a positional value at relativePos:", relativeDepth, "value:", v)
|
||||
|
||||
// set original value for help output
|
||||
val.defaultValue = *val.AssignmentVar
|
||||
|
||||
// defrerence the struct pointer, then set the pointer property within it
|
||||
*val.AssignmentVar = v
|
||||
// debugPrint("set positional to value", *val.AssignmentVar)
|
||||
foundPositional = true
|
||||
val.Found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// if there aren't any positional flags but there are subcommands that
|
||||
// were not used, display a useful message with subcommand options.
|
||||
if !foundPositional && p.ShowHelpOnUnexpected {
|
||||
debugPrint("No positional at position", relativeDepth)
|
||||
var foundSubcommandAtDepth bool
|
||||
for _, cmd := range sc.Subcommands {
|
||||
if cmd.Position == relativeDepth {
|
||||
foundSubcommandAtDepth = true
|
||||
}
|
||||
}
|
||||
|
||||
// if there is a subcommand here but it was not specified, display them all
|
||||
// as a suggestion to the user before exiting.
|
||||
if foundSubcommandAtDepth {
|
||||
// determine which name to use in upcoming help output
|
||||
fmt.Fprintln(os.Stderr, sc.Name+":", "No subcommand or positional value found at position", strconv.Itoa(relativeDepth)+".")
|
||||
var output string
|
||||
for _, cmd := range sc.Subcommands {
|
||||
if cmd.Hidden {
|
||||
continue
|
||||
}
|
||||
output = output + " " + cmd.Name
|
||||
}
|
||||
// if there are available subcommands, let the user know
|
||||
if len(output) > 0 {
|
||||
output = strings.TrimLeft(output, " ")
|
||||
fmt.Println("Available subcommands:", output)
|
||||
}
|
||||
exitOrPanic(2)
|
||||
}
|
||||
|
||||
// if there were not any flags or subcommands at this position at all, then
|
||||
// throw an error (display Help if necessary)
|
||||
p.ShowHelpWithMessage("Unexpected argument: " + v)
|
||||
exitOrPanic(2)
|
||||
}
|
||||
}
|
||||
|
||||
// if help was requested and we should show help when h is passed,
|
||||
if helpRequested && p.ShowHelpWithHFlag {
|
||||
p.ShowHelp()
|
||||
exitOrPanic(0)
|
||||
}
|
||||
|
||||
// find any positionals that were not used on subcommands that were
|
||||
// found and throw help (unknown argument)
|
||||
for _, pv := range p.PositionalFlags {
|
||||
if pv.Required && !pv.Found {
|
||||
p.ShowHelpWithMessage("Required global positional variable " + pv.Name + " not found at position " + strconv.Itoa(pv.Position))
|
||||
exitOrPanic(2)
|
||||
}
|
||||
}
|
||||
for _, pv := range sc.PositionalFlags {
|
||||
if pv.Required && !pv.Found {
|
||||
p.ShowHelpWithMessage("Required positional of subcommand " + sc.Name + " named " + pv.Name + " not found at position " + strconv.Itoa(pv.Position))
|
||||
exitOrPanic(2)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FlagExists lets you know if the flag name exists as either a short or long
|
||||
// name in the (sub)command
|
||||
func (sc *Subcommand) FlagExists(name string) bool {
|
||||
|
||||
for _, f := range sc.Flags {
|
||||
if f.HasName(name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// AttachSubcommand adds a possible subcommand to the Parser.
|
||||
func (sc *Subcommand) AttachSubcommand(newSC *Subcommand, relativePosition int) {
|
||||
|
||||
// assign the depth of the subcommand when its attached
|
||||
newSC.Position = relativePosition
|
||||
|
||||
// ensure no subcommands at this depth with this name
|
||||
for _, other := range sc.Subcommands {
|
||||
if newSC.Position == other.Position {
|
||||
if newSC.Name != "" {
|
||||
if newSC.Name == other.Name {
|
||||
log.Panicln("Unable to add subcommand because one already exists at position" + strconv.Itoa(newSC.Position) + " with name " + other.Name)
|
||||
}
|
||||
}
|
||||
if newSC.ShortName != "" {
|
||||
if newSC.ShortName == other.ShortName {
|
||||
log.Panicln("Unable to add subcommand because one already exists at position" + strconv.Itoa(newSC.Position) + " with name " + other.ShortName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure no positionals at this depth
|
||||
for _, other := range sc.PositionalFlags {
|
||||
if newSC.Position == other.Position {
|
||||
log.Panicln("Unable to add subcommand because a positional value already exists at position " + strconv.Itoa(newSC.Position) + ": " + other.Name)
|
||||
}
|
||||
}
|
||||
|
||||
sc.Subcommands = append(sc.Subcommands, newSC)
|
||||
}
|
||||
|
||||
// add is a "generic" to add flags of any type. Checks the supplied parent
|
||||
// parser to ensure that the user isn't setting version or help flags that
|
||||
// conflict with the built-in help and version flag behavior.
|
||||
func (sc *Subcommand) add(assignmentVar interface{}, shortName string, longName string, description string) {
|
||||
|
||||
// if the flag is already used, throw an error
|
||||
for _, existingFlag := range sc.Flags {
|
||||
if longName != "" && existingFlag.LongName == longName {
|
||||
log.Panicln("Flag " + longName + " added to subcommand " + sc.Name + " but the name is already assigned.")
|
||||
}
|
||||
if shortName != "" && existingFlag.ShortName == shortName {
|
||||
log.Panicln("Flag " + shortName + " added to subcommand " + sc.Name + " but the short name is already assigned.")
|
||||
}
|
||||
}
|
||||
|
||||
newFlag := Flag{
|
||||
AssignmentVar: assignmentVar,
|
||||
ShortName: shortName,
|
||||
LongName: longName,
|
||||
Description: description,
|
||||
}
|
||||
sc.Flags = append(sc.Flags, &newFlag)
|
||||
}
|
||||
|
||||
// String adds a new string flag
|
||||
func (sc *Subcommand) String(assignmentVar *string, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// StringSlice adds a new slice of strings flag
|
||||
// Specify the flag multiple times to fill the slice
|
||||
func (sc *Subcommand) StringSlice(assignmentVar *[]string, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Bool adds a new bool flag
|
||||
func (sc *Subcommand) Bool(assignmentVar *bool, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// BoolSlice adds a new slice of bools flag
|
||||
// Specify the flag multiple times to fill the slice
|
||||
func (sc *Subcommand) BoolSlice(assignmentVar *[]bool, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// ByteSlice adds a new slice of bytes flag
|
||||
// Specify the flag multiple times to fill the slice. Takes hex as input.
|
||||
func (sc *Subcommand) ByteSlice(assignmentVar *[]byte, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Duration adds a new time.Duration flag.
|
||||
// Input format is described in time.ParseDuration().
|
||||
// Example values: 1h, 1h50m, 32s
|
||||
func (sc *Subcommand) Duration(assignmentVar *time.Duration, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// DurationSlice adds a new time.Duration flag.
|
||||
// Input format is described in time.ParseDuration().
|
||||
// Example values: 1h, 1h50m, 32s
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) DurationSlice(assignmentVar *[]time.Duration, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float32 adds a new float32 flag.
|
||||
func (sc *Subcommand) Float32(assignmentVar *float32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float32Slice adds a new float32 flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Float32Slice(assignmentVar *[]float32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float64 adds a new float64 flag.
|
||||
func (sc *Subcommand) Float64(assignmentVar *float64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Float64Slice adds a new float64 flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Float64Slice(assignmentVar *[]float64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int adds a new int flag
|
||||
func (sc *Subcommand) Int(assignmentVar *int, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IntSlice adds a new int slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) IntSlice(assignmentVar *[]int, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt adds a new uint flag
|
||||
func (sc *Subcommand) UInt(assignmentVar *uint, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UIntSlice adds a new uint slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) UIntSlice(assignmentVar *[]uint, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt64 adds a new uint64 flag
|
||||
func (sc *Subcommand) UInt64(assignmentVar *uint64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt64Slice adds a new uint64 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) UInt64Slice(assignmentVar *[]uint64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt32 adds a new uint32 flag
|
||||
func (sc *Subcommand) UInt32(assignmentVar *uint32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt32Slice adds a new uint32 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) UInt32Slice(assignmentVar *[]uint32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt16 adds a new uint16 flag
|
||||
func (sc *Subcommand) UInt16(assignmentVar *uint16, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt16Slice adds a new uint16 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) UInt16Slice(assignmentVar *[]uint16, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt8 adds a new uint8 flag
|
||||
func (sc *Subcommand) UInt8(assignmentVar *uint8, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// UInt8Slice adds a new uint8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) UInt8Slice(assignmentVar *[]uint8, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int64 adds a new int64 flag.
|
||||
func (sc *Subcommand) Int64(assignmentVar *int64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int64Slice adds a new int64 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Int64Slice(assignmentVar *[]int64, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int32 adds a new int32 flag
|
||||
func (sc *Subcommand) Int32(assignmentVar *int32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int32Slice adds a new int32 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Int32Slice(assignmentVar *[]int32, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int16 adds a new int16 flag
|
||||
func (sc *Subcommand) Int16(assignmentVar *int16, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int16Slice adds a new int16 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Int16Slice(assignmentVar *[]int16, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int8 adds a new int8 flag
|
||||
func (sc *Subcommand) Int8(assignmentVar *int8, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// Int8Slice adds a new int8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) Int8Slice(assignmentVar *[]int8, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IP adds a new net.IP flag.
|
||||
func (sc *Subcommand) IP(assignmentVar *net.IP, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPSlice adds a new int8 slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) IPSlice(assignmentVar *[]net.IP, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// HardwareAddr adds a new net.HardwareAddr flag.
|
||||
func (sc *Subcommand) HardwareAddr(assignmentVar *net.HardwareAddr, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// HardwareAddrSlice adds a new net.HardwareAddr slice flag.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) HardwareAddrSlice(assignmentVar *[]net.HardwareAddr, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPMask adds a new net.IPMask flag. IPv4 Only.
|
||||
func (sc *Subcommand) IPMask(assignmentVar *net.IPMask, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// IPMaskSlice adds a new net.HardwareAddr slice flag. IPv4 only.
|
||||
// Specify the flag multiple times to fill the slice.
|
||||
func (sc *Subcommand) IPMaskSlice(assignmentVar *[]net.IPMask, shortName string, longName string, description string) {
|
||||
sc.add(assignmentVar, shortName, longName, description)
|
||||
}
|
||||
|
||||
// AddPositionalValue adds a positional value to the subcommand. the
|
||||
// relativePosition starts at 1 and is relative to the subcommand it belongs to
|
||||
func (sc *Subcommand) AddPositionalValue(assignmentVar *string, name string, relativePosition int, required bool, description string) {
|
||||
|
||||
// ensure no other positionals are at this depth
|
||||
for _, other := range sc.PositionalFlags {
|
||||
if relativePosition == other.Position {
|
||||
log.Panicln("Unable to add positional value because one already exists at position: " + strconv.Itoa(relativePosition))
|
||||
}
|
||||
}
|
||||
|
||||
// ensure no subcommands at this depth
|
||||
for _, other := range sc.Subcommands {
|
||||
if relativePosition == other.Position {
|
||||
log.Panicln("Unable to add positional value a subcommand already exists at position: " + strconv.Itoa(relativePosition))
|
||||
}
|
||||
}
|
||||
|
||||
newPositionalValue := PositionalValue{
|
||||
Name: name,
|
||||
Position: relativePosition,
|
||||
AssignmentVar: assignmentVar,
|
||||
Required: required,
|
||||
Description: description,
|
||||
}
|
||||
sc.PositionalFlags = append(sc.PositionalFlags, &newPositionalValue)
|
||||
}
|
||||
|
||||
// SetValueForKey sets the value for the specified key. If setting a bool
|
||||
// value, then send "true" or "false" as strings. The returned bool indicates
|
||||
// that a value was set.
|
||||
func (sc *Subcommand) SetValueForKey(key string, value string) (bool, error) {
|
||||
|
||||
// debugPrint("Looking to set key", key, "to value", value)
|
||||
// check for and assign flags that match the key
|
||||
for _, f := range sc.Flags {
|
||||
// debugPrint("Evaluating string flag", f.ShortName, "==", key, "||", f.LongName, "==", key)
|
||||
if f.ShortName == key || f.LongName == key {
|
||||
// debugPrint("Setting string value for", key, "to", value)
|
||||
f.identifyAndAssignValue(value)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// debugPrint(sc.Name, "was unable to find a key named", key, "to set to value", value)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ensureNoConflictWithBuiltinHelp ensures that the flags on this subcommand do
|
||||
// not conflict with the builtin help flags (-h or --help). Exits the program
|
||||
// if a conflict is found.
|
||||
func (sc *Subcommand) ensureNoConflictWithBuiltinHelp() {
|
||||
for _, f := range sc.Flags {
|
||||
if f.LongName == helpFlagLongName {
|
||||
sc.exitBecauseOfHelpFlagConflict(f.LongName)
|
||||
}
|
||||
if f.LongName == helpFlagShortName {
|
||||
sc.exitBecauseOfHelpFlagConflict(f.LongName)
|
||||
}
|
||||
if f.ShortName == helpFlagLongName {
|
||||
sc.exitBecauseOfHelpFlagConflict(f.ShortName)
|
||||
}
|
||||
if f.ShortName == helpFlagShortName {
|
||||
sc.exitBecauseOfHelpFlagConflict(f.ShortName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensureNoConflictWithBuiltinVersion ensures that the flags on this subcommand do
|
||||
// not conflict with the builtin version flag (--version). Exits the program
|
||||
// if a conflict is found.
|
||||
func (sc *Subcommand) ensureNoConflictWithBuiltinVersion() {
|
||||
for _, f := range sc.Flags {
|
||||
if f.LongName == versionFlagLongName {
|
||||
sc.exitBecauseOfVersionFlagConflict(f.LongName)
|
||||
}
|
||||
if f.ShortName == versionFlagLongName {
|
||||
sc.exitBecauseOfVersionFlagConflict(f.ShortName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// exitBecauseOfVersionFlagConflict exits the program with a message about how to prevent
|
||||
// flags being defined from conflicting with the builtin flags.
|
||||
func (sc *Subcommand) exitBecauseOfVersionFlagConflict(flagName string) {
|
||||
fmt.Println(`Flag with name '` + flagName + `' conflicts with the internal --version flag in flaggy.
|
||||
|
||||
You must either change the flag's name, or disable flaggy's internal version
|
||||
flag with 'flaggy.DefaultParser.ShowVersionWithVersionFlag = false'. If you are using
|
||||
a custom parser, you must instead set '.ShowVersionWithVersionFlag = false' on it.`)
|
||||
exitOrPanic(1)
|
||||
}
|
||||
|
||||
// exitBecauseOfHelpFlagConflict exits the program with a message about how to prevent
|
||||
// flags being defined from conflicting with the builtin flags.
|
||||
func (sc *Subcommand) exitBecauseOfHelpFlagConflict(flagName string) {
|
||||
fmt.Println(`Flag with name '` + flagName + `' conflicts with the internal --help or -h flag in flaggy.
|
||||
|
||||
You must either change the flag's name, or disable flaggy's internal help
|
||||
flag with 'flaggy.DefaultParser.ShowHelpWithHFlag = false'. If you are using
|
||||
a custom parser, you must instead set '.ShowHelpWithHFlag = false' on it.`)
|
||||
exitOrPanic(1)
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue