1package modes
2
3import (
4	"testing"
5
6	"src.elv.sh/pkg/cli"
7	. "src.elv.sh/pkg/cli/clitest"
8	"src.elv.sh/pkg/cli/histutil"
9	"src.elv.sh/pkg/cli/term"
10	"src.elv.sh/pkg/cli/tk"
11	"src.elv.sh/pkg/ui"
12)
13
14func TestHistWalk(t *testing.T) {
15	f := Setup(WithSpec(func(spec *cli.AppSpec) {
16		spec.CodeAreaState.Buffer = tk.CodeBuffer{Content: "ls", Dot: 2}
17	}))
18	defer f.Stop()
19
20	f.App.Redraw()
21	buf0 := f.MakeBuffer("ls", term.DotHere)
22	f.TTY.TestBuffer(t, buf0)
23
24	getCfg := func() HistwalkSpec {
25		store := histutil.NewMemStore(
26			// 0       1        2         3       4         5
27			"echo", "ls -l", "echo a", "echo", "echo a", "ls -a")
28		return HistwalkSpec{
29			Store:  store,
30			Prefix: "ls",
31			Bindings: tk.MapBindings{
32				term.K(ui.Up):        func(w tk.Widget) { w.(Histwalk).Prev() },
33				term.K(ui.Down):      func(w tk.Widget) { w.(Histwalk).Next() },
34				term.K('[', ui.Ctrl): func(tk.Widget) { f.App.PopAddon() },
35			},
36		}
37	}
38
39	startHistwalk(f.App, getCfg())
40	buf5 := f.MakeBuffer(
41		"ls -a", Styles,
42		"  ___", term.DotHere, "\n",
43		" HISTORY #5 ", Styles,
44		"************",
45	)
46	f.TTY.TestBuffer(t, buf5)
47
48	f.TTY.Inject(term.K(ui.Up))
49	buf1 := f.MakeBuffer(
50		"ls -l", Styles,
51		"  ___", term.DotHere, "\n",
52		" HISTORY #1 ", Styles,
53		"************",
54	)
55	f.TTY.TestBuffer(t, buf1)
56
57	f.TTY.Inject(term.K(ui.Down))
58	f.TTY.TestBuffer(t, buf5)
59
60	f.TTY.Inject(term.K('[', ui.Ctrl))
61	f.TTY.TestBuffer(t, buf0)
62
63	// Start over and accept.
64	startHistwalk(f.App, getCfg())
65	f.TTY.TestBuffer(t, buf5)
66	f.TTY.Inject(term.K(' '))
67	f.TestTTY(t, "ls -a ", term.DotHere)
68}
69
70func TestHistWalk_FocusedWidgetNotCodeArea(t *testing.T) {
71	testFocusedWidgetNotCodeArea(t, func(app cli.App) error {
72		store := histutil.NewMemStore("foo")
73		_, err := NewHistwalk(app, HistwalkSpec{Store: store})
74		return err
75	})
76}
77
78func TestHistWalk_NoWalker(t *testing.T) {
79	f := Setup()
80	defer f.Stop()
81
82	startHistwalk(f.App, HistwalkSpec{})
83	f.TestTTYNotes(t, "no history store")
84}
85
86func TestHistWalk_NoMatch(t *testing.T) {
87	f := Setup(WithSpec(func(spec *cli.AppSpec) {
88		spec.CodeAreaState.Buffer = tk.CodeBuffer{Content: "ls", Dot: 2}
89	}))
90	defer f.Stop()
91
92	f.App.Redraw()
93	buf0 := f.MakeBuffer("ls", term.DotHere)
94	f.TTY.TestBuffer(t, buf0)
95
96	store := histutil.NewMemStore("echo 1", "echo 2")
97	cfg := HistwalkSpec{Store: store, Prefix: "ls"}
98	startHistwalk(f.App, cfg)
99	// Test that an error message has been written to the notes buffer.
100	f.TestTTYNotes(t, "end of history")
101	// Test that buffer has not changed - histwalk addon is not active.
102	f.TTY.TestBuffer(t, buf0)
103}
104
105func TestHistWalk_FallbackHandler(t *testing.T) {
106	f := Setup()
107	defer f.Stop()
108
109	store := histutil.NewMemStore("ls")
110	startHistwalk(f.App, HistwalkSpec{Store: store, Prefix: ""})
111	f.TestTTY(t,
112		"ls", Styles,
113		"__", term.DotHere, "\n",
114		" HISTORY #0 ", Styles,
115		"************",
116	)
117
118	f.TTY.Inject(term.K(ui.Backspace))
119	f.TestTTY(t, "l", term.DotHere)
120}
121
122func startHistwalk(app cli.App, cfg HistwalkSpec) {
123	w, err := NewHistwalk(app, cfg)
124	if err != nil {
125		app.Notify(err.Error())
126		return
127	}
128	app.PushAddon(w)
129	app.Redraw()
130}
131