github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/edit/listing_test.go (about)

     1  package edit
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/markusbkk/elvish/pkg/cli/term"
     7  	"github.com/markusbkk/elvish/pkg/store/storedefs"
     8  	"github.com/markusbkk/elvish/pkg/ui"
     9  )
    10  
    11  func TestListingBuiltins(t *testing.T) {
    12  	// Use the custom listing mode since it doesn't require special setup. The
    13  	// builtins work the same across all listing modes.
    14  
    15  	f := setup(t)
    16  	evals(f.Evaler,
    17  		`fn item {|x| put [&to-show=$x &to-accept=$x &to-filter=$x] }`,
    18  		`edit:listing:start-custom [(item 1) (item 2) (item 3)]`)
    19  	buf1 := f.MakeBuffer(
    20  		"~> \n",
    21  		" LISTING  ", Styles,
    22  		"********* ", term.DotHere, "\n",
    23  		"1                                                 ", Styles,
    24  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
    25  		"2                                                 \n",
    26  		"3                                                 ",
    27  	)
    28  	f.TTYCtrl.TestBuffer(t, buf1)
    29  
    30  	evals(f.Evaler, "edit:listing:down", "edit:redraw")
    31  	buf2 := f.MakeBuffer(
    32  		"~> \n",
    33  		" LISTING  ", Styles,
    34  		"********* ", term.DotHere, "\n",
    35  		"1                                                 \n",
    36  		"2                                                 \n", Styles,
    37  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
    38  		"3                                                 ",
    39  	)
    40  	f.TTYCtrl.TestBuffer(t, buf2)
    41  
    42  	evals(f.Evaler, "edit:listing:down", "edit:redraw")
    43  	buf3 := f.MakeBuffer(
    44  		"~> \n",
    45  		" LISTING  ", Styles,
    46  		"********* ", term.DotHere, "\n",
    47  		"1                                                 \n",
    48  		"2                                                 \n",
    49  		"3                                                 ", Styles,
    50  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
    51  	)
    52  	f.TTYCtrl.TestBuffer(t, buf3)
    53  
    54  	evals(f.Evaler, "edit:listing:down", "edit:redraw")
    55  	f.TTYCtrl.TestBuffer(t, buf3)
    56  
    57  	evals(f.Evaler, "edit:listing:down-cycle", "edit:redraw")
    58  	f.TTYCtrl.TestBuffer(t, buf1)
    59  
    60  	evals(f.Evaler, "edit:listing:up", "edit:redraw")
    61  	f.TTYCtrl.TestBuffer(t, buf1)
    62  
    63  	evals(f.Evaler, "edit:listing:up-cycle", "edit:redraw")
    64  	f.TTYCtrl.TestBuffer(t, buf3)
    65  
    66  	evals(f.Evaler, "edit:listing:page-up", "edit:redraw")
    67  	f.TTYCtrl.TestBuffer(t, buf1)
    68  
    69  	evals(f.Evaler, "edit:listing:page-down", "edit:redraw")
    70  	f.TTYCtrl.TestBuffer(t, buf3)
    71  }
    72  
    73  // Smoke tests for individual addons.
    74  
    75  func TestHistlistAddon(t *testing.T) {
    76  	f := setup(t, storeOp(func(s storedefs.Store) {
    77  		s.AddCmd("ls")
    78  		s.AddCmd("echo")
    79  		s.AddCmd("ls")
    80  		s.AddCmd("LS")
    81  	}))
    82  
    83  	f.TTYCtrl.Inject(term.K('R', ui.Ctrl))
    84  	f.TestTTY(t,
    85  		"~> \n",
    86  		" HISTORY (dedup on)  ", Styles,
    87  		"******************** ", term.DotHere, "\n",
    88  		"   2 echo\n",
    89  		"   3 ls\n",
    90  		"   4 LS                                           ", Styles,
    91  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
    92  	)
    93  
    94  	evals(f.Evaler, `edit:histlist:toggle-dedup`)
    95  	f.TestTTY(t,
    96  		"~> \n",
    97  		" HISTORY  ", Styles,
    98  		"********* ", term.DotHere, "\n",
    99  		"   1 ls\n",
   100  		"   2 echo\n",
   101  		"   3 ls\n",
   102  		"   4 LS                                           ", Styles,
   103  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   104  	)
   105  
   106  	evals(f.Evaler, `edit:histlist:toggle-dedup`)
   107  
   108  	// Filtering is case-insensitive when filter is all lower case.
   109  	f.TTYCtrl.Inject(term.K('l'))
   110  	f.TestTTY(t,
   111  		"~> \n",
   112  		" HISTORY (dedup on)  l", Styles,
   113  		"********************  ", term.DotHere, "\n",
   114  		"   3 ls\n",
   115  		"   4 LS                                           ", Styles,
   116  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   117  	)
   118  
   119  	// Filtering is case-sensitive when filter is not all lower case.
   120  	f.TTYCtrl.Inject(term.K(ui.Backspace), term.K('L'))
   121  	f.TestTTY(t,
   122  		"~> \n",
   123  		" HISTORY (dedup on)  L", Styles,
   124  		"********************  ", term.DotHere, "\n",
   125  		"   4 LS                                           ", Styles,
   126  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   127  	)
   128  }
   129  
   130  func TestLastCmdAddon(t *testing.T) {
   131  	f := setup(t, storeOp(func(s storedefs.Store) {
   132  		s.AddCmd("echo hello world")
   133  	}))
   134  
   135  	f.TTYCtrl.Inject(term.K(',', ui.Alt))
   136  	f.TestTTY(t,
   137  		"~> \n",
   138  		" LASTCMD  ", Styles,
   139  		"********* ", term.DotHere, "\n",
   140  		"    echo hello world                              \n", Styles,
   141  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   142  		"  0 echo\n",
   143  		"  1 hello\n",
   144  		"  2 world",
   145  	)
   146  }
   147  
   148  func TestCustomListing_PassingList(t *testing.T) {
   149  	f := setup(t)
   150  
   151  	evals(f.Evaler,
   152  		`var items = [[&to-filter=1 &to-accept=echo &to-show=echo]
   153  		              [&to-filter=2  &to-accept=put &to-show=(styled put green)]]`,
   154  		`edit:listing:start-custom $items &accept=$edit:insert-at-dot~ &caption=A`)
   155  	f.TestTTY(t,
   156  		"~> \n",
   157  		"A ", Styles,
   158  		"* ", term.DotHere, "\n",
   159  		"echo                                              \n", Styles,
   160  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   161  		"put                                               ", Styles,
   162  		"vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv",
   163  	)
   164  	// Filter - "put" will be selected.
   165  	f.TTYCtrl.Inject(term.K('2'))
   166  	// Accept.
   167  	f.TTYCtrl.Inject(term.K('\n'))
   168  	f.TestTTY(t,
   169  		"~> put", Styles,
   170  		"   vvv", term.DotHere,
   171  	)
   172  }
   173  
   174  func TestCustomListing_PassingValueCallback(t *testing.T) {
   175  	f := setup(t)
   176  
   177  	evals(f.Evaler,
   178  		`var f = {|q| put [&to-accept='q '$q &to-show=(styled 'q '$q blue)] }`,
   179  		`edit:listing:start-custom $f &caption=A`)
   180  	// Query.
   181  	f.TTYCtrl.Inject(term.K('x'))
   182  	f.TestTTY(t,
   183  		"~> \n",
   184  		"A x", Styles,
   185  		"*  ", term.DotHere, "\n",
   186  		"q x                                               ", Styles,
   187  		"##################################################",
   188  	)
   189  	// No-op accept.
   190  	f.TTYCtrl.Inject(term.K('\n'))
   191  	f.TestTTY(t, "~> ", term.DotHere)
   192  }
   193  
   194  func TestCustomListing_PassingBytesCallback(t *testing.T) {
   195  	f := setup(t)
   196  
   197  	evals(f.Evaler,
   198  		`var f = {|q| echo '# '$q }`,
   199  		`edit:listing:start-custom $f &accept=$edit:insert-at-dot~ &caption=A `+
   200  			`&binding=(edit:binding-table [&Ctrl-X=$edit:listing:accept~])`)
   201  	// Test that the query function is used to generate candidates. Also test
   202  	// the caption.
   203  	f.TTYCtrl.Inject(term.K('x'))
   204  	f.TestTTY(t,
   205  		"~> \n",
   206  		"A x", Styles,
   207  		"*  ", term.DotHere, "\n",
   208  		"# x                                               ", Styles,
   209  		"++++++++++++++++++++++++++++++++++++++++++++++++++",
   210  	)
   211  	// Test both the binding and the accept callback.
   212  	f.TTYCtrl.Inject(term.K('X', ui.Ctrl))
   213  	f.TestTTY(t,
   214  		"~> # x", Styles,
   215  		"   ccc", term.DotHere)
   216  }