mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-05 21:46:49 -04:00
Keep your place in the diff when switching diff renderers
Cycling through the diff renderers is for comparing how they show the same change, which is hard to do from the top of the diff each time. The line you were on is the same line of the same file whichever renderer draws it, so the restore finds it again — by the records a renderer states, where it speaks the protocol, and by parsing its output as a diff otherwise. The restore sits in DiffHelper.RenderToMainAgain. A switch between a dark and a light terminal background renders the diff again through the same helper, so it keeps your place as well. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0eeb8adcbf
commit
f1f5479d47
@@ -67,8 +67,8 @@ func (gui *Gui) resetHelpersAndControllers() {
|
||||
worktreeHelper,
|
||||
searchHelper,
|
||||
)
|
||||
diffHelper := helpers.NewDiffHelper(helperCommon)
|
||||
diffLineHelper := helpers.NewDiffLineHelper(helperCommon)
|
||||
diffHelper := helpers.NewDiffHelper(helperCommon, diffLineHelper)
|
||||
cherryPickHelper := helpers.NewCherryPickHelper(
|
||||
helperCommon,
|
||||
rebaseHelper,
|
||||
|
||||
@@ -14,12 +14,14 @@ import (
|
||||
)
|
||||
|
||||
type DiffHelper struct {
|
||||
c *HelperCommon
|
||||
c *HelperCommon
|
||||
diffLineHelper *DiffLineHelper
|
||||
}
|
||||
|
||||
func NewDiffHelper(c *HelperCommon) *DiffHelper {
|
||||
func NewDiffHelper(c *HelperCommon, diffLineHelper *DiffLineHelper) *DiffHelper {
|
||||
return &DiffHelper{
|
||||
c: c,
|
||||
c: c,
|
||||
diffLineHelper: diffLineHelper,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +109,11 @@ func (self *DiffHelper) RenderToMainAgain() {
|
||||
if currentSide.GetKey() == currentKey ||
|
||||
currentKey == context.NORMAL_MAIN_CONTEXT_KEY ||
|
||||
currentKey == context.NORMAL_SECONDARY_CONTEXT_KEY {
|
||||
// Whatever changed can make the diff come out differently, such as a new
|
||||
// renderer laying it out its own way, so the line you were looking at could
|
||||
// end up anywhere in the view; keep it in front of you.
|
||||
self.diffLineHelper.PreserveDiffPositionOnRerender(self.c.Contexts().Normal.GetView())
|
||||
self.diffLineHelper.PreserveDiffPositionOnRerender(self.c.Contexts().NormalSecondary.GetView())
|
||||
currentSide.HandleRenderToMain()
|
||||
}
|
||||
}
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package main_view
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var KeepPositionInBothPanesWhenSwitchingDiffRenderers = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Switching to another diff renderer keeps the place in the lower pane too, not only in the upper one",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
Width: 120,
|
||||
Height: 30,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Gui.UseHunkModeInStagingView = false
|
||||
// Renderers that speak the metadata protocol, so that focusing the main view
|
||||
// keeps their rendering rather than falling back to git's own diff.
|
||||
cfg.GetUserConfig().Git.DiffRenderers = []config.DiffRendererConfig{
|
||||
{Name: "plain", Command: `printf '\033]1717;1\007'; cat`},
|
||||
// The same diff, three lines further down the view. (Lines before the
|
||||
// diff's own header aren't part of it, so it still reads the same.)
|
||||
{Name: "banner", Command: `printf '\033]1717;1\007'; printf 'rendered for you\n\n\n'; cat`},
|
||||
}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
lines := make([]string, 40)
|
||||
for i := range lines {
|
||||
lines[i] = fmt.Sprintf("line%02d", i+1)
|
||||
}
|
||||
shell.CreateFileAndAdd("file1", strings.Join(lines, "\n")+"\n")
|
||||
shell.Commit("one")
|
||||
|
||||
// Four staged changes to have a diff worth scrolling in the lower pane, and one
|
||||
// unstaged one to split the file's diff across both panes.
|
||||
for _, i := range []int{5, 15, 25, 35} {
|
||||
lines[i-1] = strings.ToUpper(lines[i-1])
|
||||
}
|
||||
shell.UpdateFile("file1", strings.Join(lines, "\n")+"\n")
|
||||
shell.GitAddAll()
|
||||
|
||||
lines[39] = strings.ToUpper(lines[39])
|
||||
shell.UpdateFile("file1", strings.Join(lines, "\n")+"\n")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.FocusMainView)
|
||||
|
||||
t.Views().Main().
|
||||
IsFocused().
|
||||
PressTab()
|
||||
|
||||
t.Views().Secondary().
|
||||
IsFocused().
|
||||
Press(keys.Main.NextHunk).
|
||||
Press(keys.Main.NextHunk).
|
||||
Press(keys.Main.NextHunk).
|
||||
SelectedLines(
|
||||
Contains("-line35"),
|
||||
).
|
||||
SelectedLineIdx(35).
|
||||
OriginY(14).
|
||||
Press(keys.Universal.CycleDiffRenderers).
|
||||
Tap(func() {
|
||||
t.ExpectToast(Equals("Diff renderer: banner (2 of 2)"))
|
||||
}).
|
||||
// The banner pushed the whole diff three lines down, and the lower pane came
|
||||
// along with it, just as the upper one would have.
|
||||
SelectedLines(
|
||||
Contains("-line35"),
|
||||
).
|
||||
SelectedLineIdx(38).
|
||||
OriginY(17)
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,75 @@
|
||||
package main_view
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/config"
|
||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||
)
|
||||
|
||||
var KeepPositionWhenSwitchingDiffRenderers = NewIntegrationTest(NewIntegrationTestArgs{
|
||||
Description: "Switching to another diff renderer keeps the line you were looking at where it was",
|
||||
ExtraCmdArgs: []string{},
|
||||
Skip: false,
|
||||
Width: 120,
|
||||
Height: 30,
|
||||
SetupConfig: func(cfg *config.AppConfig) {
|
||||
cfg.GetUserConfig().Gui.UseHunkModeInStagingView = false
|
||||
cfg.GetUserConfig().Git.DiffRenderers = []config.DiffRendererConfig{
|
||||
{Name: "plain", Command: "cat"},
|
||||
// The same diff, three lines further down the view. (Lines before the
|
||||
// diff's own header aren't part of it, so it still reads the same.)
|
||||
{Name: "banner", Command: `printf 'rendered for you\n\n\n'; cat`},
|
||||
}
|
||||
},
|
||||
SetupRepo: func(shell *Shell) {
|
||||
lines := make([]string, 40)
|
||||
for i := range lines {
|
||||
lines[i] = fmt.Sprintf("line%02d", i+1)
|
||||
}
|
||||
shell.CreateFileAndAdd("file1", strings.Join(lines, "\n")+"\n")
|
||||
shell.Commit("one")
|
||||
|
||||
for _, i := range []int{5, 15, 25, 35} {
|
||||
lines[i-1] = strings.ToUpper(lines[i-1])
|
||||
}
|
||||
shell.UpdateFile("file1", strings.Join(lines, "\n")+"\n")
|
||||
},
|
||||
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||
t.Views().Files().
|
||||
IsFocused().
|
||||
Press(keys.Universal.FocusMainView)
|
||||
|
||||
t.Views().Main().
|
||||
IsFocused().
|
||||
Press(keys.Main.NextHunk).
|
||||
Press(keys.Main.NextHunk).
|
||||
Press(keys.Main.NextHunk).
|
||||
SelectedLines(
|
||||
Contains("-line35"),
|
||||
).
|
||||
SelectedLineIdx(35).
|
||||
OriginY(14).
|
||||
Press(keys.Universal.CycleDiffRenderers).
|
||||
Tap(func() {
|
||||
t.ExpectToast(Equals("Diff renderer: banner (2 of 2)"))
|
||||
}).
|
||||
// The banner pushed the whole diff three lines down, and the view came
|
||||
// along with it: the same line on the same screen row (38 - 17 = 21).
|
||||
SelectedLines(
|
||||
Contains("-line35"),
|
||||
).
|
||||
SelectedLineIdx(38).
|
||||
OriginY(17).
|
||||
Press(keys.Universal.CycleDiffRenderers).
|
||||
Tap(func() {
|
||||
t.ExpectToast(Equals("Diff renderer: plain (1 of 2)"))
|
||||
}).
|
||||
SelectedLines(
|
||||
Contains("-line35"),
|
||||
).
|
||||
SelectedLineIdx(35).
|
||||
OriginY(14)
|
||||
},
|
||||
})
|
||||
@@ -372,7 +372,9 @@ var tests = []*components.IntegrationTest{
|
||||
main_view.FileNavigationScrollsToTheTop,
|
||||
main_view.HideSelectionWhenChangesVanish,
|
||||
main_view.KeepPositionInBothPanesWhenChangingContextSize,
|
||||
main_view.KeepPositionInBothPanesWhenSwitchingDiffRenderers,
|
||||
main_view.KeepPositionWhenChangingContextSize,
|
||||
main_view.KeepPositionWhenSwitchingDiffRenderers,
|
||||
main_view.KeepPositionWhenTheSelectionIsOffScreen,
|
||||
main_view.KeepScrollWhenTheDiffCantBeRead,
|
||||
main_view.KeepSelectionVisibleWhenDiffShrinks,
|
||||
|
||||
Reference in New Issue
Block a user