Skip to content

Commit 9099ff3

Browse files
committed
Better autocomplete for zsh
1 parent f399c12 commit 9099ff3

File tree

4 files changed

+74
-44
lines changed

4 files changed

+74
-44
lines changed

internal/complete/complete.go

Lines changed: 28 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,13 @@ import (
1616
"github.com/antonmedv/fx/internal/shlex"
1717
)
1818

19-
type pair struct {
20-
display string
21-
value string
19+
type Reply struct {
20+
Display string
21+
Value string
22+
Type string // "file" for files, others optional
2223
}
2324

24-
var flags = []pair{
25-
{"--help", "--help"},
26-
{"--raw", "--raw"},
27-
{"--slurp", "--slurp"},
28-
{"--themes", "--themes"},
29-
{"--version", "--version"},
30-
{"--yaml", "--yaml"},
31-
{"--strict", "--strict"},
32-
{"--no-inline", "--no-inline"},
33-
}
25+
var Flags []Reply
3426

3527
//go:embed complete.bash
3628
var Bash string
@@ -68,7 +60,7 @@ func Complete() bool {
6860

6961
func doComplete(compLine string, compWord string, withDisplay bool) {
7062
if strings.HasPrefix(compWord, "-") {
71-
compReply(filterReply(flags, compWord), withDisplay)
63+
compReply(filterReply(Flags, compWord), withDisplay)
7264
return
7365
}
7466

@@ -87,7 +79,7 @@ func doComplete(compLine string, compWord string, withDisplay bool) {
8779
}
8880
}
8981

90-
// Remove flags from args.
82+
// Remove Flags from args.
9183
args = filterArgs(args)
9284

9385
isSecondArgIsFile := false
@@ -108,7 +100,7 @@ func doComplete(compLine string, compWord string, withDisplay bool) {
108100
isSecondArgIsFile = isFile(args[1])
109101
}
110102

111-
var reply []pair
103+
var reply []Reply
112104

113105
if isSecondArgIsFile {
114106
file := args[1]
@@ -165,7 +157,7 @@ func doComplete(compLine string, compWord string, withDisplay bool) {
165157
}
166158
}
167159

168-
func globalsComplete() []pair {
160+
func globalsComplete() []Reply {
169161
var code strings.Builder
170162
code.WriteString(prelude)
171163
code.WriteString(engine.Stdlib)
@@ -178,19 +170,20 @@ func globalsComplete() []pair {
178170
}
179171

180172
if array, ok := value.Export().([]any); ok {
181-
var reply []pair
173+
var reply []Reply
182174
for _, key := range array {
183-
reply = append(reply, pair{
184-
display: key.(string),
185-
value: key.(string),
175+
reply = append(reply, Reply{
176+
Display: key.(string),
177+
Value: key.(string),
178+
Type: "global",
186179
})
187180
}
188181
return reply
189182
}
190183
return nil
191184
}
192185

193-
func keysComplete(input *jsonx.Node, args []string, compWord string) []pair {
186+
func keysComplete(input *jsonx.Node, args []string, compWord string) []Reply {
194187
args = args[2:] // Drop binary & file from the args.
195188

196189
if compWord == "" {
@@ -227,11 +220,12 @@ func keysComplete(input *jsonx.Node, args []string, compWord string) []pair {
227220

228221
if array, ok := value.Export().([]interface{}); ok {
229222
prefix := dropTail(compWord)
230-
var reply []pair
223+
var reply []Reply
231224
for _, key := range array {
232-
reply = append(reply, pair{
233-
display: "." + key.(string),
234-
value: join(prefix, key.(string)),
225+
reply = append(reply, Reply{
226+
Display: "." + key.(string),
227+
Value: join(prefix, key.(string)),
228+
Type: "key",
235229
})
236230
}
237231
return reply
@@ -256,8 +250,8 @@ func filterArgs(args []string) []string {
256250
filtered := make([]string, 0, len(args))
257251
for _, arg := range args {
258252
found := false
259-
for _, flag := range flags {
260-
if arg == flag.value {
253+
for _, flag := range Flags {
254+
if arg == flag.Value {
261255
found = true
262256
break
263257
}
@@ -269,7 +263,7 @@ func filterArgs(args []string) []string {
269263
return filtered
270264
}
271265

272-
func fileComplete(compWord string) []pair {
266+
func fileComplete(compWord string) []Reply {
273267
original := compWord
274268

275269
// Step 1: Expand ~ to home directory
@@ -301,7 +295,7 @@ func fileComplete(compWord string) []pair {
301295
}
302296

303297
// Step 4: Format matches
304-
var matches []pair
298+
var matches []Reply
305299
for _, match := range files {
306300
if match == "." || match == ".." {
307301
continue
@@ -333,9 +327,10 @@ func fileComplete(compWord string) []pair {
333327
}
334328
}
335329

336-
matches = append(matches, pair{
337-
display: filepath.Base(suggestion) + dirSuffix,
338-
value: suggestion,
330+
matches = append(matches, Reply{
331+
Display: filepath.Base(suggestion) + dirSuffix,
332+
Value: suggestion,
333+
Type: "file",
339334
})
340335
}
341336

internal/complete/complete.zsh

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,33 @@
11
#compdef fx
22

33
_fx() {
4-
local reply
4+
local -a reply
55
reply=("${(@f)$(COMP_ZSH="${LBUFFER}" fx)}")
66
if (( ${#reply} )); then
7-
local -a insert display
7+
local -a insert_files display_files insert_other display_other
8+
local line display rest value typ
9+
810
for line in "${reply[@]}"; do
9-
display+=("${line%%$'\t'*}")
10-
insert+=("${line#*$'\t'}")
11+
display="${line%%$'\t'*}"
12+
rest="${line#*$'\t'}"
13+
value="${rest%%$'\t'*}"
14+
typ="${rest#*$'\t'}"
15+
16+
if [[ "$typ" == "file" ]]; then
17+
display_files+=("$display")
18+
insert_files+=("$value")
19+
else
20+
display_other+=("$display")
21+
insert_other+=("$value")
22+
fi
1123
done
12-
compadd -f -S '' -d display -a insert
24+
25+
if (( ${#insert_files} )); then
26+
compadd -f -d display_files -a insert_files
27+
fi
28+
if (( ${#insert_other} )); then
29+
compadd -S '' -d display_other -a insert_other
30+
fi
1331
fi
1432
}
1533

internal/complete/utils.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ import (
77
"strings"
88
)
99

10-
func compReply(reply []pair, withDisplay bool) {
10+
func compReply(reply []Reply, withDisplay bool) {
1111
var lines []string
1212
for _, line := range reply {
1313
if withDisplay {
14-
lines = append(lines, fmt.Sprintf("%s\t%s", line.display, line.value))
14+
lines = append(lines, fmt.Sprintf("%s\t%s\t%s", line.Display, line.Value, line.Type))
1515
} else {
16-
lines = append(lines, line.value)
16+
lines = append(lines, line.Value)
1717
}
1818
}
1919
fmt.Print(strings.Join(lines, "\n"))
2020
}
2121

22-
func filterReply(reply []pair, compWord string) []pair {
23-
var filtered []pair
22+
func filterReply(reply []Reply, compWord string) []Reply {
23+
var filtered []Reply
2424
for _, word := range reply {
25-
if strings.HasPrefix(word.value, compWord) {
25+
if strings.HasPrefix(word.Value, compWord) {
2626
filtered = append(filtered, word)
2727
}
2828
}

main.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,23 @@ var (
4343
flagNoInline bool
4444
)
4545

46+
var flags = []string{
47+
"--help",
48+
"--raw",
49+
"--slurp",
50+
"--themes",
51+
"--version",
52+
"--yaml",
53+
"--strict",
54+
"--no-inline",
55+
}
56+
57+
func init() {
58+
for _, name := range flags {
59+
complete.Flags = append(complete.Flags, complete.Reply{name, name, "flag"})
60+
}
61+
}
62+
4663
func main() {
4764
if _, ok := os.LookupEnv("FX_PPROF"); ok {
4865
f, err := os.Create("cpu.prof")

0 commit comments

Comments
 (0)