From f3227207f0ce58865e8678a86c4097a2f2874ff5 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Mon, 4 May 2026 14:29:41 +0300 Subject: [PATCH 1/2] feat: toggle mouse capture with M to enable text selection Bind M to flip the bubbletea MouseMode between AllMotion and None. While off, the terminal regains native click-and-drag selection so users can copy diff lines (e.g. when reviewing changes via --watch). A "mouse off" indicator is shown in the footer alongside the existing watch label. --- README.md | 5 +++++ pkg/ui/keys.go | 6 ++++++ pkg/ui/tui.go | 17 ++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6d79886..edbd6a4 100644 --- a/README.md +++ b/README.md @@ -226,9 +226,14 @@ If you want the exact delta configuration I'm using - [it can be found here](htt | i | Cycle icon style | | o | Open file in $EDITOR | | s | Toggle side-by-side/unified view | +| M | Toggle mouse capture (for native text selection / copy) | | Tab | Switch focus between the panes | | q | Quit | +While mouse capture is on, your terminal can't do its native click-and-drag selection. Press M to release the mouse so you can select and copy lines from the diff (the footer shows `mouse off`); press M again to restore mouse scroll/click. Tip: in side-by-side mode the selection spans both columns — switch to unified with s first, or use your terminal's block-select modifier (Option+drag in iTerm2 / Terminal.app, Alt+drag in many Linux terminals). + +Most terminals (iTerm2, Terminal.app, Alacritty, kitty, WezTerm, GNOME Terminal) also let you hold Shift while dragging to bypass mouse capture without toggling. + ## Discord Have questions? Join our [Discord community](https://discord.gg/SXNXp9NctV)! diff --git a/pkg/ui/keys.go b/pkg/ui/keys.go index 32bb9be..114a8fc 100644 --- a/pkg/ui/keys.go +++ b/pkg/ui/keys.go @@ -24,6 +24,7 @@ type KeyMap struct { ToggleIconStyle key.Binding ToggleHelp key.Binding ToggleMessage key.Binding + ToggleMouse key.Binding } var keys = &KeyMap{ @@ -111,6 +112,10 @@ var keys = &KeyMap{ key.WithKeys("m"), key.WithHelp("m", "commit info"), ), + ToggleMouse: key.NewBinding( + key.WithKeys("M"), + key.WithHelp("M", "toggle mouse (text select)"), + ), } func KeyGroups() [][]key.Binding { @@ -133,6 +138,7 @@ func KeyGroups() [][]key.Binding { keys.ToggleIconStyle, }, { keys.ToggleMessage, + keys.ToggleMouse, keys.ToggleHelp, keys.Quit, }} diff --git a/pkg/ui/tui.go b/pkg/ui/tui.go index feb7bda..e4d4b34 100644 --- a/pkg/ui/tui.go +++ b/pkg/ui/tui.go @@ -95,6 +95,7 @@ type mainModel struct { pendingCursorPath string watchInFlight bool repoRoot string + mouseDisabled bool } func New(input string, cfg config.Config) mainModel { @@ -255,6 +256,10 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.search.SetWidth(m.searchWidth()) dfCmd := m.diffViewer.SetSize(m.width-sidebarWidth, h) cmds = append(cmds, dfCmd) + case key.Matches(msg, keys.ToggleMouse): + m.mouseDisabled = !m.mouseDisabled + m.draggingSidebar = false + return m, tea.Batch(cmds...) case key.Matches(msg, keys.ToggleIconStyle): m.cycleIconStyle() case key.Matches(msg, keys.ToggleDiffView): @@ -488,7 +493,11 @@ func (m mainModel) searchUpdate(msg tea.Msg) (mainModel, []tea.Cmd) { func (m mainModel) View() tea.View { var view tea.View view.AltScreen = true - view.MouseMode = tea.MouseModeAllMotion + if m.mouseDisabled { + view.MouseMode = tea.MouseModeNone + } else { + view.MouseMode = tea.MouseModeAllMotion + } view.KeyboardEnhancements.ReportEventTypes = true // Determine colors based on active panel. @@ -826,6 +835,12 @@ func (m mainModel) footerView() string { usedWidth += lipgloss.Width(sep) + lipgloss.Width(watchLabel) } + if m.mouseDisabled { + mouseLabel := base.Foreground(lipgloss.Yellow).Render("mouse off") + parts = append(parts, sep, mouseLabel) + usedWidth += lipgloss.Width(sep) + lipgloss.Width(mouseLabel) + } + spacing := base.Render(strings.Repeat(" ", max(0, m.width-usedWidth))) parts = append(parts, spacing, help) return base. From 11348140daf6e94565694810d34ab37f74e6fb36 Mon Sep 17 00:00:00 2001 From: Janne Sinivirta Date: Mon, 4 May 2026 14:47:45 +0300 Subject: [PATCH 2/2] refactor: bind visual select to v and label footer 'visual select' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switches the toggle from M (awkward shift+m next to lowercase m for commit info) to v, mirroring vim's visual-select mnemonic. Renames the footer indicator from 'mouse off' to 'visual select' since users press the key to *enable* mouse-driven text selection — 'mouse off' described the underlying capture state but read as a regression. --- README.md | 4 ++-- pkg/ui/keys.go | 4 ++-- pkg/ui/tui.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index edbd6a4..7c37aa9 100644 --- a/README.md +++ b/README.md @@ -226,11 +226,11 @@ If you want the exact delta configuration I'm using - [it can be found here](htt | i | Cycle icon style | | o | Open file in $EDITOR | | s | Toggle side-by-side/unified view | -| M | Toggle mouse capture (for native text selection / copy) | +| v | Visual select mode (release mouse for native text selection / copy) | | Tab | Switch focus between the panes | | q | Quit | -While mouse capture is on, your terminal can't do its native click-and-drag selection. Press M to release the mouse so you can select and copy lines from the diff (the footer shows `mouse off`); press M again to restore mouse scroll/click. Tip: in side-by-side mode the selection spans both columns — switch to unified with s first, or use your terminal's block-select modifier (Option+drag in iTerm2 / Terminal.app, Alt+drag in many Linux terminals). +While mouse capture is on, your terminal can't do its native click-and-drag selection. Press v to enter visual select mode — this releases the mouse so you can select and copy lines from the diff (the footer shows `visual select`); press v again to restore mouse scroll/click. Tip: in side-by-side mode the selection spans both columns — switch to unified with s first, or use your terminal's block-select modifier (Option+drag in iTerm2 / Terminal.app, Alt+drag in many Linux terminals). Most terminals (iTerm2, Terminal.app, Alacritty, kitty, WezTerm, GNOME Terminal) also let you hold Shift while dragging to bypass mouse capture without toggling. diff --git a/pkg/ui/keys.go b/pkg/ui/keys.go index 114a8fc..77183a9 100644 --- a/pkg/ui/keys.go +++ b/pkg/ui/keys.go @@ -113,8 +113,8 @@ var keys = &KeyMap{ key.WithHelp("m", "commit info"), ), ToggleMouse: key.NewBinding( - key.WithKeys("M"), - key.WithHelp("M", "toggle mouse (text select)"), + key.WithKeys("v"), + key.WithHelp("v", "visual select"), ), } diff --git a/pkg/ui/tui.go b/pkg/ui/tui.go index e4d4b34..ea35993 100644 --- a/pkg/ui/tui.go +++ b/pkg/ui/tui.go @@ -836,7 +836,7 @@ func (m mainModel) footerView() string { } if m.mouseDisabled { - mouseLabel := base.Foreground(lipgloss.Yellow).Render("mouse off") + mouseLabel := base.Foreground(lipgloss.Yellow).Render("visual select") parts = append(parts, sep, mouseLabel) usedWidth += lipgloss.Width(sep) + lipgloss.Width(mouseLabel) }