mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-12 16:46:25 -04:00
Anchor a drag-selection at the clicked line in the focused main view
Click-and-drag in the focused main view turns a hunk selection into a range, but it was anchored at the change block's far end — where selecting a hunk leaves the range anchor — rather than the clicked line. And on a context line, where the click leaves no range anchor at all, dragging just moved the single selected line instead of opening a range. Remember the line each mouse-down lands on (the click can show a whole hunk, so it can't be read back from the view) and, as the drag proceeds, anchor the range there while the cursor end follows the mouse as gocui already moves it. Works for a click that focuses the view and for one while it's already focused, on change and context lines alike. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
79ce7f3382
commit
96fa098845
|
|
@ -10,6 +10,10 @@ type MainContext struct {
|
|||
*SearchTrait
|
||||
|
||||
diffSelect DiffSelectState
|
||||
// dragAnchorViewLine is the view line a mouse-down landed on, remembered so a drag
|
||||
// that follows can anchor its range there. The click can show a whole hunk (a range
|
||||
// with a different anchor), so the clicked line can't be read back from the view.
|
||||
dragAnchorViewLine int
|
||||
}
|
||||
|
||||
var _ types.ISearchableContext = (*MainContext)(nil)
|
||||
|
|
@ -48,6 +52,17 @@ func (self *MainContext) DiffSelectState() *DiffSelectState {
|
|||
return &self.diffSelect
|
||||
}
|
||||
|
||||
// SetDragAnchorViewLine records the view line a mouse-down landed on, so a drag that
|
||||
// follows can anchor its range there (see dragAnchorViewLine).
|
||||
func (self *MainContext) SetDragAnchorViewLine(viewLine int) {
|
||||
self.dragAnchorViewLine = viewLine
|
||||
}
|
||||
|
||||
// DragAnchorViewLine returns the view line the last mouse-down landed on.
|
||||
func (self *MainContext) DragAnchorViewLine() int {
|
||||
return self.dragAnchorViewLine
|
||||
}
|
||||
|
||||
func NewMainContext(
|
||||
view *gocui.View,
|
||||
windowName string,
|
||||
|
|
|
|||
|
|
@ -182,6 +182,14 @@ func (self *MainViewController) GetMouseKeybindings(opts types.KeybindingsOpts)
|
|||
Handler: self.onClickInOtherViewOfMainViewPair,
|
||||
FocusedView: self.otherContext.GetViewName(),
|
||||
},
|
||||
{
|
||||
// Dragging after a click extends a range selection from the clicked line.
|
||||
ViewName: self.context.GetViewName(),
|
||||
Key: gocui.MouseLeft,
|
||||
Modifier: gocui.ModMotion,
|
||||
Handler: self.onDragInFocusedView,
|
||||
FocusedView: self.context.GetViewName(),
|
||||
},
|
||||
{
|
||||
// Alt- or shift-click anywhere on a diff line opens it in the editor,
|
||||
// without focusing the view or creating a selection. Two modifiers
|
||||
|
|
@ -296,6 +304,9 @@ func placeOrHideInitialDiffSelection(c *ControllerCommon, mainContext *context.M
|
|||
return
|
||||
}
|
||||
if clickedViewLine >= 0 {
|
||||
// Remember where the click landed so a drag that follows anchors its range there,
|
||||
// even when the click selects a whole hunk (whose anchor is the block's far end).
|
||||
mainContext.SetDragAnchorViewLine(clickedViewLine)
|
||||
if c.UserConfig().Gui.UseHunkModeInStagingView && c.Helpers().Staging.IsChangeLine(view, clickedViewLine) {
|
||||
mainContext.DiffSelectState().Mode = context.DiffSelectModeHunk
|
||||
selectDiffHunk(c, mainContext, clickedViewLine)
|
||||
|
|
@ -998,6 +1009,9 @@ func (self *MainViewController) selectClickedDiffLine(opts gocui.ViewMouseBindin
|
|||
return nil
|
||||
}
|
||||
view := self.context.GetView()
|
||||
// Remember where the click landed so a drag that follows anchors its range there,
|
||||
// even when this click selects a whole hunk (whose anchor is the block's far end).
|
||||
self.context.SetDragAnchorViewLine(opts.Y)
|
||||
if self.sel().Mode == context.DiffSelectModeHunk && self.c.Helpers().Staging.IsChangeLine(view, opts.Y) {
|
||||
self.selectHunkAround(opts.Y)
|
||||
} else {
|
||||
|
|
@ -1010,6 +1024,25 @@ func (self *MainViewController) selectClickedDiffLine(opts gocui.ViewMouseBindin
|
|||
return nil
|
||||
}
|
||||
|
||||
// onDragInFocusedView extends a range selection as the mouse is dragged after a click,
|
||||
// anchored at the line the click landed on (DragAnchorViewLine) — not wherever the click
|
||||
// left the selection, since a click can select a whole hunk whose far end would otherwise
|
||||
// become the anchor. Dragging turns hunk mode off: you get a plain range from the clicked
|
||||
// line to the line under the cursor, which gocui has already moved here. A no-op when the
|
||||
// view holds no selectable diff.
|
||||
func (self *MainViewController) onDragInFocusedView(gocui.ViewMouseBindingOpts) error {
|
||||
view := self.context.GetView()
|
||||
if !self.isDiffView() || !view.Highlight {
|
||||
return nil
|
||||
}
|
||||
sel := self.sel()
|
||||
sel.Mode = context.DiffSelectModeRange
|
||||
sel.RangeIsSticky = false
|
||||
sel.UserEnabledHunkMode = false
|
||||
view.SetRangeSelectStart(self.context.DragAnchorViewLine())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *MainViewController) openSearch() error {
|
||||
if manager := self.c.GetViewBufferManagerForView(self.context.GetView()); manager != nil {
|
||||
manager.ReadToEnd(func() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue