feat(cd): optionally complete from zoxide's database

`cd` completes from FileGenerator, which reads one directory: the one you
are standing in. So `cd proj` only ever resolves when proj happens to be
a child of the current directory, and returns nothing at all otherwise --
including for directories visited constantly. That is the opposite of
what cd is normally reached for, and it reads as completion being broken
rather than as a scope limit.

zoxide.extend-cd routes `cd` through the generator `z` already uses, so
local children are offered first and zoxide's frecency database fills in
everything else, reachable by name from anywhere.

Off by default: it shells out to zoxide, and offering absolute paths from
outside the current directory is a real change in what `cd` proposes.

The query is also cached for two seconds. Generators run on every
keystroke and `zoxide query -l` is a subprocess costing ~11ms here, which
is the whole redraw budget; the list only changes when the user changes
directory, so the window costs nothing. This applies to `z` and `zi` too,
which were paying it per keystroke already.
This commit is contained in:
Kenny B
2026-08-14 13:01:02 +03:00
committed by thejoker.msk
parent 2b82e016b9
commit 0b2221d5e9
4 changed files with 73 additions and 11 deletions
+9
View File
@@ -3,6 +3,7 @@ package fs
import (
"strings"
"github.com/versenilvis/iris/internal/config"
"github.com/versenilvis/iris/spec"
)
@@ -12,6 +13,14 @@ func init() {
Description: "change directory",
MaxArgs: 0,
Generator: func(tokens []string, prefix string, partial string) []spec.Suggestion {
// The file generator only reads the current directory, so `cd proj`
// comes back empty unless its parent is where you already are --
// which is not how cd is typically used. zoxide.extend-cd folds in
// the frecency database that `z` already queries, making any
// directory zoxide has seen reachable by name from anywhere.
if config.Get().Zoxide.ExtendCd {
return ZoxideGenerator()(tokens, prefix, partial)
}
fullQuery := strings.Join(tokens[1:], " ")
return spec.FileGenerator("/")(tokens, prefix, fullQuery)
},