From 87d473dc8f61f8b633c037b40eb9190045a7c88c Mon Sep 17 00:00:00 2001 From: Jakob Borg Date: Mon, 17 Feb 2014 09:12:58 +0100 Subject: [PATCH] Remove obsolete go-flags package --- github.com/jessevdk/go-flags/LICENSE | 26 -- github.com/jessevdk/go-flags/README.md | 128 ------- github.com/jessevdk/go-flags/assert_test.go | 82 ----- .../jessevdk/go-flags/check_crosscompile.sh | 16 - github.com/jessevdk/go-flags/closest.go | 61 ---- github.com/jessevdk/go-flags/command.go | 84 ----- .../jessevdk/go-flags/command_private.go | 161 --------- github.com/jessevdk/go-flags/command_test.go | 255 -------------- github.com/jessevdk/go-flags/convert.go | 315 ----------------- github.com/jessevdk/go-flags/error.go | 113 ------ github.com/jessevdk/go-flags/example_test.go | 95 ----- github.com/jessevdk/go-flags/examples/add.go | 23 -- github.com/jessevdk/go-flags/examples/main.go | 75 ---- github.com/jessevdk/go-flags/examples/rm.go | 23 -- github.com/jessevdk/go-flags/flags.go | 141 -------- github.com/jessevdk/go-flags/group.go | 80 ----- github.com/jessevdk/go-flags/group_private.go | 263 -------------- github.com/jessevdk/go-flags/group_test.go | 160 --------- github.com/jessevdk/go-flags/help.go | 275 --------------- github.com/jessevdk/go-flags/help_test.go | 153 -------- github.com/jessevdk/go-flags/ini.go | 146 -------- github.com/jessevdk/go-flags/ini_private.go | 333 ------------------ github.com/jessevdk/go-flags/ini_test.go | 170 --------- github.com/jessevdk/go-flags/long_test.go | 85 ----- github.com/jessevdk/go-flags/man.go | 134 ------- github.com/jessevdk/go-flags/marshal_test.go | 78 ---- github.com/jessevdk/go-flags/multitag.go | 140 -------- github.com/jessevdk/go-flags/option.go | 95 ----- .../jessevdk/go-flags/option_private.go | 125 ------- github.com/jessevdk/go-flags/options_test.go | 45 --- .../jessevdk/go-flags/optstyle_other.go | 54 --- .../jessevdk/go-flags/optstyle_windows.go | 85 ----- github.com/jessevdk/go-flags/parser.go | 212 ----------- .../jessevdk/go-flags/parser_private.go | 243 ------------- github.com/jessevdk/go-flags/pointer_test.go | 81 ----- github.com/jessevdk/go-flags/short_test.go | 169 --------- github.com/jessevdk/go-flags/tag_test.go | 39 -- github.com/jessevdk/go-flags/termsize.go | 5 - github.com/jessevdk/go-flags/unknown_test.go | 66 ---- 39 files changed, 4834 deletions(-) delete mode 100644 github.com/jessevdk/go-flags/LICENSE delete mode 100644 github.com/jessevdk/go-flags/README.md delete mode 100644 github.com/jessevdk/go-flags/assert_test.go delete mode 100755 github.com/jessevdk/go-flags/check_crosscompile.sh delete mode 100644 github.com/jessevdk/go-flags/closest.go delete mode 100644 github.com/jessevdk/go-flags/command.go delete mode 100644 github.com/jessevdk/go-flags/command_private.go delete mode 100644 github.com/jessevdk/go-flags/command_test.go delete mode 100644 github.com/jessevdk/go-flags/convert.go delete mode 100644 github.com/jessevdk/go-flags/error.go delete mode 100644 github.com/jessevdk/go-flags/example_test.go delete mode 100644 github.com/jessevdk/go-flags/examples/add.go delete mode 100644 github.com/jessevdk/go-flags/examples/main.go delete mode 100644 github.com/jessevdk/go-flags/examples/rm.go delete mode 100644 github.com/jessevdk/go-flags/flags.go delete mode 100644 github.com/jessevdk/go-flags/group.go delete mode 100644 github.com/jessevdk/go-flags/group_private.go delete mode 100644 github.com/jessevdk/go-flags/group_test.go delete mode 100644 github.com/jessevdk/go-flags/help.go delete mode 100644 github.com/jessevdk/go-flags/help_test.go delete mode 100644 github.com/jessevdk/go-flags/ini.go delete mode 100644 github.com/jessevdk/go-flags/ini_private.go delete mode 100644 github.com/jessevdk/go-flags/ini_test.go delete mode 100644 github.com/jessevdk/go-flags/long_test.go delete mode 100644 github.com/jessevdk/go-flags/man.go delete mode 100644 github.com/jessevdk/go-flags/marshal_test.go delete mode 100644 github.com/jessevdk/go-flags/multitag.go delete mode 100644 github.com/jessevdk/go-flags/option.go delete mode 100644 github.com/jessevdk/go-flags/option_private.go delete mode 100644 github.com/jessevdk/go-flags/options_test.go delete mode 100644 github.com/jessevdk/go-flags/optstyle_other.go delete mode 100644 github.com/jessevdk/go-flags/optstyle_windows.go delete mode 100644 github.com/jessevdk/go-flags/parser.go delete mode 100644 github.com/jessevdk/go-flags/parser_private.go delete mode 100644 github.com/jessevdk/go-flags/pointer_test.go delete mode 100644 github.com/jessevdk/go-flags/short_test.go delete mode 100644 github.com/jessevdk/go-flags/tag_test.go delete mode 100644 github.com/jessevdk/go-flags/termsize.go delete mode 100644 github.com/jessevdk/go-flags/unknown_test.go diff --git a/github.com/jessevdk/go-flags/LICENSE b/github.com/jessevdk/go-flags/LICENSE deleted file mode 100644 index bcca0d521..000000000 --- a/github.com/jessevdk/go-flags/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/github.com/jessevdk/go-flags/README.md b/github.com/jessevdk/go-flags/README.md deleted file mode 100644 index 4194e2c41..000000000 --- a/github.com/jessevdk/go-flags/README.md +++ /dev/null @@ -1,128 +0,0 @@ -go-flags: a go library for parsing command line arguments -========================================================= - -This library provides similar functionality to the builtin flag library of -go, but provides much more functionality and nicer formatting. From the -documentation: - -Package flags provides an extensive command line option parser. -The flags package is similar in functionality to the go builtin flag package -but provides more options and uses reflection to provide a convenient and -succinct way of specifying command line options. - -Supported features: -* Options with short names (-v) -* Options with long names (--verbose) -* Options with and without arguments (bool v.s. other type) -* Options with optional arguments and default values -* Multiple option groups each containing a set of options -* Generate and print well-formatted help message -* Passing remaining command line arguments after -- (optional) -* Ignoring unknown command line options (optional) -* Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification -* Supports multiple short options -aux -* Supports all primitive go types (string, int{8..64}, uint{8..64}, float) -* Supports same option multiple times (can store in slice or last option counts) -* Supports maps -* Supports function callbacks - -The flags package uses structs, reflection and struct field tags -to allow users to specify command line options. This results in very simple -and consise specification of your application options. For example: - - type Options struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - } - -This specifies one option with a short name -v and a long name --verbose. -When either -v or --verbose is found on the command line, a 'true' value -will be appended to the Verbose field. e.g. when specifying -vvv, the -resulting value of Verbose will be {[true, true, true]}. - -Example: --------- - var opts struct { - // Slice of bool will append 'true' each time the option - // is encountered (can be set multiple times, like -vvv) - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - - // Example of automatic marshalling to desired type (uint) - Offset uint `long:"offset" description:"Offset"` - - // Example of a callback, called each time the option is found. - Call func(string) `short:"c" description:"Call phone number"` - - // Example of a required flag - Name string `short:"n" long:"name" description:"A name" required:"true"` - - // Example of a value name - File string `short:"f" long:"file" description:"A file" value-name:"FILE"` - - // Example of a pointer - Ptr *int `short:"p" description:"A pointer to an integer"` - - // Example of a slice of strings - StringSlice []string `short:"s" description:"A slice of strings"` - - // Example of a slice of pointers - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - - // Example of a map - IntMap map[string]int `long:"intmap" description:"A map from string to int"` - } - - // Callback which will invoke callto: to call a number. - // Note that this works just on OS X (and probably only with - // Skype) but it shows the idea. - opts.Call = func(num string) { - cmd := exec.Command("open", "callto:"+num) - cmd.Start() - cmd.Process.Release() - } - - // Make some fake arguments to parse. - args := []string{ - "-vv", - "--offset=5", - "-n", "Me", - "-p", "3", - "-s", "hello", - "-s", "world", - "--ptrslice", "hello", - "--ptrslice", "world", - "--intmap", "a:1", - "--intmap", "b:5", - "arg1", - "arg2", - "arg3", - } - - // Parse flags from `args'. Note that here we use flags.ParseArgs for - // the sake of making a working example. Normally, you would simply use - // flags.Parse(&opts) which uses os.Args - args, err := flags.ParseArgs(&opts, args) - - if err != nil { - panic(err) - os.Exit(1) - } - - fmt.Printf("Verbosity: %v\n", opts.Verbose) - fmt.Printf("Offset: %d\n", opts.Offset) - fmt.Printf("Name: %s\n", opts.Name) - fmt.Printf("Ptr: %d\n", *opts.Ptr) - fmt.Printf("StringSlice: %v\n", opts.StringSlice) - fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) - fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) - fmt.Printf("Remaining args: %s\n", strings.Join(args, " ")) - - // Output: Verbosity: [true true] - // Offset: 5 - // Name: Me - // Ptr: 3 - // StringSlice: [hello world] - // PtrSlice: [hello world] - // IntMap: [a:1 b:5] - // Remaining args: arg1 arg2 arg3 - -More information can be found in the godocs: diff --git a/github.com/jessevdk/go-flags/assert_test.go b/github.com/jessevdk/go-flags/assert_test.go deleted file mode 100644 index 49d093c34..000000000 --- a/github.com/jessevdk/go-flags/assert_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package flags - -import ( - "testing" -) - -func assertString(t *testing.T, a string, b string) { - if a != b { - t.Errorf("Expected %#v, but got %#v", b, a) - } -} -func assertStringArray(t *testing.T, a []string, b []string) { - if len(a) != len(b) { - t.Errorf("Expected %#v, but got %#v", b, a) - return - } - - for i, v := range a { - if b[i] != v { - t.Errorf("Expected %#v, but got %#v", b, a) - return - } - } -} - -func assertBoolArray(t *testing.T, a []bool, b []bool) { - if len(a) != len(b) { - t.Errorf("Expected %#v, but got %#v", b, a) - return - } - - for i, v := range a { - if b[i] != v { - t.Errorf("Expected %#v, but got %#v", b, a) - return - } - } -} - -func assertParserSuccess(t *testing.T, data interface{}, args ...string) (*Parser, []string) { - parser := NewParser(data, Default&^PrintErrors) - ret, err := parser.ParseArgs(args) - - if err != nil { - t.Fatalf("Unexpected parse error: %s", err) - return nil, nil - } - - return parser, ret -} - -func assertParseSuccess(t *testing.T, data interface{}, args ...string) []string { - _, ret := assertParserSuccess(t, data, args...) - return ret -} - -func assertError(t *testing.T, err error, typ ErrorType, msg string) { - if err == nil { - t.Fatalf("Expected error: %s", msg) - return - } - - if e, ok := err.(*Error); !ok { - t.Fatalf("Expected Error type, but got %#v", err) - return - } else { - if e.Type != typ { - t.Errorf("Expected error type {%s}, but got {%s}", typ, e.Type) - } - - if e.Message != msg { - t.Errorf("Expected error message %#v, but got %#v", msg, e.Message) - } - } -} - -func assertParseFail(t *testing.T, typ ErrorType, msg string, data interface{}, args ...string) { - parser := NewParser(data, Default&^PrintErrors) - _, err := parser.ParseArgs(args) - - assertError(t, err, typ, msg) -} diff --git a/github.com/jessevdk/go-flags/check_crosscompile.sh b/github.com/jessevdk/go-flags/check_crosscompile.sh deleted file mode 100755 index c494f6119..000000000 --- a/github.com/jessevdk/go-flags/check_crosscompile.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -set -e - -echo '# linux arm7' -GOARM=7 GOARCH=arm GOOS=linux go build -echo '# linux arm5' -GOARM=5 GOARCH=arm GOOS=linux go build -echo '# windows 386' -GOARCH=386 GOOS=windows go build -echo '# windows amd64' -GOARCH=amd64 GOOS=windows go build -echo '# darwin' -GOARCH=amd64 GOOS=darwin go build -echo '# freebsd' -GOARCH=amd64 GOOS=freebsd go build diff --git a/github.com/jessevdk/go-flags/closest.go b/github.com/jessevdk/go-flags/closest.go deleted file mode 100644 index ba6f5f0c6..000000000 --- a/github.com/jessevdk/go-flags/closest.go +++ /dev/null @@ -1,61 +0,0 @@ -package flags - -func levenshtein(s string, t string) int { - if len(s) == 0 { - return len(t) - } - - if len(t) == 0 { - return len(s) - } - - var l1, l2, l3 int - - if len(s) == 1 { - l1 = len(t) + 1 - } else { - l1 = levenshtein(s[1:len(s)-1], t) + 1 - } - - if len(t) == 1 { - l2 = len(s) + 1 - } else { - l2 = levenshtein(t[1:len(t)-1], s) + 1 - } - - l3 = levenshtein(s[1:len(s)], t[1:len(t)]) - - if s[0] != t[0] { - l3 += 1 - } - - if l2 < l1 { - l1 = l2 - } - - if l1 < l3 { - return l1 - } - - return l3 -} - -func closestChoice(cmd string, choices []string) (string, int) { - if len(choices) == 0 { - return "", 0 - } - - mincmd := -1 - mindist := -1 - - for i, c := range choices { - l := levenshtein(cmd, c) - - if mincmd < 0 || l < mindist { - mindist = l - mincmd = i - } - } - - return choices[mincmd], mindist -} diff --git a/github.com/jessevdk/go-flags/command.go b/github.com/jessevdk/go-flags/command.go deleted file mode 100644 index 5e99cd663..000000000 --- a/github.com/jessevdk/go-flags/command.go +++ /dev/null @@ -1,84 +0,0 @@ -package flags - -// Command represents an application command. Commands can be added to the -// parser (which itself is a command) and are selected/executed when its name -// is specified on the command line. The Command type embeds a Group and -// therefore also carries a set of command specific options. -type Command struct { - // Embedded, see Group for more information - *Group - - // The name by which the command can be invoked - Name string - - // The active sub command (set by parsing) or nil - Active *Command - - commands []*Command - hasBuiltinHelpGroup bool -} - -// Commander is an interface which can be implemented by any command added in -// the options. When implemented, the Execute method will be called for the last -// specified (sub)command providing the remaining command line arguments. -type Commander interface { - // Execute will be called for the last active (sub)command. The - // args argument contains the remaining command line arguments. The - // error that Execute returns will be eventually passed out of the - // Parse method of the Parser. - Execute(args []string) error -} - -// Usage is an interface which can be implemented to show a custom usage string -// in the help message shown for a command. -type Usage interface { - // Usage is called for commands to allow customized printing of command - // usage in the generated help message. - Usage() string -} - -// AddCommand adds a new command to the parser with the given name and data. The -// data needs to be a pointer to a struct from which the fields indicate which -// options are in the command. The provided data can implement the Command and -// Usage interfaces. -func (c *Command) AddCommand(command string, shortDescription string, longDescription string, data interface{}) (*Command, error) { - cmd := newCommand(command, shortDescription, longDescription, data) - - if err := cmd.scan(); err != nil { - return nil, err - } - - c.commands = append(c.commands, cmd) - return cmd, nil -} - -// AddGroup adds a new group to the command with the given name and data. The -// data needs to be a pointer to a struct from which the fields indicate which -// options are in the group. -func (c *Command) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) { - group := newGroup(shortDescription, longDescription, data) - - if err := group.scanType(c.scanSubCommandHandler(group)); err != nil { - return nil, err - } - - c.groups = append(c.groups, group) - return group, nil -} - -// Commands returns a list of subcommands of this command. -func (c *Command) Commands() []*Command { - return c.commands -} - -// Find locates the subcommand with the given name and returns it. If no such -// command can be found Find will return nil. -func (c *Command) Find(name string) *Command { - for _, cc := range c.commands { - if cc.Name == name { - return cc - } - } - - return nil -} diff --git a/github.com/jessevdk/go-flags/command_private.go b/github.com/jessevdk/go-flags/command_private.go deleted file mode 100644 index dcb82fd87..000000000 --- a/github.com/jessevdk/go-flags/command_private.go +++ /dev/null @@ -1,161 +0,0 @@ -package flags - -import ( - "reflect" - "sort" - "strings" - "unsafe" -) - -type lookup struct { - shortNames map[string]*Option - longNames map[string]*Option - - required map[*Option]bool - commands map[string]*Command -} - -func newCommand(name string, shortDescription string, longDescription string, data interface{}) *Command { - return &Command{ - Group: newGroup(shortDescription, longDescription, data), - Name: name, - } -} - -func (c *Command) scanSubCommandHandler(parentg *Group) scanHandler { - f := func(realval reflect.Value, sfield *reflect.StructField) (bool, error) { - mtag := newMultiTag(string(sfield.Tag)) - - if err := mtag.Parse(); err != nil { - return true, err - } - - subcommand := mtag.Get("command") - - if len(subcommand) != 0 { - ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr())) - - shortDescription := mtag.Get("description") - longDescription := mtag.Get("long-description") - - if _, err := c.AddCommand(subcommand, shortDescription, longDescription, ptrval.Interface()); err != nil { - return true, err - } - - return true, nil - } - - return parentg.scanSubGroupHandler(realval, sfield) - } - - return f -} - -func (c *Command) scan() error { - return c.scanType(c.scanSubCommandHandler(c.Group)) -} - -func (c *Command) eachCommand(f func(*Command), recurse bool) { - f(c) - - for _, cc := range c.commands { - if recurse { - cc.eachCommand(f, true) - } else { - f(cc) - } - } -} - -func (c *Command) eachActiveGroup(f func(g *Group)) { - c.eachGroup(f) - - if c.Active != nil { - c.Active.eachActiveGroup(f) - } -} - -func (c *Command) addHelpGroups(showHelp func() error) { - if !c.hasBuiltinHelpGroup { - c.addHelpGroup(showHelp) - c.hasBuiltinHelpGroup = true - } - - for _, cc := range c.commands { - cc.addHelpGroups(showHelp) - } -} - -func (c *Command) makeLookup() lookup { - ret := lookup{ - shortNames: make(map[string]*Option), - longNames: make(map[string]*Option), - - required: make(map[*Option]bool), - commands: make(map[string]*Command), - } - - c.eachGroup(func(g *Group) { - for _, option := range g.options { - if option.Required && option.canCli() { - ret.required[option] = true - } - - if option.ShortName != 0 { - ret.shortNames[string(option.ShortName)] = option - } - - if len(option.LongName) > 0 { - ret.longNames[option.LongName] = option - } - } - }) - - for _, subcommand := range c.commands { - ret.commands[subcommand.Name] = subcommand - } - - return ret -} - -func (c *Command) groupByName(name string) *Group { - if grp := c.Group.groupByName(name); grp != nil { - return grp - } - - for _, subc := range c.commands { - prefix := subc.Name + "." - - if strings.HasPrefix(name, prefix) { - if grp := subc.groupByName(name[len(prefix):]); grp != nil { - return grp - } - } else if name == subc.Name { - return subc.Group - } - } - - return nil -} - -type commandList []*Command - -func (c commandList) Less(i, j int) bool { - return c[i].Name < c[j].Name -} - -func (c commandList) Len() int { - return len(c) -} - -func (c commandList) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -func (c *Command) sortedCommands() []*Command { - ret := make(commandList, len(c.commands)) - copy(ret, c.commands) - - sort.Sort(ret) - return []*Command(ret) -} diff --git a/github.com/jessevdk/go-flags/command_test.go b/github.com/jessevdk/go-flags/command_test.go deleted file mode 100644 index f58031d06..000000000 --- a/github.com/jessevdk/go-flags/command_test.go +++ /dev/null @@ -1,255 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestCommandInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g") - - assertStringArray(t, ret, []string{}) - - if p.Active == nil { - t.Errorf("Expected active command") - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } - - if p.Command.Find("cmd") != p.Active { - t.Errorf("Expected to find command `cmd' to be active") - } -} - -func TestCommandInlineMulti(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - C1 struct { - } `command:"c1"` - - C2 struct { - G bool `short:"g"` - } `command:"c2"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "c2", "-g") - - assertStringArray(t, ret, []string{}) - - if p.Active == nil { - t.Errorf("Expected active command") - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.C2.G { - t.Errorf("Expected C2.G to be true") - } - - if p.Command.Find("c1") == nil { - t.Errorf("Expected to find command `c1'") - } - - if c2 := p.Command.Find("c2"); c2 == nil { - t.Errorf("Expected to find command `c2'") - } else if c2 != p.Active { - t.Errorf("Expected to find command `c2' to be active") - } -} - -func TestCommandFlagOrder1(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseFail(t, ErrUnknownFlag, "unknown flag `g'", &opts, "-v", "-g", "cmd") -} - -func TestCommandFlagOrder2(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - } `command:"cmd"` - }{} - - assertParseFail(t, ErrUnknownFlag, "unknown flag `v'", &opts, "cmd", "-v", "-g") -} - -func TestCommandEstimate(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - p := NewParser(&opts, None) - _, err := p.ParseArgs([]string{}) - - assertError(t, err, ErrRequired, "Please specify one command of: add or remove") -} - -type testCommand struct { - G bool `short:"g"` - Executed bool - EArgs []string -} - -func (c *testCommand) Execute(args []string) error { - c.Executed = true - c.EArgs = args - - return nil -} - -func TestCommandExecute(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command testCommand `command:"cmd"` - }{} - - assertParseSuccess(t, &opts, "-v", "cmd", "-g", "a", "b") - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.Executed { - t.Errorf("Did not execute command") - } - - if !opts.Command.G { - t.Errorf("Expected Command.C to be true") - } - - assertStringArray(t, opts.Command.EArgs, []string{"a", "b"}) -} - -func TestCommandClosest(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Cmd1 struct { - } `command:"remove"` - - Cmd2 struct { - } `command:"add"` - }{} - - assertParseFail(t, ErrRequired, "Unknown command `addd', did you mean `add'?", &opts, "-v", "addd") -} - -func TestCommandAdd(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - var cmd = struct { - G bool `short:"g"` - }{} - - p := NewParser(&opts, Default) - c, err := p.AddCommand("cmd", "", "", &cmd) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - ret, err := p.ParseArgs([]string{"-v", "cmd", "-g", "rest"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !cmd.G { - t.Errorf("Expected Command.G to be true") - } - - if p.Command.Find("cmd") != c { - t.Errorf("Expected to find command `cmd'") - } - - if p.Commands()[0] != c { - t.Errorf("Espected command #v, but got #v", c, p.Commands()[0]) - } - - if c.Options()[0].ShortName != 'g' { - t.Errorf("Expected short name `g' but got %v", c.Options()[0].ShortName) - } -} - -func TestCommandNestedInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Command struct { - G bool `short:"g"` - - Nested struct { - N string `long:"n"` - } `command:"nested"` - } `command:"cmd"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "cmd", "-g", "nested", "--n", "n", "rest") - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Command.G { - t.Errorf("Expected Command.G to be true") - } - - assertString(t, opts.Command.Nested.N, "n") - - if c := p.Command.Find("cmd"); c == nil { - t.Errorf("Expected to find command `cmd'") - } else { - if c != p.Active { - t.Errorf("Expected `cmd' to be the active parser command") - } - - if nested := c.Find("nested"); nested == nil { - t.Errorf("Expected to find command `nested'") - } else if nested != c.Active { - t.Errorf("Expected to find command `nested' to be the active `cmd' command") - } - } -} diff --git a/github.com/jessevdk/go-flags/convert.go b/github.com/jessevdk/go-flags/convert.go deleted file mode 100644 index 948a50682..000000000 --- a/github.com/jessevdk/go-flags/convert.go +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright 2012 Jesse van den Kieboom. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flags - -import ( - "fmt" - "reflect" - "strconv" - "strings" - "time" -) - -// Marshaler is the interface implemented by types that can marshal themselves -// to a string representation of the flag. -type Marshaler interface { - // MarshalFlag marshals a flag value to its string representation. - MarshalFlag() (string, error) -} - -// Unmarshaler is the interface implemented by types that can unmarshal a flag -// argument to themselves. The provided value is directly passed from the -// command line. -type Unmarshaler interface { - // UnmarshalFlag unmarshals a string value representation to the flag - // value (which therefore needs to be a pointer receiver). - UnmarshalFlag(value string) error -} - -func getBase(options multiTag, base int) (int, error) { - sbase := options.Get("base") - - var err error - var ivbase int64 - - if sbase != "" { - ivbase, err = strconv.ParseInt(sbase, 10, 32) - base = int(ivbase) - } - - return base, err -} - -func convertMarshal(val reflect.Value) (bool, string, error) { - // Check first for the Marshaler interface - if val.Type().NumMethod() > 0 && val.CanInterface() { - if marshaler, ok := val.Interface().(Marshaler); ok { - ret, err := marshaler.MarshalFlag() - return true, ret, err - } - } - - return false, "", nil -} - -func convertToString(val reflect.Value, options multiTag) (string, error) { - if ok, ret, err := convertMarshal(val); ok { - return ret, err - } - - tp := val.Type() - - // Support for time.Duration - if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() { - stringer := val.Interface().(fmt.Stringer) - return stringer.String(), nil - } - - switch tp.Kind() { - case reflect.String: - return val.String(), nil - case reflect.Bool: - if val.Bool() { - return "true", nil - } - - return "false", nil - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - base, _ := getBase(options, 10) - return strconv.FormatInt(val.Int(), base), nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - base, _ := getBase(options, 10) - return strconv.FormatUint(val.Uint(), base), nil - case reflect.Float32, reflect.Float64: - return strconv.FormatFloat(val.Float(), 'g', -1, tp.Bits()), nil - case reflect.Slice: - if val.Len() == 0 { - return "", nil - } - - ret := "[" - - for i := 0; i < val.Len(); i++ { - if i != 0 { - ret += ", " - } - - item, err := convertToString(val.Index(i), options) - - if err != nil { - return "", err - } - - ret += item - } - - return ret + "]", nil - case reflect.Map: - ret := "{" - - for i, key := range val.MapKeys() { - if i != 0 { - ret += ", " - } - - item, err := convertToString(val.MapIndex(key), options) - - if err != nil { - return "", err - } - - ret += item - } - - return ret + "}", nil - case reflect.Ptr: - return convertToString(reflect.Indirect(val), options) - case reflect.Interface: - if !val.IsNil() { - return convertToString(val.Elem(), options) - } - } - - return "", nil -} - -func convertUnmarshal(val string, retval reflect.Value) (bool, error) { - if retval.Type().NumMethod() > 0 && retval.CanInterface() { - if unmarshaler, ok := retval.Interface().(Unmarshaler); ok { - return true, unmarshaler.UnmarshalFlag(val) - } - } - - if retval.Type().Kind() != reflect.Ptr && retval.CanAddr() { - return convertUnmarshal(val, retval.Addr()) - } - - if retval.Type().Kind() == reflect.Interface && !retval.IsNil() { - return convertUnmarshal(val, retval.Elem()) - } - - return false, nil -} - -func convert(val string, retval reflect.Value, options multiTag) error { - if ok, err := convertUnmarshal(val, retval); ok { - return err - } - - tp := retval.Type() - - // Support for time.Duration - if tp == reflect.TypeOf((*time.Duration)(nil)).Elem() { - parsed, err := time.ParseDuration(val) - - if err != nil { - return err - } - - retval.SetInt(int64(parsed)) - return nil - } - - switch tp.Kind() { - case reflect.String: - retval.SetString(val) - case reflect.Bool: - if val == "" { - retval.SetBool(true) - } else { - b, err := strconv.ParseBool(val) - - if err != nil { - return err - } - - retval.SetBool(b) - } - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - base, err := getBase(options, 10) - - if err != nil { - return err - } - - parsed, err := strconv.ParseInt(val, base, tp.Bits()) - - if err != nil { - return err - } - - retval.SetInt(parsed) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - base, err := getBase(options, 10) - - if err != nil { - return err - } - - parsed, err := strconv.ParseUint(val, base, tp.Bits()) - - if err != nil { - return err - } - - retval.SetUint(parsed) - case reflect.Float32, reflect.Float64: - parsed, err := strconv.ParseFloat(val, tp.Bits()) - - if err != nil { - return err - } - - retval.SetFloat(parsed) - case reflect.Slice: - elemtp := tp.Elem() - - elemvalptr := reflect.New(elemtp) - elemval := reflect.Indirect(elemvalptr) - - if err := convert(val, elemval, options); err != nil { - return err - } - - retval.Set(reflect.Append(retval, elemval)) - case reflect.Map: - parts := strings.SplitN(val, ":", 2) - - key := parts[0] - var value string - - if len(parts) == 2 { - value = parts[1] - } - - keytp := tp.Key() - keyval := reflect.New(keytp) - - if err := convert(key, keyval, options); err != nil { - return err - } - - valuetp := tp.Elem() - valueval := reflect.New(valuetp) - - if err := convert(value, valueval, options); err != nil { - return err - } - - if retval.IsNil() { - retval.Set(reflect.MakeMap(tp)) - } - - retval.SetMapIndex(reflect.Indirect(keyval), reflect.Indirect(valueval)) - case reflect.Ptr: - if retval.IsNil() { - retval.Set(reflect.New(retval.Type().Elem())) - } - - return convert(val, reflect.Indirect(retval), options) - case reflect.Interface: - if !retval.IsNil() { - return convert(val, retval.Elem(), options) - } - } - - return nil -} - -func wrapText(s string, l int, prefix string) string { - // Basic text wrapping of s at spaces to fit in l - var ret string - - s = strings.TrimSpace(s) - - for len(s) > l { - // Try to split on space - suffix := "" - - pos := strings.LastIndex(s[:l], " ") - - if pos < 0 { - pos = l - 1 - suffix = "-\n" - } - - if len(ret) != 0 { - ret += "\n" + prefix - } - - ret += strings.TrimSpace(s[:pos]) + suffix - s = strings.TrimSpace(s[pos:]) - } - - if len(s) > 0 { - if len(ret) != 0 { - ret += "\n" + prefix - } - - return ret + s - } - - return ret -} diff --git a/github.com/jessevdk/go-flags/error.go b/github.com/jessevdk/go-flags/error.go deleted file mode 100644 index 14db093e2..000000000 --- a/github.com/jessevdk/go-flags/error.go +++ /dev/null @@ -1,113 +0,0 @@ -package flags - -import ( - "fmt" -) - -// ErrorType represents the type of error. -type ErrorType uint - -const ( - // ErrUnknown indicates a generic error. - ErrUnknown ErrorType = iota - - // ErrExpectedArgument indicates that an argument was expected. - ErrExpectedArgument - - // ErrUnknownFlag indicates an unknown flag. - ErrUnknownFlag - - // ErrUnknownGroup indicates an unknown group. - ErrUnknownGroup - - // ErrMarshal indicates a marshalling error while converting values. - ErrMarshal - - // ErrHelp indicates that the builtin help was shown (the error - // contains the help message). - ErrHelp - - // ErrNoArgumentForBool indicates that an argument was given for a - // boolean flag (which don't not take any arguments). - ErrNoArgumentForBool - - // ErrRequired indicates that a required flag was not provided. - ErrRequired - - // ErrShortNameTooLong indicates that a short flag name was specified, - // longer than one character. - ErrShortNameTooLong - - // ErrDuplicatedFlag indicates that a short or long flag has been - // defined more than once - ErrDuplicatedFlag - - // ErrTag indicates an error while parsing flag tags. - ErrTag -) - -// String returns a string representation of the error type. -func (e ErrorType) String() string { - switch e { - case ErrUnknown: - return "unknown" - case ErrExpectedArgument: - return "expected argument" - case ErrUnknownFlag: - return "unknown flag" - case ErrUnknownGroup: - return "unknown group" - case ErrMarshal: - return "marshal" - case ErrHelp: - return "help" - case ErrNoArgumentForBool: - return "no argument for bool" - case ErrRequired: - return "required" - case ErrShortNameTooLong: - return "short name too long" - case ErrDuplicatedFlag: - return "duplicated flag" - case ErrTag: - return "tag" - } - - return "unknown" -} - -// Error represents a parser error. The error returned from Parse is of this -// type. The error contains both a Type and Message. -type Error struct { - // The type of error - Type ErrorType - - // The error message - Message string -} - -// Error returns the error's message -func (e *Error) Error() string { - return e.Message -} - -func newError(tp ErrorType, message string) *Error { - return &Error{ - Type: tp, - Message: message, - } -} - -func newErrorf(tp ErrorType, format string, args ...interface{}) *Error { - return newError(tp, fmt.Sprintf(format, args...)) -} - -func wrapError(err error) *Error { - ret, ok := err.(*Error) - - if !ok { - return newError(ErrUnknown, err.Error()) - } - - return ret -} diff --git a/github.com/jessevdk/go-flags/example_test.go b/github.com/jessevdk/go-flags/example_test.go deleted file mode 100644 index 5de7bff7e..000000000 --- a/github.com/jessevdk/go-flags/example_test.go +++ /dev/null @@ -1,95 +0,0 @@ -// Example of use of the flags package. -package flags - -import ( - "fmt" - "os" - "os/exec" - "strings" -) - -func Example() { - var opts struct { - // Slice of bool will append 'true' each time the option - // is encountered (can be set multiple times, like -vvv) - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - - // Example of automatic marshalling to desired type (uint) - Offset uint `long:"offset" description:"Offset"` - - // Example of a callback, called each time the option is found. - Call func(string) `short:"c" description:"Call phone number"` - - // Example of a required flag - Name string `short:"n" long:"name" description:"A name" required:"true"` - - // Example of a value name - File string `short:"f" long:"file" description:"A file" value-name:"FILE"` - - // Example of a pointer - Ptr *int `short:"p" description:"A pointer to an integer"` - - // Example of a slice of strings - StringSlice []string `short:"s" description:"A slice of strings"` - - // Example of a slice of pointers - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - - // Example of a map - IntMap map[string]int `long:"intmap" description:"A map from string to int"` - } - - // Callback which will invoke callto: to call a number. - // Note that this works just on OS X (and probably only with - // Skype) but it shows the idea. - opts.Call = func(num string) { - cmd := exec.Command("open", "callto:"+num) - cmd.Start() - cmd.Process.Release() - } - - // Make some fake arguments to parse. - args := []string{ - "-vv", - "--offset=5", - "-n", "Me", - "-p", "3", - "-s", "hello", - "-s", "world", - "--ptrslice", "hello", - "--ptrslice", "world", - "--intmap", "a:1", - "--intmap", "b:5", - "arg1", - "arg2", - "arg3", - } - - // Parse flags from `args'. Note that here we use flags.ParseArgs for - // the sake of making a working example. Normally, you would simply use - // flags.Parse(&opts) which uses os.Args - args, err := ParseArgs(&opts, args) - - if err != nil { - panic(err) - os.Exit(1) - } - - fmt.Printf("Verbosity: %v\n", opts.Verbose) - fmt.Printf("Offset: %d\n", opts.Offset) - fmt.Printf("Name: %s\n", opts.Name) - fmt.Printf("Ptr: %d\n", *opts.Ptr) - fmt.Printf("StringSlice: %v\n", opts.StringSlice) - fmt.Printf("PtrSlice: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1]) - fmt.Printf("IntMap: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"]) - fmt.Printf("Remaining args: %s\n", strings.Join(args, " ")) - - // Output: Verbosity: [true true] - // Offset: 5 - // Name: Me - // Ptr: 3 - // StringSlice: [hello world] - // PtrSlice: [hello world] - // IntMap: [a:1 b:5] - // Remaining args: arg1 arg2 arg3 -} diff --git a/github.com/jessevdk/go-flags/examples/add.go b/github.com/jessevdk/go-flags/examples/add.go deleted file mode 100644 index 57d8f232b..000000000 --- a/github.com/jessevdk/go-flags/examples/add.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "fmt" -) - -type AddCommand struct { - All bool `short:"a" long:"all" description:"Add all files"` -} - -var addCommand AddCommand - -func (x *AddCommand) Execute(args []string) error { - fmt.Printf("Adding (all=%v): %#v\n", x.All, args) - return nil -} - -func init() { - parser.AddCommand("add", - "Add a file", - "The add command adds a file to the repository. Use -a to add all files.", - &addCommand) -} diff --git a/github.com/jessevdk/go-flags/examples/main.go b/github.com/jessevdk/go-flags/examples/main.go deleted file mode 100644 index 7132bba12..000000000 --- a/github.com/jessevdk/go-flags/examples/main.go +++ /dev/null @@ -1,75 +0,0 @@ -package main - -import ( - "errors" - "fmt" - "github.com/calmh/syncthing/github.com/jessevdk/go-flags" - "os" - "strconv" - "strings" -) - -type EditorOptions struct { - Input string `short:"i" long:"input" description:"Input file" default:"-"` - Output string `short:"o" long:"output" description:"Output file" default:"-"` -} - -type Point struct { - X, Y int -} - -func (p *Point) UnmarshalFlag(value string) error { - parts := strings.Split(value, ",") - - if len(parts) != 2 { - return errors.New("Expected two numbers separated by a ,") - } - - x, err := strconv.ParseInt(parts[0], 10, 32) - - if err != nil { - return err - } - - y, err := strconv.ParseInt(parts[1], 10, 32) - - if err != nil { - return err - } - - p.X = int(x) - p.Y = int(y) - - return nil -} - -func (p Point) MarshalFlag() (string, error) { - return fmt.Sprintf("%d,%d", p.X, p.Y), nil -} - -type Options struct { - // Example of verbosity with level - Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` - - // Example of optional value - User string `short:"u" long:"user" description:"User name" optional:"yes" optional-value:"pancake"` - - // Example of map with multiple default values - Users map[string]string `long:"users" description:"User e-mail map" default:"system:system@example.org" default:"admin:admin@example.org"` - - // Example of option group - Editor EditorOptions `group:"Editor Options"` - - // Example of custom type Marshal/Unmarshal - Point Point `long:"point" description:"A x,y point" default:"1,2"` -} - -var options Options - -var parser = flags.NewParser(&options, flags.Default) - -func main() { - if _, err := parser.Parse(); err != nil { - os.Exit(1) - } -} diff --git a/github.com/jessevdk/go-flags/examples/rm.go b/github.com/jessevdk/go-flags/examples/rm.go deleted file mode 100644 index c9c1dd03a..000000000 --- a/github.com/jessevdk/go-flags/examples/rm.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "fmt" -) - -type RmCommand struct { - Force bool `short:"f" long:"force" description:"Force removal of files"` -} - -var rmCommand RmCommand - -func (x *RmCommand) Execute(args []string) error { - fmt.Printf("Removing (force=%v): %#v\n", x.Force, args) - return nil -} - -func init() { - parser.AddCommand("rm", - "Remove a file", - "The rm command removes a file to the repository. Use -f to force removal of files.", - &rmCommand) -} diff --git a/github.com/jessevdk/go-flags/flags.go b/github.com/jessevdk/go-flags/flags.go deleted file mode 100644 index 9b7728632..000000000 --- a/github.com/jessevdk/go-flags/flags.go +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright 2012 Jesse van den Kieboom. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package flags provides an extensive command line option parser. -// The flags package is similar in functionality to the go builtin flag package -// but provides more options and uses reflection to provide a convenient and -// succinct way of specifying command line options. -// -// Supported features: -// Options with short names (-v) -// Options with long names (--verbose) -// Options with and without arguments (bool v.s. other type) -// Options with optional arguments and default values -// Multiple option groups each containing a set of options -// Generate and print well-formatted help message -// Passing remaining command line arguments after -- (optional) -// Ignoring unknown command line options (optional) -// Supports -I/usr/include -I=/usr/include -I /usr/include option argument specification -// Supports multiple short options -aux -// Supports all primitive go types (string, int{8..64}, uint{8..64}, float) -// Supports same option multiple times (can store in slice or last option counts) -// Supports maps -// Supports function callbacks -// -// Additional features specific to Windows: -// Options with short names (/v) -// Options with long names (/verbose) -// Windows-style options with arguments use a colon as the delimiter -// Modify generated help message with Windows-style / options -// -// The flags package uses structs, reflection and struct field tags -// to allow users to specify command line options. This results in very simple -// and consise specification of your application options. For example: -// -// type Options struct { -// Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` -// } -// -// This specifies one option with a short name -v and a long name --verbose. -// When either -v or --verbose is found on the command line, a 'true' value -// will be appended to the Verbose field. e.g. when specifying -vvv, the -// resulting value of Verbose will be {[true, true, true]}. -// -// Slice options work exactly the same as primitive type options, except that -// whenever the option is encountered, a value is appended to the slice. -// -// Map options from string to primitive type are also supported. On the command -// line, you specify the value for such an option as key:value. For example -// -// type Options struct { -// AuthorInfo string[string] `short:"a"` -// } -// -// Then, the AuthorInfo map can be filled with something like -// -a name:Jesse -a "surname:van den Kieboom". -// -// Finally, for full control over the conversion between command line argument -// values and options, user defined types can choose to implement the Marshaler -// and Unmarshaler interfaces. -// -// Available field tags: -// short: the short name of the option (single character) -// long: the long name of the option -// description: the description of the option (optional) -// optional: whether an argument of the option is optional (optional) -// optional-value: the value of an optional option when the option occurs -// without an argument. This tag can be specified multiple -// times in the case of maps or slices (optional) -// default: the default value of an option. This tag can be specified -// multiple times in the case of slices or maps (optional). -// default-mask: when specified, this value will be displayed in the help -// instead of the actual default value. This is useful -// mostly for hiding otherwise sensitive information from -// showing up in the help. If default-mask takes the special -// value "-", then no default value will be shown at all -// (optional) -// required: whether an option is required to appear on the command -// line. If a required option is not present, the parser -// will return ErrRequired. -// base: a base (radix) used to convert strings to integer values, -// the default base is 10 (i.e. decimal) (optional) -// value-name: the name of the argument value (to be shown in the help, -// (optional) -// group: when specified on a struct field, makes the struct field -// a separate group with the given name (optional). -// command: when specified on a struct field, makes the struct field -// a (sub)command with the given name (optional). -// -// Either short: or long: must be specified to make the field eligible as an -// option. -// -// -// Option groups: -// -// Option groups are a simple way to semantically separate your options. The -// only real difference is in how your options will appear in the builtin -// generated help. All options in a particular group are shown together in the -// help under the name of the group. -// -// There are currently three ways to specify option groups. -// -// 1. Use NewNamedParser specifying the various option groups. -// 2. Use AddGroup to add a group to an existing parser. -// 3. Add a struct field to the toplevel options annotated with the -// group:"group-name" tag. -// -// -// -// Commands: -// -// The flags package also has basic support for commands. Commands are often -// used in monolithic applications that support various commands or actions. -// Take git for example, all of the add, commit, checkout, etc. are called -// commands. Using commands you can easily separate multiple functions of your -// application. -// -// There are currently two ways to specifiy a command. -// -// 1. Use AddCommand on an existing parser. -// 2. Add a struct field to your options struct annotated with the -// command:"command-name" tag. -// -// The most common, idiomatic way to implement commands is to define a global -// parser instance and implement each command in a separate file. These -// command files should define a go init function which calls AddCommand on -// the global parser. -// -// When parsing ends and there is an active command and that command implements -// the Commander interface, then its Execute method will be run with the -// remaining command line arguments. -// -// Command structs can have options which become valid to parse after the -// command has been specified on the command line. It is currently not valid -// to specify options from the parent level of the command after the command -// name has occurred. Thus, given a toplevel option "-v" and a command "add": -// -// Valid: ./app -v add -// Invalid: ./app add -v -// -package flags diff --git a/github.com/jessevdk/go-flags/group.go b/github.com/jessevdk/go-flags/group.go deleted file mode 100644 index 4e01736b2..000000000 --- a/github.com/jessevdk/go-flags/group.go +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2012 Jesse van den Kieboom. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flags - -import ( - "errors" - "strings" -) - -// ErrNotPointerToStruct indicates that a provided data container is not -// a pointer to a struct. Only pointers to structs are valid data containers -// for options. -var ErrNotPointerToStruct = errors.New("provided data is not a pointer to struct") - -// Group represents an option group. Option groups can be used to logically -// group options together under a description. Groups are only used to provide -// more structure to options both for the user (as displayed in the help message) -// and for you, since groups can be nested. -type Group struct { - // A short description of the group. The - // short description is primarily used in the builtin generated help - // message - ShortDescription string - - // A long description of the group. The long - // description is primarily used to present information on commands - // (Command embeds Group) in the builtin generated help and man pages. - LongDescription string - - // All the options in the group - options []*Option - - // All the subgroups - groups []*Group - - data interface{} -} - -// AddGroup adds a new group to the command with the given name and data. The -// data needs to be a pointer to a struct from which the fields indicate which -// options are in the group. -func (g *Group) AddGroup(shortDescription string, longDescription string, data interface{}) (*Group, error) { - group := newGroup(shortDescription, longDescription, data) - - if err := group.scan(); err != nil { - return nil, err - } - - g.groups = append(g.groups, group) - return group, nil -} - -// Groups returns the list of groups embedded in this group. -func (g *Group) Groups() []*Group { - return g.groups -} - -// Options returns the list of options in this group. -func (g *Group) Options() []*Option { - return g.options -} - -// Find locates the subgroup with the given short description and returns it. -// If no such group can be found Find will return nil. Note that the description -// is matched case insensitively. -func (g *Group) Find(shortDescription string) *Group { - lshortDescription := strings.ToLower(shortDescription) - - var ret *Group - - g.eachGroup(func(gg *Group) { - if gg != g && strings.ToLower(gg.ShortDescription) == lshortDescription { - ret = gg - } - }) - - return ret -} diff --git a/github.com/jessevdk/go-flags/group_private.go b/github.com/jessevdk/go-flags/group_private.go deleted file mode 100644 index 87c0f15ff..000000000 --- a/github.com/jessevdk/go-flags/group_private.go +++ /dev/null @@ -1,263 +0,0 @@ -package flags - -import ( - "reflect" - "unicode/utf8" - "unsafe" -) - -type scanHandler func(reflect.Value, *reflect.StructField) (bool, error) - -func newGroup(shortDescription string, longDescription string, data interface{}) *Group { - return &Group{ - ShortDescription: shortDescription, - LongDescription: longDescription, - - data: data, - } -} - -func (g *Group) optionByName(name string, namematch func(*Option, string) bool) *Option { - prio := 0 - var retopt *Option - - for _, opt := range g.options { - if namematch != nil && namematch(opt, name) && prio < 4 { - retopt = opt - prio = 4 - } - - if name == opt.field.Name && prio < 3 { - retopt = opt - prio = 3 - } - - if name == opt.LongName && prio < 2 { - retopt = opt - prio = 2 - } - - if opt.ShortName != 0 && name == string(opt.ShortName) && prio < 1 { - retopt = opt - prio = 1 - } - } - - return retopt -} - -func (g *Group) storeDefaults() { - for _, option := range g.options { - // First. empty out the value - if len(option.Default) > 0 { - option.clear() - } - - for _, d := range option.Default { - option.set(&d) - } - - if !option.value.CanSet() { - continue - } - - option.defaultValue = reflect.ValueOf(option.value.Interface()) - } -} - -func (g *Group) eachGroup(f func(*Group)) { - f(g) - - for _, gg := range g.groups { - gg.eachGroup(f) - } -} - -func (g *Group) scanStruct(realval reflect.Value, sfield *reflect.StructField, handler scanHandler) error { - stype := realval.Type() - - if sfield != nil { - if ok, err := handler(realval, sfield); err != nil { - return err - } else if ok { - return nil - } - } - - for i := 0; i < stype.NumField(); i++ { - field := stype.Field(i) - - // PkgName is set only for non-exported fields, which we ignore - if field.PkgPath != "" { - continue - } - - mtag := newMultiTag(string(field.Tag)) - - if err := mtag.Parse(); err != nil { - return err - } - - // Skip fields with the no-flag tag - if mtag.Get("no-flag") != "" { - continue - } - - // Dive deep into structs or pointers to structs - kind := field.Type.Kind() - fld := realval.Field(i) - - if kind == reflect.Struct { - if err := g.scanStruct(fld, &field, handler); err != nil { - return err - } - } else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { - if fld.IsNil() { - fld.Set(reflect.New(fld.Type().Elem())) - } - - if err := g.scanStruct(reflect.Indirect(fld), &field, handler); err != nil { - return err - } - } - - longname := mtag.Get("long") - shortname := mtag.Get("short") - - // Need at least either a short or long name - if longname == "" && shortname == "" && mtag.Get("ini-name") == "" { - continue - } - - short := rune(0) - rc := utf8.RuneCountInString(shortname) - - if rc > 1 { - return newErrorf(ErrShortNameTooLong, - "short names can only be 1 character long, not `%s'", - shortname) - - } else if rc == 1 { - short, _ = utf8.DecodeRuneInString(shortname) - } - - description := mtag.Get("description") - def := mtag.GetMany("default") - optionalValue := mtag.GetMany("optional-value") - valueName := mtag.Get("value-name") - defaultMask := mtag.Get("default-mask") - - optional := (mtag.Get("optional") != "") - required := (mtag.Get("required") != "") - - option := &Option{ - Description: description, - ShortName: short, - LongName: longname, - Default: def, - OptionalArgument: optional, - OptionalValue: optionalValue, - Required: required, - ValueName: valueName, - DefaultMask: defaultMask, - - field: field, - value: realval.Field(i), - tag: mtag, - } - - g.options = append(g.options, option) - } - - return nil -} - -func (g *Group) checkForDuplicateFlags() *Error { - shortNames := make(map[rune]*Option) - longNames := make(map[string]*Option) - - var duplicateError *Error - - g.eachGroup(func(g *Group) { - for _, option := range g.options { - if option.LongName != "" { - if otherOption, ok := longNames[option.LongName]; ok { - duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same long name as option `%s'", option, otherOption) - return - } - longNames[option.LongName] = option - } - if option.ShortName != 0 { - if otherOption, ok := shortNames[option.ShortName]; ok { - duplicateError = newErrorf(ErrDuplicatedFlag, "option `%s' uses the same short name as option `%s'", option, otherOption) - return - } - shortNames[option.ShortName] = option - } - } - }) - - return duplicateError -} - -func (g *Group) scanSubGroupHandler(realval reflect.Value, sfield *reflect.StructField) (bool, error) { - mtag := newMultiTag(string(sfield.Tag)) - - if err := mtag.Parse(); err != nil { - return true, err - } - - subgroup := mtag.Get("group") - - if len(subgroup) != 0 { - ptrval := reflect.NewAt(realval.Type(), unsafe.Pointer(realval.UnsafeAddr())) - description := mtag.Get("description") - - if _, err := g.AddGroup(subgroup, description, ptrval.Interface()); err != nil { - return true, err - } - - return true, nil - } - - return false, nil -} - -func (g *Group) scanType(handler scanHandler) error { - // Get all the public fields in the data struct - ptrval := reflect.ValueOf(g.data) - - if ptrval.Type().Kind() != reflect.Ptr { - panic(ErrNotPointerToStruct) - } - - stype := ptrval.Type().Elem() - - if stype.Kind() != reflect.Struct { - panic(ErrNotPointerToStruct) - } - - realval := reflect.Indirect(ptrval) - - if err := g.scanStruct(realval, nil, handler); err != nil { - return err - } - - if err := g.checkForDuplicateFlags(); err != nil { - return err - } - - return nil -} - -func (g *Group) scan() error { - return g.scanType(g.scanSubGroupHandler) -} - -func (g *Group) groupByName(name string) *Group { - if len(name) == 0 { - return g - } - - return g.Find(name) -} diff --git a/github.com/jessevdk/go-flags/group_test.go b/github.com/jessevdk/go-flags/group_test.go deleted file mode 100644 index 281047a1c..000000000 --- a/github.com/jessevdk/go-flags/group_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestGroupInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Group struct { - G bool `short:"g"` - } `group:"Grouped Options"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "-g") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Group.G { - t.Errorf("Expected Group.G to be true") - } - - if p.Command.Group.Find("Grouped Options") == nil { - t.Errorf("Expected to find group `Grouped Options'") - } -} - -func TestGroupAdd(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - var grp = struct { - G bool `short:"g"` - }{} - - p := NewParser(&opts, Default) - g, err := p.AddGroup("Grouped Options", "", &grp) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - ret, err := p.ParseArgs([]string{"-v", "-g", "rest"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !grp.G { - t.Errorf("Expected Group.G to be true") - } - - if p.Command.Group.Find("Grouped Options") != g { - t.Errorf("Expected to find group `Grouped Options'") - } - - if p.Groups()[1] != g { - t.Errorf("Espected group #v, but got #v", g, p.Groups()[0]) - } - - if g.Options()[0].ShortName != 'g' { - t.Errorf("Expected short name `g' but got %v", g.Options()[0].ShortName) - } -} - -func TestGroupNestedInline(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - - Group struct { - G bool `short:"g"` - - Nested struct { - N string `long:"n"` - } `group:"Nested Options"` - } `group:"Grouped Options"` - }{} - - p, ret := assertParserSuccess(t, &opts, "-v", "-g", "--n", "n", "rest") - - assertStringArray(t, ret, []string{"rest"}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - if !opts.Group.G { - t.Errorf("Expected Group.G to be true") - } - - assertString(t, opts.Group.Nested.N, "n") - - if p.Command.Group.Find("Grouped Options") == nil { - t.Errorf("Expected to find group `Grouped Options'") - } - - if p.Command.Group.Find("Nested Options") == nil { - t.Errorf("Expected to find group `Nested Options'") - } -} - -func TestDuplicateShortFlags(t *testing.T) { - var opts struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"` - Variables []string `short:"v" long:"variable" description:"Set a variable value."` - } - - args := []string{ - "--verbose", - "-v", "123", - "-v", "456", - } - - _, err := ParseArgs(&opts, args) - - if err == nil { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } else { - err2 := err.(*Error) - if err2.Type != ErrDuplicatedFlag { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } - } -} - -func TestDuplicateLongFlags(t *testing.T) { - var opts struct { - Test1 []bool `short:"a" long:"testing" description:"Test 1"` - Test2 []string `short:"b" long:"testing" description:"Test 2."` - } - - args := []string{ - "--testing", - } - - _, err := ParseArgs(&opts, args) - - if err == nil { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } else { - err2 := err.(*Error) - if err2.Type != ErrDuplicatedFlag { - t.Errorf("Expected an error with type ErrDuplicatedFlag") - } - } -} diff --git a/github.com/jessevdk/go-flags/help.go b/github.com/jessevdk/go-flags/help.go deleted file mode 100644 index e1d9e5fc5..000000000 --- a/github.com/jessevdk/go-flags/help.go +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2012 Jesse van den Kieboom. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flags - -import ( - "bufio" - "bytes" - "fmt" - "io" - "reflect" - "strings" - "unicode/utf8" -) - -type alignmentInfo struct { - maxLongLen int - hasShort bool - hasValueName bool - terminalColumns int -} - -func (p *Parser) getAlignmentInfo() alignmentInfo { - ret := alignmentInfo{ - maxLongLen: 0, - hasShort: false, - hasValueName: false, - terminalColumns: getTerminalColumns(), - } - - if ret.terminalColumns <= 0 { - ret.terminalColumns = 80 - } - - p.eachActiveGroup(func(grp *Group) { - for _, info := range grp.options { - if info.ShortName != 0 { - ret.hasShort = true - } - - lv := utf8.RuneCountInString(info.ValueName) - - if lv != 0 { - ret.hasValueName = true - } - - l := utf8.RuneCountInString(info.LongName) + lv - - if l > ret.maxLongLen { - ret.maxLongLen = l - } - } - }) - - return ret -} - -func (p *Parser) writeHelpOption(writer *bufio.Writer, option *Option, info alignmentInfo) { - line := &bytes.Buffer{} - - distanceBetweenOptionAndDescription := 2 - paddingBeforeOption := 2 - - line.WriteString(strings.Repeat(" ", paddingBeforeOption)) - - if option.ShortName != 0 { - line.WriteRune(defaultShortOptDelimiter) - line.WriteRune(option.ShortName) - } else if info.hasShort { - line.WriteString(" ") - } - - descstart := info.maxLongLen + paddingBeforeOption + distanceBetweenOptionAndDescription - - if info.hasShort { - descstart += 2 - } - - if info.maxLongLen > 0 { - descstart += 4 - } - - if info.hasValueName { - descstart += 3 - } - - if len(option.LongName) > 0 { - if option.ShortName != 0 { - line.WriteString(", ") - } else if info.hasShort { - line.WriteString(" ") - } - - line.WriteString(defaultLongOptDelimiter) - line.WriteString(option.LongName) - } - - if option.canArgument() { - line.WriteRune(defaultNameArgDelimiter) - - if len(option.ValueName) > 0 { - line.WriteString(option.ValueName) - } - } - - written := line.Len() - line.WriteTo(writer) - - if option.Description != "" { - dw := descstart - written - writer.WriteString(strings.Repeat(" ", dw)) - - def := "" - defs := option.Default - - if len(option.DefaultMask) != 0 { - if option.DefaultMask != "-" { - def = option.DefaultMask - } - } else if len(defs) == 0 && option.canArgument() { - var showdef bool - - switch option.field.Type.Kind() { - case reflect.Func, reflect.Ptr: - showdef = !option.value.IsNil() - case reflect.Slice, reflect.String, reflect.Array: - showdef = option.value.Len() > 0 - case reflect.Map: - showdef = !option.value.IsNil() && option.value.Len() > 0 - default: - zeroval := reflect.Zero(option.field.Type) - showdef = !reflect.DeepEqual(zeroval.Interface(), option.value.Interface()) - } - - if showdef { - def, _ = convertToString(option.value, option.tag) - } - } else if len(defs) != 0 { - def = strings.Join(defs, ", ") - } - - var desc string - - if def != "" { - desc = fmt.Sprintf("%s (%v)", option.Description, def) - } else { - desc = option.Description - } - - writer.WriteString(wrapText(desc, - info.terminalColumns-descstart, - strings.Repeat(" ", descstart))) - } - - writer.WriteString("\n") -} - -func maxCommandLength(s []*Command) int { - if len(s) == 0 { - return 0 - } - - ret := len(s[0].Name) - - for _, v := range s[1:] { - l := len(v.Name) - - if l > ret { - ret = l - } - } - - return ret -} - -// WriteHelp writes a help message containing all the possible options and -// their descriptions to the provided writer. Note that the HelpFlag parser -// option provides a convenient way to add a -h/--help option group to the -// command line parser which will automatically show the help messages using -// this method. -func (p *Parser) WriteHelp(writer io.Writer) { - if writer == nil { - return - } - - wr := bufio.NewWriter(writer) - aligninfo := p.getAlignmentInfo() - - cmd := p.Command - - for cmd.Active != nil { - cmd = cmd.Active - } - - if p.Name != "" { - wr.WriteString("Usage:\n") - wr.WriteString(" ") - - allcmd := p.Command - - for allcmd != nil { - var usage string - - if allcmd == p.Command { - if len(p.Usage) != 0 { - usage = p.Usage - } else { - usage = "[OPTIONS]" - } - } else if us, ok := allcmd.data.(Usage); ok { - usage = us.Usage() - } else { - usage = fmt.Sprintf("[%s-OPTIONS]", allcmd.Name) - } - - if len(usage) != 0 { - fmt.Fprintf(wr, " %s %s", allcmd.Name, usage) - } else { - fmt.Fprintf(wr, " %s", allcmd.Name) - } - - allcmd = allcmd.Active - } - - fmt.Fprintln(wr) - - if len(cmd.LongDescription) != 0 { - fmt.Fprintln(wr) - - t := wrapText(cmd.LongDescription, - aligninfo.terminalColumns, - "") - - fmt.Fprintln(wr, t) - } - } - - p.eachActiveGroup(func(grp *Group) { - first := true - - for _, info := range grp.options { - if info.canCli() { - if first { - fmt.Fprintf(wr, "\n%s:\n", grp.ShortDescription) - first = false - } - - p.writeHelpOption(wr, info, aligninfo) - } - } - }) - - scommands := cmd.sortedCommands() - - if len(scommands) > 0 { - maxnamelen := maxCommandLength(scommands) - - fmt.Fprintln(wr) - fmt.Fprintln(wr, "Available commands:") - - for _, c := range scommands { - fmt.Fprintf(wr, " %s", c.Name) - - if len(c.ShortDescription) > 0 { - pad := strings.Repeat(" ", maxnamelen-len(c.Name)) - fmt.Fprintf(wr, "%s %s", pad, c.ShortDescription) - } - - fmt.Fprintln(wr) - } - } - - wr.Flush() -} diff --git a/github.com/jessevdk/go-flags/help_test.go b/github.com/jessevdk/go-flags/help_test.go deleted file mode 100644 index c93195e0c..000000000 --- a/github.com/jessevdk/go-flags/help_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package flags - -import ( - "bytes" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "testing" - "time" -) - -func helpDiff(a, b string) (string, error) { - atmp, err := ioutil.TempFile("", "help-diff") - - if err != nil { - return "", err - } - - btmp, err := ioutil.TempFile("", "help-diff") - - if err != nil { - return "", err - } - - if _, err := io.WriteString(atmp, a); err != nil { - return "", err - } - - if _, err := io.WriteString(btmp, b); err != nil { - return "", err - } - - ret, err := exec.Command("diff", "-u", "-d", "--label", "got", atmp.Name(), "--label", "expected", btmp.Name()).Output() - - os.Remove(atmp.Name()) - os.Remove(btmp.Name()) - - return string(ret), nil -} - -type helpOptions struct { - Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information" ini-name:"verbose"` - Call func(string) `short:"c" description:"Call phone number" ini-name:"call"` - PtrSlice []*string `long:"ptrslice" description:"A slice of pointers to string"` - - OnlyIni string `ini-name:"only-ini" description:"Option only available in ini"` - - Other struct { - StringSlice []string `short:"s" description:"A slice of strings"` - IntMap map[string]int `long:"intmap" description:"A map from string to int" ini-name:"int-map"` - } `group:"Other Options"` -} - -func TestHelp(t *testing.T) { - var opts helpOptions - - p := NewNamedParser("TestHelp", HelpFlag) - p.AddGroup("Application Options", "The application options", &opts) - - _, err := p.ParseArgs([]string{"--help"}) - - if err == nil { - t.Fatalf("Expected help error") - } - - if e, ok := err.(*Error); !ok { - t.Fatalf("Expected flags.Error, but got %#T", err) - } else { - if e.Type != ErrHelp { - t.Errorf("Expected flags.ErrHelp type, but got %s", e.Type) - } - - expected := `Usage: - TestHelp [OPTIONS] - -Application Options: - -v, --verbose Show verbose debug information - -c= Call phone number - --ptrslice= A slice of pointers to string - -Other Options: - -s= A slice of strings - --intmap= A map from string to int - -Help Options: - -h, --help Show this help message -` - - if e.Message != expected { - ret, err := helpDiff(e.Message, expected) - - if err != nil { - t.Errorf("Unexpected diff error: %s", err) - t.Errorf("Unexpected help message, expected:\n\n%s\n\nbut got\n\n%s", expected, e.Message) - } else { - t.Errorf("Unexpected help message:\n\n%s", ret) - } - } - } -} - -func TestMan(t *testing.T) { - var opts helpOptions - - p := NewNamedParser("TestMan", HelpFlag) - p.ShortDescription = "Test manpage generation" - p.LongDescription = "This is a somewhat longer description of what this does" - p.AddGroup("Application Options", "The application options", &opts) - - var buf bytes.Buffer - p.WriteManPage(&buf) - - got := buf.String() - - tt := time.Now() - - expected := fmt.Sprintf(`.TH TestMan 1 "%s" -.SH NAME -TestMan \- Test manpage generation -.SH SYNOPSIS -\fBTestMan\fP [OPTIONS] -.SH DESCRIPTION -This is a somewhat longer description of what this does -.SH OPTIONS -.TP -\fB-v, --verbose\fP -Show verbose debug information -.TP -\fB-c\fP -Call phone number -.TP -\fB--ptrslice\fP -A slice of pointers to string -.TP -\fB-s\fP -A slice of strings -.TP -\fB--intmap\fP -A map from string to int -`, tt.Format("2 January 2006")) - - if got != expected { - ret, err := helpDiff(got, expected) - - if err != nil { - t.Errorf("Unexpected man page, expected:\n\n%s\n\nbut got\n\n%s", expected, got) - } else { - t.Errorf("Unexpected man page:\n\n%s", ret) - } - } -} diff --git a/github.com/jessevdk/go-flags/ini.go b/github.com/jessevdk/go-flags/ini.go deleted file mode 100644 index 59ccb3aff..000000000 --- a/github.com/jessevdk/go-flags/ini.go +++ /dev/null @@ -1,146 +0,0 @@ -package flags - -import ( - "fmt" - "io" - "os" -) - -// IniError contains location information on where in the ini file an error -// occured. -type IniError struct { - // The error message. - Message string - - // The filename of the file in which the error occurred. - File string - - // The line number at which the error occurred. - LineNumber uint -} - -// Error provides a "file:line: message" formatted message of the ini error. -func (x *IniError) Error() string { - return fmt.Sprintf("%s:%d: %s", - x.File, - x.LineNumber, - x.Message) -} - -// IniOptions for writing ini files -type IniOptions uint - -const ( - // IniNone indicates no options. - IniNone IniOptions = 0 - - // IniIncludeDefaults indicates that default values should be written - // when writing options to an ini file. - IniIncludeDefaults = 1 << iota - - // IniIncludeComments indicates that comments containing the description - // of an option should be written when writing options to an ini file. - IniIncludeComments - - // IniDefault provides a default set of options. - IniDefault = IniIncludeComments -) - -// IniParser is a utility to read and write flags options from and to ini -// files. -type IniParser struct { - parser *Parser -} - -// NewIniParser creates a new ini parser for a given Parser. -func NewIniParser(p *Parser) *IniParser { - return &IniParser{ - parser: p, - } -} - -// IniParse is a convenience function to parse command line options with default -// settings from an ini file. The provided data is a pointer to a struct -// representing the default option group (named "Application Options"). For -// more control, use flags.NewParser. -func IniParse(filename string, data interface{}) error { - p := NewParser(data, Default) - return NewIniParser(p).ParseFile(filename) -} - -// ParseFile parses flags from an ini formatted file. See Parse for more -// information on the ini file foramt. The returned errors can be of the type -// flags.Error or flags.IniError. -func (i *IniParser) ParseFile(filename string) error { - i.parser.storeDefaults() - - ini, err := readIniFromFile(filename) - - if err != nil { - return err - } - - return i.parse(ini) -} - -// Parse parses flags from an ini format. You can use ParseFile as a -// convenience function to parse from a filename instead of a general -// io.Reader. -// -// The format of the ini file is as follows: -// -// [Option group name] -// option = value -// -// Each section in the ini file represents an option group or command in the -// flags parser. The default flags parser option group (i.e. when using -// flags.Parse) is named 'Application Options'. The ini option name is matched -// in the following order: -// -// 1. Compared to the ini-name tag on the option struct field (if present) -// 2. Compared to the struct field name -// 3. Compared to the option long name (if present) -// 4. Compared to the option short name (if present) -// -// Sections for nested groups and commands can be addressed using a dot `.' -// namespacing notation (i.e [subcommand.Options]). Group section names are -// matched case insensitive. -// -// The returned errors can be of the type flags.Error or -// flags.IniError. -func (i *IniParser) Parse(reader io.Reader) error { - i.parser.storeDefaults() - - ini, err := readIni(reader, "") - - if err != nil { - return err - } - - return i.parse(ini) -} - -// WriteFile writes the flags as ini format into a file. See WriteIni -// for more information. The returned error occurs when the specified file -// could not be opened for writing. -func (i *IniParser) WriteFile(filename string, options IniOptions) error { - file, err := os.Create(filename) - - if err != nil { - return err - } - - defer file.Close() - i.Write(file, options) - - return nil -} - -// Write writes the current values of all the flags to an ini format. -// See Parse for more information on the ini file format. You typically -// call this only after settings have been parsed since the default values of each -// option are stored just before parsing the flags (this is only relevant when -// IniIncludeDefaults is _not_ set in options). -func (i *IniParser) Write(writer io.Writer, options IniOptions) { - writeIni(i, writer, options) -} diff --git a/github.com/jessevdk/go-flags/ini_private.go b/github.com/jessevdk/go-flags/ini_private.go deleted file mode 100644 index 4ccda73ee..000000000 --- a/github.com/jessevdk/go-flags/ini_private.go +++ /dev/null @@ -1,333 +0,0 @@ -package flags - -import ( - "bufio" - "fmt" - "io" - "os" - "reflect" - "strings" -) - -type iniValue struct { - Name string - Value string -} - -type iniSection []iniValue -type ini map[string]iniSection - -func readFullLine(reader *bufio.Reader) (string, error) { - var line []byte - - for { - l, more, err := reader.ReadLine() - - if err != nil { - return "", err - } - - if line == nil && !more { - return string(l), nil - } - - line = append(line, l...) - - if !more { - break - } - } - - return string(line), nil -} - -func optionIniName(option *Option) string { - name := option.tag.Get("_read-ini-name") - - if len(name) != 0 { - return name - } - - name = option.tag.Get("ini-name") - - if len(name) != 0 { - return name - } - - return option.field.Name -} - -func writeGroupIni(group *Group, namespace string, writer io.Writer, options IniOptions) { - var sname string - - if len(namespace) != 0 { - sname = namespace + "." + group.ShortDescription - } else { - sname = group.ShortDescription - } - - sectionwritten := false - comments := (options & IniIncludeComments) != IniNone - - for _, option := range group.options { - if option.isFunc() { - continue - } - - if len(option.tag.Get("no-ini")) != 0 { - continue - } - - val := option.value - - if (options&IniIncludeDefaults) == IniNone && - reflect.DeepEqual(val, option.defaultValue) { - continue - } - - if !sectionwritten { - fmt.Fprintf(writer, "[%s]\n", sname) - sectionwritten = true - } - - if comments { - fmt.Fprintf(writer, "; %s\n", option.Description) - } - - oname := optionIniName(option) - - switch val.Type().Kind() { - case reflect.Slice: - for idx := 0; idx < val.Len(); idx++ { - v, _ := convertToString(val.Index(idx), option.tag) - fmt.Fprintf(writer, "%s = %s\n", oname, v) - } - - if val.Len() == 0 { - fmt.Fprintf(writer, "; %s =\n", oname) - } - case reflect.Map: - for _, key := range val.MapKeys() { - k, _ := convertToString(key, option.tag) - v, _ := convertToString(val.MapIndex(key), option.tag) - - fmt.Fprintf(writer, "%s = %s:%s\n", oname, k, v) - } - - if val.Len() == 0 { - fmt.Fprintf(writer, "; %s =\n", oname) - } - default: - v, _ := convertToString(val, option.tag) - - if len(v) != 0 { - fmt.Fprintf(writer, "%s = %s\n", oname, v) - } else { - fmt.Fprintf(writer, "%s =\n", oname) - } - } - - if comments { - fmt.Fprintln(writer) - } - } - - if sectionwritten && !comments { - fmt.Fprintln(writer) - } -} - -func writeCommandIni(command *Command, namespace string, writer io.Writer, options IniOptions) { - command.eachGroup(func(group *Group) { - writeGroupIni(group, namespace, writer, options) - }) - - for _, c := range command.commands { - var nns string - - if len(namespace) != 0 { - nns = c.Name + "." + nns - } else { - nns = c.Name - } - - writeCommandIni(c, nns, writer, options) - } -} - -func writeIni(parser *IniParser, writer io.Writer, options IniOptions) { - writeCommandIni(parser.parser.Command, "", writer, options) -} - -func readIniFromFile(filename string) (ini, error) { - file, err := os.Open(filename) - - if err != nil { - return nil, err - } - - defer file.Close() - - return readIni(file, filename) -} - -func readIni(contents io.Reader, filename string) (ini, error) { - ret := make(ini) - - reader := bufio.NewReader(contents) - - // Empty global section - section := make(iniSection, 0, 10) - sectionname := "" - - ret[sectionname] = section - - var lineno uint - - for { - line, err := readFullLine(reader) - - if err == io.EOF { - break - } - - if err != nil { - return nil, err - } - - lineno++ - line = strings.TrimSpace(line) - - // Skip empty lines and lines starting with ; (comments) - if len(line) == 0 || line[0] == ';' { - continue - } - - if line[0] == '[' { - if line[0] != '[' || line[len(line)-1] != ']' { - return nil, &IniError{ - Message: "malformed section header", - File: filename, - LineNumber: lineno, - } - } - - name := strings.TrimSpace(line[1 : len(line)-1]) - - if len(name) == 0 { - return nil, &IniError{ - Message: "empty section name", - File: filename, - LineNumber: lineno, - } - } - - sectionname = name - section = ret[name] - - if section == nil { - section = make(iniSection, 0, 10) - ret[name] = section - } - - continue - } - - // Parse option here - keyval := strings.SplitN(line, "=", 2) - - if len(keyval) != 2 { - return nil, &IniError{ - Message: fmt.Sprintf("malformed key=value (%s)", line), - File: filename, - LineNumber: lineno, - } - } - - name := strings.TrimSpace(keyval[0]) - value := strings.TrimSpace(keyval[1]) - - section = append(section, iniValue{ - Name: name, - Value: value, - }) - - ret[sectionname] = section - } - - return ret, nil -} - -func (i *IniParser) matchingGroups(name string) []*Group { - if len(name) == 0 { - var ret []*Group - - i.parser.eachGroup(func(g *Group) { - ret = append(ret, g) - }) - - return ret - } - - g := i.parser.groupByName(name) - - if g != nil { - return []*Group{g} - } - - return nil -} - -func (i *IniParser) parse(ini ini) error { - p := i.parser - - for name, section := range ini { - groups := i.matchingGroups(name) - - if len(groups) == 0 { - return newError(ErrUnknownGroup, - fmt.Sprintf("could not find option group `%s'", name)) - } - - for _, inival := range section { - var opt *Option - - for _, group := range groups { - opt = group.optionByName(inival.Name, func(o *Option, n string) bool { - return strings.ToLower(o.tag.Get("ini-name")) == strings.ToLower(n) - }) - - if opt != nil && len(opt.tag.Get("no-ini")) != 0 { - opt = nil - } - - if opt != nil { - break - } - } - - if opt == nil { - if (p.Options & IgnoreUnknown) == None { - return newError(ErrUnknownFlag, - fmt.Sprintf("unknown option: %s", inival.Name)) - } - - continue - } - - pval := &inival.Value - - if !opt.canArgument() && len(inival.Value) == 0 { - pval = nil - } - - if err := opt.set(pval); err != nil { - return wrapError(err) - } - - opt.tag.Set("_read-ini-name", inival.Name) - } - } - - return nil -} diff --git a/github.com/jessevdk/go-flags/ini_test.go b/github.com/jessevdk/go-flags/ini_test.go deleted file mode 100644 index caff08c11..000000000 --- a/github.com/jessevdk/go-flags/ini_test.go +++ /dev/null @@ -1,170 +0,0 @@ -package flags - -import ( - "bytes" - "strings" - "testing" -) - -func TestWriteIni(t *testing.T) { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - p.ParseArgs([]string{"-vv", "--intmap=a:2", "--intmap", "b:3"}) - - inip := NewIniParser(p) - - var b bytes.Buffer - inip.Write(&b, IniDefault|IniIncludeDefaults) - - got := b.String() - expected := `[Application Options] -; Show verbose debug information -verbose = true -verbose = true - -; A slice of pointers to string -; PtrSlice = - -; Option only available in ini -only-ini = - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:2 -int-map = b:3 - -` - - if got != expected { - ret, err := helpDiff(got, expected) - - if err != nil { - t.Errorf("Unexpected ini, expected:\n\n%s\n\nbut got\n\n%s", expected, got) - } else { - t.Errorf("Unexpected ini:\n\n%s", ret) - } - } -} - -func TestReadIni(t *testing.T) { - var opts helpOptions - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := ` -; Show verbose debug information -verbose = true -verbose = true - -[Application Options] -; A slice of pointers to string -; PtrSlice = - -[Other Options] -; A slice of strings -; StringSlice = - -; A map from string to int -int-map = a:2 -int-map = b:3 - -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - assertBoolArray(t, opts.Verbose, []bool{true, true}) - - if v, ok := opts.Other.IntMap["a"]; !ok { - t.Errorf("Expected \"a\" in Other.IntMap") - } else if v != 2 { - t.Errorf("Expected Other.IntMap[\"a\"] = 2, but got %v", v) - } - - if v, ok := opts.Other.IntMap["b"]; !ok { - t.Errorf("Expected \"b\" in Other.IntMap") - } else if v != 3 { - t.Errorf("Expected Other.IntMap[\"b\"] = 3, but got %v", v) - } -} - -func TestIniCommands(t *testing.T) { - var opts struct { - Value string `short:"v" long:"value"` - - Add struct { - Name int `short:"n" long:"name" ini-name:"AliasName"` - - Other struct { - O string `short:"o" long:"other"` - } `group:"Other Options"` - } `command:"add"` - } - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := `[Application Options] -value = some value - -[add] -AliasName = 5 - -[add.Other Options] -other = subgroup -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err != nil { - t.Fatalf("Unexpected error: %s", err) - } - - assertString(t, opts.Value, "some value") - - if opts.Add.Name != 5 { - t.Errorf("Expected opts.Add.Name to be 5, but got %v", opts.Add.Name) - } - - assertString(t, opts.Add.Other.O, "subgroup") -} - -func TestIniNoIni(t *testing.T) { - var opts struct { - Value string `short:"v" long:"value" no-ini:"yes"` - } - - p := NewNamedParser("TestIni", Default) - p.AddGroup("Application Options", "The application options", &opts) - - inip := NewIniParser(p) - - inic := `[Application Options] -value = some value -` - - b := strings.NewReader(inic) - err := inip.Parse(b) - - if err == nil { - t.Fatalf("Expected error") - } - - assertError(t, err, ErrUnknownFlag, "unknown option: value") -} diff --git a/github.com/jessevdk/go-flags/long_test.go b/github.com/jessevdk/go-flags/long_test.go deleted file mode 100644 index 02fc8c701..000000000 --- a/github.com/jessevdk/go-flags/long_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestLong(t *testing.T) { - var opts = struct { - Value bool `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestLongArg(t *testing.T) { - var opts = struct { - Value string `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongArgEqual(t *testing.T) { - var opts = struct { - Value string `long:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value=value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongDefault(t *testing.T) { - var opts = struct { - Value string `long:"value" default:"value"` - }{} - - ret := assertParseSuccess(t, &opts) - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongOptional(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestLongOptionalArg(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value", "no") - - assertStringArray(t, ret, []string{"no"}) - assertString(t, opts.Value, "value") -} - -func TestLongOptionalArgEqual(t *testing.T) { - var opts = struct { - Value string `long:"value" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "--value=value", "no") - - assertStringArray(t, ret, []string{"no"}) - assertString(t, opts.Value, "value") -} diff --git a/github.com/jessevdk/go-flags/man.go b/github.com/jessevdk/go-flags/man.go deleted file mode 100644 index 93d6149d6..000000000 --- a/github.com/jessevdk/go-flags/man.go +++ /dev/null @@ -1,134 +0,0 @@ -package flags - -import ( - "fmt" - "io" - "strings" - "time" -) - -func formatForMan(wr io.Writer, s string) { - for { - idx := strings.IndexRune(s, '`') - - if idx < 0 { - fmt.Fprintf(wr, "%s", s) - break - } - - fmt.Fprintf(wr, "%s", s[:idx]) - - s = s[idx+1:] - idx = strings.IndexRune(s, '\'') - - if idx < 0 { - fmt.Fprintf(wr, "%s", s) - break - } - - fmt.Fprintf(wr, "\\fB%s\\fP", s[:idx]) - s = s[idx+1:] - } -} - -func writeManPageOptions(wr io.Writer, grp *Group) { - grp.eachGroup(func(group *Group) { - for _, opt := range group.options { - if !opt.canCli() { - continue - } - - fmt.Fprintln(wr, ".TP") - fmt.Fprintf(wr, "\\fB") - - if opt.ShortName != 0 { - fmt.Fprintf(wr, "-%c", opt.ShortName) - } - - if len(opt.LongName) != 0 { - if opt.ShortName != 0 { - fmt.Fprintf(wr, ", ") - } - - fmt.Fprintf(wr, "--%s", opt.LongName) - } - - fmt.Fprintln(wr, "\\fP") - formatForMan(wr, opt.Description) - fmt.Fprintln(wr, "") - } - }) -} - -func writeManPageSubCommands(wr io.Writer, name string, root *Command) { - commands := root.sortedCommands() - - for _, c := range commands { - var nn string - - if len(name) != 0 { - nn = name + " " + c.Name - } else { - nn = c.Name - } - - writeManPageCommand(wr, nn, c) - } -} - -func writeManPageCommand(wr io.Writer, name string, command *Command) { - fmt.Fprintf(wr, ".SS %s\n", name) - fmt.Fprintln(wr, command.ShortDescription) - - if len(command.LongDescription) > 0 { - fmt.Fprintln(wr, "") - - cmdstart := fmt.Sprintf("The %s command", command.Name) - - if strings.HasPrefix(command.LongDescription, cmdstart) { - fmt.Fprintf(wr, "The \\fI%s\\fP command", command.Name) - - formatForMan(wr, command.LongDescription[len(cmdstart):]) - fmt.Fprintln(wr, "") - } else { - formatForMan(wr, command.LongDescription) - fmt.Fprintln(wr, "") - } - } - - writeManPageOptions(wr, command.Group) - writeManPageSubCommands(wr, name, command) -} - -// WriteManPage writes a basic man page in groff format to the specified -// writer. -func (p *Parser) WriteManPage(wr io.Writer) { - t := time.Now() - - fmt.Fprintf(wr, ".TH %s 1 \"%s\"\n", p.Name, t.Format("2 January 2006")) - fmt.Fprintln(wr, ".SH NAME") - fmt.Fprintf(wr, "%s \\- %s\n", p.Name, p.ShortDescription) - fmt.Fprintln(wr, ".SH SYNOPSIS") - - usage := p.Usage - - if len(usage) == 0 { - usage = "[OPTIONS]" - } - - fmt.Fprintf(wr, "\\fB%s\\fP %s\n", p.Name, usage) - fmt.Fprintln(wr, ".SH DESCRIPTION") - - formatForMan(wr, p.LongDescription) - fmt.Fprintln(wr, "") - - fmt.Fprintln(wr, ".SH OPTIONS") - - writeManPageOptions(wr, p.Command.Group) - - if len(p.commands) > 0 { - fmt.Fprintln(wr, ".SH COMMANDS") - - writeManPageSubCommands(wr, "", p.Command) - } -} diff --git a/github.com/jessevdk/go-flags/marshal_test.go b/github.com/jessevdk/go-flags/marshal_test.go deleted file mode 100644 index 9378db1bb..000000000 --- a/github.com/jessevdk/go-flags/marshal_test.go +++ /dev/null @@ -1,78 +0,0 @@ -package flags - -import ( - "fmt" - "testing" -) - -type marshalled bool - -func (m *marshalled) UnmarshalFlag(value string) error { - if value == "yes" { - *m = true - } else if value == "no" { - *m = false - } else { - return fmt.Errorf("`%s' is not a valid value, please specify `yes' or `no'", value) - } - - return nil -} - -func (m marshalled) MarshalFlag() string { - if m { - return "yes" - } - - return "no" -} - -func TestMarshal(t *testing.T) { - var opts = struct { - Value marshalled `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v=yes") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestMarshalDefault(t *testing.T) { - var opts = struct { - Value marshalled `short:"v" default:"yes"` - }{} - - ret := assertParseSuccess(t, &opts) - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestMarshalOptional(t *testing.T) { - var opts = struct { - Value marshalled `short:"v" optional:"yes" optional-value:"yes"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestMarshalError(t *testing.T) { - var opts = struct { - Value marshalled `short:"v"` - }{} - - assertParseFail(t, ErrMarshal, "invalid argument for flag `-v' (expected flags.marshalled): `invalid' is not a valid value, please specify `yes' or `no'", &opts, "-vinvalid") -} diff --git a/github.com/jessevdk/go-flags/multitag.go b/github.com/jessevdk/go-flags/multitag.go deleted file mode 100644 index 96bb1a31d..000000000 --- a/github.com/jessevdk/go-flags/multitag.go +++ /dev/null @@ -1,140 +0,0 @@ -package flags - -import ( - "strconv" -) - -type multiTag struct { - value string - cache map[string][]string -} - -func newMultiTag(v string) multiTag { - return multiTag{ - value: v, - } -} - -func (x *multiTag) scan() (map[string][]string, error) { - v := x.value - - ret := make(map[string][]string) - - // This is mostly copied from reflect.StructTag.Get - for v != "" { - i := 0 - - // Skip whitespace - for i < len(v) && v[i] == ' ' { - i++ - } - - v = v[i:] - - if v == "" { - break - } - - // Scan to colon to find key - i = 0 - - for i < len(v) && v[i] != ' ' && v[i] != ':' && v[i] != '"' { - i++ - } - - if i >= len(v) { - return nil, newErrorf(ErrTag, "expected `:' after key name, but got end of tag (in `%v`)", x.value) - } - - if v[i] != ':' { - return nil, newErrorf(ErrTag, "expected `:' after key name, but got `%v' (in `%v`)", v[i], x.value) - } - - if i+1 >= len(v) { - return nil, newErrorf(ErrTag, "expected `\"' to start tag value at end of tag (in `%v`)", x.value) - } - - if v[i+1] != '"' { - return nil, newErrorf(ErrTag, "expected `\"' to start tag value, but got `%v' (in `%v`)", v[i+1], x.value) - } - - name := v[:i] - v = v[i+1:] - - // Scan quoted string to find value - i = 1 - - for i < len(v) && v[i] != '"' { - if v[i] == '\n' { - return nil, newErrorf(ErrTag, "unexpected newline in tag value `%v' (in `%v`)", name, x.value) - } - - if v[i] == '\\' { - i++ - } - i++ - } - - if i >= len(v) { - return nil, newErrorf(ErrTag, "expected end of tag value `\"' at end of tag (in `%v`)", x.value) - } - - val, err := strconv.Unquote(v[:i+1]) - - if err != nil { - return nil, newErrorf(ErrTag, "Malformed value of tag `%v:%v` => %v (in `%v`)", name, v[:i+1], err, x.value) - } - - v = v[i+1:] - - ret[name] = append(ret[name], val) - } - - return ret, nil -} - -func (x *multiTag) Parse() error { - vals, err := x.scan() - x.cache = vals - - return err -} - -func (x *multiTag) cached() map[string][]string { - if x.cache == nil { - cache, _ := x.scan() - - if cache == nil { - cache = make(map[string][]string) - } - - x.cache = cache - } - - return x.cache -} - -func (x *multiTag) Get(key string) string { - c := x.cached() - - if v, ok := c[key]; ok { - return v[len(v)-1] - } - - return "" -} - -func (x *multiTag) GetMany(key string) []string { - c := x.cached() - return c[key] -} - -func (x *multiTag) Set(key string, value string) { - c := x.cached() - c[key] = []string{value} -} - -func (x *multiTag) SetMany(key string, value []string) { - c := x.cached() - c[key] = value -} diff --git a/github.com/jessevdk/go-flags/option.go b/github.com/jessevdk/go-flags/option.go deleted file mode 100644 index 150a94f73..000000000 --- a/github.com/jessevdk/go-flags/option.go +++ /dev/null @@ -1,95 +0,0 @@ -package flags - -import ( - "fmt" - "reflect" - "unicode/utf8" -) - -// Option flag information. Contains a description of the option, short and -// long name as well as a default value and whether an argument for this -// flag is optional. -type Option struct { - // The description of the option flag. This description is shown - // automatically in the builtin help. - Description string - - // The short name of the option (a single character). If not 0, the - // option flag can be 'activated' using -. Either ShortName - // or LongName needs to be non-empty. - ShortName rune - - // The long name of the option. If not "", the option flag can be - // activated using --. Either ShortName or LongName needs - // to be non-empty. - LongName string - - // The default value of the option. - Default []string - - // If true, specifies that the argument to an option flag is optional. - // When no argument to the flag is specified on the command line, the - // value of Default will be set in the field this option represents. - // This is only valid for non-boolean options. - OptionalArgument bool - - // The optional value of the option. The optional value is used when - // the option flag is marked as having an OptionalArgument. This means - // that when the flag is specified, but no option argument is given, - // the value of the field this option represents will be set to - // OptionalValue. This is only valid for non-boolean options. - OptionalValue []string - - // If true, the option _must_ be specified on the command line. If the - // option is not specified, the parser will generate an ErrRequired type - // error. - Required bool - - // A name for the value of an option shown in the Help as --flag [ValueName] - ValueName string - - // A mask value to show in the help instead of the default value. This - // is useful for hiding sensitive information in the help, such as - // passwords. - DefaultMask string - - // The struct field which the option represents. - field reflect.StructField - - // The struct field value which the option represents. - value reflect.Value - - defaultValue reflect.Value - iniUsedName string - tag multiTag -} - -// String converts an option to a human friendly readable string describing the -// option. -func (option *Option) String() string { - var s string - var short string - - if option.ShortName != 0 { - data := make([]byte, utf8.RuneLen(option.ShortName)) - utf8.EncodeRune(data, option.ShortName) - short = string(data) - - if len(option.LongName) != 0 { - s = fmt.Sprintf("%s%s, %s%s", - string(defaultShortOptDelimiter), short, - defaultLongOptDelimiter, option.LongName) - } else { - s = fmt.Sprintf("%s%s", string(defaultShortOptDelimiter), short) - } - } else if len(option.LongName) != 0 { - s = fmt.Sprintf("%s%s", defaultLongOptDelimiter, option.LongName) - } - - return s -} - -// Value returns the option value as an interface{}. -func (option *Option) Value() interface{} { - return option.value.Interface() -} diff --git a/github.com/jessevdk/go-flags/option_private.go b/github.com/jessevdk/go-flags/option_private.go deleted file mode 100644 index cba601134..000000000 --- a/github.com/jessevdk/go-flags/option_private.go +++ /dev/null @@ -1,125 +0,0 @@ -package flags - -import ( - "reflect" -) - -// Set the value of an option to the specified value. An error will be returned -// if the specified value could not be converted to the corresponding option -// value type. -func (option *Option) set(value *string) error { - if option.isFunc() { - return option.call(value) - } else if value != nil { - return convert(*value, option.value, option.tag) - } else { - return convert("", option.value, option.tag) - } - - return nil -} - -func (option *Option) canCli() bool { - return option.ShortName != 0 || len(option.LongName) != 0 -} - -func (option *Option) canArgument() bool { - if u := option.isUnmarshaler(); u != nil { - return true - } - - return !option.isBool() -} - -func (option *Option) clear() { - tp := option.value.Type() - - switch tp.Kind() { - case reflect.Func: - // Skip - case reflect.Map: - // Empty the map - option.value.Set(reflect.MakeMap(tp)) - default: - zeroval := reflect.Zero(tp) - option.value.Set(zeroval) - } -} - -func (option *Option) isUnmarshaler() Unmarshaler { - v := option.value - - for { - if !v.CanInterface() { - return nil - } - - i := v.Interface() - - if u, ok := i.(Unmarshaler); ok { - return u - } - - if !v.CanAddr() { - return nil - } - - v = v.Addr() - } - - return nil -} - -func (option *Option) isBool() bool { - tp := option.value.Type() - - for { - switch tp.Kind() { - case reflect.Bool: - return true - case reflect.Slice: - return (tp.Elem().Kind() == reflect.Bool) - case reflect.Func: - return tp.NumIn() == 0 - case reflect.Ptr: - tp = tp.Elem() - default: - return false - } - } - - return false -} - -func (option *Option) isFunc() bool { - return option.value.Type().Kind() == reflect.Func -} - -func (option *Option) call(value *string) error { - var retval []reflect.Value - - if value == nil { - retval = option.value.Call(nil) - } else { - tp := option.value.Type().In(0) - - val := reflect.New(tp) - val = reflect.Indirect(val) - - if err := convert(*value, val, option.tag); err != nil { - return err - } - - retval = option.value.Call([]reflect.Value{val}) - } - - if len(retval) == 1 && retval[0].Type() == reflect.TypeOf((*error)(nil)).Elem() { - if retval[0].Interface() == nil { - return nil - } - - return retval[0].Interface().(error) - } - - return nil -} diff --git a/github.com/jessevdk/go-flags/options_test.go b/github.com/jessevdk/go-flags/options_test.go deleted file mode 100644 index b0fe9f456..000000000 --- a/github.com/jessevdk/go-flags/options_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestPassDoubleDash(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - p := NewParser(&opts, PassDoubleDash) - ret, err := p.ParseArgs([]string{"-v", "--", "-v", "-g"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - assertStringArray(t, ret, []string{"-v", "-g"}) -} - -func TestPassAfterNonOption(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - p := NewParser(&opts, PassAfterNonOption) - ret, err := p.ParseArgs([]string{"-v", "arg", "-v", "-g"}) - - if err != nil { - t.Fatalf("Unexpected error: %v", err) - return - } - - if !opts.Value { - t.Errorf("Expected Value to be true") - } - - assertStringArray(t, ret, []string{"arg", "-v", "-g"}) -} diff --git a/github.com/jessevdk/go-flags/optstyle_other.go b/github.com/jessevdk/go-flags/optstyle_other.go deleted file mode 100644 index 248996c5a..000000000 --- a/github.com/jessevdk/go-flags/optstyle_other.go +++ /dev/null @@ -1,54 +0,0 @@ -// +build !windows - -package flags - -import ( - "strings" -) - -const ( - defaultShortOptDelimiter = '-' - defaultLongOptDelimiter = "--" - defaultNameArgDelimiter = '=' -) - -func argumentIsOption(arg string) bool { - return len(arg) > 0 && arg[0] == '-' -} - -// stripOptionPrefix returns the option without the prefix and whether or -// not the option is a long option or not. -func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { - if strings.HasPrefix(optname, "--") { - return "--", optname[2:], true - } else if strings.HasPrefix(optname, "-") { - return "-", optname[1:], false - } - - return "", optname, false -} - -// splitOption attempts to split the passed option into a name and an argument. -// When there is no argument specified, nil will be returned for it. -func splitOption(prefix string, option string, islong bool) (string, *string) { - pos := strings.Index(option, "=") - - if (islong && pos >= 0) || (!islong && pos == 1) { - rest := option[pos+1:] - return option[:pos], &rest - } - - return option, nil -} - -// addHelpGroup adds a new group that contains default help parameters. -func (c *Command) addHelpGroup(showHelp func() error) *Group { - var help struct { - ShowHelp func() error `short:"h" long:"help" description:"Show this help message"` - } - - help.ShowHelp = showHelp - ret, _ := c.AddGroup("Help Options", "", &help) - - return ret -} diff --git a/github.com/jessevdk/go-flags/optstyle_windows.go b/github.com/jessevdk/go-flags/optstyle_windows.go deleted file mode 100644 index 8823c56fc..000000000 --- a/github.com/jessevdk/go-flags/optstyle_windows.go +++ /dev/null @@ -1,85 +0,0 @@ -package flags - -import ( - "strings" -) - -// Windows uses a front slash for both short and long options. Also it uses -// a colon for name/argument delimter. -const ( - defaultShortOptDelimiter = '/' - defaultLongOptDelimiter = "/" - defaultNameArgDelimiter = ':' -) - -func argumentIsOption(arg string) bool { - // Windows-style options allow front slash for the option - // delimiter. - return len(arg) > 0 && (arg[0] == '-' || arg[0] == '/') -} - -// stripOptionPrefix returns the option without the prefix and whether or -// not the option is a long option or not. -func stripOptionPrefix(optname string) (prefix string, name string, islong bool) { - // Determine if the argument is a long option or not. Windows - // typically supports both long and short options with a single - // front slash as the option delimiter, so handle this situation - // nicely. - possplit := 0 - - if strings.HasPrefix(optname, "--") { - possplit = 2 - islong = true - } else if strings.HasPrefix(optname, "-") { - possplit = 1 - islong = false - } else if strings.HasPrefix(optname, "/") { - possplit = 1 - islong = len(optname) > 2 - } - - return optname[:possplit], optname[possplit:], islong -} - -// splitOption attempts to split the passed option into a name and an argument. -// When there is no argument specified, nil will be returned for it. -func splitOption(prefix string, option string, islong bool) (string, *string) { - if len(option) == 0 { - return option, nil - } - - // Windows typically uses a colon for the option name and argument - // delimiter while POSIX typically uses an equals. Support both styles, - // but don't allow the two to be mixed. That is to say /foo:bar and - // --foo=bar are acceptable, but /foo=bar and --foo:bar are not. - var pos int - - if prefix == "/" { - pos = strings.Index(option, ":") - } else if len(prefix) > 0 { - pos = strings.Index(option, "=") - } - - if (islong && pos >= 0) || (!islong && pos == 1) { - rest := option[pos+1:] - return option[:pos], &rest - } - - return option, nil -} - -// addHelpGroup adds a new group that contains default help parameters. -func (c *Command) addHelpGroup(showHelp func() error) *Group { - // Windows CLI applications typically use /? for help, so make both - // that available as well as the POSIX style h and help. - var help struct { - ShowHelpWindows func() error `short:"?" description:"Show this help message"` - ShowHelpPosix func() error `short:"h" long:"help" description:"Show this help message"` - } - - help.ShowHelpWindows = showHelp - help.ShowHelpPosix = showHelp - - ret, _ := c.AddGroup("Help Options", "", &help) - return ret -} diff --git a/github.com/jessevdk/go-flags/parser.go b/github.com/jessevdk/go-flags/parser.go deleted file mode 100644 index 481d35387..000000000 --- a/github.com/jessevdk/go-flags/parser.go +++ /dev/null @@ -1,212 +0,0 @@ -// Copyright 2012 Jesse van den Kieboom. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package flags - -import ( - "os" - "path" -) - -// A Parser provides command line option parsing. It can contain several -// option groups each with their own set of options. -type Parser struct { - // Embedded, see Command for more information - *Command - - // A usage string to be displayed in the help message. - Usage string - - // Option flags changing the behavior of the parser. - Options Options - - internalError error -} - -// Options provides parser options that change the behavior of the option -// parser. -type Options uint - -const ( - // None indicates no options. - None Options = 0 - - // HelpFlag adds a default Help Options group to the parser containing - // -h and --help options. When either -h or --help is specified on the - // command line, the parser will return the special error of type - // ErrHelp. When PrintErrors is also specified, then the help message - // will also be automatically printed to os.Stderr. - HelpFlag = 1 << iota - - // PassDoubleDash passes all arguments after a double dash, --, as - // remaining command line arguments (i.e. they will not be parsed for - // flags). - PassDoubleDash - - // IgnoreUnknown ignores any unknown options and passes them as - // remaining command line arguments instead of generating an error. - IgnoreUnknown - - // PrintErrors prints any errors which occurred during parsing to - // os.Stderr. - PrintErrors - - // PassAfterNonOption passes all arguments after the first non option - // as remaining command line arguments. This is equivalent to strict - // POSIX processing. - PassAfterNonOption - - // Default is a convenient default set of options which should cover - // most of the uses of the flags package. - Default = HelpFlag | PrintErrors | PassDoubleDash -) - -// Parse is a convenience function to parse command line options with default -// settings. The provided data is a pointer to a struct representing the -// default option group (named "Application Options"). For more control, use -// flags.NewParser. -func Parse(data interface{}) ([]string, error) { - return NewParser(data, Default).Parse() -} - -// ParseArgs is a convenience function to parse command line options with default -// settings. The provided data is a pointer to a struct representing the -// default option group (named "Application Options"). The args argument is -// the list of command line arguments to parse. If you just want to parse the -// default program command line arguments (i.e. os.Args), then use flags.Parse -// instead. For more control, use flags.NewParser. -func ParseArgs(data interface{}, args []string) ([]string, error) { - return NewParser(data, Default).ParseArgs(args) -} - -// NewParser creates a new parser. It uses os.Args[0] as the application -// name and then calls Parser.NewNamedParser (see Parser.NewNamedParser for -// more details). The provided data is a pointer to a struct representing the -// default option group (named "Application Options"), or nil if the default -// group should not be added. The options parameter specifies a set of options -// for the parser. -func NewParser(data interface{}, options Options) *Parser { - ret := NewNamedParser(path.Base(os.Args[0]), options) - - if data != nil { - _, ret.internalError = ret.AddGroup("Application Options", "", data) - } - - return ret -} - -// NewNamedParser creates a new parser. The appname is used to display the -// executable name in the builtin help message. Option groups and commands can -// be added to this parser by using AddGroup and AddCommand. -func NewNamedParser(appname string, options Options) *Parser { - return &Parser{ - Command: newCommand(appname, "", "", nil), - Options: options, - } -} - -// Parse parses the command line arguments from os.Args using Parser.ParseArgs. -// For more detailed information see ParseArgs. -func (p *Parser) Parse() ([]string, error) { - return p.ParseArgs(os.Args[1:]) -} - -// ParseArgs parses the command line arguments according to the option groups that -// were added to the parser. On successful parsing of the arguments, the -// remaining, non-option, arguments (if any) are returned. The returned error -// indicates a parsing error and can be used with PrintError to display -// contextual information on where the error occurred exactly. -// -// When the common help group has been added (AddHelp) and either -h or --help -// was specified in the command line arguments, a help message will be -// automatically printed. Furthermore, the special error type ErrHelp is returned. -// It is up to the caller to exit the program if so desired. -func (p *Parser) ParseArgs(args []string) ([]string, error) { - if p.internalError != nil { - return nil, p.internalError - } - - p.eachCommand(func(c *Command) { - p.eachGroup(func(g *Group) { - g.storeDefaults() - }) - }, true) - - // Add builtin help group to all commands if necessary - if (p.Options & HelpFlag) != None { - p.addHelpGroups(p.showBuiltinHelp) - } - - s := &parseState{ - args: args, - retargs: make([]string, 0, len(args)), - command: p.Command, - lookup: p.makeLookup(), - } - - for !s.eof() { - arg := s.pop() - - // When PassDoubleDash is set and we encounter a --, then - // simply append all the rest as arguments and break out - if (p.Options&PassDoubleDash) != None && arg == "--" { - s.retargs = append(s.retargs, s.args...) - break - } - - if !argumentIsOption(arg) { - // Note: this also sets s.err, so we can just check for - // nil here and use s.err later - if p.parseNonOption(s) != nil { - break - } - - continue - } - - var err error - var option *Option - - prefix, optname, islong := stripOptionPrefix(arg) - optname, argument := splitOption(prefix, optname, islong) - - if islong { - option, err = p.parseLong(s, optname, argument) - } else { - option, err = p.parseShort(s, optname, argument) - } - - if err != nil { - ignoreUnknown := (p.Options & IgnoreUnknown) != None - parseErr := wrapError(err) - - if !(parseErr.Type == ErrUnknownFlag && ignoreUnknown) { - s.err = parseErr - break - } - - if ignoreUnknown { - s.retargs = append(s.retargs, arg) - } - } else { - delete(s.lookup.required, option) - } - } - - if s.err == nil { - s.checkRequired() - } - - if s.err != nil { - return nil, p.printError(s.err) - } - - if len(s.command.commands) != 0 { - return nil, p.printError(s.estimateCommand()) - } else if cmd, ok := s.command.data.(Commander); ok { - return nil, p.printError(cmd.Execute(s.retargs)) - } - - return s.retargs, nil -} diff --git a/github.com/jessevdk/go-flags/parser_private.go b/github.com/jessevdk/go-flags/parser_private.go deleted file mode 100644 index 21518ac6a..000000000 --- a/github.com/jessevdk/go-flags/parser_private.go +++ /dev/null @@ -1,243 +0,0 @@ -package flags - -import ( - "bytes" - "fmt" - "os" - "strings" - "unicode/utf8" -) - -type parseState struct { - arg string - args []string - retargs []string - err error - - command *Command - lookup lookup -} - -func (p *parseState) eof() bool { - return len(p.args) == 0 -} - -func (p *parseState) pop() string { - if p.eof() { - return "" - } - - p.arg = p.args[0] - p.args = p.args[1:] - - return p.arg -} - -func (p *parseState) peek() string { - if p.eof() { - return "" - } - - return p.args[0] -} - -func (p *parseState) checkRequired() error { - required := p.lookup.required - - if len(required) == 0 { - return nil - } - - names := make([]string, 0, len(required)) - - for k := range required { - names = append(names, "`"+k.String()+"'") - } - - var msg string - - if len(names) == 1 { - msg = fmt.Sprintf("the required flag %s was not specified", names[0]) - } else { - msg = fmt.Sprintf("the required flags %s and %s were not specified", - strings.Join(names[:len(names)-1], ", "), names[len(names)-1]) - } - - p.err = newError(ErrRequired, msg) - return p.err -} - -func (p *parseState) estimateCommand() error { - commands := p.command.sortedCommands() - cmdnames := make([]string, len(commands)) - - for i, v := range commands { - cmdnames[i] = v.Name - } - - var msg string - - if len(p.retargs) != 0 { - c, l := closestChoice(p.retargs[0], cmdnames) - msg = fmt.Sprintf("Unknown command `%s'", p.retargs[0]) - - if float32(l)/float32(len(c)) < 0.5 { - msg = fmt.Sprintf("%s, did you mean `%s'?", msg, c) - } else if len(cmdnames) == 1 { - msg = fmt.Sprintf("%s. You should use the %s command", - msg, - cmdnames[0]) - } else { - msg = fmt.Sprintf("%s. Please specify one command of: %s or %s", - msg, - strings.Join(cmdnames[:len(cmdnames)-1], ", "), - cmdnames[len(cmdnames)-1]) - } - } else { - if len(cmdnames) == 1 { - msg = fmt.Sprintf("Please specify the %s command", cmdnames[0]) - } else { - msg = fmt.Sprintf("Please specify one command of: %s or %s", - strings.Join(cmdnames[:len(cmdnames)-1], ", "), - cmdnames[len(cmdnames)-1]) - } - } - - return newError(ErrRequired, msg) -} - -func (p *Parser) parseOption(s *parseState, name string, option *Option, canarg bool, argument *string) (retoption *Option, err error) { - if !option.canArgument() { - if argument != nil { - msg := fmt.Sprintf("bool flag `%s' cannot have an argument", option) - return option, newError(ErrNoArgumentForBool, msg) - } - - err = option.set(nil) - } else if argument != nil { - err = option.set(argument) - } else if canarg && !s.eof() { - arg := s.pop() - err = option.set(&arg) - } else if option.OptionalArgument { - option.clear() - - for _, v := range option.OptionalValue { - err = option.set(&v) - - if err != nil { - break - } - } - } else { - msg := fmt.Sprintf("expected argument for flag `%s'", option) - err = newError(ErrExpectedArgument, msg) - } - - if err != nil { - if _, ok := err.(*Error); !ok { - msg := fmt.Sprintf("invalid argument for flag `%s' (expected %s): %s", - option, - option.value.Type(), - err.Error()) - - err = newError(ErrMarshal, msg) - } - } - - return option, err -} - -func (p *Parser) parseLong(s *parseState, name string, argument *string) (option *Option, err error) { - if option := s.lookup.longNames[name]; option != nil { - // Only long options that are required can consume an argument - // from the argument list - canarg := !option.OptionalArgument - - return p.parseOption(s, name, option, canarg, argument) - } - - return nil, newError(ErrUnknownFlag, fmt.Sprintf("unknown flag `%s'", name)) -} - -func (p *Parser) splitShortConcatArg(s *parseState, optname string) (string, *string) { - c, n := utf8.DecodeRuneInString(optname) - - if n == len(optname) { - return optname, nil - } - - first := string(c) - - if option := s.lookup.shortNames[first]; option != nil && option.canArgument() { - arg := optname[n:] - return first, &arg - } - - return optname, nil -} - -func (p *Parser) parseShort(s *parseState, optname string, argument *string) (option *Option, err error) { - if argument == nil { - optname, argument = p.splitShortConcatArg(s, optname) - } - - for i, c := range optname { - shortname := string(c) - - if option = s.lookup.shortNames[shortname]; option != nil { - // Only the last short argument can consume an argument from - // the arguments list, and only if it's non optional - canarg := (i+utf8.RuneLen(c) == len(optname)) && !option.OptionalArgument - - if _, err := p.parseOption(s, shortname, option, canarg, argument); err != nil { - return option, err - } - } else { - return nil, newError(ErrUnknownFlag, fmt.Sprintf("unknown flag `%s'", shortname)) - } - - // Only the first option can have a concatted argument, so just - // clear argument here - argument = nil - } - - return option, nil -} - -func (p *Parser) parseNonOption(s *parseState) error { - if cmd := s.lookup.commands[s.arg]; cmd != nil { - if err := s.checkRequired(); err != nil { - return err - } - - s.command.Active = cmd - - s.command = cmd - s.lookup = cmd.makeLookup() - } else if (p.Options & PassAfterNonOption) != None { - // If PassAfterNonOption is set then all remaining arguments - // are considered positional - s.retargs = append(append(s.retargs, s.arg), s.args...) - s.args = []string{} - } else { - s.retargs = append(s.retargs, s.arg) - } - - return nil -} - -func (p *Parser) showBuiltinHelp() error { - var b bytes.Buffer - - p.WriteHelp(&b) - return newError(ErrHelp, b.String()) -} - -func (p *Parser) printError(err error) error { - if err != nil && (p.Options&PrintErrors) != None { - fmt.Fprintln(os.Stderr, err) - } - - return err -} diff --git a/github.com/jessevdk/go-flags/pointer_test.go b/github.com/jessevdk/go-flags/pointer_test.go deleted file mode 100644 index e17445f69..000000000 --- a/github.com/jessevdk/go-flags/pointer_test.go +++ /dev/null @@ -1,81 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestPointerBool(t *testing.T) { - var opts = struct { - Value *bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !*opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestPointerString(t *testing.T) { - var opts = struct { - Value *string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, *opts.Value, "value") -} - -func TestPointerSlice(t *testing.T) { - var opts = struct { - Value *[]string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value1", "-v", "value2") - - assertStringArray(t, ret, []string{}) - assertStringArray(t, *opts.Value, []string{"value1", "value2"}) -} - -func TestPointerMap(t *testing.T) { - var opts = struct { - Value *map[string]int `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "k1:2", "-v", "k2:-5") - - assertStringArray(t, ret, []string{}) - - if v, ok := (*opts.Value)["k1"]; !ok { - t.Errorf("Expected key \"k1\" to exist") - } else if v != 2 { - t.Errorf("Expected \"k1\" to be 2, but got %#v", v) - } - - if v, ok := (*opts.Value)["k2"]; !ok { - t.Errorf("Expected key \"k2\" to exist") - } else if v != -5 { - t.Errorf("Expected \"k2\" to be -5, but got %#v", v) - } -} - -type PointerGroup struct { - Value bool `short:"v"` -} - -func TestPointerGroup(t *testing.T) { - var opts = struct { - Group *PointerGroup `group:"Group Options"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !opts.Group.Value { - t.Errorf("Expected Group.Value to be true") - } -} diff --git a/github.com/jessevdk/go-flags/short_test.go b/github.com/jessevdk/go-flags/short_test.go deleted file mode 100644 index 20a7a38db..000000000 --- a/github.com/jessevdk/go-flags/short_test.go +++ /dev/null @@ -1,169 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestShort(t *testing.T) { - var opts = struct { - Value bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v") - - assertStringArray(t, ret, []string{}) - - if !opts.Value { - t.Errorf("Expected Value to be true") - } -} - -func TestShortTooLong(t *testing.T) { - var opts = struct { - Value bool `short:"vv"` - }{} - - assertParseFail(t, ErrShortNameTooLong, "short names can only be 1 character long, not `vv'", &opts) -} - -func TestShortRequired(t *testing.T) { - var opts = struct { - Value bool `short:"v" required:"true"` - }{} - - assertParseFail(t, ErrRequired, "the required flag `-v' was not specified", &opts) -} - -func TestShortMultiConcat(t *testing.T) { - var opts = struct { - V bool `short:"v"` - O bool `short:"o"` - F bool `short:"f"` - }{} - - ret := assertParseSuccess(t, &opts, "-vo", "-f") - - assertStringArray(t, ret, []string{}) - - if !opts.V { - t.Errorf("Expected V to be true") - } - - if !opts.O { - t.Errorf("Expected O to be true") - } - - if !opts.F { - t.Errorf("Expected F to be true") - } -} - -func TestShortMultiSlice(t *testing.T) { - var opts = struct { - Values []bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "-v") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.Values, []bool{true, true}) -} - -func TestShortMultiSliceConcat(t *testing.T) { - var opts = struct { - Values []bool `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vvv") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.Values, []bool{true, true, true}) -} - -func TestShortWithEqualArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v=value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortWithArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vvalue") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortArg(t *testing.T) { - var opts = struct { - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-v", "value") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "value") -} - -func TestShortMultiWithEqualArg(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - assertParseFail(t, ErrExpectedArgument, "expected argument for flag `-v'", &opts, "-ffv=value") -} - -func TestShortMultiArg(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-ffv", "value") - - assertStringArray(t, ret, []string{}) - assertBoolArray(t, opts.F, []bool{true, true}) - assertString(t, opts.Value, "value") -} - -func TestShortMultiArgConcatFail(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - assertParseFail(t, ErrExpectedArgument, "expected argument for flag `-v'", &opts, "-ffvvalue") -} - -func TestShortMultiArgConcat(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v"` - }{} - - ret := assertParseSuccess(t, &opts, "-vff") - - assertStringArray(t, ret, []string{}) - assertString(t, opts.Value, "ff") -} - -func TestShortOptional(t *testing.T) { - var opts = struct { - F []bool `short:"f"` - Value string `short:"v" optional:"yes" optional-value:"value"` - }{} - - ret := assertParseSuccess(t, &opts, "-fv", "f") - - assertStringArray(t, ret, []string{"f"}) - assertString(t, opts.Value, "value") -} diff --git a/github.com/jessevdk/go-flags/tag_test.go b/github.com/jessevdk/go-flags/tag_test.go deleted file mode 100644 index a549b4e5a..000000000 --- a/github.com/jessevdk/go-flags/tag_test.go +++ /dev/null @@ -1,39 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestTagMissingColon(t *testing.T) { - var opts = struct { - Value bool `short` - }{} - - assertParseFail(t, ErrTag, "expected `:' after key name, but got end of tag (in `short`)", &opts, "") -} - -func TestTagMissingValue(t *testing.T) { - var opts = struct { - Value bool `short:` - }{} - - assertParseFail(t, ErrTag, "expected `\"' to start tag value at end of tag (in `short:`)", &opts, "") -} - -func TestTagMissingQuote(t *testing.T) { - var opts = struct { - Value bool `short:"v` - }{} - - assertParseFail(t, ErrTag, "expected end of tag value `\"' at end of tag (in `short:\"v`)", &opts, "") -} - -func TestTagNewline(t *testing.T) { - var opts = struct { - Value bool `long:"verbose" description:"verbose -something"` - }{} - - assertParseFail(t, ErrTag, "unexpected newline in tag value `description' (in `long:\"verbose\" description:\"verbose\nsomething\"`)", &opts, "") -} - diff --git a/github.com/jessevdk/go-flags/termsize.go b/github.com/jessevdk/go-flags/termsize.go deleted file mode 100644 index 7583a3da6..000000000 --- a/github.com/jessevdk/go-flags/termsize.go +++ /dev/null @@ -1,5 +0,0 @@ -package flags - -func getTerminalColumns() int { - return 80 -} diff --git a/github.com/jessevdk/go-flags/unknown_test.go b/github.com/jessevdk/go-flags/unknown_test.go deleted file mode 100644 index 858be4588..000000000 --- a/github.com/jessevdk/go-flags/unknown_test.go +++ /dev/null @@ -1,66 +0,0 @@ -package flags - -import ( - "testing" -) - -func TestUnknownFlags(t *testing.T) { - var opts = struct { - Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` - }{} - - args := []string{ - "-f", - } - - p := NewParser(&opts, 0) - args, err := p.ParseArgs(args) - - if err == nil { - t.Fatal("Expected error for unknown argument") - } -} - -func TestIgnoreUnknownFlags(t *testing.T) { - var opts = struct { - Verbose []bool `short:"v" long:"verbose" description:"Verbose output"` - }{} - - args := []string{ - "hello", - "world", - "-v", - "--foo=bar", - "--verbose", - "-f", - } - - p := NewParser(&opts, IgnoreUnknown) - args, err := p.ParseArgs(args) - - if err != nil { - t.Fatal(err) - } - - exargs := []string{ - "hello", - "world", - "--foo=bar", - "-f", - } - - issame := (len(args) == len(exargs)) - - if issame { - for i := 0; i < len(args); i++ { - if args[i] != exargs[i] { - issame = false - break - } - } - } - - if !issame { - t.Fatalf("Expected %v but got %v", exargs, args) - } -}