Skip to content

Commit

Permalink
extend lastcmd mode to support all the previous cmds
Browse files Browse the repository at this point in the history
Signed-off-by: Tw <tw19881113@gmail.com>
  • Loading branch information
tw4452852 authored and xiaq committed Aug 27, 2024
1 parent 5d04fd3 commit 50dad91
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 32 deletions.
44 changes: 29 additions & 15 deletions pkg/cli/modes/lastcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,26 @@ func NewLastcmd(app cli.App, cfg LastcmdSpec) (Lastcmd, error) {
}
c := cfg.Store.Cursor("")
c.Prev()
cmd, err := c.Get()
if err != nil {
return nil, fmt.Errorf("db error: %v", err)
}
wordifier := cfg.Wordifier
if wordifier == nil {
wordifier = strings.Fields
}
cmdText := cmd.Text
words := wordifier(cmdText)
entries := make([]lastcmdEntry, len(words)+1)
entries[0] = lastcmdEntry{content: cmdText}
for i, word := range words {
entries[i+1] = lastcmdEntry{strconv.Itoa(i), strconv.Itoa(i - len(words)), word}

get_items := func(c histutil.Cursor) []lastcmdEntry {
cmd, err := c.Get()
if err != nil {
return []lastcmdEntry{}
}

wordifier := cfg.Wordifier
if wordifier == nil {
wordifier = strings.Fields
}
cmdText := cmd.Text
words := wordifier(cmdText)
entries := make([]lastcmdEntry, len(words)+1)
entries[0] = lastcmdEntry{content: cmdText}
for i, word := range words {
entries[i+1] = lastcmdEntry{strconv.Itoa(i), strconv.Itoa(i - len(words)), word}
}

return entries
}

accept := func(text string) {
Expand All @@ -74,9 +80,17 @@ func NewLastcmd(app cli.App, cfg LastcmdSpec) (Lastcmd, error) {
OnAccept: func(it tk.Items, i int) {
accept(it.(lastcmdItems).entries[i].content)
},
OnUnderFlow: func(lb tk.ListBox) {
c.Prev()
lb.Reset(filterLastcmdItems(get_items(c), ""), 0)
},
OnOverFlow: func(lb tk.ListBox) {
c.Next()
lb.Reset(filterLastcmdItems(get_items(c), ""), 0)
},
},
OnFilter: func(w tk.ComboBox, p string) {
items := filterLastcmdItems(entries, p)
items := filterLastcmdItems(get_items(c), p)
if len(items.entries) == 1 {
accept(items.entries[0].content)
} else {
Expand Down
59 changes: 42 additions & 17 deletions pkg/cli/modes/lastcmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,6 @@ func TestNewLastcmd_FocusedWidgetNotCodeArea(t *testing.T) {
})
}

func TestNewLastcmd_StoreError(t *testing.T) {
f := Setup()
defer f.Stop()

db := histutil.NewFaultyInMemoryDB()
store, err := histutil.NewDBStore(db)
if err != nil {
panic(err)
}
db.SetOneOffError(errMock)

_, err = NewLastcmd(f.App, LastcmdSpec{Store: store})
if err.Error() != "db error: mock error" {
t.Error("expect db error")
}
}

func TestLastcmd(t *testing.T) {
f := Setup()
defer f.Stop()
Expand Down Expand Up @@ -115,3 +98,45 @@ func startLastcmd(app cli.App, spec LastcmdSpec) {
w, err := NewLastcmd(app, spec)
startMode(app, w, err)
}

func TestLastcmdOverFlow(t *testing.T) {
f := Setup()
defer f.Stop()

st := histutil.NewMemStore("foo", "bar")
startLastcmd(f.App, LastcmdSpec{
Store: st,
})

// Test UI.
f.TestTTY(t,
"\n", // empty code area
" LASTCMD ", Styles,
"********* ", term.DotHere, "\n",
" bar \n", Styles,
"++++++++++++++++++++++++++++++++++++++++++++++++++",
" 0 bar",
)

// Test underflow.
f.TTY.Inject(term.K(ui.Up, ui.Alt))
f.TestTTY(t,
"\n", // empty code area
" LASTCMD ", Styles,
"********* ", term.DotHere, "\n",
" foo \n", Styles,
"++++++++++++++++++++++++++++++++++++++++++++++++++",
" 0 foo",
)

// Test overflow.
f.TTY.Inject(term.K(ui.Down, ui.Alt))
f.TestTTY(t,
"\n", // empty code area
" LASTCMD ", Styles,
"********* ", term.DotHere, "\n",
" bar \n", Styles,
"++++++++++++++++++++++++++++++++++++++++++++++++++",
" 0 bar",
)
}
16 changes: 16 additions & 0 deletions pkg/cli/tk/listbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ type ListBoxSpec struct {
OnSelect func(it Items, i int)
// A function called on the accept event.
OnAccept func(it Items, i int)
// A function called when selecting before the beginning of the items.
OnUnderFlow func(ListBox)
// A function called when selecting after the ending of the items.
OnOverFlow func(ListBox)
// Whether the listbox should be rendered in a horizontal layout. Note that
// in the horizontal layout, items must have only one line.
Horizontal bool
Expand Down Expand Up @@ -65,6 +69,12 @@ func NewListBox(spec ListBoxSpec) ListBox {
if spec.OnAccept == nil {
spec.OnAccept = func(Items, int) {}
}
if spec.OnUnderFlow == nil {
spec.OnUnderFlow = func(ListBox) {}
}
if spec.OnOverFlow == nil {
spec.OnOverFlow = func(ListBox) {}
}
if spec.OnSelect == nil {
spec.OnSelect = func(Items, int) {}
} else {
Expand Down Expand Up @@ -284,6 +294,12 @@ func (w *listBox) Handle(event term.Event) bool {
case term.K(ui.Enter):
w.Accept()
return true
case term.K(ui.Up, ui.Alt):
w.OnUnderFlow(w)
return true
case term.K(ui.Down, ui.Alt):
w.OnOverFlow(w)
return true
}
return false
}
Expand Down

0 comments on commit 50dad91

Please sign in to comment.