aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/posener
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/posener')
-rw-r--r--vendor/github.com/posener/complete/.gitignore2
-rw-r--r--vendor/github.com/posener/complete/.travis.yml17
-rw-r--r--vendor/github.com/posener/complete/LICENSE.txt21
-rw-r--r--vendor/github.com/posener/complete/args.go102
-rw-r--r--vendor/github.com/posener/complete/cmd/cmd.go128
-rw-r--r--vendor/github.com/posener/complete/cmd/install/bash.go32
-rw-r--r--vendor/github.com/posener/complete/cmd/install/install.go92
-rw-r--r--vendor/github.com/posener/complete/cmd/install/utils.go118
-rw-r--r--vendor/github.com/posener/complete/cmd/install/zsh.go39
-rw-r--r--vendor/github.com/posener/complete/command.go111
-rw-r--r--vendor/github.com/posener/complete/complete.go95
-rw-r--r--vendor/github.com/posener/complete/log.go23
-rw-r--r--vendor/github.com/posener/complete/match/file.go19
-rw-r--r--vendor/github.com/posener/complete/match/match.go6
-rw-r--r--vendor/github.com/posener/complete/match/prefix.go9
-rw-r--r--vendor/github.com/posener/complete/metalinter.json21
-rw-r--r--vendor/github.com/posener/complete/predict.go41
-rw-r--r--vendor/github.com/posener/complete/predict_files.go108
-rw-r--r--vendor/github.com/posener/complete/predict_set.go12
-rw-r--r--vendor/github.com/posener/complete/readme.md116
-rw-r--r--vendor/github.com/posener/complete/test.sh12
-rw-r--r--vendor/github.com/posener/complete/utils.go46
22 files changed, 1170 insertions, 0 deletions
diff --git a/vendor/github.com/posener/complete/.gitignore b/vendor/github.com/posener/complete/.gitignore
new file mode 100644
index 0000000..1363720
--- /dev/null
+++ b/vendor/github.com/posener/complete/.gitignore
@@ -0,0 +1,2 @@
1.idea
2coverage.txt
diff --git a/vendor/github.com/posener/complete/.travis.yml b/vendor/github.com/posener/complete/.travis.yml
new file mode 100644
index 0000000..c2798f8
--- /dev/null
+++ b/vendor/github.com/posener/complete/.travis.yml
@@ -0,0 +1,17 @@
1language: go
2sudo: false
3go:
4 - 1.9
5 - 1.8
6
7before_install:
8 - go get -u -t ./...
9 - go get -u gopkg.in/alecthomas/gometalinter.v1
10 - gometalinter.v1 --install
11
12script:
13 - gometalinter.v1 --config metalinter.json ./...
14 - ./test.sh
15
16after_success:
17 - bash <(curl -s https://codecov.io/bash)
diff --git a/vendor/github.com/posener/complete/LICENSE.txt b/vendor/github.com/posener/complete/LICENSE.txt
new file mode 100644
index 0000000..16249b4
--- /dev/null
+++ b/vendor/github.com/posener/complete/LICENSE.txt
@@ -0,0 +1,21 @@
1The MIT License
2
3Copyright (c) 2017 Eyal Posener
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE. \ No newline at end of file
diff --git a/vendor/github.com/posener/complete/args.go b/vendor/github.com/posener/complete/args.go
new file mode 100644
index 0000000..1ba4d69
--- /dev/null
+++ b/vendor/github.com/posener/complete/args.go
@@ -0,0 +1,102 @@
1package complete
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7 "unicode"
8)
9
10// Args describes command line arguments
11type Args struct {
12 // All lists of all arguments in command line (not including the command itself)
13 All []string
14 // Completed lists of all completed arguments in command line,
15 // If the last one is still being typed - no space after it,
16 // it won't appear in this list of arguments.
17 Completed []string
18 // Last argument in command line, the one being typed, if the last
19 // character in the command line is a space, this argument will be empty,
20 // otherwise this would be the last word.
21 Last string
22 // LastCompleted is the last argument that was fully typed.
23 // If the last character in the command line is space, this would be the
24 // last word, otherwise, it would be the word before that.
25 LastCompleted string
26}
27
28// Directory gives the directory of the current written
29// last argument if it represents a file name being written.
30// in case that it is not, we fall back to the current directory.
31func (a Args) Directory() string {
32 if info, err := os.Stat(a.Last); err == nil && info.IsDir() {
33 return fixPathForm(a.Last, a.Last)
34 }
35 dir := filepath.Dir(a.Last)
36 if info, err := os.Stat(dir); err != nil || !info.IsDir() {
37 return "./"
38 }
39 return fixPathForm(a.Last, dir)
40}
41
42func newArgs(line string) Args {
43 var (
44 all []string
45 completed []string
46 )
47 parts := splitFields(line)
48 if len(parts) > 0 {
49 all = parts[1:]
50 completed = removeLast(parts[1:])
51 }
52 return Args{
53 All: all,
54 Completed: completed,
55 Last: last(parts),
56 LastCompleted: last(completed),
57 }
58}
59
60func splitFields(line string) []string {
61 parts := strings.Fields(line)
62 if len(line) > 0 && unicode.IsSpace(rune(line[len(line)-1])) {
63 parts = append(parts, "")
64 }
65 parts = splitLastEqual(parts)
66 return parts
67}
68
69func splitLastEqual(line []string) []string {
70 if len(line) == 0 {
71 return line
72 }
73 parts := strings.Split(line[len(line)-1], "=")
74 return append(line[:len(line)-1], parts...)
75}
76
77func (a Args) from(i int) Args {
78 if i > len(a.All) {
79 i = len(a.All)
80 }
81 a.All = a.All[i:]
82
83 if i > len(a.Completed) {
84 i = len(a.Completed)
85 }
86 a.Completed = a.Completed[i:]
87 return a
88}
89
90func removeLast(a []string) []string {
91 if len(a) > 0 {
92 return a[:len(a)-1]
93 }
94 return a
95}
96
97func last(args []string) string {
98 if len(args) == 0 {
99 return ""
100 }
101 return args[len(args)-1]
102}
diff --git a/vendor/github.com/posener/complete/cmd/cmd.go b/vendor/github.com/posener/complete/cmd/cmd.go
new file mode 100644
index 0000000..7137dee
--- /dev/null
+++ b/vendor/github.com/posener/complete/cmd/cmd.go
@@ -0,0 +1,128 @@
1// Package cmd used for command line options for the complete tool
2package cmd
3
4import (
5 "errors"
6 "flag"
7 "fmt"
8 "os"
9 "strings"
10
11 "github.com/posener/complete/cmd/install"
12)
13
14// CLI for command line
15type CLI struct {
16 Name string
17 InstallName string
18 UninstallName string
19
20 install bool
21 uninstall bool
22 yes bool
23}
24
25const (
26 defaultInstallName = "install"
27 defaultUninstallName = "uninstall"
28)
29
30// Run is used when running complete in command line mode.
31// this is used when the complete is not completing words, but to
32// install it or uninstall it.
33func (f *CLI) Run() bool {
34 err := f.validate()
35 if err != nil {
36 os.Stderr.WriteString(err.Error() + "\n")
37 os.Exit(1)
38 }
39
40 switch {
41 case f.install:
42 f.prompt()
43 err = install.Install(f.Name)
44 case f.uninstall:
45 f.prompt()
46 err = install.Uninstall(f.Name)
47 default:
48 // non of the action flags matched,
49 // returning false should make the real program execute
50 return false
51 }
52
53 if err != nil {
54 fmt.Printf("%s failed! %s\n", f.action(), err)
55 os.Exit(3)
56 }
57 fmt.Println("Done!")
58 return true
59}
60
61// prompt use for approval
62// exit if approval was not given
63func (f *CLI) prompt() {
64 defer fmt.Println(f.action() + "ing...")
65 if f.yes {
66 return
67 }
68 fmt.Printf("%s completion for %s? ", f.action(), f.Name)
69 var answer string
70 fmt.Scanln(&answer)
71
72 switch strings.ToLower(answer) {
73 case "y", "yes":
74 return
75 default:
76 fmt.Println("Cancelling...")
77 os.Exit(1)
78 }
79}
80
81// AddFlags adds the CLI flags to the flag set.
82// If flags is nil, the default command line flags will be taken.
83// Pass non-empty strings as installName and uninstallName to override the default
84// flag names.
85func (f *CLI) AddFlags(flags *flag.FlagSet) {
86 if flags == nil {
87 flags = flag.CommandLine
88 }
89
90 if f.InstallName == "" {
91 f.InstallName = defaultInstallName
92 }
93 if f.UninstallName == "" {
94 f.UninstallName = defaultUninstallName
95 }
96
97 if flags.Lookup(f.InstallName) == nil {
98 flags.BoolVar(&f.install, f.InstallName, false,
99 fmt.Sprintf("Install completion for %s command", f.Name))
100 }
101 if flags.Lookup(f.UninstallName) == nil {
102 flags.BoolVar(&f.uninstall, f.UninstallName, false,
103 fmt.Sprintf("Uninstall completion for %s command", f.Name))
104 }
105 if flags.Lookup("y") == nil {
106 flags.BoolVar(&f.yes, "y", false, "Don't prompt user for typing 'yes'")
107 }
108}
109
110// validate the CLI
111func (f *CLI) validate() error {
112 if f.install && f.uninstall {
113 return errors.New("Install and uninstall are mutually exclusive")
114 }
115 return nil
116}
117
118// action name according to the CLI values.
119func (f *CLI) action() string {
120 switch {
121 case f.install:
122 return "Install"
123 case f.uninstall:
124 return "Uninstall"
125 default:
126 return "unknown"
127 }
128}
diff --git a/vendor/github.com/posener/complete/cmd/install/bash.go b/vendor/github.com/posener/complete/cmd/install/bash.go
new file mode 100644
index 0000000..a287f99
--- /dev/null
+++ b/vendor/github.com/posener/complete/cmd/install/bash.go
@@ -0,0 +1,32 @@
1package install
2
3import "fmt"
4
5// (un)install in bash
6// basically adds/remove from .bashrc:
7//
8// complete -C </path/to/completion/command> <command>
9type bash struct {
10 rc string
11}
12
13func (b bash) Install(cmd, bin string) error {
14 completeCmd := b.cmd(cmd, bin)
15 if lineInFile(b.rc, completeCmd) {
16 return fmt.Errorf("already installed in %s", b.rc)
17 }
18 return appendToFile(b.rc, completeCmd)
19}
20
21func (b bash) Uninstall(cmd, bin string) error {
22 completeCmd := b.cmd(cmd, bin)
23 if !lineInFile(b.rc, completeCmd) {
24 return fmt.Errorf("does not installed in %s", b.rc)
25 }
26
27 return removeFromFile(b.rc, completeCmd)
28}
29
30func (bash) cmd(cmd, bin string) string {
31 return fmt.Sprintf("complete -C %s %s", bin, cmd)
32}
diff --git a/vendor/github.com/posener/complete/cmd/install/install.go b/vendor/github.com/posener/complete/cmd/install/install.go
new file mode 100644
index 0000000..082a226
--- /dev/null
+++ b/vendor/github.com/posener/complete/cmd/install/install.go
@@ -0,0 +1,92 @@
1package install
2
3import (
4 "errors"
5 "os"
6 "os/user"
7 "path/filepath"
8
9 "github.com/hashicorp/go-multierror"
10)
11
12type installer interface {
13 Install(cmd, bin string) error
14 Uninstall(cmd, bin string) error
15}
16
17// Install complete command given:
18// cmd: is the command name
19func Install(cmd string) error {
20 is := installers()
21 if len(is) == 0 {
22 return errors.New("Did not find any shells to install")
23 }
24 bin, err := getBinaryPath()
25 if err != nil {
26 return err
27 }
28
29 for _, i := range is {
30 errI := i.Install(cmd, bin)
31 if errI != nil {
32 err = multierror.Append(err, errI)
33 }
34 }
35
36 return err
37}
38
39// Uninstall complete command given:
40// cmd: is the command name
41func Uninstall(cmd string) error {
42 is := installers()
43 if len(is) == 0 {
44 return errors.New("Did not find any shells to uninstall")
45 }
46 bin, err := getBinaryPath()
47 if err != nil {
48 return err
49 }
50
51 for _, i := range is {
52 errI := i.Uninstall(cmd, bin)
53 if errI != nil {
54 multierror.Append(err, errI)
55 }
56 }
57
58 return err
59}
60
61func installers() (i []installer) {
62 for _, rc := range [...]string{".bashrc", ".bash_profile", ".bash_login", ".profile"} {
63 if f := rcFile(rc); f != "" {
64 i = append(i, bash{f})
65 break
66 }
67 }
68 if f := rcFile(".zshrc"); f != "" {
69 i = append(i, zsh{f})
70 }
71 return
72}
73
74func getBinaryPath() (string, error) {
75 bin, err := os.Executable()
76 if err != nil {
77 return "", err
78 }
79 return filepath.Abs(bin)
80}
81
82func rcFile(name string) string {
83 u, err := user.Current()
84 if err != nil {
85 return ""
86 }
87 path := filepath.Join(u.HomeDir, name)
88 if _, err := os.Stat(path); err != nil {
89 return ""
90 }
91 return path
92}
diff --git a/vendor/github.com/posener/complete/cmd/install/utils.go b/vendor/github.com/posener/complete/cmd/install/utils.go
new file mode 100644
index 0000000..2c8b44c
--- /dev/null
+++ b/vendor/github.com/posener/complete/cmd/install/utils.go
@@ -0,0 +1,118 @@
1package install
2
3import (
4 "bufio"
5 "fmt"
6 "io"
7 "io/ioutil"
8 "os"
9)
10
11func lineInFile(name string, lookFor string) bool {
12 f, err := os.Open(name)
13 if err != nil {
14 return false
15 }
16 defer f.Close()
17 r := bufio.NewReader(f)
18 prefix := []byte{}
19 for {
20 line, isPrefix, err := r.ReadLine()
21 if err == io.EOF {
22 return false
23 }
24 if err != nil {
25 return false
26 }
27 if isPrefix {
28 prefix = append(prefix, line...)
29 continue
30 }
31 line = append(prefix, line...)
32 if string(line) == lookFor {
33 return true
34 }
35 prefix = prefix[:0]
36 }
37}
38
39func appendToFile(name string, content string) error {
40 f, err := os.OpenFile(name, os.O_RDWR|os.O_APPEND, 0)
41 if err != nil {
42 return err
43 }
44 defer f.Close()
45 _, err = f.WriteString(fmt.Sprintf("\n%s\n", content))
46 return err
47}
48
49func removeFromFile(name string, content string) error {
50 backup := name + ".bck"
51 err := copyFile(name, backup)
52 if err != nil {
53 return err
54 }
55 temp, err := removeContentToTempFile(name, content)
56 if err != nil {
57 return err
58 }
59
60 err = copyFile(temp, name)
61 if err != nil {
62 return err
63 }
64
65 return os.Remove(backup)
66}
67
68func removeContentToTempFile(name, content string) (string, error) {
69 rf, err := os.Open(name)
70 if err != nil {
71 return "", err
72 }
73 defer rf.Close()
74 wf, err := ioutil.TempFile("/tmp", "complete-")
75 if err != nil {
76 return "", err
77 }
78 defer wf.Close()
79
80 r := bufio.NewReader(rf)
81 prefix := []byte{}
82 for {
83 line, isPrefix, err := r.ReadLine()
84 if err == io.EOF {
85 break
86 }
87 if err != nil {
88 return "", err
89 }
90 if isPrefix {
91 prefix = append(prefix, line...)
92 continue
93 }
94 line = append(prefix, line...)
95 str := string(line)
96 if str == content {
97 continue
98 }
99 wf.WriteString(str + "\n")
100 prefix = prefix[:0]
101 }
102 return wf.Name(), nil
103}
104
105func copyFile(src string, dst string) error {
106 in, err := os.Open(src)
107 if err != nil {
108 return err
109 }
110 defer in.Close()
111 out, err := os.Create(dst)
112 if err != nil {
113 return err
114 }
115 defer out.Close()
116 _, err = io.Copy(out, in)
117 return err
118}
diff --git a/vendor/github.com/posener/complete/cmd/install/zsh.go b/vendor/github.com/posener/complete/cmd/install/zsh.go
new file mode 100644
index 0000000..a625f53
--- /dev/null
+++ b/vendor/github.com/posener/complete/cmd/install/zsh.go
@@ -0,0 +1,39 @@
1package install
2
3import "fmt"
4
5// (un)install in zsh
6// basically adds/remove from .zshrc:
7//
8// autoload -U +X bashcompinit && bashcompinit"
9// complete -C </path/to/completion/command> <command>
10type zsh struct {
11 rc string
12}
13
14func (z zsh) Install(cmd, bin string) error {
15 completeCmd := z.cmd(cmd, bin)
16 if lineInFile(z.rc, completeCmd) {
17 return fmt.Errorf("already installed in %s", z.rc)
18 }
19
20 bashCompInit := "autoload -U +X bashcompinit && bashcompinit"
21 if !lineInFile(z.rc, bashCompInit) {
22 completeCmd = bashCompInit + "\n" + completeCmd
23 }
24
25 return appendToFile(z.rc, completeCmd)
26}
27
28func (z zsh) Uninstall(cmd, bin string) error {
29 completeCmd := z.cmd(cmd, bin)
30 if !lineInFile(z.rc, completeCmd) {
31 return fmt.Errorf("does not installed in %s", z.rc)
32 }
33
34 return removeFromFile(z.rc, completeCmd)
35}
36
37func (zsh) cmd(cmd, bin string) string {
38 return fmt.Sprintf("complete -o nospace -C %s %s", bin, cmd)
39}
diff --git a/vendor/github.com/posener/complete/command.go b/vendor/github.com/posener/complete/command.go
new file mode 100644
index 0000000..82d37d5
--- /dev/null
+++ b/vendor/github.com/posener/complete/command.go
@@ -0,0 +1,111 @@
1package complete
2
3// Command represents a command line
4// It holds the data that enables auto completion of command line
5// Command can also be a sub command.
6type Command struct {
7 // Sub is map of sub commands of the current command
8 // The key refer to the sub command name, and the value is it's
9 // Command descriptive struct.
10 Sub Commands
11
12 // Flags is a map of flags that the command accepts.
13 // The key is the flag name, and the value is it's predictions.
14 Flags Flags
15
16 // GlobalFlags is a map of flags that the command accepts.
17 // Global flags that can appear also after a sub command.
18 GlobalFlags Flags
19
20 // Args are extra arguments that the command accepts, those who are
21 // given without any flag before.
22 Args Predictor
23}
24
25// Predict returns all possible predictions for args according to the command struct
26func (c *Command) Predict(a Args) []string {
27 options, _ := c.predict(a)
28 return options
29}
30
31// Commands is the type of Sub member, it maps a command name to a command struct
32type Commands map[string]Command
33
34// Predict completion of sub command names names according to command line arguments
35func (c Commands) Predict(a Args) (prediction []string) {
36 for sub := range c {
37 prediction = append(prediction, sub)
38 }
39 return
40}
41
42// Flags is the type Flags of the Flags member, it maps a flag name to the flag predictions.
43type Flags map[string]Predictor
44
45// Predict completion of flags names according to command line arguments
46func (f Flags) Predict(a Args) (prediction []string) {
47 for flag := range f {
48 // If the flag starts with a hyphen, we avoid emitting the prediction
49 // unless the last typed arg contains a hyphen as well.
50 flagHyphenStart := len(flag) != 0 && flag[0] == '-'
51 lastHyphenStart := len(a.Last) != 0 && a.Last[0] == '-'
52 if flagHyphenStart && !lastHyphenStart {
53 continue
54 }
55 prediction = append(prediction, flag)
56 }
57 return
58}
59
60// predict options
61// only is set to true if no more options are allowed to be returned
62// those are in cases of special flag that has specific completion arguments,
63// and other flags or sub commands can't come after it.
64func (c *Command) predict(a Args) (options []string, only bool) {
65
66 // search sub commands for predictions first
67 subCommandFound := false
68 for i, arg := range a.Completed {
69 if cmd, ok := c.Sub[arg]; ok {
70 subCommandFound = true
71
72 // recursive call for sub command
73 options, only = cmd.predict(a.from(i))
74 if only {
75 return
76 }
77
78 // We matched so stop searching. Continuing to search can accidentally
79 // match a subcommand with current set of commands, see issue #46.
80 break
81 }
82 }
83
84 // if last completed word is a global flag that we need to complete
85 if predictor, ok := c.GlobalFlags[a.LastCompleted]; ok && predictor != nil {
86 Log("Predicting according to global flag %s", a.LastCompleted)
87 return predictor.Predict(a), true
88 }
89
90 options = append(options, c.GlobalFlags.Predict(a)...)
91
92 // if a sub command was entered, we won't add the parent command
93 // completions and we return here.
94 if subCommandFound {
95 return
96 }
97
98 // if last completed word is a command flag that we need to complete
99 if predictor, ok := c.Flags[a.LastCompleted]; ok && predictor != nil {
100 Log("Predicting according to flag %s", a.LastCompleted)
101 return predictor.Predict(a), true
102 }
103
104 options = append(options, c.Sub.Predict(a)...)
105 options = append(options, c.Flags.Predict(a)...)
106 if c.Args != nil {
107 options = append(options, c.Args.Predict(a)...)
108 }
109
110 return
111}
diff --git a/vendor/github.com/posener/complete/complete.go b/vendor/github.com/posener/complete/complete.go
new file mode 100644
index 0000000..185d1e8
--- /dev/null
+++ b/vendor/github.com/posener/complete/complete.go
@@ -0,0 +1,95 @@
1// Package complete provides a tool for bash writing bash completion in go.
2//
3// Writing bash completion scripts is a hard work. This package provides an easy way
4// to create bash completion scripts for any command, and also an easy way to install/uninstall
5// the completion of the command.
6package complete
7
8import (
9 "flag"
10 "fmt"
11 "io"
12 "os"
13
14 "github.com/posener/complete/cmd"
15 "github.com/posener/complete/match"
16)
17
18const (
19 envComplete = "COMP_LINE"
20 envDebug = "COMP_DEBUG"
21)
22
23// Complete structs define completion for a command with CLI options
24type Complete struct {
25 Command Command
26 cmd.CLI
27 Out io.Writer
28}
29
30// New creates a new complete command.
31// name is the name of command we want to auto complete.
32// IMPORTANT: it must be the same name - if the auto complete
33// completes the 'go' command, name must be equal to "go".
34// command is the struct of the command completion.
35func New(name string, command Command) *Complete {
36 return &Complete{
37 Command: command,
38 CLI: cmd.CLI{Name: name},
39 Out: os.Stdout,
40 }
41}
42
43// Run runs the completion and add installation flags beforehand.
44// The flags are added to the main flag CommandLine variable.
45func (c *Complete) Run() bool {
46 c.AddFlags(nil)
47 flag.Parse()
48 return c.Complete()
49}
50
51// Complete a command from completion line in environment variable,
52// and print out the complete options.
53// returns success if the completion ran or if the cli matched
54// any of the given flags, false otherwise
55// For installation: it assumes that flags were added and parsed before
56// it was called.
57func (c *Complete) Complete() bool {
58 line, ok := getLine()
59 if !ok {
60 // make sure flags parsed,
61 // in case they were not added in the main program
62 return c.CLI.Run()
63 }
64 Log("Completing line: %s", line)
65 a := newArgs(line)
66 Log("Completing last field: %s", a.Last)
67 options := c.Command.Predict(a)
68 Log("Options: %s", options)
69
70 // filter only options that match the last argument
71 matches := []string{}
72 for _, option := range options {
73 if match.Prefix(option, a.Last) {
74 matches = append(matches, option)
75 }
76 }
77 Log("Matches: %s", matches)
78 c.output(matches)
79 return true
80}
81
82func getLine() (string, bool) {
83 line := os.Getenv(envComplete)
84 if line == "" {
85 return "", false
86 }
87 return line, true
88}
89
90func (c *Complete) output(options []string) {
91 // stdout of program defines the complete options
92 for _, option := range options {
93 fmt.Fprintln(c.Out, option)
94 }
95}
diff --git a/vendor/github.com/posener/complete/log.go b/vendor/github.com/posener/complete/log.go
new file mode 100644
index 0000000..797a80c
--- /dev/null
+++ b/vendor/github.com/posener/complete/log.go
@@ -0,0 +1,23 @@
1package complete
2
3import (
4 "io"
5 "io/ioutil"
6 "log"
7 "os"
8)
9
10// Log is used for debugging purposes
11// since complete is running on tab completion, it is nice to
12// have logs to the stderr (when writing your own completer)
13// to write logs, set the COMP_DEBUG environment variable and
14// use complete.Log in the complete program
15var Log = getLogger()
16
17func getLogger() func(format string, args ...interface{}) {
18 var logfile io.Writer = ioutil.Discard
19 if os.Getenv(envDebug) != "" {
20 logfile = os.Stderr
21 }
22 return log.New(logfile, "complete ", log.Flags()).Printf
23}
diff --git a/vendor/github.com/posener/complete/match/file.go b/vendor/github.com/posener/complete/match/file.go
new file mode 100644
index 0000000..051171e
--- /dev/null
+++ b/vendor/github.com/posener/complete/match/file.go
@@ -0,0 +1,19 @@
1package match
2
3import "strings"
4
5// File returns true if prefix can match the file
6func File(file, prefix string) bool {
7 // special case for current directory completion
8 if file == "./" && (prefix == "." || prefix == "") {
9 return true
10 }
11 if prefix == "." && strings.HasPrefix(file, ".") {
12 return true
13 }
14
15 file = strings.TrimPrefix(file, "./")
16 prefix = strings.TrimPrefix(prefix, "./")
17
18 return strings.HasPrefix(file, prefix)
19}
diff --git a/vendor/github.com/posener/complete/match/match.go b/vendor/github.com/posener/complete/match/match.go
new file mode 100644
index 0000000..812fcac
--- /dev/null
+++ b/vendor/github.com/posener/complete/match/match.go
@@ -0,0 +1,6 @@
1package match
2
3// Match matches two strings
4// it is used for comparing a term to the last typed
5// word, the prefix, and see if it is a possible auto complete option.
6type Match func(term, prefix string) bool
diff --git a/vendor/github.com/posener/complete/match/prefix.go b/vendor/github.com/posener/complete/match/prefix.go
new file mode 100644
index 0000000..9a01ba6
--- /dev/null
+++ b/vendor/github.com/posener/complete/match/prefix.go
@@ -0,0 +1,9 @@
1package match
2
3import "strings"
4
5// Prefix is a simple Matcher, if the word is it's prefix, there is a match
6// Match returns true if a has the prefix as prefix
7func Prefix(long, prefix string) bool {
8 return strings.HasPrefix(long, prefix)
9}
diff --git a/vendor/github.com/posener/complete/metalinter.json b/vendor/github.com/posener/complete/metalinter.json
new file mode 100644
index 0000000..799c1d0
--- /dev/null
+++ b/vendor/github.com/posener/complete/metalinter.json
@@ -0,0 +1,21 @@
1{
2 "Vendor": true,
3 "DisableAll": true,
4 "Enable": [
5 "gofmt",
6 "goimports",
7 "interfacer",
8 "goconst",
9 "misspell",
10 "unconvert",
11 "gosimple",
12 "golint",
13 "structcheck",
14 "deadcode",
15 "vet"
16 ],
17 "Exclude": [
18 "initTests is unused"
19 ],
20 "Deadline": "2m"
21}
diff --git a/vendor/github.com/posener/complete/predict.go b/vendor/github.com/posener/complete/predict.go
new file mode 100644
index 0000000..8207063
--- /dev/null
+++ b/vendor/github.com/posener/complete/predict.go
@@ -0,0 +1,41 @@
1package complete
2
3// Predictor implements a predict method, in which given
4// command line arguments returns a list of options it predicts.
5type Predictor interface {
6 Predict(Args) []string
7}
8
9// PredictOr unions two predicate functions, so that the result predicate
10// returns the union of their predication
11func PredictOr(predictors ...Predictor) Predictor {
12 return PredictFunc(func(a Args) (prediction []string) {
13 for _, p := range predictors {
14 if p == nil {
15 continue
16 }
17 prediction = append(prediction, p.Predict(a)...)
18 }
19 return
20 })
21}
22
23// PredictFunc determines what terms can follow a command or a flag
24// It is used for auto completion, given last - the last word in the already
25// in the command line, what words can complete it.
26type PredictFunc func(Args) []string
27
28// Predict invokes the predict function and implements the Predictor interface
29func (p PredictFunc) Predict(a Args) []string {
30 if p == nil {
31 return nil
32 }
33 return p(a)
34}
35
36// PredictNothing does not expect anything after.
37var PredictNothing Predictor
38
39// PredictAnything expects something, but nothing particular, such as a number
40// or arbitrary name.
41var PredictAnything = PredictFunc(func(Args) []string { return nil })
diff --git a/vendor/github.com/posener/complete/predict_files.go b/vendor/github.com/posener/complete/predict_files.go
new file mode 100644
index 0000000..c8adf7e
--- /dev/null
+++ b/vendor/github.com/posener/complete/predict_files.go
@@ -0,0 +1,108 @@
1package complete
2
3import (
4 "io/ioutil"
5 "os"
6 "path/filepath"
7 "strings"
8
9 "github.com/posener/complete/match"
10)
11
12// PredictDirs will search for directories in the given started to be typed
13// path, if no path was started to be typed, it will complete to directories
14// in the current working directory.
15func PredictDirs(pattern string) Predictor {
16 return files(pattern, false)
17}
18
19// PredictFiles will search for files matching the given pattern in the started to
20// be typed path, if no path was started to be typed, it will complete to files that
21// match the pattern in the current working directory.
22// To match any file, use "*" as pattern. To match go files use "*.go", and so on.
23func PredictFiles(pattern string) Predictor {
24 return files(pattern, true)
25}
26
27func files(pattern string, allowFiles bool) PredictFunc {
28
29 // search for files according to arguments,
30 // if only one directory has matched the result, search recursively into
31 // this directory to give more results.
32 return func(a Args) (prediction []string) {
33 prediction = predictFiles(a, pattern, allowFiles)
34
35 // if the number of prediction is not 1, we either have many results or
36 // have no results, so we return it.
37 if len(prediction) != 1 {
38 return
39 }
40
41 // only try deeper, if the one item is a directory
42 if stat, err := os.Stat(prediction[0]); err != nil || !stat.IsDir() {
43 return
44 }
45
46 a.Last = prediction[0]
47 return predictFiles(a, pattern, allowFiles)
48 }
49}
50
51func predictFiles(a Args, pattern string, allowFiles bool) []string {
52 if strings.HasSuffix(a.Last, "/..") {
53 return nil
54 }
55
56 dir := a.Directory()
57 files := listFiles(dir, pattern, allowFiles)
58
59 // add dir if match
60 files = append(files, dir)
61
62 return PredictFilesSet(files).Predict(a)
63}
64
65// PredictFilesSet predict according to file rules to a given set of file names
66func PredictFilesSet(files []string) PredictFunc {
67 return func(a Args) (prediction []string) {
68 // add all matching files to prediction
69 for _, f := range files {
70 f = fixPathForm(a.Last, f)
71
72 // test matching of file to the argument
73 if match.File(f, a.Last) {
74 prediction = append(prediction, f)
75 }
76 }
77 return
78 }
79}
80
81func listFiles(dir, pattern string, allowFiles bool) []string {
82 // set of all file names
83 m := map[string]bool{}
84
85 // list files
86 if files, err := filepath.Glob(filepath.Join(dir, pattern)); err == nil {
87 for _, f := range files {
88 if stat, err := os.Stat(f); err != nil || stat.IsDir() || allowFiles {
89 m[f] = true
90 }
91 }
92 }
93
94 // list directories
95 if dirs, err := ioutil.ReadDir(dir); err == nil {
96 for _, d := range dirs {
97 if d.IsDir() {
98 m[filepath.Join(dir, d.Name())] = true
99 }
100 }
101 }
102
103 list := make([]string, 0, len(m))
104 for k := range m {
105 list = append(list, k)
106 }
107 return list
108}
diff --git a/vendor/github.com/posener/complete/predict_set.go b/vendor/github.com/posener/complete/predict_set.go
new file mode 100644
index 0000000..fa4a34a
--- /dev/null
+++ b/vendor/github.com/posener/complete/predict_set.go
@@ -0,0 +1,12 @@
1package complete
2
3// PredictSet expects specific set of terms, given in the options argument.
4func PredictSet(options ...string) Predictor {
5 return predictSet(options)
6}
7
8type predictSet []string
9
10func (p predictSet) Predict(a Args) []string {
11 return p
12}
diff --git a/vendor/github.com/posener/complete/readme.md b/vendor/github.com/posener/complete/readme.md
new file mode 100644
index 0000000..74077e3
--- /dev/null
+++ b/vendor/github.com/posener/complete/readme.md
@@ -0,0 +1,116 @@
1# complete
2
3[![Build Status](https://travis-ci.org/posener/complete.svg?branch=master)](https://travis-ci.org/posener/complete)
4[![codecov](https://codecov.io/gh/posener/complete/branch/master/graph/badge.svg)](https://codecov.io/gh/posener/complete)
5[![GoDoc](https://godoc.org/github.com/posener/complete?status.svg)](http://godoc.org/github.com/posener/complete)
6[![Go Report Card](https://goreportcard.com/badge/github.com/posener/complete)](https://goreportcard.com/report/github.com/posener/complete)
7
8A tool for bash writing bash completion in go.
9
10Writing bash completion scripts is a hard work. This package provides an easy way
11to create bash completion scripts for any command, and also an easy way to install/uninstall
12the completion of the command.
13
14## go command bash completion
15
16In [gocomplete](./gocomplete) there is an example for bash completion for the `go` command line.
17
18This is an example that uses the `complete` package on the `go` command - the `complete` package
19can also be used to implement any completions, see [Usage](#usage).
20
21### Install
22
231. Type in your shell:
24```
25go get -u github.com/posener/complete/gocomplete
26gocomplete -install
27```
28
292. Restart your shell
30
31Uninstall by `gocomplete -uninstall`
32
33### Features
34
35- Complete `go` command, including sub commands and all flags.
36- Complete packages names or `.go` files when necessary.
37- Complete test names after `-run` flag.
38
39## complete package
40
41Supported shells:
42
43- [x] bash
44- [x] zsh
45
46### Usage
47
48Assuming you have program called `run` and you want to have bash completion
49for it, meaning, if you type `run` then space, then press the `Tab` key,
50the shell will suggest relevant complete options.
51
52In that case, we will create a program called `runcomplete`, a go program,
53with a `func main()` and so, that will make the completion of the `run`
54program. Once the `runcomplete` will be in a binary form, we could
55`runcomplete -install` and that will add to our shell all the bash completion
56options for `run`.
57
58So here it is:
59
60```go
61import "github.com/posener/complete"
62
63func main() {
64
65 // create a Command object, that represents the command we want
66 // to complete.
67 run := complete.Command{
68
69 // Sub defines a list of sub commands of the program,
70 // this is recursive, since every command is of type command also.
71 Sub: complete.Commands{
72
73 // add a build sub command
74 "build": complete.Command {
75
76 // define flags of the build sub command
77 Flags: complete.Flags{
78 // build sub command has a flag '-cpus', which
79 // expects number of cpus after it. in that case
80 // anything could complete this flag.
81 "-cpus": complete.PredictAnything,
82 },
83 },
84 },
85
86 // define flags of the 'run' main command
87 Flags: complete.Flags{
88 // a flag -o, which expects a file ending with .out after
89 // it, the tab completion will auto complete for files matching
90 // the given pattern.
91 "-o": complete.PredictFiles("*.out"),
92 },
93
94 // define global flags of the 'run' main command
95 // those will show up also when a sub command was entered in the
96 // command line
97 GlobalFlags: complete.Flags{
98
99 // a flag '-h' which does not expects anything after it
100 "-h": complete.PredictNothing,
101 },
102 }
103
104 // run the command completion, as part of the main() function.
105 // this triggers the autocompletion when needed.
106 // name must be exactly as the binary that we want to complete.
107 complete.New("run", run).Run()
108}
109```
110
111### Self completing program
112
113In case that the program that we want to complete is written in go we
114can make it self completing.
115
116Here is an [example](./example/self/main.go)
diff --git a/vendor/github.com/posener/complete/test.sh b/vendor/github.com/posener/complete/test.sh
new file mode 100644
index 0000000..56bfcf1
--- /dev/null
+++ b/vendor/github.com/posener/complete/test.sh
@@ -0,0 +1,12 @@
1#!/usr/bin/env bash
2
3set -e
4echo "" > coverage.txt
5
6for d in $(go list ./... | grep -v vendor); do
7 go test -v -race -coverprofile=profile.out -covermode=atomic $d
8 if [ -f profile.out ]; then
9 cat profile.out >> coverage.txt
10 rm profile.out
11 fi
12done \ No newline at end of file
diff --git a/vendor/github.com/posener/complete/utils.go b/vendor/github.com/posener/complete/utils.go
new file mode 100644
index 0000000..58b8b79
--- /dev/null
+++ b/vendor/github.com/posener/complete/utils.go
@@ -0,0 +1,46 @@
1package complete
2
3import (
4 "os"
5 "path/filepath"
6 "strings"
7)
8
9// fixPathForm changes a file name to a relative name
10func fixPathForm(last string, file string) string {
11 // get wording directory for relative name
12 workDir, err := os.Getwd()
13 if err != nil {
14 return file
15 }
16
17 abs, err := filepath.Abs(file)
18 if err != nil {
19 return file
20 }
21
22 // if last is absolute, return path as absolute
23 if filepath.IsAbs(last) {
24 return fixDirPath(abs)
25 }
26
27 rel, err := filepath.Rel(workDir, abs)
28 if err != nil {
29 return file
30 }
31
32 // fix ./ prefix of path
33 if rel != "." && strings.HasPrefix(last, ".") {
34 rel = "./" + rel
35 }
36
37 return fixDirPath(rel)
38}
39
40func fixDirPath(path string) string {
41 info, err := os.Stat(path)
42 if err == nil && info.IsDir() && !strings.HasSuffix(path, "/") {
43 path += "/"
44 }
45 return path
46}