1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
diff --git a/commands/commands.go b/commands/commands.go
index c2137a585200dacaef35ca7336077e373a156992..d76194af90df9603823a99734e2d69faa8e1b221 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"reflect"
- "sort"
"strings"
"unicode"
@@ -153,11 +152,6 @@
func GetTemplateCompletion(
cmd string,
) ([]string, string, bool) {
- args, err := splitCmd(cmd)
- if err != nil || len(args) == 0 {
- return nil, "", false
- }
-
countLeft := strings.Count(cmd, "{{")
if countLeft == 0 {
return nil, "", false
@@ -197,48 +191,16 @@ return nil, "", false
}
// GetCompletions returns the completion options and the command prefix
-func (cmds *Commands) GetCompletions(
- cmd string,
+func GetCompletions(
+ cmd Command, args *opt.Args,
) (options []string, prefix string) {
- log.Tracef("completing command: %s", cmd)
-
- // start completion
- args, err := splitCmd(cmd)
- if err != nil {
- return
- }
-
- // nothing entered, list all commands
- if len(args) == 0 {
- options = cmds.Names()
- sort.Strings(options)
- return
- }
-
- // complete command name
- spaceTerminated := cmd[len(cmd)-1] == ' '
- if len(args) == 1 && !spaceTerminated {
- for _, n := range cmds.Names() {
- options = append(options, n+" ")
- }
- options = CompletionFromList(options, args)
-
- return
- }
-
- // look for command in dictionary
- c, ok := cmds.dict()[args[0]]
- if !ok {
- return
- }
-
// complete options
var spec string
- if provider, ok := c.(OptionsProvider); ok {
+ if provider, ok := cmd.(OptionsProvider); ok {
spec = provider.Options()
}
- parser, err := newParser(cmd, spec, spaceTerminated)
+ parser, err := newParser(args.String(), spec, strings.HasSuffix(args.String(), " "))
if err != nil {
log.Debugf("completion parser failed: %v", err)
return
@@ -256,15 +218,15 @@ option += " "
}
options = append(options, option)
}
- prefix = cmd
+ prefix = args.String()
case OPTION_ARGUMENT:
- cmpl, ok := c.(OptionCompleter)
+ cmpl, ok := cmd.(OptionCompleter)
if !ok {
return
}
- stem := cmd
+ stem := args.String()
if parser.arg != "" {
- stem = strings.TrimSuffix(cmd, parser.arg)
+ stem = strings.TrimSuffix(stem, parser.arg)
}
pad := ""
if !strings.HasSuffix(stem, " ") {
@@ -277,14 +239,16 @@ options = append(options, pad+escape(option)+" ")
}
prefix = stem
case OPERAND:
- stem := strings.Join(args[:parser.optind], " ")
- for _, option := range c.Complete(args[1:]) {
+ clone := args.Clone()
+ clone.Cut(clone.Count() - parser.optind)
+ args.Shift(1)
+ for _, option := range cmd.Complete(args.Args()) {
if strings.Contains(option, " ") {
option = escape(option)
}
options = append(options, " "+option)
}
- prefix = stem
+ prefix = clone.String()
}
return
diff --git a/commands/prompt.go b/commands/prompt.go
index d42a659715e99ef1dcba4ba7f5a40cc369bf9874..dd259c303c2dc8a44297ff2f78f20f0c91a8723c 100644
--- a/commands/prompt.go
+++ b/commands/prompt.go
@@ -40,7 +40,7 @@ } else {
if hascommand {
return nil
}
- cs, _ = GlobalCommands.GetCompletions(args[1])
+ cs = GlobalCommands.Names()
}
if cs == nil {
return nil
diff --git a/main.go b/main.go
index 43e980e9455ba596589229adce38b9c312524f49..dc7d0267abfb4ae44c2bdc0424af78366b39d3b9 100644
--- a/main.go
+++ b/main.go
@@ -125,21 +125,38 @@ }
return err
}
-func getCompletions(cmd string) ([]string, string) {
- if options, prefix, ok := commands.GetTemplateCompletion(cmd); ok {
+func getCompletions(cmdline string) ([]string, string) {
+ cmdline = strings.TrimLeft(cmdline, ":")
+
+ // complete template terms
+ if options, prefix, ok := commands.GetTemplateCompletion(cmdline); ok {
+ sort.Strings(options)
return options, prefix
}
- var completions []string
- var prefix string
- for _, set := range getCommands(app.SelectedTabContent()) {
- options, s := set.GetCompletions(cmd)
- if s != "" {
- prefix = s
+
+ args := opt.LexArgs(cmdline)
+ cmds := getCommands(app.SelectedTabContent())
+
+ if args.Count() < 2 && args.TrailingSpace() == "" {
+ // complete command names
+ var completions []string
+ for _, set := range cmds {
+ for _, n := range set.Names() {
+ if strings.HasPrefix(n, cmdline) {
+ completions = append(completions, n)
+ }
+ }
}
- completions = append(completions, options...)
+ sort.Strings(completions)
+ return completions, ""
+ }
+
+ // complete command arguments
+ _, cmd := expandAbbreviations(args.Arg(0), cmds)
+ if cmd == nil {
+ return nil, cmdline
}
- sort.Strings(completions)
- return completions, prefix
+ return commands.GetCompletions(cmd, args)
}
// set at build time
|