mirror of
https://github.com/jesseduffield/lazygit.git
synced 2024-11-26 09:00:57 +02:00
Mod: Added flaggy to vendor directory
Signed-off-by: Glenn Vriesman <glenn.vriesman@gmail.com>
This commit is contained in:
parent
431f1aa766
commit
d8a6f173c3
14
vendor/github.com/integrii/flaggy/.gitignore
generated
vendored
Normal file
14
vendor/github.com/integrii/flaggy/.gitignore
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
|
||||
.glide/
|
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>
|
252
vendor/github.com/integrii/flaggy/README.md
generated
vendored
Normal file
252
vendor/github.com/integrii/flaggy/README.md
generated
vendored
Normal file
@ -0,0 +1,252 @@
|
||||
<p align="center">
|
||||
|
||||
<img src="/logo.png" />
|
||||
<br />
|
||||
<a href="https://goreportcard.com/report/github.com/integrii/flaggy"><img src="https://goreportcard.com/badge/github.com/integrii/flaggy"></a>
|
||||
<a href="https://travis-ci.org/integrii/flaggy"><img src="https://travis-ci.org/integrii/flaggy.svg?branch=master"></a>
|
||||
<a href="http://godoc.org/github.com/integrii/flaggy"><img src="https://camo.githubusercontent.com/d48cccd1ce67ddf8ba7fc356ec1087f3f7aa6d12/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f6c696c65696f2f6c696c653f7374617475732e737667"></a>
|
||||
<a href="http://unlicense.org/"><img src="https://img.shields.io/badge/license-Unlicense-blue.svg"></a>
|
||||
<a href="https://cover.run/go?repo=github.com%2Fintegrii%2Fflaggy&tag=golang-1.10"><img src="https://cover.run/go/github.com/integrii/flaggy.svg?style=flat&tag=golang-1.10"></a>
|
||||
<a href="https://github.com/avelino/awesome-go"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg"></a>
|
||||
</p>
|
||||
|
||||
Sensible and _fast_ command-line flag parsing with excellent support for **subcommands** and **positional values**. Flags can be at any position. Flaggy has no required project or package layout like [Cobra requires](https://github.com/spf13/cobra/issues/641), and **no external dependencies**!
|
||||
|
||||
Check out the [godoc](http://godoc.org/github.com/integrii/flaggy), [examples directory](https://github.com/integrii/flaggy/tree/master/examples), and [examples in this readme](https://github.com/integrii/flaggy#super-simple-example) to get started quickly. You can also read the Flaggy introduction post with helpful examples [on my weblog](https://ericgreer.info/post/a-better-flags-package-for-go/).
|
||||
|
||||
# Installation
|
||||
|
||||
`go get -u github.com/integrii/flaggy`
|
||||
|
||||
# Key Features
|
||||
|
||||
- Very easy to use ([see examples below](https://github.com/integrii/flaggy#super-simple-example))
|
||||
- 35 different flag types supported
|
||||
- Any flag can be at any position
|
||||
- Pretty and readable help output by default
|
||||
- Positional subcommands
|
||||
- Positional parameters
|
||||
- Suggested subcommands when a subcommand is typo'd
|
||||
- Nested subcommands
|
||||
- Both global and subcommand specific flags
|
||||
- Both global and subcommand specific positional parameters
|
||||
- Customizable help templates for both the global command and subcommands
|
||||
- Customizable appended/prepended help messages for both the global command and subcommands
|
||||
- Simple function that displays help followed by a custom message string
|
||||
- Flags and subcommands may have both a short and long name
|
||||
- Unlimited trailing arguments after a `--`
|
||||
- Flags can use a single dash or double dash (`--flag`, `-flag`, `-f`, `--f`)
|
||||
- Flags can have `=` assignment operators, or use a space (`--flag=value`, `--flag value`)
|
||||
- Flags support single quote globs with spaces (`--flag 'this is all one value'`)
|
||||
- Flags of slice types can be passed multiple times (`-f one -f two -f three`)
|
||||
- Optional but default version output with `--version`
|
||||
- Optional but default help output with `-h` or `--help`
|
||||
- Optional but default help output when any invalid or unknown parameter is passed
|
||||
- It's _fast_. All flag and subcommand parsing takes less than `1ms` in most programs.
|
||||
|
||||
|
||||
# Example Help Output
|
||||
|
||||
```
|
||||
testCommand - Description goes here. Get more information at http://flaggy.
|
||||
This is a prepend for help
|
||||
|
||||
Usage:
|
||||
testCommand [subcommandA|subcommandB|subcommandC] [testPositionalA] [testPositionalB]
|
||||
|
||||
Positional Variables:
|
||||
testPositionalA - (Required) Test positional A does some things with a positional value. (default: defaultValue)
|
||||
testPositionalB - Test positional B does some less than serious things with a positional value.
|
||||
|
||||
Subcommands:
|
||||
subcommandA (a) - Subcommand A is a command that does stuff
|
||||
subcommandB (b) - Subcommand B is a command that does other stuff
|
||||
subcommandC (c) - Subcommand C is a command that does SERIOUS stuff
|
||||
|
||||
Flags:
|
||||
--version Displays the program version string.
|
||||
-h --help Displays help with available flag, subcommand, and positional value parameters.
|
||||
-s --stringFlag This is a test string flag that does some stringy string stuff.
|
||||
-i --intFlg This is a test int flag that does some interesting int stuff. (default: 5)
|
||||
-b --boolFlag This is a test bool flag that does some booly bool stuff. (default: true)
|
||||
-d --durationFlag This is a test duration flag that does some untimely stuff. (default: 1h23s)
|
||||
|
||||
This is an append for help
|
||||
This is a help add-on message
|
||||
```
|
||||
|
||||
# Super Simple Example
|
||||
|
||||
`./yourApp -f test`
|
||||
|
||||
```go
|
||||
// Declare variables and their defaults
|
||||
var stringFlag = "defaultValue"
|
||||
|
||||
// Add a flag
|
||||
flaggy.String(&stringFlag, "f", "flag", "A test string flag")
|
||||
|
||||
// Parse the flag
|
||||
flaggy.Parse()
|
||||
|
||||
// Use the flag
|
||||
print(stringFlag)
|
||||
```
|
||||
|
||||
|
||||
# Example with Subcommand
|
||||
|
||||
`./yourApp subcommandExample -f test`
|
||||
|
||||
```go
|
||||
// Declare variables and their defaults
|
||||
var stringFlag = "defaultValue"
|
||||
|
||||
// Create the subcommand
|
||||
subcommand := flaggy.NewSubcommand("subcommandExample")
|
||||
|
||||
// Add a flag to the subcommand
|
||||
subcommand.String(&stringFlag, "f", "flag", "A test string flag")
|
||||
|
||||
// Add the subcommand to the parser at position 1
|
||||
flaggy.AttachSubcommand(subcommand, 1)
|
||||
|
||||
// Parse the subcommand and all flags
|
||||
flaggy.Parse()
|
||||
|
||||
// Use the flag
|
||||
print(stringFlag)
|
||||
```
|
||||
|
||||
# Example with Nested Subcommands, Various Flags and Trailing Arguments
|
||||
|
||||
`./yourApp subcommandExample --flag=5 nestedSubcommand -t test -y -- trailingArg`
|
||||
|
||||
```go
|
||||
// Declare variables and their defaults
|
||||
var stringFlagF = "defaultValueF"
|
||||
var intFlagT = 3
|
||||
var boolFlagB bool
|
||||
|
||||
// Create the subcommands
|
||||
subcommandExample := flaggy.NewSubcommand("subcommandExample")
|
||||
nestedSubcommand := flaggy.NewSubcommand("nestedSubcommand")
|
||||
|
||||
// Add a flag to both subcommands
|
||||
subcommandExample.String(&stringFlagF, "t", "testFlag", "A test string flag")
|
||||
nestedSubcommand.Int(&intFlagT, "f", "flag", "A test int flag")
|
||||
|
||||
// add a global bool flag for fun
|
||||
flaggy.Bool(&boolFlagB, "y", "yes", "A sample boolean flag")
|
||||
|
||||
// attach the nested subcommand to the parent subcommand at position 1
|
||||
subcommandExample.AttachSubcommand(nestedSubcommand, 1)
|
||||
// attach the base subcommand to the parser at position 1
|
||||
flaggy.AttachSubcommand(subcommandExample, 1)
|
||||
|
||||
// Parse everything, then use the flags and trailing arguments
|
||||
flaggy.Parse()
|
||||
print(stringFlagF)
|
||||
print(intFlagT)
|
||||
print(boolFlagB)
|
||||
print(flaggy.TrailingArguments[0])
|
||||
```
|
||||
|
||||
# Supported Flag Types:
|
||||
|
||||
- string
|
||||
- []string
|
||||
- bool
|
||||
- []bool
|
||||
- time.Duration
|
||||
- []time.Duration
|
||||
- float32
|
||||
- []float32
|
||||
- float64
|
||||
- []float64
|
||||
- uint
|
||||
- uint64
|
||||
- []uint64
|
||||
- uint32
|
||||
- []uint32
|
||||
- uint16
|
||||
- []uint16
|
||||
- uint8
|
||||
- []uint8
|
||||
- []byte
|
||||
- int
|
||||
- []int
|
||||
- int64
|
||||
- []int64
|
||||
- int32
|
||||
- []int32
|
||||
- int16
|
||||
- []int16
|
||||
- int8
|
||||
- []int8
|
||||
- net.IP
|
||||
- []net.IP
|
||||
- net.HardwareAddr
|
||||
- []net.HardwareAddr
|
||||
- net.IPMask
|
||||
- []net.IPMask
|
||||
|
||||
|
||||
# Recommended Program Structure
|
||||
|
||||
Best practice when using flaggy includes setting your program's name, description, and version (at build time).
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import "github.com/integrii/flaggy"
|
||||
|
||||
// make a variable for the version which will be set at build time
|
||||
var version = "unknown"
|
||||
|
||||
// keep subcommands as globals so you can easily check if they were used later on
|
||||
var mySubcommand *flaggy.Subcommand
|
||||
|
||||
func init() {
|
||||
// Set your program's name and description. These appear in help output.
|
||||
flaggy.SetName("Test Program")
|
||||
flaggy.SetDescription("A little example program")
|
||||
|
||||
// you can disable various things by changing bools on the default parser
|
||||
// (or your own parser if you have created one)
|
||||
flaggy.DefaultParser.ShowHelpOnUnexpected = false
|
||||
|
||||
// you can set a help prepend or append on the default parser
|
||||
flaggy.DefaultParser.AdditionalHelpPrepend = "http://github.com/integrii/flaggy"
|
||||
|
||||
// create any subcommands and set their parameters
|
||||
mySubcommand = flaggy.NewSubcommand("mySubcommand")
|
||||
mySubcommand.Description = "My great subcommand!"
|
||||
|
||||
// set the version and parse all inputs into variables
|
||||
flaggy.SetVersion(version)
|
||||
flaggy.Parse()
|
||||
}
|
||||
func main(){
|
||||
if mySubcommand.Used {
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can use the following build command to set the `version` variable in the above program at build time.
|
||||
|
||||
```bash
|
||||
# build your app and set the version string
|
||||
$ go build -ldflags='-X main.version=1.0.3-a3db3'
|
||||
$ ./yourApp version
|
||||
Version: 1.0.3-a3db3
|
||||
$ ./yourApp --help
|
||||
Test Program - A little example program
|
||||
http://github.com/integrii/flaggy
|
||||
```
|
||||
|
||||
|
||||
# Contributions
|
||||
|
||||
Please feel free to open an issue if you find any bugs or see any features that make sense. Pull requests will be reviewed and accepted if they make sense, but it is always wise to submit a proposal issue before any major changes.
|
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())
|
||||
}
|
||||
}
|
3
vendor/github.com/integrii/flaggy/go.mod
generated
vendored
Normal file
3
vendor/github.com/integrii/flaggy/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module github.com/integrii/flaggy
|
||||
|
||||
go 1.12
|
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}}
|
||||
`
|
221
vendor/github.com/integrii/flaggy/helpValues.go
generated
vendored
Normal file
221
vendor/github.com/integrii/flaggy/helpValues.go
generated
vendored
Normal file
@ -0,0 +1,221 @@
|
||||
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
|
||||
}
|
||||
|
||||
// parse help values out if the flag hasn't been parsed yet
|
||||
if !f.parsed {
|
||||
f.parsed = true
|
||||
// parse the default value as a string and remember it for help output
|
||||
f.defaultValue, _ = f.returnAssignmentVarValueAsString()
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
BIN
vendor/github.com/integrii/flaggy/logo.png
generated
vendored
Normal file
BIN
vendor/github.com/integrii/flaggy/logo.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
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)
|
||||
}
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -72,6 +72,8 @@ github.com/hashicorp/hcl/hcl/scanner
|
||||
github.com/hashicorp/hcl/hcl/strconv
|
||||
github.com/hashicorp/hcl/json/scanner
|
||||
github.com/hashicorp/hcl/json/token
|
||||
# github.com/integrii/flaggy v1.2.2
|
||||
github.com/integrii/flaggy
|
||||
# github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99
|
||||
github.com/jbenet/go-context/io
|
||||
# github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63
|
||||
|
Loading…
Reference in New Issue
Block a user