From 111fcdb9a857a9747ff0c6fcaac35a4deeb98abc Mon Sep 17 00:00:00 2001 From: Ayman Bagabas Date: Mon, 22 Jul 2024 14:57:15 -0400 Subject: [PATCH] feat!: use new bubbletea input api --- README.md | 2 +- filepicker/filepicker.go | 4 ++-- go.mod | 10 +++++----- go.sum | 14 ++++++++++++-- key/key.go | 2 +- list/list.go | 6 +++--- paginator/paginator.go | 2 +- table/table.go | 2 +- textarea/textarea.go | 5 ++++- textarea/textarea_test.go | 10 +++++----- textinput/textinput.go | 7 +++++-- viewport/viewport.go | 11 ++++------- 12 files changed, 44 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index f6e4d21..b0a021f 100644 --- a/README.md +++ b/README.md @@ -185,7 +185,7 @@ var DefaultKeyMap = KeyMap{ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, DefaultKeyMap.Up): // The user pressed up diff --git a/filepicker/filepicker.go b/filepicker/filepicker.go index 9a1235a..3f06921 100644 --- a/filepicker/filepicker.go +++ b/filepicker/filepicker.go @@ -254,7 +254,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.Height = msg.Height - marginBottom } m.max = m.Height - 1 - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.GoToTop): m.selected = 0 @@ -463,7 +463,7 @@ func (m Model) didSelectFile(msg tea.Msg) (bool, string) { return false, "" } switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: // If the msg does not match the Select keymap then this could not have been a selection. if !key.Matches(msg, m.KeyMap.Select) { return false, "" diff --git a/go.mod b/go.mod index 57141d9..7cc3885 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,10 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbletea v0.27.0 + github.com/charmbracelet/bubbletea v0.27.1-0.20240822171457-833cc7865cbf github.com/charmbracelet/harmonica v0.2.0 - github.com/charmbracelet/lipgloss v0.12.1 - github.com/charmbracelet/x/ansi v0.1.4 + github.com/charmbracelet/lipgloss v0.13.0 + github.com/charmbracelet/x/ansi v0.2.3 github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b github.com/dustin/go-humanize v1.0.1 github.com/lucasb-eyer/go-colorful v1.2.0 @@ -22,8 +22,8 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.0 // indirect github.com/charmbracelet/x/input v0.1.0 // indirect - github.com/charmbracelet/x/term v0.1.1 // indirect - github.com/charmbracelet/x/windows v0.1.0 // indirect + github.com/charmbracelet/x/term v0.2.0 // indirect + github.com/charmbracelet/x/windows v0.2.0 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index a6bd9e9..cff9fce 100644 --- a/go.sum +++ b/go.sum @@ -8,20 +8,30 @@ github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWp github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/charmbracelet/bubbletea v0.27.0 h1:Mznj+vvYuYagD9Pn2mY7fuelGvP0HAXtZYGgRBCbHvU= github.com/charmbracelet/bubbletea v0.27.0/go.mod h1:5MdP9XH6MbQkgGhnlxUqCNmBXf9I74KRQ8HIidRxV1Y= +github.com/charmbracelet/bubbletea v0.27.1-0.20240822171457-833cc7865cbf h1:ikOQDpp9yCkJJ0N7XHqnkSXq7hf1NA4jnVCwbJFZw7s= +github.com/charmbracelet/bubbletea v0.27.1-0.20240822171457-833cc7865cbf/go.mod h1:83gxYOCiWJ5xJjxGj4bxaRA7SvntKUl0XVid/+tuF9E= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= +github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY= github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY= +github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAMdlwSltxJyULnrYbkZpp4k58Co7Tah3ciKhSNo0Q= github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/charmbracelet/x/input v0.1.0 h1:TEsGSfZYQyOtp+STIjyBq6tpRaorH0qpwZUj8DavAhQ= github.com/charmbracelet/x/input v0.1.0/go.mod h1:ZZwaBxPF7IG8gWWzPUVqHEtWhc1+HXJPNuerJGRGZ28= github.com/charmbracelet/x/term v0.1.1 h1:3cosVAiPOig+EV4X9U+3LDgtwwAoEzJjNdwbXDjF6yI= github.com/charmbracelet/x/term v0.1.1/go.mod h1:wB1fHt5ECsu3mXYusyzcngVWWlu1KKUmmLhfgr/Flxw= -github.com/charmbracelet/x/windows v0.1.0 h1:gTaxdvzDM5oMa/I2ZNF7wN78X/atWemG9Wph7Ika2k4= -github.com/charmbracelet/x/windows v0.1.0/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= +github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= +github.com/charmbracelet/x/windows v0.1.2 h1:Iumiwq2G+BRmgoayww/qfcvof7W/3uLoelhxojXlRWg= +github.com/charmbracelet/x/windows v0.1.2/go.mod h1:GLEO/l+lizvFDBPLIOk+49gdX49L9YWMB5t+DZd0jkQ= +github.com/charmbracelet/x/windows v0.2.0 h1:ilXA1GJjTNkgOm94CLPeSz7rar54jtFatdmoiONPuEw= +github.com/charmbracelet/x/windows v0.2.0/go.mod h1:ZibNFR49ZFqCXgP76sYanisxRyC+EYrBE7TTknD8s1s= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= diff --git a/key/key.go b/key/key.go index 0682665..0c79a7a 100644 --- a/key/key.go +++ b/key/key.go @@ -20,7 +20,7 @@ // // func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // switch msg := msg.(type) { -// case tea.KeyMsg: +// case tea.KeyPressMsg: // switch { // case key.Matches(msg, DefaultKeyMap.Up): // // The user pressed up diff --git a/list/list.go b/list/list.go index 17e6e15..8d5fb50 100644 --- a/list/list.go +++ b/list/list.go @@ -771,7 +771,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { var cmds []tea.Cmd switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: if key.Matches(msg, m.KeyMap.ForceQuit) { return m, tea.Quit } @@ -806,7 +806,7 @@ func (m *Model) handleBrowsing(msg tea.Msg) tea.Cmd { numItems := len(m.VisibleItems()) switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { // Note: we match clear filter before quit because, by default, they're // both mapped to escape. @@ -875,7 +875,7 @@ func (m *Model) handleFiltering(msg tea.Msg) tea.Cmd { var cmds []tea.Cmd // Handle keys - if msg, ok := msg.(tea.KeyMsg); ok { + if msg, ok := msg.(tea.KeyPressMsg); ok { switch { case key.Matches(msg, m.KeyMap.CancelWhileFiltering): m.resetFiltering() diff --git a/paginator/paginator.go b/paginator/paginator.go index 82dc3ed..87e777a 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -152,7 +152,7 @@ var NewModel = New // Update is the Tea update function which binds keystrokes to pagination. func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.NextPage): m.NextPage() diff --git a/table/table.go b/table/table.go index 6103c83..3b931ff 100644 --- a/table/table.go +++ b/table/table.go @@ -205,7 +205,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.LineUp): m.MoveUp(1) diff --git a/textarea/textarea.go b/textarea/textarea.go index 153f39e..34c6f93 100644 --- a/textarea/textarea.go +++ b/textarea/textarea.go @@ -973,7 +973,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.DeleteAfterCursor): m.col = clamp(m.col, 0, len(m.value[m.row])) @@ -1063,6 +1063,9 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.insertRunesFromUserInput(msg.Runes) } + case tea.PasteMsg: + m.insertRunesFromUserInput([]rune(msg)) + case pasteMsg: m.insertRunesFromUserInput([]rune(msg)) diff --git a/textarea/textarea_test.go b/textarea/textarea_test.go index 41d626c..fa18f4b 100644 --- a/textarea/textarea_test.go +++ b/textarea/textarea_test.go @@ -234,7 +234,7 @@ func TestVerticalNavigationKeepsCursorHorizontalPosition(t *testing.T) { t.Fatal("Expected cursor to be on the fourth character because there are two double width runes on the first line.") } - downMsg := tea.KeyMsg{Type: tea.KeyDown, Alt: false, Runes: []rune{}} + downMsg := tea.KeyPressMsg{Type: tea.KeyDown, Runes: []rune{}} textarea, _ = textarea.Update(downMsg) lineInfo = textarea.LineInfo() @@ -273,7 +273,7 @@ func TestVerticalNavigationShouldRememberPositionWhileTraversing(t *testing.T) { } // Let's go up. - upMsg := tea.KeyMsg{Type: tea.KeyUp, Alt: false, Runes: []rune{}} + upMsg := tea.KeyPressMsg{Type: tea.KeyUp, Runes: []rune{}} textarea, _ = textarea.Update(upMsg) // We should be at the end of the second line. @@ -292,7 +292,7 @@ func TestVerticalNavigationShouldRememberPositionWhileTraversing(t *testing.T) { } // Let's go down, twice. - downMsg := tea.KeyMsg{Type: tea.KeyDown, Alt: false, Runes: []rune{}} + downMsg := tea.KeyPressMsg{Type: tea.KeyDown, Runes: []rune{}} textarea, _ = textarea.Update(downMsg) textarea, _ = textarea.Update(downMsg) @@ -308,7 +308,7 @@ func TestVerticalNavigationShouldRememberPositionWhileTraversing(t *testing.T) { // work. textarea, _ = textarea.Update(upMsg) - leftMsg := tea.KeyMsg{Type: tea.KeyLeft, Alt: false, Runes: []rune{}} + leftMsg := tea.KeyPressMsg{Type: tea.KeyLeft, Runes: []rune{}} textarea, _ = textarea.Update(leftMsg) if textarea.col != 4 || textarea.row != 1 { @@ -1716,7 +1716,7 @@ func newTextArea() Model { } func keyPress(key rune) tea.Msg { - return tea.KeyMsg{Type: tea.KeyRunes, Runes: []rune{key}, Alt: false} + return tea.KeyPressMsg{Type: tea.KeyRunes, Runes: []rune{key}} } func sendString(m Model, str string) Model { diff --git a/textinput/textinput.go b/textinput/textinput.go index 93bc150..bef5f41 100644 --- a/textinput/textinput.go +++ b/textinput/textinput.go @@ -555,7 +555,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { } // Need to check for completion before, because key is configurable and might be double assigned - keyMsg, ok := msg.(tea.KeyMsg) + keyMsg, ok := msg.(tea.KeyPressMsg) if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) { if m.canAcceptSuggestion() { m.value = append(m.value, m.matchedSuggestions[m.currentSuggestionIndex][len(m.value):]...) @@ -568,7 +568,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { oldPos := m.pos //nolint switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.DeleteWordBackward): m.deleteWordBackward() @@ -623,6 +623,9 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { // because value might be something that does not match the completion prefix m.updateSuggestions() + case tea.PasteMsg: + m.insertRunesFromUserInput([]rune(msg)) + case pasteMsg: m.insertRunesFromUserInput([]rune(msg)) diff --git a/viewport/viewport.go b/viewport/viewport.go index e0a4cc3..81d0d40 100644 --- a/viewport/viewport.go +++ b/viewport/viewport.go @@ -292,7 +292,7 @@ func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { - case tea.KeyMsg: + case tea.KeyPressMsg: switch { case key.Matches(msg, m.KeyMap.PageDown): lines := m.ViewDown() @@ -331,18 +331,15 @@ func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) { } } - case tea.MouseMsg: - if !m.MouseWheelEnabled || msg.Action != tea.MouseActionPress { - break - } + case tea.MouseWheelMsg: switch msg.Button { - case tea.MouseButtonWheelUp: + case tea.MouseWheelUp: lines := m.LineUp(m.MouseWheelDelta) if m.HighPerformanceRendering { cmd = ViewUp(m, lines) } - case tea.MouseButtonWheelDown: + case tea.MouseWheelDown: lines := m.LineDown(m.MouseWheelDelta) if m.HighPerformanceRendering { cmd = ViewDown(m, lines)