github.com/elves/elvish@v0.15.0/pkg/edit/completion_test.go (about) 1 package edit 2 3 import ( 4 "testing" 5 6 "github.com/elves/elvish/pkg/cli/term" 7 "github.com/elves/elvish/pkg/eval" 8 . "github.com/elves/elvish/pkg/eval/evaltest" 9 "github.com/elves/elvish/pkg/eval/vals" 10 "github.com/elves/elvish/pkg/testutil" 11 ) 12 13 func TestCompletionAddon(t *testing.T) { 14 f := setup() 15 defer f.Cleanup() 16 testutil.ApplyDir(testutil.Dir{"a": "", "b": ""}) 17 18 feedInput(f.TTYCtrl, "echo \t") 19 f.TestTTY(t, 20 "~> echo a \n", Styles, 21 " vvvv __", 22 " COMPLETING argument ", Styles, 23 "********************* ", term.DotHere, "\n", 24 "a b", Styles, 25 "+ ", 26 ) 27 } 28 29 func TestCompletionAddon_CompletesLongestCommonPrefix(t *testing.T) { 30 f := setup() 31 defer f.Cleanup() 32 testutil.ApplyDir(testutil.Dir{"foo1": "", "foo2": "", "foo": "", "fox": ""}) 33 34 feedInput(f.TTYCtrl, "echo \t") 35 f.TestTTY(t, 36 "~> echo fo", Styles, 37 " vvvv", term.DotHere, 38 ) 39 40 feedInput(f.TTYCtrl, "\t") 41 f.TestTTY(t, 42 "~> echo foo \n", Styles, 43 " vvvv ____", 44 " COMPLETING argument ", Styles, 45 "********************* ", term.DotHere, "\n", 46 "foo foo1 foo2 fox", Styles, 47 "+++ ", 48 ) 49 } 50 51 func TestCompleteFilename(t *testing.T) { 52 f := setup() 53 defer f.Cleanup() 54 testutil.ApplyDir(testutil.Dir{"d": testutil.Dir{"a": "", "b": ""}}) 55 56 evals(f.Evaler, `@cands = (edit:complete-filename ls ./d/a)`) 57 testGlobal(t, f.Evaler, 58 "cands", 59 vals.MakeList( 60 complexItem{Stem: "./d/a", CodeSuffix: " "}, 61 complexItem{Stem: "./d/b", CodeSuffix: " "})) 62 } 63 64 func TestComplexCandidate(t *testing.T) { 65 TestWithSetup(t, func(ev *eval.Evaler) { 66 ev.AddGlobal(eval.NsBuilder{}.AddGoFn("", "cc", complexCandidate).Ns()) 67 }, 68 That("kind-of (cc stem)").Puts("map"), 69 That("keys (cc stem)").Puts("stem", "code-suffix", "display"), 70 That("repr (cc a/b &code-suffix=' ' &display=A/B)").Prints( 71 "(edit:complex-candidate a/b &code-suffix=' ' &display=A/B)\n"), 72 That("eq (cc stem) (cc stem)").Puts(true), 73 That("eq (cc stem &code-suffix=' ') (cc stem)").Puts(false), 74 That("eq (cc stem &display=STEM) (cc stem)").Puts(false), 75 That("put [&(cc stem)=value][(cc stem)]").Puts("value"), 76 That("put (cc a/b &code-suffix=' ' &display=A/B)[stem code-suffix display]"). 77 Puts("a/b", " ", "A/B"), 78 ) 79 } 80 81 func TestComplexCandidate_InEditModule(t *testing.T) { 82 // A sanity check that the complex-candidate command is part of the edit 83 // module. 84 f := setup() 85 defer f.Cleanup() 86 87 evals(f.Evaler, `stem = (edit:complex-candidate stem)[stem]`) 88 testGlobal(t, f.Evaler, "stem", "stem") 89 } 90 91 func TestCompletionArgCompleter_ArgsAndValueOutput(t *testing.T) { 92 f := setup() 93 defer f.Cleanup() 94 95 evals(f.Evaler, 96 `foo-args = []`, 97 `fn foo { }`, 98 `edit:completion:arg-completer[foo] = [@args]{ 99 foo-args = $args 100 put 1val 101 edit:complex-candidate 2val &display=2VAL 102 }`) 103 104 feedInput(f.TTYCtrl, "foo foo1 foo2 \t") 105 f.TestTTY(t, 106 "~> foo foo1 foo2 1val\n", Styles, 107 " vvv ____", 108 " COMPLETING argument ", Styles, 109 "********************* ", term.DotHere, "\n", 110 "1val 2VAL", Styles, 111 "++++ ", 112 ) 113 testGlobal(t, f.Evaler, 114 "foo-args", vals.MakeList("foo", "foo1", "foo2", "")) 115 } 116 117 func TestCompletionArgCompleter_BytesOutput(t *testing.T) { 118 f := setup() 119 defer f.Cleanup() 120 121 evals(f.Evaler, 122 `fn foo { }`, 123 `edit:completion:arg-completer[foo] = [@args]{ 124 echo 1val 125 echo 2val 126 }`) 127 128 feedInput(f.TTYCtrl, "foo foo1 foo2 \t") 129 f.TestTTY(t, 130 "~> foo foo1 foo2 1val\n", Styles, 131 " vvv ____", 132 " COMPLETING argument ", Styles, 133 "********************* ", term.DotHere, "\n", 134 "1val 2val", Styles, 135 "++++ ", 136 ) 137 } 138 139 func TestCompleteSudo(t *testing.T) { 140 f := setup() 141 defer f.Cleanup() 142 143 evals(f.Evaler, 144 `fn foo { }`, 145 `edit:completion:arg-completer[foo] = [@args]{ 146 echo val1 147 echo val2 148 }`, 149 `@cands = (edit:complete-sudo sudo foo '')`) 150 testGlobal(t, f.Evaler, "cands", vals.MakeList("val1", "val2")) 151 } 152 153 func TestCompletionMatcher(t *testing.T) { 154 f := setup() 155 defer f.Cleanup() 156 testutil.ApplyDir(testutil.Dir{"foo": "", "oof": ""}) 157 158 evals(f.Evaler, `edit:completion:matcher[''] = $edit:match-substr~`) 159 feedInput(f.TTYCtrl, "echo f\t") 160 f.TestTTY(t, 161 "~> echo foo \n", Styles, 162 " vvvv ____", 163 " COMPLETING argument ", Styles, 164 "********************* ", term.DotHere, "\n", 165 "foo oof", Styles, 166 "+++ ", 167 ) 168 } 169 170 func TestBuiltinMatchers(t *testing.T) { 171 f := setup() 172 defer f.Cleanup() 173 174 evals(f.Evaler, 175 `@prefix = (edit:match-prefix ab [ab abc cab acb ba [ab] [a b] [b a]])`, 176 `@substr = (edit:match-substr ab [ab abc cab acb ba [ab] [a b] [b a]])`, 177 `@subseq = (edit:match-subseq ab [ab abc cab acb ba [ab] [a b] [b a]])`, 178 ) 179 testGlobals(t, f.Evaler, map[string]interface{}{ 180 "prefix": vals.MakeList(true, true, false, false, false, false, false, false), 181 "substr": vals.MakeList(true, true, true, false, false, true, false, false), 182 "subseq": vals.MakeList(true, true, true, true, false, true, true, false), 183 }) 184 } 185 186 func TestBuiltinMatchers_Options(t *testing.T) { 187 f := setup() 188 defer f.Cleanup() 189 190 // The two options work identically on all the builtin matchers, so we only 191 // test for match-prefix for simplicity. 192 evals(f.Evaler, 193 `@a = (edit:match-prefix &ignore-case ab [abc aBc AbC])`, 194 `@b = (edit:match-prefix &ignore-case aB [abc aBc AbC])`, 195 `@c = (edit:match-prefix &smart-case ab [abc aBc Abc])`, 196 `@d = (edit:match-prefix &smart-case aB [abc aBc AbC])`, 197 ) 198 testGlobals(t, f.Evaler, map[string]interface{}{ 199 "a": vals.MakeList(true, true, true), 200 "b": vals.MakeList(true, true, true), 201 "c": vals.MakeList(true, true, true), 202 "d": vals.MakeList(false, true, false), 203 }) 204 }