Skip to content

Commit bdff0c8

Browse files
committed
WIP
1 parent 71bc6a1 commit bdff0c8

File tree

10 files changed

+164
-15
lines changed

10 files changed

+164
-15
lines changed

pkg/commands/patch/patch.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,38 @@ func (self *Patch) LineNumberOfLine(idx int) int {
105105
return hunk.newStart + offset
106106
}
107107

108+
// Takes a line number in the new file and returns the line index in the patch.
109+
// This is the opposite of LineNumberOfLine.
110+
// If the line number is not contained in any of the hunks, it returns the
111+
// closest position.
112+
func (self *Patch) PatchLineForLineNumber(lineNumber int) int {
113+
if len(self.hunks) == 0 {
114+
return len(self.header)
115+
}
116+
117+
for hunkIdx, hunk := range self.hunks {
118+
if lineNumber <= hunk.newStart {
119+
return self.HunkStartIdx(hunkIdx)
120+
}
121+
122+
if lineNumber < hunk.newStart+hunk.newLength() {
123+
lines := hunk.bodyLines
124+
offset := lineNumber - hunk.newStart
125+
for i, line := range lines {
126+
if offset == 0 {
127+
return self.HunkStartIdx(hunkIdx) + i + 1
128+
}
129+
130+
if line.Kind == ADDITION || line.Kind == CONTEXT {
131+
offset--
132+
}
133+
}
134+
}
135+
}
136+
137+
return self.LineCount() - 1
138+
}
139+
108140
// Returns hunk index containing the line at the given patch line index
109141
func (self *Patch) HunkContainingLine(idx int) int {
110142
for hunkIdx, hunk := range self.hunks {

pkg/gui/controllers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ func (gui *Gui) resetHelpersAndControllers() {
5555

5656
gpgHelper := helpers.NewGpgHelper(helperCommon)
5757
viewHelper := helpers.NewViewHelper(helperCommon, gui.State.Contexts)
58+
windowHelper := helpers.NewWindowHelper(helperCommon, viewHelper)
5859
patchBuildingHelper := helpers.NewPatchBuildingHelper(helperCommon)
59-
stagingHelper := helpers.NewStagingHelper(helperCommon)
60+
stagingHelper := helpers.NewStagingHelper(helperCommon, windowHelper)
6061
mergeConflictsHelper := helpers.NewMergeConflictsHelper(helperCommon)
6162
searchHelper := helpers.NewSearchHelper(helperCommon)
6263

@@ -76,7 +77,6 @@ func (gui *Gui) resetHelpersAndControllers() {
7677
rebaseHelper,
7778
)
7879
bisectHelper := helpers.NewBisectHelper(helperCommon)
79-
windowHelper := helpers.NewWindowHelper(helperCommon, viewHelper)
8080
modeHelper := helpers.NewModeHelper(
8181
helperCommon,
8282
diffHelper,

pkg/gui/controllers/commits_files_controller.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package controllers
22

33
import (
44
"errors"
5+
"path/filepath"
56
"strings"
67

78
"github.com/jesseduffield/gocui"
@@ -136,6 +137,12 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []
136137

137138
func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
138139
return []*gocui.ViewMouseBinding{
140+
{
141+
ViewName: "main",
142+
Key: gocui.MouseLeft,
143+
Handler: self.onClickMain,
144+
FocusedView: self.context().GetViewName(),
145+
},
139146
{
140147
ViewName: "patchBuilding",
141148
Key: gocui.MouseLeft,
@@ -184,7 +191,30 @@ func (self *CommitFilesController) onClickMain(opts gocui.ViewMouseBindingOpts)
184191
if node == nil {
185192
return nil
186193
}
187-
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y})
194+
195+
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine("main", opts.Y)
196+
if !ok {
197+
line = -1
198+
}
199+
200+
if !node.IsFile() && ok {
201+
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
202+
if err != nil {
203+
return err
204+
}
205+
self.context().CommitFileTreeViewModel.ExpandToPath(relativePath)
206+
self.c.PostRefreshUpdate(self.context())
207+
208+
idx, ok := self.context().CommitFileTreeViewModel.GetIndexForPath(relativePath)
209+
if ok {
210+
self.context().SetSelectedLineIdx(idx)
211+
self.context().GetViewTrait().FocusPoint(
212+
self.context().ModelIndexToViewIndex(idx))
213+
node = self.context().GetSelected()
214+
}
215+
}
216+
217+
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y, ClickedViewRealLineIdx: line})
188218
}
189219

190220
func (self *CommitFilesController) copyDiffToClipboard(path string, toastMessage string) error {
@@ -472,7 +502,7 @@ func (self *CommitFilesController) currentFromToReverseForPatchBuilding() (strin
472502
}
473503

474504
func (self *CommitFilesController) enter(node *filetree.CommitFileNode) error {
475-
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
505+
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
476506
}
477507

478508
func (self *CommitFilesController) enterCommitFile(node *filetree.CommitFileNode, opts types.OnFocusOpts) error {

pkg/gui/controllers/files_controller.go

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package controllers
33
import (
44
"errors"
55
"fmt"
6+
"path/filepath"
67
"strings"
78

89
"github.com/jesseduffield/gocui"
@@ -496,7 +497,7 @@ func (self *FilesController) getSelectedFile() *models.File {
496497
}
497498

498499
func (self *FilesController) enter() error {
499-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
500+
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
500501
}
501502

502503
func (self *FilesController) collapseAll() error {
@@ -1108,12 +1109,42 @@ func (self *FilesController) handleStashSave(stashFunc func(message string) erro
11081109
return nil
11091110
}
11101111

1112+
func (self *FilesController) onClickMainOrSecondary(windowName string, opts gocui.ViewMouseBindingOpts) error {
1113+
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(windowName, opts.Y)
1114+
if !ok {
1115+
line = -1
1116+
}
1117+
1118+
node := self.context().GetSelected()
1119+
if node == nil {
1120+
return nil
1121+
}
1122+
1123+
if !node.IsFile() && ok {
1124+
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
1125+
if err != nil {
1126+
return err
1127+
}
1128+
self.context().FileTreeViewModel.ExpandToPath(relativePath)
1129+
self.c.PostRefreshUpdate(self.context())
1130+
1131+
idx, ok := self.context().FileTreeViewModel.GetIndexForPath(relativePath)
1132+
if ok {
1133+
self.context().SetSelectedLineIdx(idx)
1134+
self.context().GetViewTrait().FocusPoint(
1135+
self.context().ModelIndexToViewIndex(idx))
1136+
}
1137+
}
1138+
1139+
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: windowName, ClickedViewLineIdx: line, ClickedViewRealLineIdx: line})
1140+
}
1141+
11111142
func (self *FilesController) onClickMain(opts gocui.ViewMouseBindingOpts) error {
1112-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y})
1143+
return self.onClickMainOrSecondary("main", opts)
11131144
}
11141145

11151146
func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error {
1116-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "secondary", ClickedViewLineIdx: opts.Y})
1147+
return self.onClickMainOrSecondary("secondary", opts)
11171148
}
11181149

11191150
func (self *FilesController) fetch() error {

pkg/gui/controllers/helpers/patch_building_helper.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ func (self *PatchBuildingHelper) Reset() error {
5454

5555
func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpts) {
5656
selectedLineIdx := -1
57+
selectedRealLineIdx := -1
5758
if opts.ClickedWindowName == "main" {
5859
selectedLineIdx = opts.ClickedViewLineIdx
60+
selectedRealLineIdx = opts.ClickedViewRealLineIdx
5961
}
6062

6163
if !self.c.Git().Patch.PatchBuilder.Active() {
@@ -87,7 +89,7 @@ func (self *PatchBuildingHelper) RefreshPatchBuildingPanel(opts types.OnFocusOpt
8789

8890
oldState := context.GetState()
8991

90-
state := patch_exploring.NewState(diff, selectedLineIdx, context.GetView(), oldState)
92+
state := patch_exploring.NewState(diff, selectedLineIdx, selectedRealLineIdx, context.GetView(), oldState)
9193
context.SetState(state)
9294
if state == nil {
9395
self.Escape()

pkg/gui/controllers/helpers/staging_helper.go

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
package helpers
22

33
import (
4+
"regexp"
5+
46
"github.com/jesseduffield/lazygit/pkg/commands/models"
57
"github.com/jesseduffield/lazygit/pkg/gui/patch_exploring"
68
"github.com/jesseduffield/lazygit/pkg/gui/types"
9+
"github.com/jesseduffield/lazygit/pkg/utils"
710
)
811

912
type StagingHelper struct {
10-
c *HelperCommon
13+
c *HelperCommon
14+
windowHelper *WindowHelper
1115
}
1216

1317
func NewStagingHelper(
1418
c *HelperCommon,
19+
windowHelper *WindowHelper,
1520
) *StagingHelper {
1621
return &StagingHelper{
17-
c: c,
22+
c: c,
23+
windowHelper: windowHelper,
1824
}
1925
}
2026

@@ -30,12 +36,16 @@ func (self *StagingHelper) RefreshStagingPanel(focusOpts types.OnFocusOpts) {
3036
}
3137

3238
mainSelectedLineIdx := -1
39+
mainSelectedRealLineIdx := -1
3340
secondarySelectedLineIdx := -1
41+
secondarySelectedRealLineIdx := -1
3442
if focusOpts.ClickedViewLineIdx > 0 {
3543
if secondaryFocused {
3644
secondarySelectedLineIdx = focusOpts.ClickedViewLineIdx
45+
secondarySelectedRealLineIdx = focusOpts.ClickedViewRealLineIdx
3746
} else {
3847
mainSelectedLineIdx = focusOpts.ClickedViewLineIdx
48+
mainSelectedRealLineIdx = focusOpts.ClickedViewRealLineIdx
3949
}
4050
}
4151

@@ -63,11 +73,11 @@ func (self *StagingHelper) RefreshStagingPanel(focusOpts types.OnFocusOpts) {
6373
secondaryContext.GetMutex().Lock()
6474

6575
mainContext.SetState(
66-
patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainContext.GetView(), mainContext.GetState()),
76+
patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainSelectedRealLineIdx, mainContext.GetView(), mainContext.GetState()),
6777
)
6878

6979
secondaryContext.SetState(
70-
patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondaryContext.GetView(), secondaryContext.GetState()),
80+
patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondarySelectedRealLineIdx, secondaryContext.GetView(), secondaryContext.GetState()),
7181
)
7282

7383
mainState := mainContext.GetState()
@@ -124,3 +134,20 @@ func (self *StagingHelper) secondaryStagingFocused() bool {
124134
func (self *StagingHelper) mainStagingFocused() bool {
125135
return self.c.Context().CurrentStatic().GetKey() == self.c.Contexts().Staging.GetKey()
126136
}
137+
138+
func (self *StagingHelper) GetFileAndLineForClickedDiffLine(windowName string, lineIdx int) (string, int, bool) {
139+
v, _ := self.c.GocuiGui().View(self.windowHelper.GetViewNameForWindow(windowName))
140+
hyperlink, ok := v.HyperLinkInLine(lineIdx, "lazygit-edit:")
141+
if !ok {
142+
return "", 0, false
143+
}
144+
145+
re := regexp.MustCompile(`^lazygit-edit://(.+?):(\d+)$`)
146+
matches := re.FindStringSubmatch(hyperlink)
147+
if matches == nil {
148+
return "", 0, false
149+
}
150+
filepath := matches[1]
151+
lineNumber := utils.MustConvertToInt(matches[2])
152+
return filepath, lineNumber, true
153+
}

pkg/gui/controllers/patch_explorer_controller.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,15 @@ func (self *PatchExplorerController) GetMouseKeybindings(opts types.KeybindingsO
160160
return self.withRenderAndFocus(self.HandleMouseDown)()
161161
}
162162

163+
_, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(self.context.GetWindowName(), opts.Y)
164+
if !ok {
165+
line = -1
166+
}
167+
163168
self.c.Context().Push(self.context, types.OnFocusOpts{
164-
ClickedWindowName: self.context.GetWindowName(),
165-
ClickedViewLineIdx: opts.Y,
169+
ClickedWindowName: self.context.GetWindowName(),
170+
ClickedViewLineIdx: opts.Y,
171+
ClickedViewRealLineIdx: line,
166172
})
167173

168174
return nil

pkg/gui/patch_exploring/state.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const (
3838
HUNK
3939
)
4040

41-
func NewState(diff string, selectedLineIdx int, view *gocui.View, oldState *State) *State {
41+
func NewState(diff string, selectedLineIdx int, selectedRealLineIdx int, view *gocui.View, oldState *State) *State {
4242
if oldState != nil && diff == oldState.diff && selectedLineIdx == -1 {
4343
// if we're here then we can return the old state. If selectedLineIdx was not -1
4444
// then that would mean we were trying to click and potentially drag a range, which
@@ -54,6 +54,10 @@ func NewState(diff string, selectedLineIdx int, view *gocui.View, oldState *Stat
5454

5555
viewLineIndices, patchLineIndices := wrapPatchLines(diff, view)
5656

57+
if selectedRealLineIdx != -1 {
58+
selectedLineIdx = patch.PatchLineForLineNumber(selectedRealLineIdx)
59+
}
60+
5761
rangeStartLineIdx := 0
5862
if oldState != nil {
5963
rangeStartLineIdx = oldState.rangeStartLineIdx

pkg/gui/types/context.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ type IViewTrait interface {
217217
type OnFocusOpts struct {
218218
ClickedWindowName string
219219
ClickedViewLineIdx int
220+
221+
// If not -1, takes precedence over ClickedViewLineIdx.
222+
ClickedViewRealLineIdx int
220223
}
221224

222225
type OnFocusLostOpts struct {

vendor/github.com/jesseduffield/gocui/view.go

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)