From 9f2b392ddb8c023bed0f1cdd46a5c201ec84166a Mon Sep 17 00:00:00 2001 From: David Dworken Date: Fri, 19 May 2023 17:14:33 -0700 Subject: [PATCH] Add key binding to select an entry and cd into that directory --- client/client_test.go | 8 +++ client/lib/goldens/TestTui-HelpPage | 7 +- client/lib/goldens/TestTui-SelectAndCd | 1 + client/lib/tui.go | 88 ++++++++++++++++---------- 4 files changed, 68 insertions(+), 36 deletions(-) create mode 100644 client/lib/goldens/TestTui-SelectAndCd diff --git a/client/client_test.go b/client/client_test.go index b413d06..ad47e1a 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1959,6 +1959,14 @@ func TestTui(t *testing.T) { out = strings.TrimSpace(strings.Split(out, "hishtory tquery")[1]) testutils.CompareGoldens(t, out, "TestTui-HelpPageClosed") + // Test selecting and cd-ing + out = captureTerminalOutput(t, tester, []string{ + "hishtory SPACE tquery ENTER", + "C-x", + }) + out = strings.Split(strings.TrimSpace(strings.Split(out, "hishtory tquery")[1]), "\n")[0] + testutils.CompareGoldens(t, out, "TestTui-SelectAndCd") + // Assert there are no leaked connections assertNoLeakedConnections(t) } diff --git a/client/lib/goldens/TestTui-HelpPage b/client/lib/goldens/TestTui-HelpPage index 76e1415..efac015 100644 --- a/client/lib/goldens/TestTui-HelpPage +++ b/client/lib/goldens/TestTui-HelpPage @@ -25,6 +25,7 @@ Search Query: > ls │ │ └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ hiSHtory: Search your shell history -↑ scroll up ↓ scroll down pgup page up pgdn page down -← move left → move right shift+← scroll the table left shift+→ scroll the table right -enter select an entry ctrl+k delete the highlighted entry esc exit hiSHtory ctrl+h help \ No newline at end of file +↑ scroll up ↓ scroll down pgup page up pgdn page down +← move left → move right shift+← scroll the table left shift+→ scroll the table right +enter select an entry ctrl+k delete the highlighted entry esc exit hiSHtory ctrl+h help +ctrl+x select an entry and cd into that directory \ No newline at end of file diff --git a/client/lib/goldens/TestTui-SelectAndCd b/client/lib/goldens/TestTui-SelectAndCd new file mode 100644 index 0000000..2e70fdb --- /dev/null +++ b/client/lib/goldens/TestTui-SelectAndCd @@ -0,0 +1 @@ +cd /tmp/; echo '1234567890qwertyuiopasdfghjklzxxcvbnm0987654321_0_1234567890qwertyuiopasdfghjklzxxcvbnm0987654321_1_1234567890qwertyuiopasdfghjklzxxcvbnm0987654321_2_1234567890qwertyuiopasdfghjklzxxcv \ No newline at end of file diff --git a/client/lib/tui.go b/client/lib/tui.go index 0ddfb38..172ddf9 100644 --- a/client/lib/tui.go +++ b/client/lib/tui.go @@ -26,25 +26,26 @@ import ( const TABLE_HEIGHT = 20 const PADDED_NUM_ENTRIES = TABLE_HEIGHT * 5 -var selectedCommand string = "" +var SELECTED_COMMAND string = "" var baseStyle = lipgloss.NewStyle(). BorderStyle(lipgloss.NormalBorder()). BorderForeground(lipgloss.Color("240")) type keyMap struct { - Up key.Binding - Down key.Binding - PageUp key.Binding - PageDown key.Binding - SelectEntry key.Binding - Left key.Binding - Right key.Binding - TableLeft key.Binding - TableRight key.Binding - DeleteEntry key.Binding - Help key.Binding - Quit key.Binding + Up key.Binding + Down key.Binding + PageUp key.Binding + PageDown key.Binding + SelectEntry key.Binding + SelectEntryAndChangeDir key.Binding + Left key.Binding + Right key.Binding + TableLeft key.Binding + TableRight key.Binding + DeleteEntry key.Binding + Help key.Binding + Quit key.Binding } var fakeTitleKeyBinding key.Binding = key.NewBinding( @@ -63,7 +64,7 @@ func (k keyMap) ShortHelp() []key.Binding { func (k keyMap) FullHelp() [][]key.Binding { return [][]key.Binding{ - {fakeTitleKeyBinding, k.Up, k.Left, k.SelectEntry}, + {fakeTitleKeyBinding, k.Up, k.Left, k.SelectEntry, k.SelectEntryAndChangeDir}, {fakeEmptyKeyBinding, k.Down, k.Right, k.DeleteEntry}, {fakeEmptyKeyBinding, k.PageUp, k.TableLeft, k.Quit}, {fakeEmptyKeyBinding, k.PageDown, k.TableRight, k.Help}, @@ -73,54 +74,66 @@ func (k keyMap) FullHelp() [][]key.Binding { var keys = keyMap{ Up: key.NewBinding( key.WithKeys("up", "alt+OA", "ctrl+p"), - key.WithHelp("↑", "scroll up"), + key.WithHelp("↑ ", "scroll up "), ), Down: key.NewBinding( key.WithKeys("down", "alt+OB", "ctrl+n"), - key.WithHelp("↓", "scroll down"), + key.WithHelp("↓ ", "scroll down "), ), PageUp: key.NewBinding( key.WithKeys("pgup"), - key.WithHelp("pgup", "page up"), + key.WithHelp("pgup", "page up "), ), PageDown: key.NewBinding( key.WithKeys("pgdown"), - key.WithHelp("pgdn", "page down"), + key.WithHelp("pgdn", "page down "), ), SelectEntry: key.NewBinding( key.WithKeys("enter"), - key.WithHelp("enter", "select an entry"), + key.WithHelp("enter", "select an entry "), + ), + SelectEntryAndChangeDir: key.NewBinding( + key.WithKeys("ctrl+x"), + key.WithHelp("ctrl+x", "select an entry and cd into that directory"), ), Left: key.NewBinding( key.WithKeys("left"), - key.WithHelp("←", "move left"), + key.WithHelp("← ", "move left "), ), Right: key.NewBinding( key.WithKeys("right"), - key.WithHelp("→", "move right"), + key.WithHelp("→ ", "move right "), ), TableLeft: key.NewBinding( key.WithKeys("shift+left"), - key.WithHelp("shift+←", "scroll the table left"), + key.WithHelp("shift+← ", "scroll the table left "), ), TableRight: key.NewBinding( key.WithKeys("shift+right"), - key.WithHelp("shift+→", "scroll the table right"), + key.WithHelp("shift+→ ", "scroll the table right "), ), DeleteEntry: key.NewBinding( key.WithKeys("ctrl+k"), - key.WithHelp("ctrl+k", "delete the highlighted entry"), + key.WithHelp("ctrl+k", "delete the highlighted entry "), ), Help: key.NewBinding( key.WithKeys("ctrl+h"), - key.WithHelp("ctrl+h", "help"), + key.WithHelp("ctrl+h", "help "), ), Quit: key.NewBinding( key.WithKeys("esc", "ctrl+c", "ctrl+d"), - key.WithHelp("esc", "exit hiSHtory"), + key.WithHelp("esc", "exit hiSHtory "), ), } +type SelectStatus int64 + +const ( + NotSelected SelectStatus = iota + Selected + SelectedWithChangeDir +) + type model struct { // context ctx *context.Context @@ -141,7 +154,7 @@ type model struct { // The entries in the table tableEntries []*data.HistoryEntry // Whether the user has hit enter to select an entry and the TUI is thus about to quit. - selected bool + selected SelectStatus // The search box for the query queryInput textinput.Model @@ -226,7 +239,12 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return m, tea.Quit case key.Matches(msg, keys.SelectEntry): if len(m.tableEntries) != 0 { - m.selected = true + m.selected = Selected + } + return m, tea.Quit + case key.Matches(msg, keys.SelectEntryAndChangeDir): + if len(m.tableEntries) != 0 { + m.selected = SelectedWithChangeDir } return m, tea.Quit case key.Matches(msg, keys.DeleteEntry): @@ -282,8 +300,12 @@ func (m model) View() string { if m.fatalErr != nil { return fmt.Sprintf("An unrecoverable error occured: %v\n", m.fatalErr) } - if m.selected { - selectedCommand = m.tableEntries[m.table.Cursor()].Command + if m.selected == Selected || m.selected == SelectedWithChangeDir { + SELECTED_COMMAND = m.tableEntries[m.table.Cursor()].Command + if m.selected == SelectedWithChangeDir { + changeDir := m.tableEntries[m.table.Cursor()].CurrentWorkingDirectory + SELECTED_COMMAND = "cd " + changeDir + "; " + SELECTED_COMMAND + } return "" } if m.quitting { @@ -560,10 +582,10 @@ func TuiQuery(ctx *context.Context, initialQuery string) error { if err != nil { return err } - if selectedCommand == "" && os.Getenv("HISHTORY_TERM_INTEGRATION") != "" { + if SELECTED_COMMAND == "" && os.Getenv("HISHTORY_TERM_INTEGRATION") != "" { // Print out the initialQuery instead so that we don't clear the terminal - selectedCommand = initialQuery + SELECTED_COMMAND = initialQuery } - fmt.Printf("%s\n", strings.ReplaceAll(selectedCommand, "\\n", "\n")) + fmt.Printf("%s\n", strings.ReplaceAll(SELECTED_COMMAND, "\\n", "\n")) return nil }