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  }