Skip to content

Commit

Permalink
Add first/last page keypresses (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
Evertras authored Mar 4, 2022
1 parent f036087 commit 6525a3f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 22 deletions.
12 changes: 10 additions & 2 deletions table/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ type KeyMap struct {

RowSelectToggle key.Binding

PageDown key.Binding
PageUp key.Binding
PageDown key.Binding
PageUp key.Binding
PageFirst key.Binding
PageLast key.Binding

Filter key.Binding
}
Expand All @@ -33,6 +35,12 @@ func DefaultKeyMap() KeyMap {
PageUp: key.NewBinding(
key.WithKeys("left", "h", "pgup"),
),
PageFirst: key.NewBinding(
key.WithKeys("home", "g"),
),
PageLast: key.NewBinding(
key.WithKeys("end", "G"),
),
Filter: key.NewBinding(
key.WithKeys("/"),
),
Expand Down
18 changes: 18 additions & 0 deletions table/pagination.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ func (m *Model) pageUp() {
m.rowCursorIndex = m.currentPage * m.pageSize
}

func (m *Model) pageFirst() {
if m.pageSize == 0 || len(m.GetVisibleRows()) <= m.pageSize {
return
}

m.currentPage = 0
m.rowCursorIndex = 0
}

func (m *Model) pageLast() {
if m.pageSize == 0 || len(m.GetVisibleRows()) <= m.pageSize {
return
}

m.currentPage = m.MaxPages() - 1
m.rowCursorIndex = m.currentPage * m.pageSize
}

func (m *Model) expectedPageForRowIndex(rowIndex int) int {
if m.pageSize == 0 {
return 0
Expand Down
48 changes: 29 additions & 19 deletions table/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,34 @@ func (m Model) updateFilterTextInput(msg tea.Msg) (Model, tea.Cmd) {
return m, cmd
}

func (m *Model) handleKeypress(msg tea.KeyMsg) {
switch {
case key.Matches(msg, m.keyMap.RowDown):
m.moveHighlightDown()

case key.Matches(msg, m.keyMap.RowUp):
m.moveHighlightUp()

case key.Matches(msg, m.keyMap.RowSelectToggle):
m.toggleSelect()

case key.Matches(msg, m.keyMap.PageDown):
m.pageDown()

case key.Matches(msg, m.keyMap.PageUp):
m.pageUp()

case key.Matches(msg, m.keyMap.PageFirst):
m.pageFirst()

case key.Matches(msg, m.keyMap.PageLast):
m.pageLast()

case key.Matches(msg, m.keyMap.Filter):
m.filterTextInput.Focus()
}
}

// Update responds to input from the user or other messages from Bubble Tea.
func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if !m.focused {
Expand All @@ -71,25 +99,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) {

switch msg := msg.(type) {
case tea.KeyMsg:
switch {
case key.Matches(msg, m.keyMap.RowDown):
m.moveHighlightDown()

case key.Matches(msg, m.keyMap.RowUp):
m.moveHighlightUp()

case key.Matches(msg, m.keyMap.RowSelectToggle):
m.toggleSelect()

case key.Matches(msg, m.keyMap.PageDown):
m.pageDown()

case key.Matches(msg, m.keyMap.PageUp):
m.pageUp()

case key.Matches(msg, m.keyMap.Filter):
m.filterTextInput.Focus()
}
m.handleKeypress(msg)
}

return m, nil
Expand Down
66 changes: 65 additions & 1 deletion table/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,56 @@ func TestUnfocusedDoesntMove(t *testing.T) {
assert.True(t, ok, "Failed to convert to string")

assert.Equal(t, "first", id, "Should still be on first row")

model, _ = model.Update(tea.KeyMsg{
Type: tea.KeyHome,
})
}

func TestPageKeysDoNothingWhenNoPages(t *testing.T) {
cols := []Column{
NewColumn("id", "ID", 3),
}

model := New(cols).WithRows([]Row{
NewRow(RowData{
"id": "first",
}),
NewRow(RowData{
"id": "second",
}),
NewRow(RowData{
"id": "third",
}),
}).Focused(true)

pageMoveKeys := []tea.Msg{
tea.KeyMsg{Type: tea.KeyLeft},
tea.KeyMsg{Type: tea.KeyRight},
tea.KeyMsg{Type: tea.KeyHome},
tea.KeyMsg{Type: tea.KeyEnd},
}

checkNoMove := func() string {
str, ok := model.HighlightedRow().Data["id"].(string)

assert.True(t, ok, "Failed to convert to string")

assert.Equal(t, "first", str, "Shouldn't move")

return str
}

for _, msg := range pageMoveKeys {
model, _ = model.Update(msg)
checkNoMove()
}
}

func TestFocusedMovesWhenArrowsPressed(t *testing.T) {
// This is a long test with a lot of movement keys pressed, that's okay because
// it's simply repetitive and tracking the same kind of state change many times
// nolint: funlen
func TestFocusedMovesWhenMoveKeysPressedPaged(t *testing.T) {
cols := []Column{
NewColumn("id", "ID", 3),
}
Expand All @@ -57,6 +104,8 @@ func TestFocusedMovesWhenArrowsPressed(t *testing.T) {
keyDown := tea.KeyMsg{Type: tea.KeyDown}
keyLeft := tea.KeyMsg{Type: tea.KeyLeft}
keyRight := tea.KeyMsg{Type: tea.KeyRight}
keyHome := tea.KeyMsg{Type: tea.KeyHome}
keyEnd := tea.KeyMsg{Type: tea.KeyEnd}

curID := func() string {
str, ok := model.HighlightedRow().Data["id"].(string)
Expand Down Expand Up @@ -91,6 +140,21 @@ func TestFocusedMovesWhenArrowsPressed(t *testing.T) {

model, _ = model.Update(keyLeft)
assert.Equal(t, "first", curID(), "Moving left should move back to first page")

model, _ = model.Update(keyDown)
assert.Equal(t, "second", curID(), "Should be back down to second row")

model, _ = model.Update(keyHome)
assert.Equal(t, "first", curID(), "Hitting home should go to first page and select first row")

model, _ = model.Update(keyHome)
assert.Equal(t, "first", curID(), "Hitting home a second time should not move pages")

model, _ = model.Update(keyEnd)
assert.Equal(t, "third", curID(), "Hitting end should move to last page")

model, _ = model.Update(keyEnd)
assert.Equal(t, "third", curID(), "Hitting end a second time should not move pages")
}

func TestFocusedMovesWithCustomKeyMap(t *testing.T) {
Expand Down

0 comments on commit 6525a3f

Please sign in to comment.