diff options
author | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
---|---|---|
committer | Alex Pilon <apilon@hashicorp.com> | 2019-02-22 18:24:37 -0500 |
commit | 15c0b25d011f37e7c20aeca9eaf461f78285b8d9 (patch) | |
tree | 255c250a5c9d4801c74092d33b7337d8c14438ff /vendor/github.com/posener | |
parent | 07971ca38143c5faf951d152fba370ddcbe26ad5 (diff) | |
download | terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.gz terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.tar.zst terraform-provider-statuscake-15c0b25d011f37e7c20aeca9eaf461f78285b8d9.zip |
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
Updated via: go get github.com/hashicorp/terraform@sdk-v0.11-with-go-modules and go mod tidy
Diffstat (limited to 'vendor/github.com/posener')
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 | ||
2 | coverage.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 @@ | |||
1 | language: go | ||
2 | sudo: false | ||
3 | go: | ||
4 | - 1.9 | ||
5 | - 1.8 | ||
6 | |||
7 | before_install: | ||
8 | - go get -u -t ./... | ||
9 | - go get -u gopkg.in/alecthomas/gometalinter.v1 | ||
10 | - gometalinter.v1 --install | ||
11 | |||
12 | script: | ||
13 | - gometalinter.v1 --config metalinter.json ./... | ||
14 | - ./test.sh | ||
15 | |||
16 | after_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 @@ | |||
1 | The MIT License | ||
2 | |||
3 | Copyright (c) 2017 Eyal Posener | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in | ||
13 | all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
21 | THE 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 @@ | |||
1 | package complete | ||
2 | |||
3 | import ( | ||
4 | "os" | ||
5 | "path/filepath" | ||
6 | "strings" | ||
7 | "unicode" | ||
8 | ) | ||
9 | |||
10 | // Args describes command line arguments | ||
11 | type 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. | ||
31 | func (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 | |||
42 | func 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 | |||
60 | func 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 | |||
69 | func 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 | |||
77 | func (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 | |||
90 | func removeLast(a []string) []string { | ||
91 | if len(a) > 0 { | ||
92 | return a[:len(a)-1] | ||
93 | } | ||
94 | return a | ||
95 | } | ||
96 | |||
97 | func 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 | ||
2 | package cmd | ||
3 | |||
4 | import ( | ||
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 | ||
15 | type CLI struct { | ||
16 | Name string | ||
17 | InstallName string | ||
18 | UninstallName string | ||
19 | |||
20 | install bool | ||
21 | uninstall bool | ||
22 | yes bool | ||
23 | } | ||
24 | |||
25 | const ( | ||
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. | ||
33 | func (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 | ||
63 | func (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. | ||
85 | func (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 | ||
111 | func (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. | ||
119 | func (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 @@ | |||
1 | package install | ||
2 | |||
3 | import "fmt" | ||
4 | |||
5 | // (un)install in bash | ||
6 | // basically adds/remove from .bashrc: | ||
7 | // | ||
8 | // complete -C </path/to/completion/command> <command> | ||
9 | type bash struct { | ||
10 | rc string | ||
11 | } | ||
12 | |||
13 | func (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 | |||
21 | func (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 | |||
30 | func (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 @@ | |||
1 | package install | ||
2 | |||
3 | import ( | ||
4 | "errors" | ||
5 | "os" | ||
6 | "os/user" | ||
7 | "path/filepath" | ||
8 | |||
9 | "github.com/hashicorp/go-multierror" | ||
10 | ) | ||
11 | |||
12 | type 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 | ||
19 | func 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 | ||
41 | func 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 | |||
61 | func 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 | |||
74 | func getBinaryPath() (string, error) { | ||
75 | bin, err := os.Executable() | ||
76 | if err != nil { | ||
77 | return "", err | ||
78 | } | ||
79 | return filepath.Abs(bin) | ||
80 | } | ||
81 | |||
82 | func 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 @@ | |||
1 | package install | ||
2 | |||
3 | import ( | ||
4 | "bufio" | ||
5 | "fmt" | ||
6 | "io" | ||
7 | "io/ioutil" | ||
8 | "os" | ||
9 | ) | ||
10 | |||
11 | func 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 | |||
39 | func 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 | |||
49 | func 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 | |||
68 | func 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 | |||
105 | func 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 @@ | |||
1 | package install | ||
2 | |||
3 | import "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> | ||
10 | type zsh struct { | ||
11 | rc string | ||
12 | } | ||
13 | |||
14 | func (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 | |||
28 | func (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 | |||
37 | func (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 @@ | |||
1 | package 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. | ||
6 | type 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 | ||
26 | func (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 | ||
32 | type Commands map[string]Command | ||
33 | |||
34 | // Predict completion of sub command names names according to command line arguments | ||
35 | func (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. | ||
43 | type Flags map[string]Predictor | ||
44 | |||
45 | // Predict completion of flags names according to command line arguments | ||
46 | func (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. | ||
64 | func (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. | ||
6 | package complete | ||
7 | |||
8 | import ( | ||
9 | "flag" | ||
10 | "fmt" | ||
11 | "io" | ||
12 | "os" | ||
13 | |||
14 | "github.com/posener/complete/cmd" | ||
15 | "github.com/posener/complete/match" | ||
16 | ) | ||
17 | |||
18 | const ( | ||
19 | envComplete = "COMP_LINE" | ||
20 | envDebug = "COMP_DEBUG" | ||
21 | ) | ||
22 | |||
23 | // Complete structs define completion for a command with CLI options | ||
24 | type 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. | ||
35 | func 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. | ||
45 | func (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. | ||
57 | func (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 | |||
82 | func getLine() (string, bool) { | ||
83 | line := os.Getenv(envComplete) | ||
84 | if line == "" { | ||
85 | return "", false | ||
86 | } | ||
87 | return line, true | ||
88 | } | ||
89 | |||
90 | func (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 @@ | |||
1 | package complete | ||
2 | |||
3 | import ( | ||
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 | ||
15 | var Log = getLogger() | ||
16 | |||
17 | func 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 @@ | |||
1 | package match | ||
2 | |||
3 | import "strings" | ||
4 | |||
5 | // File returns true if prefix can match the file | ||
6 | func 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 @@ | |||
1 | package 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. | ||
6 | type 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 @@ | |||
1 | package match | ||
2 | |||
3 | import "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 | ||
7 | func 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 @@ | |||
1 | package complete | ||
2 | |||
3 | // Predictor implements a predict method, in which given | ||
4 | // command line arguments returns a list of options it predicts. | ||
5 | type 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 | ||
11 | func 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. | ||
26 | type PredictFunc func(Args) []string | ||
27 | |||
28 | // Predict invokes the predict function and implements the Predictor interface | ||
29 | func (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. | ||
37 | var PredictNothing Predictor | ||
38 | |||
39 | // PredictAnything expects something, but nothing particular, such as a number | ||
40 | // or arbitrary name. | ||
41 | var 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 @@ | |||
1 | package complete | ||
2 | |||
3 | import ( | ||
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. | ||
15 | func 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. | ||
23 | func PredictFiles(pattern string) Predictor { | ||
24 | return files(pattern, true) | ||
25 | } | ||
26 | |||
27 | func 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 | |||
51 | func 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 | ||
66 | func 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 | |||
81 | func 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 @@ | |||
1 | package complete | ||
2 | |||
3 | // PredictSet expects specific set of terms, given in the options argument. | ||
4 | func PredictSet(options ...string) Predictor { | ||
5 | return predictSet(options) | ||
6 | } | ||
7 | |||
8 | type predictSet []string | ||
9 | |||
10 | func (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 | |||
8 | A tool for bash writing bash completion in go. | ||
9 | |||
10 | Writing bash completion scripts is a hard work. This package provides an easy way | ||
11 | to create bash completion scripts for any command, and also an easy way to install/uninstall | ||
12 | the completion of the command. | ||
13 | |||
14 | ## go command bash completion | ||
15 | |||
16 | In [gocomplete](./gocomplete) there is an example for bash completion for the `go` command line. | ||
17 | |||
18 | This is an example that uses the `complete` package on the `go` command - the `complete` package | ||
19 | can also be used to implement any completions, see [Usage](#usage). | ||
20 | |||
21 | ### Install | ||
22 | |||
23 | 1. Type in your shell: | ||
24 | ``` | ||
25 | go get -u github.com/posener/complete/gocomplete | ||
26 | gocomplete -install | ||
27 | ``` | ||
28 | |||
29 | 2. Restart your shell | ||
30 | |||
31 | Uninstall 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 | |||
41 | Supported shells: | ||
42 | |||
43 | - [x] bash | ||
44 | - [x] zsh | ||
45 | |||
46 | ### Usage | ||
47 | |||
48 | Assuming you have program called `run` and you want to have bash completion | ||
49 | for it, meaning, if you type `run` then space, then press the `Tab` key, | ||
50 | the shell will suggest relevant complete options. | ||
51 | |||
52 | In that case, we will create a program called `runcomplete`, a go program, | ||
53 | with a `func main()` and so, that will make the completion of the `run` | ||
54 | program. 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 | ||
56 | options for `run`. | ||
57 | |||
58 | So here it is: | ||
59 | |||
60 | ```go | ||
61 | import "github.com/posener/complete" | ||
62 | |||
63 | func 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 | |||
113 | In case that the program that we want to complete is written in go we | ||
114 | can make it self completing. | ||
115 | |||
116 | Here 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 | |||
3 | set -e | ||
4 | echo "" > coverage.txt | ||
5 | |||
6 | for 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 | ||
12 | done \ 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 @@ | |||
1 | package complete | ||
2 | |||
3 | import ( | ||
4 | "os" | ||
5 | "path/filepath" | ||
6 | "strings" | ||
7 | ) | ||
8 | |||
9 | // fixPathForm changes a file name to a relative name | ||
10 | func 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 | |||
40 | func 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 | } | ||