Deliver shell completion query replies

This commit is contained in:
2026-11-03 04:06:05 +00:00
parent 4c47a0ca0b
commit d1f31d2931
7 changed files with 412 additions and 6 deletions

View File

@@ -12,6 +12,7 @@ import (
"strings"
"testing"
commandmeta "gitea.maximumdirect.net/eric/CommandKit/internal/commandmeta"
spfcobra "github.com/spf13/cobra"
)
@@ -33,6 +34,20 @@ func TestCompletionScriptGeneration(t *testing.T) {
}
}
func TestCompletionReplyFiltersUnrepresentableValues(t *testing.T) {
result := commandmeta.CompletionResult{Kind: commandmeta.CompletionChoices, Prefix: "-c", Choices: []commandmeta.CompletionChoice{
{Value: "good", Description: "one\ntwo\tthree"}, {Value: ""}, {Value: "bad\nline"}, {Value: "bad\tfield"}, {Value: "bad\x00byte"},
}}
reply, err := CompletionReply(result)
want := fmt.Sprintf("%s-c\ngood\tone two three\n:%d\n", completionPathPrefixMarker, spfcobra.ShellCompDirectiveNoFileComp)
if err != nil || reply != want {
t.Fatalf("reply=%q error=%v", reply, err)
}
if _, err := CompletionReply(commandmeta.CompletionResult{Kind: 255}); err == nil {
t.Fatal("unsupported strategy accepted")
}
}
type shortCompletionWriter struct{}
func (shortCompletionWriter) Write(p []byte) (int, error) { return len(p) - 1, nil }
@@ -61,9 +76,26 @@ sys.stdout.write(os.environ['PROBE_REPLY'])
if err := os.WriteFile(filepath.Join(dir, "partial file"), nil, 0o644); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "foo=bar"), nil, 0o644); err != nil {
t.Fatal(err)
}
reply := func(candidates string, directive spfcobra.ShellCompDirective) string {
return fmt.Sprintf("%s:%d\n", candidates, directive)
}
pathReply := func(kind commandmeta.CompletionKind, prefix string) string {
result, err := CompletionReply(commandmeta.CompletionResult{Kind: kind, Prefix: prefix})
if err != nil {
t.Fatal(err)
}
return result
}
choiceReply := func(prefix, value string) string {
result, err := CompletionReply(commandmeta.CompletionResult{Kind: commandmeta.CompletionChoices, Prefix: prefix, Choices: []commandmeta.CompletionChoice{{Value: value, Description: "value"}}})
if err != nil {
t.Fatal(err)
}
return result
}
tests := []struct {
name, line, reply string
query, executed []string
@@ -74,8 +106,17 @@ sys.stdout.write(os.environ['PROBE_REPLY'])
{"attached file", `probe --config=./partial\ f`, reply("", spfcobra.ShellCompDirectiveDefault), []string{"__complete", "--config=./partial f"}, []string{"--config=./partial file"}},
{"directory", "probe ./partial", reply("", spfcobra.ShellCompDirectiveFilterDirs), []string{"__complete", "./partial"}, []string{"./partial dir"}},
{"attached directory", "probe --config=./partial", reply("", spfcobra.ShellCompDirectiveFilterDirs), []string{"__complete", "--config=./partial"}, []string{"--config=./partial dir"}},
{"short attached file", `probe -c./partial\ f`, pathReply(commandmeta.CompletionFiles, "-c"), []string{"__complete", "-c./partial f"}, []string{"-c./partial file"}},
{"short cluster directory", "probe -sc./partial", pathReply(commandmeta.CompletionDirectories, "-sc"), []string{"__complete", "-sc./partial"}, []string{"-sc./partial dir"}},
{"short path with equals", "probe -cfoo=ba", pathReply(commandmeta.CompletionFiles, "-c"), []string{"__complete", "-cfoo=ba"}, []string{"-cfoo=bar"}},
{"short attached choice", "probe -cbl", choiceReply("-c", "blue"), []string{"__complete", "-cbl"}, []string{"-cblue"}},
{"short choice with equals", "probe -cfoo=ba", choiceReply("-c", "foo=bar"), []string{"__complete", "-cfoo=ba"}, []string{"-cfoo=bar"}},
{"short no suggestions", "probe -cnomatch", pathReply(commandmeta.CompletionChoices, "-c"), []string{"__complete", "-cnomatch"}, []string{"-cnomatch"}},
{"literal prefix marker", "probe __commandkit_path_pre", choiceReply("", completionPathPrefixMarker+"-c"), []string{"__complete", "__commandkit_path_pre"}, []string{completionPathPrefixMarker + "-c"}},
{"literal marker attached", "probe --config=__commandkit_path_pre", choiceReply("--config=", completionPathPrefixMarker+"-c"), []string{"__complete", "--config=__commandkit_path_pre"}, []string{"--config=" + completionPathPrefixMarker + "-c"}},
{"empty", "probe ", reply("", spfcobra.ShellCompDirectiveNoFileComp), []string{"__complete", ""}, []string{}},
{"no file fallback", `probe ./partial\ f`, reply("", spfcobra.ShellCompDirectiveNoFileComp), []string{"__complete", "./partial f"}, []string{"./partial f"}},
{"error no fallback", `probe ./partial\ f`, reply("", spfcobra.ShellCompDirectiveError), []string{"__complete", "./partial f"}, []string{"./partial f"}},
{"cluster", "probe -ab", reply("-abc\tflag\n", spfcobra.ShellCompDirectiveNoFileComp), []string{"__complete", "-ab"}, []string{"-abc"}},
{"quoted argument", "probe 'alpha beta' --config=./par", reply("./partial file\tdescription\n", spfcobra.ShellCompDirectiveNoFileComp), []string{"__complete", "alpha beta", "--config=./par"}, []string{"alpha beta", "--config=./partial file"}},
}