From b3d94e08b2437646df9795598c9b5e9e2a2998d0 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Sun, 9 Aug 2026 23:15:33 +0200 Subject: [PATCH] Draw the diff selection as a narrow bar rather than across the line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that a diff view always carries a selection, the highlight fights the diff itself for the line's colours. Painting the selection across the whole line takes over the background, and a selected hunk becomes one solid block with no boundary between what was removed and what replaced it — the more lines you select, the less you can read. This isn't specific to renderers like delta that say which side of the diff a line is on by colouring its background, though they suffer most: git's own output puts red and green text on that background, which reads badly too. Since there is no rendering of a diff that a full-width highlight doesn't degrade, there is nothing here worth configuring — the bar is simply what diff views use. Left edge only, and two columns wide: every convention for marking a row of coloured content — change bars, diff gutters, selection gutters — puts the marker on the left, and bracketing both edges reads as framing instead. Co-authored-by: Claude Opus 5 (1M context) --- pkg/gocui/view.go | 9 ++++++++- pkg/gui/views.go | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pkg/gocui/view.go b/pkg/gocui/view.go index e08ffd576..6f2ef869f 100644 --- a/pkg/gocui/view.go +++ b/pkg/gocui/view.go @@ -164,6 +164,12 @@ type View struct { // instead of Sel{Bg,Fg}Colors for highlighting selected lines. HighlightInactive bool + // If SelectedLineColorWidth is greater than zero, a highlighted line is painted + // in the selection colors on that many columns at its left edge only, rather + // than across its whole width, leaving the line's own colors to show through. + // For content that conveys meaning by color of its own. + SelectedLineColorWidth int + // If Frame is true, a border will be drawn around the view. Frame bool @@ -869,7 +875,8 @@ func (v *View) setCharacter(x, y int, ch string, fgColor, bgColor Attribute, isW rangeSelectEnd = max(relativeRangeSelectStart, v.cy) } - if y >= rangeSelectStart && y <= rangeSelectEnd { + colorWidth := v.SelectedLineColorWidth + if y >= rangeSelectStart && y <= rangeSelectEnd && (colorWidth == 0 || x < colorWidth) { fgColor = applySelTextColor(fgColor, v.SelTextColor) if v.HighlightInactive || !isWindowFocused { bgColor = (bgColor & AttrStyleBits) | v.InactiveViewSelBgColor diff --git a/pkg/gui/views.go b/pkg/gui/views.go index 2fb115f91..e73b18dfd 100644 --- a/pkg/gui/views.go +++ b/pkg/gui/views.go @@ -168,6 +168,15 @@ func (gui *Gui) createAllViews() error { gui.Views.Snake.FgColor = gocui.ColorGreen + // The main views show diffs, whose own colors say what each line is: which side of + // the diff it's on, and often its syntax highlighting too. A selection painted + // across the whole line takes those colors over, which for a whole selected hunk + // leaves one unreadable block; so mark the selection with a narrow bar at the left + // edge instead, and leave the rest of the line to the diff. Two columns, enough to + // read as a marker rather than as an artefact. + gui.Views.Main.SelectedLineColorWidth = 2 + gui.Views.Secondary.SelectedLineColorWidth = 2 + return nil }