Repository: Evertras/bubble-table
Pull request #65 (2022-04-19 13:20:00)

Add shortcut to clear filter and escape filtering
Escape key will now exit filtering, as well as clear the filter if not currently actively typing in the filter.  Clearing the filter is a configurable keymap.

This is theoretically a breaking change if someone was using the escape key along with table filtering and expected some other behavior, but this seems incredibly unlikely and the keymap can be redone in their application if this is the case.

Evertras: Helps #64 

Patch:
diff --git a/examples/filter/main.go b/examples/filter/main.go
index 71efab1..5ff19e0 100644
--- a/examples/filter/main.go
+++ b/examples/filter/main.go
@@ -71,7 +71,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	switch msg := msg.(type) {
 	case tea.KeyMsg:
 		switch msg.String() {
-		case "ctrl+c", "esc", "q":
+		case "ctrl+c", "q":
 			cmds = append(cmds, tea.Quit)
 		}
 
@@ -84,7 +84,7 @@ func (m Model) View() string {
 	body := strings.Builder{}
 
 	body.WriteString("A filtered simple default table\n" +
-		"Currently filter by Title and Author, press / to filter.\nPress q or ctrl+c to quit\n\n")
+		"Currently filter by Title and Author, press / + letters to start filtering, and escape to clear filter.\nPress q or ctrl+c to quit\n\n")
 
 	body.WriteString(m.table.View())
 
diff --git a/table/keys.go b/table/keys.go
index 3aa9fab..dbf4c1b 100644
--- a/table/keys.go
+++ b/table/keys.go
@@ -14,7 +14,14 @@ type KeyMap struct {
 	PageFirst key.Binding
 	PageLast  key.Binding
 
+	// Filter allows the user to start typing and filter the rows.
 	Filter key.Binding
+
+	// FilterBlur is the key that stops the user's input from typing into the filter.
+	FilterBlur key.Binding
+
+	// FilterClear will clear the filter while it's blurred.
+	FilterClear key.Binding
 }
 
 // DefaultKeyMap returns a set of sensible defaults for controlling a focused table.
@@ -44,5 +51,11 @@ func DefaultKeyMap() KeyMap {
 		Filter: key.NewBinding(
 			key.WithKeys("/"),
 		),
+		FilterBlur: key.NewBinding(
+			key.WithKeys("enter", "esc"),
+		),
+		FilterClear: key.NewBinding(
+			key.WithKeys("esc"),
+		),
 	}
 }
diff --git a/table/update.go b/table/update.go
index 23e71ef..227c4ea 100644
--- a/table/update.go
+++ b/table/update.go
@@ -50,7 +50,7 @@ func (m Model) updateFilterTextInput(msg tea.Msg) (Model, tea.Cmd) {
 	var cmd tea.Cmd
 	switch msg := msg.(type) {
 	case tea.KeyMsg:
-		if msg.Type == tea.KeyEnter {
+		if key.Matches(msg, m.keyMap.FilterBlur) {
 			m.filterTextInput.Blur()
 		}
 	}
@@ -84,6 +84,9 @@ func (m *Model) handleKeypress(msg tea.KeyMsg) {
 
 	case key.Matches(msg, m.keyMap.Filter):
 		m.filterTextInput.Focus()
+
+	case key.Matches(msg, m.keyMap.FilterClear):
+		m.filterTextInput.Reset()
 	}
 }
 


Test patch:
diff --git a/table/update_test.go b/table/update_test.go
index 7937910..b13ada8 100644
--- a/table/update_test.go
+++ b/table/update_test.go
@@ -293,6 +293,10 @@ func TestFilterWithKeypresses(t *testing.T) {
 		model, _ = model.Update(tea.KeyMsg{Type: tea.KeyEnter})
 	}
 
+	hitEscape := func() {
+		model, _ = model.Update(tea.KeyMsg{Type: tea.KeyEscape})
+	}
+
 	visible := model.GetVisibleRows()
 
 	assert.Len(t, visible, 2)
@@ -310,5 +314,13 @@ func TestFilterWithKeypresses(t *testing.T) {
 
 	hitKey('x')
 
+	visible = model.GetVisibleRows()
+
 	assert.Len(t, visible, 1)
+
+	hitEscape()
+
+	visible = model.GetVisibleRows()
+
+	assert.Len(t, visible, 2)
 }