2019-11-03 02:32:11 +08:00
|
|
|
package cliedit
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
2019-12-05 06:11:54 +08:00
|
|
|
"github.com/elves/elvish/cli/term"
|
2019-11-10 06:28:27 +08:00
|
|
|
"github.com/elves/elvish/eval/vals"
|
2019-11-03 02:32:11 +08:00
|
|
|
"github.com/elves/elvish/util"
|
|
|
|
)
|
|
|
|
|
2019-11-10 06:28:27 +08:00
|
|
|
func TestCompletionAddon(t *testing.T) {
|
2019-11-08 23:49:43 +08:00
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
2019-11-04 22:07:28 +08:00
|
|
|
util.ApplyDir(util.Dir{"a": "", "b": ""})
|
2019-11-03 02:32:11 +08:00
|
|
|
|
2019-11-08 23:49:43 +08:00
|
|
|
feedInput(f.TTYCtrl, "echo \t")
|
2019-11-03 08:19:17 +08:00
|
|
|
wantBuf := bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-12-05 06:11:54 +08:00
|
|
|
"~> echo a \n", styles,
|
2019-11-03 08:14:01 +08:00
|
|
|
" gggg --",
|
2019-11-03 02:32:11 +08:00
|
|
|
"COMPLETING argument ", styles,
|
2019-12-05 06:11:54 +08:00
|
|
|
"mmmmmmmmmmmmmmmmmmm ", term.DotHere, "\n",
|
2019-11-03 02:32:11 +08:00
|
|
|
"a b", styles,
|
|
|
|
"# ",
|
2019-11-18 18:41:22 +08:00
|
|
|
).
|
2019-11-03 02:32:11 +08:00
|
|
|
Buffer()
|
2019-11-08 23:49:43 +08:00
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
2019-11-03 02:32:11 +08:00
|
|
|
}
|
2019-11-10 06:28:27 +08:00
|
|
|
|
2019-11-19 07:22:43 +08:00
|
|
|
func TestCompletionAddon_CompletesLongestCommonPrefix(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
util.ApplyDir(util.Dir{"foo1": "", "foo2": "", "foo": "", "fox": ""})
|
|
|
|
|
|
|
|
feedInput(f.TTYCtrl, "echo \t")
|
|
|
|
wantBuf := bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-11-19 07:22:43 +08:00
|
|
|
"~> echo fo", styles,
|
2019-12-05 06:11:54 +08:00
|
|
|
" gggg", term.DotHere).
|
2019-11-19 07:22:43 +08:00
|
|
|
Buffer()
|
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
|
|
|
|
|
|
|
feedInput(f.TTYCtrl, "\t")
|
|
|
|
wantBuf = bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-12-05 06:11:54 +08:00
|
|
|
"~> echo foo \n", styles,
|
2019-11-19 07:22:43 +08:00
|
|
|
" gggg ----",
|
|
|
|
"COMPLETING argument ", styles,
|
|
|
|
"mmmmmmmmmmmmmmmmmmm ").
|
|
|
|
SetDotHere().
|
|
|
|
Newline().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-11-19 07:22:43 +08:00
|
|
|
"foo foo1 foo2 fox", styles,
|
|
|
|
"### ",
|
|
|
|
).
|
|
|
|
Buffer()
|
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
|
|
|
}
|
|
|
|
|
2019-11-10 06:28:27 +08:00
|
|
|
func TestCompleteFilename(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
util.ApplyDir(util.Dir{"d": util.Dir{"a": "", "b": ""}})
|
|
|
|
|
|
|
|
evals(f.Evaler, `@cands = (edit:complete-filename ls ./d/a)`)
|
2019-11-10 07:12:05 +08:00
|
|
|
testGlobal(t, f.Evaler,
|
|
|
|
"cands",
|
|
|
|
vals.MakeList(
|
|
|
|
complexItem{Stem: "./d/a", CodeSuffix: " "},
|
|
|
|
complexItem{Stem: "./d/b", CodeSuffix: " "}))
|
2019-11-10 06:28:27 +08:00
|
|
|
}
|
2019-11-10 07:08:13 +08:00
|
|
|
|
|
|
|
func TestComplexCandidate(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
evals(f.Evaler,
|
|
|
|
`cand = (edit:complex-candidate a/b/c &code-suffix=' ' &display-suffix='x')`,
|
|
|
|
// Identical to $cand.
|
|
|
|
`cand2 = (edit:complex-candidate a/b/c &code-suffix=' ' &display-suffix='x')`,
|
|
|
|
// Different from $cand.
|
|
|
|
`cand3 = (edit:complex-candidate a/b/c)`,
|
|
|
|
`kind = (kind-of $cand)`,
|
|
|
|
`@keys = (keys $cand)`,
|
|
|
|
`repr = (repr $cand)`,
|
|
|
|
`eq2 = (eq $cand $cand2)`,
|
|
|
|
`eq2h = [&$cand=$true][$cand2]`,
|
|
|
|
`eq3 = (eq $cand $cand3)`,
|
|
|
|
`stem code-suffix display-suffix = $cand[stem code-suffix display-suffix]`,
|
|
|
|
)
|
|
|
|
testGlobals(t, f.Evaler, map[string]interface{}{
|
|
|
|
"kind": "map",
|
|
|
|
"keys": vals.MakeList("stem", "code-suffix", "display-suffix"),
|
|
|
|
"repr": "(edit:complex-candidate a/b/c &code-suffix=' ' &display-suffix=x)",
|
|
|
|
"eq2": true,
|
|
|
|
"eq2h": true,
|
|
|
|
"eq3": false,
|
|
|
|
|
|
|
|
"stem": "a/b/c",
|
|
|
|
"code-suffix": " ",
|
|
|
|
"display-suffix": "x",
|
|
|
|
})
|
|
|
|
}
|
2019-11-11 04:06:17 +08:00
|
|
|
|
2019-11-11 22:28:23 +08:00
|
|
|
func TestCompletionArgCompleter_ArgsAndValueOutput(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
evals(f.Evaler,
|
|
|
|
`foo-args = []`,
|
|
|
|
`fn foo { }`,
|
|
|
|
`edit:completion:arg-completer[foo] = [@args]{
|
|
|
|
foo-args = $args
|
2019-11-19 07:22:43 +08:00
|
|
|
put 1val
|
|
|
|
edit:complex-candidate 2val &display-suffix=_
|
2019-11-11 22:28:23 +08:00
|
|
|
}`)
|
|
|
|
|
|
|
|
feedInput(f.TTYCtrl, "foo foo1 foo2 \t")
|
|
|
|
wantBuf := bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-12-05 06:11:54 +08:00
|
|
|
"~> foo foo1 foo2 1val\n", styles,
|
2019-11-11 22:28:23 +08:00
|
|
|
" ggg ----",
|
|
|
|
"COMPLETING argument ", styles,
|
2019-12-05 06:11:54 +08:00
|
|
|
"mmmmmmmmmmmmmmmmmmm ", term.DotHere, "\n",
|
2019-11-19 07:22:43 +08:00
|
|
|
"1val 2val_", styles,
|
2019-11-11 22:28:23 +08:00
|
|
|
"#### ",
|
2019-11-18 18:41:22 +08:00
|
|
|
).
|
2019-11-11 22:28:23 +08:00
|
|
|
Buffer()
|
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
|
|
|
testGlobal(t, f.Evaler,
|
|
|
|
"foo-args", vals.MakeList("foo", "foo1", "foo2", ""))
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCompletionArgCompleter_BytesOutput(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
evals(f.Evaler,
|
|
|
|
`fn foo { }`,
|
|
|
|
`edit:completion:arg-completer[foo] = [@args]{
|
2019-11-19 07:22:43 +08:00
|
|
|
echo 1val
|
|
|
|
echo 2val
|
2019-11-11 22:28:23 +08:00
|
|
|
}`)
|
|
|
|
|
|
|
|
feedInput(f.TTYCtrl, "foo foo1 foo2 \t")
|
|
|
|
wantBuf := bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-12-05 06:11:54 +08:00
|
|
|
"~> foo foo1 foo2 1val\n", styles,
|
2019-11-11 22:28:23 +08:00
|
|
|
" ggg ----",
|
|
|
|
"COMPLETING argument ", styles,
|
2019-12-05 06:11:54 +08:00
|
|
|
"mmmmmmmmmmmmmmmmmmm ", term.DotHere, "\n",
|
2019-11-19 07:22:43 +08:00
|
|
|
"1val 2val", styles,
|
2019-11-11 22:28:23 +08:00
|
|
|
"#### ",
|
2019-11-18 18:41:22 +08:00
|
|
|
).
|
2019-11-11 22:28:23 +08:00
|
|
|
Buffer()
|
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
|
|
|
}
|
|
|
|
|
2019-11-13 07:45:44 +08:00
|
|
|
func TestCompleteSudo(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
evals(f.Evaler,
|
|
|
|
`fn foo { }`,
|
|
|
|
`edit:completion:arg-completer[foo] = [@args]{
|
|
|
|
echo val1
|
|
|
|
echo val2
|
|
|
|
}`,
|
|
|
|
`@cands = (edit:complete-sudo sudo foo '')`)
|
|
|
|
testGlobal(t, f.Evaler, "cands", vals.MakeList("val1", "val2"))
|
|
|
|
}
|
|
|
|
|
2019-11-11 21:35:51 +08:00
|
|
|
func TestCompletionMatcher(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
util.ApplyDir(util.Dir{"foo": "", "oof": ""})
|
|
|
|
|
|
|
|
evals(f.Evaler, `edit:completion:matcher[''] = $edit:match-substr~`)
|
|
|
|
feedInput(f.TTYCtrl, "echo f\t")
|
|
|
|
wantBuf := bb().
|
2019-12-05 06:19:37 +08:00
|
|
|
MarkLines(
|
2019-12-05 06:11:54 +08:00
|
|
|
"~> echo foo \n", styles,
|
2019-11-11 21:35:51 +08:00
|
|
|
" gggg ----",
|
|
|
|
"COMPLETING argument ", styles,
|
2019-12-05 06:11:54 +08:00
|
|
|
"mmmmmmmmmmmmmmmmmmm ", term.DotHere, "\n",
|
2019-11-11 21:35:51 +08:00
|
|
|
"foo oof", styles,
|
|
|
|
"### ",
|
2019-11-18 18:41:22 +08:00
|
|
|
).
|
2019-11-11 21:35:51 +08:00
|
|
|
Buffer()
|
|
|
|
f.TTYCtrl.TestBuffer(t, wantBuf)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestBuiltinMatchers(t *testing.T) {
|
2019-11-11 04:06:17 +08:00
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
evals(f.Evaler,
|
2019-11-11 04:19:33 +08:00
|
|
|
`@prefix = (edit:match-prefix ab [ab abc cab acb ba [ab] [a b] [b a]])`,
|
|
|
|
`@substr = (edit:match-substr ab [ab abc cab acb ba [ab] [a b] [b a]])`,
|
|
|
|
`@subseq = (edit:match-subseq ab [ab abc cab acb ba [ab] [a b] [b a]])`,
|
|
|
|
)
|
|
|
|
testGlobals(t, f.Evaler, map[string]interface{}{
|
|
|
|
"prefix": vals.MakeList(true, true, false, false, false, false, false, false),
|
|
|
|
"substr": vals.MakeList(true, true, true, false, false, true, false, false),
|
|
|
|
"subseq": vals.MakeList(true, true, true, true, false, true, true, false),
|
|
|
|
})
|
2019-11-11 04:06:17 +08:00
|
|
|
}
|
2019-11-29 06:59:49 +08:00
|
|
|
|
|
|
|
func TestBuiltinMatchers_Options(t *testing.T) {
|
|
|
|
f := setup()
|
|
|
|
defer f.Cleanup()
|
|
|
|
|
|
|
|
// The two options work identically on all the builtin matchers, so we only
|
|
|
|
// test for match-prefix for simplicity.
|
|
|
|
evals(f.Evaler,
|
|
|
|
`@a = (edit:match-prefix &ignore-case ab [abc aBc AbC])`,
|
|
|
|
`@b = (edit:match-prefix &ignore-case aB [abc aBc AbC])`,
|
|
|
|
`@c = (edit:match-prefix &smart-case ab [abc aBc Abc])`,
|
|
|
|
`@d = (edit:match-prefix &smart-case aB [abc aBc AbC])`,
|
|
|
|
)
|
|
|
|
testGlobals(t, f.Evaler, map[string]interface{}{
|
|
|
|
"a": vals.MakeList(true, true, true),
|
|
|
|
"b": vals.MakeList(true, true, true),
|
|
|
|
"c": vals.MakeList(true, true, true),
|
|
|
|
"d": vals.MakeList(false, true, false),
|
|
|
|
})
|
|
|
|
}
|