Files
iris-context/commands/fs/zoxide.go
T
VERSE ebde9ba68f refactor(commands): separate commands and its core into two folders (#32)
- I think it would be better if one for commands only, one for the spec
handling core logic so people won't be confused by the core logic inside
the commands folder (cleaner I guess)
- Regen docs
2026-07-05 11:27:30 +07:00

92 lines
2.2 KiB
Go

// please note that zoxide also shows external suggestions
// at the end of the list on command mode
// they are the old directories that you have visited
// this is a feature, not a bug, and I want to keep it
package fs
import (
"bytes"
"context"
"os"
"os/exec"
"strings"
"github.com/versenilvis/fuzzy"
"github.com/versenilvis/iris/spec"
)
func init() {
spec.Register(&spec.Spec{
Name: "z",
Description: "jump to directory",
MaxArgs: 0,
Generator: ZoxideGenerator(),
})
spec.Register(&spec.Spec{
Name: "zi",
Description: "jump to directory interactively",
MaxArgs: 0,
Generator: ZoxideGenerator(),
})
}
func ZoxideGenerator() spec.GeneratorFunc {
return func(tokens []string, prefix string, partial string) []spec.Suggestion {
fullQuery := strings.Join(tokens[1:], " ")
localSuggestions := spec.FileGenerator("/")(tokens, prefix, fullQuery)
var zoxideSuggestions []spec.Suggestion
cmd := exec.CommandContext(context.Background(), "zoxide", "query", "-l")
out, err := cmd.Output()
if err == nil {
lines := strings.Split(string(bytes.TrimSpace(out)), "\n")
var dirs []string
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" {
dirs = append(dirs, line)
}
}
home, _ := os.UserHomeDir()
if fullQuery == "" {
limit := min(len(dirs), 20)
for i := 0; i < limit; i++ {
path := dirs[i]
display := strings.Replace(path, home, "~", 1)
zoxideSuggestions = append(zoxideSuggestions, spec.Suggestion{
Cmd: path,
Desc: display,
})
}
} else if !strings.Contains(fullQuery, "/") {
searcher := fuzzy.NewPlainSearcher(dirs)
matches := searcher.SearchWithScores(fullQuery, &fuzzy.SearchOptions{Limit: 10})
for _, m := range matches {
path := m.Str
display := strings.Replace(path, home, "~", 1)
zoxideSuggestions = append(zoxideSuggestions, spec.Suggestion{
Cmd: path,
Desc: display,
})
}
}
}
var finalResults []spec.Suggestion
seen := make(map[string]bool)
finalResults = append(finalResults, localSuggestions...)
for _, s := range zoxideSuggestions {
if !seen[s.Cmd] {
finalResults = append(finalResults, s)
seen[s.Cmd] = true
}
}
return finalResults
}
}