summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDawid Dziurla <dawidd0811@gmail.com>2019-09-24 19:45:46 +0200
committerGitHub <noreply@github.com>2019-09-24 19:45:46 +0200
commit95ae806e09380e6c1602a91af6d34e8ffd770274 (patch)
tree184705ff68926b21924171b0389c208fba1a15c2
parent379dcf0972d55cb16f3d58cd475988ca2a9c5915 (diff)
parentd8a6f173c3569c676d6585f58420c12c34470f32 (diff)
Merge pull request #414 from glvr182/feature/dir-as-arg
Provide git directory as argument to Lazygit
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--main.go36
-rw-r--r--vendor/github.com/integrii/flaggy/.gitignore14
-rw-r--r--vendor/github.com/integrii/flaggy/LICENSE24
-rw-r--r--vendor/github.com/integrii/flaggy/README.md252
-rw-r--r--vendor/github.com/integrii/flaggy/argumentParser.go29
-rw-r--r--vendor/github.com/integrii/flaggy/flag.go622
-rw-r--r--vendor/github.com/integrii/flaggy/go.mod3
-rw-r--r--vendor/github.com/integrii/flaggy/help.go23
-rw-r--r--vendor/github.com/integrii/flaggy/helpValues.go221
-rw-r--r--vendor/github.com/integrii/flaggy/logo.pngbin0 -> 11556 bytes
-rw-r--r--vendor/github.com/integrii/flaggy/main.go341
-rw-r--r--vendor/github.com/integrii/flaggy/parser.go111
-rw-r--r--vendor/github.com/integrii/flaggy/positionalValue.go14
-rw-r--r--vendor/github.com/integrii/flaggy/subCommand.go691
-rw-r--r--vendor/modules.txt2
17 files changed, 2377 insertions, 9 deletions
diff --git a/go.mod b/go.mod
index eabf54077..2a8e33f0f 100644
--- a/go.mod
+++ b/go.mod
@@ -22,6 +22,7 @@ require (
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc // indirect
github.com/hashicorp/go-version v1.0.0 // indirect
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce // indirect
+ github.com/integrii/flaggy v1.2.2
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63
github.com/jesseduffield/gocui v0.3.1-0.20190908012510-092b2290ee54
diff --git a/go.sum b/go.sum
index e92744e98..1b900db41 100644
--- a/go.sum
+++ b/go.sum
@@ -48,6 +48,8 @@ github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce h1:xdsDDbiBDQTKASoGE
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/integrii/flaggy v1.2.2 h1:SzL5kyEaW+Cb3RLxGG1ch9FFDLQPB6QuMdYoNu5JIo0=
+github.com/integrii/flaggy v1.2.2/go.mod h1:tnTxHeTJbah0gQ6/K0RW0J7fMUBk9MCF5blhm43LNpI=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jesseduffield/go-getter v0.0.0-20180822080847-906e15686e63 h1:tbm85YuPi3d1LFAUr6yZyzZ4vR96ygV98rezZZ+ywbg=
diff --git a/main.go b/main.go
index 7481e24d6..0f528dd0d 100644
--- a/main.go
+++ b/main.go
@@ -1,7 +1,6 @@
package main
import (
- "flag"
"fmt"
"log"
"os"
@@ -9,6 +8,7 @@ import (
"runtime"
"github.com/go-errors/errors"
+ "github.com/integrii/flaggy"
"github.com/jesseduffield/lazygit/pkg/app"
"github.com/jesseduffield/lazygit/pkg/config"
)
@@ -18,10 +18,6 @@ var (
version = "unversioned"
date string
buildSource = "unknown"
-
- configFlag = flag.Bool("config", false, "Print the current default config")
- debuggingFlag = flag.Bool("debug", false, "a boolean")
- versionFlag = flag.Bool("v", false, "Print the current version")
)
func projectPath(path string) string {
@@ -30,17 +26,39 @@ func projectPath(path string) string {
}
func main() {
- flag.Parse()
- if *versionFlag {
+ flaggy.DefaultParser.ShowVersionWithVersionFlag = false
+
+ repoPath := "."
+ flaggy.AddPositionalValue(&repoPath, "path", 1, false, "Path of git repo")
+
+ versionFlag := false
+ flaggy.Bool(&versionFlag, "v", "version", "Print the current version")
+
+ debuggingFlag := false
+ flaggy.Bool(&debuggingFlag, "d", "debug", "Run in debug mode with logging")
+
+ configFlag := false
+ flaggy.Bool(&configFlag, "c", "config", "Print the current default config")
+
+ flaggy.Parse()
+
+ if versionFlag {
fmt.Printf("commit=%s, build date=%s, build source=%s, version=%s, os=%s, arch=%s\n", commit, date, buildSource, version, runtime.GOOS, runtime.GOARCH)
os.Exit(0)
}
- if *configFlag {
+ if configFlag {
fmt.Printf("%s\n", config.GetDefaultConfig())
os.Exit(0)
}
- appConfig, err := config.NewAppConfig("lazygit", version, commit, date, buildSource, *debuggingFlag)
+
+ if repoPath != "." {
+ if err := os.Chdir(repoPath); err != nil {
+ log.Fatal(err.Error())
+ }
+ }
+
+ appConfig, err := config.NewAppConfig("lazygit", version, commit, date, buildSource, debuggingFlag)
if err != nil {
log.Fatal(err.Error())
}
diff --git a/vendor/github.com/integrii/flaggy/.gitignore b/vendor/github.com/integrii/flaggy/.gitignore
new file mode 100644
index 000000000..a1338d685
--- /dev/null
+++ b/vendor/github.com/integrii/flaggy/.gitignore
@@ -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/
diff --git a/vendor/github.com/integrii/flaggy/LICENSE b/vendor/github.com/integrii/flaggy/LICENSE
new file mode 100644
index 000000000..cf1ab25da
--- /dev/null
+++ b/vendor/github.com/integrii/flaggy/LICENSE
@@ -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>
diff --git a/vendor/github.com/integrii/flaggy/README.md b/vendor/github.com/integrii/flaggy/README.md
new file mode 100644
index 000000000..77fa20cc0
--- /dev/null
+++ b/vendor/github.com/integrii/flaggy/README.md
@@ -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.
diff --git a/vendor/github.com/integrii/flaggy/argumentParser.go b/vendor/github.com/integrii/flaggy/argumentParser.go
new file mode 100644
index 000000000..089f2c5ce
--- /dev/null
+++ b/vendor/github.com/integrii/flaggy/argumentParser.go
@@ -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)
+}
diff --git a/vendor/github.com/integrii/flaggy/flag.go b/vendor/github.com/integrii/flaggy/flag.go
new file mode 100644
index 000000000..409ddf94d
--- /dev/null
+++ b/vendor/github.com/integrii/flaggy/flag.go
@@ -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 :