From 3c5a0580d1e6709dbc054fd4373a2f7a654e7ea0 Mon Sep 17 00:00:00 2001 From: verse91 Date: Sat, 9 May 2026 22:54:27 +0700 Subject: [PATCH] fix(zoxide/cd): support folder contains space --- commands/core/filegen.go | 7 ++++++- commands/core/lookup.go | 16 ++++++++++++++-- commands/core/utils.go | 1 + commands/fs/cd.go | 8 +++++++- commands/fs/zoxide.go | 15 +++++++-------- 5 files changed, 35 insertions(+), 12 deletions(-) diff --git a/commands/core/filegen.go b/commands/core/filegen.go index fd68b28..2cd5ad8 100644 --- a/commands/core/filegen.go +++ b/commands/core/filegen.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "sort" "strings" ) @@ -121,7 +122,7 @@ func FileGenerator(filters ...string) GeneratorFunc { } continue } - + if dirOnly { continue } @@ -139,6 +140,10 @@ func FileGenerator(filters ...string) GeneratorFunc { }) } + sort.Slice(results, func(i, j int) bool { + return strings.ToLower(results[i].Cmd) < strings.ToLower(results[j].Cmd) + }) + return results } } diff --git a/commands/core/lookup.go b/commands/core/lookup.go index c525c47..ef9a201 100644 --- a/commands/core/lookup.go +++ b/commands/core/lookup.go @@ -178,8 +178,20 @@ func Lookup(input string) []Suggestion { continue } - finalCmd := g.Cmd - finalCmd = strings.TrimSpace(linePrefix) + " " + g.Cmd + suggested := g.Cmd + if strings.Contains(suggested, " ") && !strings.HasPrefix(suggested, "\"") { + suggested = "\"" + suggested + "\"" + } + + // if the suggestion is a full path that includes + // words already in the command line (multi-word support), we replace + // the entire argument part by using prefix only + finalCmd := "" + if len(tokens) > depth+1 && strings.HasPrefix(g.Cmd, tokens[depth]) { + finalCmd = prefix + " " + suggested + } else { + finalCmd = strings.TrimSpace(linePrefix) + " " + suggested + } newTokens := tokenize(finalCmd) if len(newTokens) > 0 { diff --git a/commands/core/utils.go b/commands/core/utils.go index 07f895c..9257648 100644 --- a/commands/core/utils.go +++ b/commands/core/utils.go @@ -62,6 +62,7 @@ func hasPrefix(s, prefix string) bool { } return true } + // CI = case insensitive func HasPrefixCI(s, prefix string) bool { return hasPrefix(s, prefix) diff --git a/commands/fs/cd.go b/commands/fs/cd.go index 333f9ff..815f311 100644 --- a/commands/fs/cd.go +++ b/commands/fs/cd.go @@ -1,6 +1,8 @@ package fs import ( + "strings" + "github.com/versenilvis/iris/commands/core" ) @@ -8,6 +10,10 @@ func init() { core.Register(&core.Spec{ Name: "cd", Description: "change directory", - Generator: core.FileGenerator("/"), // Directory only + MaxArgs: 0, + Generator: func(tokens []string, prefix string, partial string) []core.Suggestion { + fullQuery := strings.Join(tokens[1:], " ") + return core.FileGenerator("/")(tokens, prefix, fullQuery) + }, }) } diff --git a/commands/fs/zoxide.go b/commands/fs/zoxide.go index 3179f44..b18d569 100644 --- a/commands/fs/zoxide.go +++ b/commands/fs/zoxide.go @@ -18,21 +18,21 @@ func init() { core.Register(&core.Spec{ Name: "z", Description: "jump to directory", - MaxArgs: 1, + MaxArgs: 0, Generator: zoxideGenerator(), }) core.Register(&core.Spec{ Name: "zi", Description: "jump to directory interactively", - MaxArgs: 1, + MaxArgs: 0, Generator: zoxideGenerator(), }) } func zoxideGenerator() core.GeneratorFunc { return func(tokens []string, prefix string, partial string) []core.Suggestion { - - localSuggestions := core.FileGenerator("/")(tokens, prefix, partial) + fullQuery := strings.Join(tokens[1:], " ") + localSuggestions := core.FileGenerator("/")(tokens, prefix, fullQuery) var zoxideSuggestions []core.Suggestion cmd := exec.Command("zoxide", "query", "-l") @@ -49,7 +49,7 @@ func zoxideGenerator() core.GeneratorFunc { home, _ := os.UserHomeDir() - if partial == "" { + if fullQuery == "" { limit := 20 if len(dirs) < limit { limit = len(dirs) @@ -62,10 +62,9 @@ func zoxideGenerator() core.GeneratorFunc { Desc: display, }) } - } else if !strings.Contains(partial, "/") { - + } else if !strings.Contains(fullQuery, "/") { searcher := fuzzyvn.NewPlainSearcher(dirs) - matches := searcher.SearchWithScores(partial, &fuzzyvn.SearchOptions{Limit: 10}) + matches := searcher.SearchWithScores(fullQuery, &fuzzyvn.SearchOptions{Limit: 10}) for _, m := range matches { path := m.Str display := strings.Replace(path, home, "~", 1)