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..6f5fe06 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, "" @@ -494,8 +494,8 @@ func (m Model) didSelectFile(msg tea.Msg) (bool, string) { return true, m.Path } - // If the msg was not a KeyMsg, then the file could not have been selected this iteration. - // Only a KeyMsg can select a file. + // If the msg was not a KeyPressMsg, then the file could not have been selected this iteration. + // Only a KeyPressMsg can select a file. default: return false, "" } diff --git a/go.mod b/go.mod index 2815703..708f031 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/atotto/clipboard v0.1.4 - github.com/charmbracelet/bubbletea v1.1.0 + github.com/charmbracelet/bubbletea v1.1.1-0.20240830154658-85c5adc127b3 github.com/charmbracelet/harmonica v0.2.0 github.com/charmbracelet/lipgloss v0.13.0 github.com/charmbracelet/x/ansi v0.2.3 @@ -22,12 +22,14 @@ require ( github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymanbagabas/go-udiff v0.2.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 github.com/mattn/go-localereader v0.0.1 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.24.0 // indirect golang.org/x/text v0.3.8 // indirect diff --git a/go.sum b/go.sum index 9eb7dd6..87a9d9e 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,8 @@ 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 v1.1.0 h1:FjAl9eAL3HBCHenhz/ZPjkKdScmaS5SK69JAK2YJK9c= github.com/charmbracelet/bubbletea v1.1.0/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4= +github.com/charmbracelet/bubbletea v1.1.1-0.20240830154658-85c5adc127b3 h1:oqDwkNLoIVbOjX0ZomkPljMtRKZvJMpYkR1A68QcbJo= +github.com/charmbracelet/bubbletea v1.1.1-0.20240830154658-85c5adc127b3/go.mod h1:RYka31SjvShLlaYsbsBSiXnneU2JUEoKvI3nrOUaJuw= 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.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw= @@ -18,6 +20,8 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b h1:MnAM github.com/charmbracelet/x/exp/golden v0.0.0-20240815200342-61de596daa2b/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= 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.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= @@ -43,6 +47,8 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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 de05a85..7b8715f 100644 --- a/paginator/paginator.go +++ b/paginator/paginator.go @@ -175,7 +175,7 @@ func WithPerPage(perPage int) Option { // 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/paginator/paginator_test.go b/paginator/paginator_test.go index 679e682..4243a19 100644 --- a/paginator/paginator_test.go +++ b/paginator/paginator_test.go @@ -76,7 +76,7 @@ func TestPrevPage(t *testing.T) { model.SetTotalPages(tt.totalPages) model.Page = tt.page - model, _ = model.Update(tea.KeyMsg{Type: tea.KeyLeft, Alt: false, Runes: []rune{}}) + model, _ = model.Update(tea.KeyPressMsg{Code: tea.KeyLeft}) if model.Page != tt.expected { t.Errorf("PrevPage() = %d, expected %d", model.Page, tt.expected) } @@ -101,7 +101,7 @@ func TestNextPage(t *testing.T) { model.SetTotalPages(tt.totalPages) model.Page = tt.page - model, _ = model.Update(tea.KeyMsg{Type: tea.KeyRight, Alt: false, Runes: []rune{}}) + model, _ = model.Update(tea.KeyPressMsg{Code: tea.KeyRight}) if model.Page != tt.expected { t.Errorf("NextPage() = %d, expected %d", model.Page, tt.expected) } diff --git a/progress/progress.go b/progress/progress.go index defa981..be5b16b 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -205,8 +205,8 @@ func New(opts ...Option) Model { var NewModel = New // Init exists to satisfy the tea.Model interface. -func (m Model) Init() tea.Cmd { - return nil +func (m Model) Init() (tea.Model, tea.Cmd) { + return m, nil } // Update is used to animate the progress bar during transitions. Use 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..a825bd0 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])) @@ -1060,7 +1060,7 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.transposeLeft() default: - m.insertRunesFromUserInput(msg.Runes) + m.insertRunesFromUserInput([]rune(msg.Text)) } case pasteMsg: diff --git a/textarea/textarea_test.go b/textarea/textarea_test.go index 41d626c..ed52180 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{Code: tea.KeyDown} 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{Code: tea.KeyUp} 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{Code: tea.KeyDown} 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{Code: tea.KeyLeft} 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{Code: key, Text: string(key)} } func sendString(m Model, str string) Model { diff --git a/textinput/textinput.go b/textinput/textinput.go index 93bc150..ec7a7c9 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() @@ -616,13 +616,16 @@ func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { m.previousSuggestion() default: // Input one or more regular characters. - m.insertRunesFromUserInput(msg.Runes) + m.insertRunesFromUserInput([]rune(msg.Text)) } // Check again if can be completed // 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..cb026c7 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,22 +331,23 @@ func (m Model) updateAsModel(msg tea.Msg) (Model, tea.Cmd) { } } - case tea.MouseMsg: - if !m.MouseWheelEnabled || msg.Action != tea.MouseActionPress { + case tea.MouseWheelMsg: + if !m.MouseWheelEnabled { break } - switch msg.Button { - case tea.MouseButtonWheelUp: - lines := m.LineUp(m.MouseWheelDelta) - if m.HighPerformanceRendering { - cmd = ViewUp(m, lines) - } - case tea.MouseButtonWheelDown: + switch msg.Button { + case tea.MouseWheelDown: lines := m.LineDown(m.MouseWheelDelta) if m.HighPerformanceRendering { cmd = ViewDown(m, lines) } + + case tea.MouseWheelUp: + lines := m.LineUp(m.MouseWheelDelta) + if m.HighPerformanceRendering { + cmd = ViewUp(m, lines) + } } }