Add basic readline-like support for using control-left and control-right to scroll horizontally by one word at a time

This commit is contained in:
David Dworken 2024-02-19 13:54:42 -08:00
parent 8c4ede4186
commit 5e87aa9eec
No known key found for this signature in database
3 changed files with 44 additions and 2 deletions

View File

@ -2092,7 +2092,7 @@ func testTui_general(t *testing.T, onlineStatus OnlineStatus) {
// Test jumping around the cursor via shortcuts
out = captureTerminalOutput(t, tester, []string{
"hishtory SPACE tquery ENTER",
"foo C-a AAA C-e ZZZ",
"foo C-a AAA SPACE C-e SPACE ZZZ",
})
out = strings.Split(stripTuiCommandPrefix(t, out), "\n")[0]
testutils.CompareGoldens(t, out, "TestTui-JumpCursor")

View File

@ -1 +1 @@
Search Query: > AAAfooZZZ
Search Query: > AAA foo ZZZ

View File

@ -58,6 +58,8 @@ type keyMap struct {
Quit key.Binding
JumpStartOfInput key.Binding
JumpEndOfInput key.Binding
JumpWordLeft key.Binding
JumpWordRight key.Binding
}
var fakeTitleKeyBinding key.Binding = key.NewBinding(
@ -144,6 +146,14 @@ var keys = keyMap{
key.WithKeys("ctrl+e"),
key.WithHelp("ctrl+e", "jump to the end of the input "),
),
JumpWordLeft: key.NewBinding(
key.WithKeys("ctrl+left"),
key.WithHelp("ctrl+left", "jump left one word "),
),
JumpWordRight: key.NewBinding(
key.WithKeys("ctrl+right"),
key.WithHelp("ctrl+right", "jump right one word "),
),
}
type SelectStatus int64
@ -357,6 +367,26 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case key.Matches(msg, keys.JumpEndOfInput):
m.queryInput.SetCursor(len(m.queryInput.Value()))
return m, nil
case key.Matches(msg, keys.JumpWordLeft):
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
lastBoundary := 0
for _, boundary := range wordBoundaries {
if boundary >= m.queryInput.Position() {
m.queryInput.SetCursor(lastBoundary)
break
}
lastBoundary = boundary
}
return m, nil
case key.Matches(msg, keys.JumpWordRight):
wordBoundaries := calculateWordBoundaries(m.queryInput.Value())
for _, boundary := range wordBoundaries {
if boundary > m.queryInput.Position() {
m.queryInput.SetCursor(boundary)
break
}
}
return m, nil
default:
pendingCommands := tea.Batch()
if m.table != nil {
@ -421,6 +451,18 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
}
}
func calculateWordBoundaries(input string) []int {
ret := make([]int, 0)
ret = append(ret, 0)
for idx, char := range input {
if char == ' ' || char == '-' {
ret = append(ret, idx)
}
}
ret = append(ret, len(input))
return ret
}
func (m model) View() string {
if m.fatalErr != nil {
return fmt.Sprintf("An unrecoverable error occured: %v\n", m.fatalErr)