Skip to content

Commit b14dfb0

Browse files
committed
WIP
1 parent f2e1587 commit b14dfb0

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"
@@ -116,6 +117,12 @@ func (self *CommitFilesController) GetKeybindings(opts types.KeybindingsOpts) []
116117

117118
func (self *CommitFilesController) GetMouseKeybindings(opts types.KeybindingsOpts) []*gocui.ViewMouseBinding {
118119
return []*gocui.ViewMouseBinding{
120+
{
121+
ViewName: "main",
122+
Key: gocui.MouseLeft,
123+
Handler: self.onClickMain,
124+
FocusedView: self.context().GetViewName(),
125+
},
119126
{
120127
ViewName: "patchBuilding",
121128
Key: gocui.MouseLeft,
@@ -164,7 +171,30 @@ func (self *CommitFilesController) onClickMain(opts gocui.ViewMouseBindingOpts)
164171
if node == nil {
165172
return nil
166173
}
167-
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y})
174+
175+
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine("main", opts.Y)
176+
if !ok {
177+
line = -1
178+
}
179+
180+
if !node.IsFile() && ok {
181+
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
182+
if err != nil {
183+
return err
184+
}
185+
self.context().CommitFileTreeViewModel.ExpandToPath(relativePath)
186+
self.c.PostRefreshUpdate(self.context())
187+
188+
idx, ok := self.context().CommitFileTreeViewModel.GetIndexForPath(relativePath)
189+
if ok {
190+
self.context().SetSelectedLineIdx(idx)
191+
self.context().GetViewTrait().FocusPoint(
192+
self.context().ModelIndexToViewIndex(idx))
193+
node = self.context().GetSelected()
194+
}
195+
}
196+
197+
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y, ClickedViewRealLineIdx: line})
168198
}
169199

170200
func (self *CommitFilesController) checkout(node *filetree.CommitFileNode) error {
@@ -349,7 +379,7 @@ func (self *CommitFilesController) currentFromToReverseForPatchBuilding() (strin
349379
}
350380

351381
func (self *CommitFilesController) enter(node *filetree.CommitFileNode) error {
352-
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
382+
return self.enterCommitFile(node, types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
353383
}
354384

355385
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
@@ -2,6 +2,7 @@ package controllers
22

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

78
"github.com/jesseduffield/gocui"
@@ -475,7 +476,7 @@ func (self *FilesController) getSelectedFile() *models.File {
475476
}
476477

477478
func (self *FilesController) enter() error {
478-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1})
479+
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "", ClickedViewLineIdx: -1, ClickedViewRealLineIdx: -1})
479480
}
480481

481482
func (self *FilesController) EnterFile(opts types.OnFocusOpts) error {
@@ -976,12 +977,42 @@ func (self *FilesController) handleStashSave(stashFunc func(message string) erro
976977
return nil
977978
}
978979

980+
func (self *FilesController) onClickMainOrSecondary(windowName string, opts gocui.ViewMouseBindingOpts) error {
981+
clickedFile, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(windowName, opts.Y)
982+
if !ok {
983+
line = -1
984+
}
985+
986+
node := self.context().GetSelected()
987+
if node == nil {
988+
return nil
989+
}
990+
991+
if !node.IsFile() && ok {
992+
relativePath, err := filepath.Rel(self.c.Git().RepoPaths.RepoPath(), clickedFile)
993+
if err != nil {
994+
return err
995+
}
996+
self.context().FileTreeViewModel.ExpandToPath(relativePath)
997+
self.c.PostRefreshUpdate(self.context())
998+
999+
idx, ok := self.context().FileTreeViewModel.GetIndexForPath(relativePath)
1000+
if ok {
1001+
self.context().SetSelectedLineIdx(idx)
1002+
self.context().GetViewTrait().FocusPoint(
1003+
self.context().ModelIndexToViewIndex(idx))
1004+
}
1005+
}
1006+
1007+
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: windowName, ClickedViewLineIdx: line, ClickedViewRealLineIdx: line})
1008+
}
1009+
9791010
func (self *FilesController) onClickMain(opts gocui.ViewMouseBindingOpts) error {
980-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "main", ClickedViewLineIdx: opts.Y})
1011+
return self.onClickMainOrSecondary("main", opts)
9811012
}
9821013

9831014
func (self *FilesController) onClickSecondary(opts gocui.ViewMouseBindingOpts) error {
984-
return self.EnterFile(types.OnFocusOpts{ClickedWindowName: "secondary", ClickedViewLineIdx: opts.Y})
1015+
return self.onClickMainOrSecondary("secondary", opts)
9851016
}
9861017

9871018
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, oldState, self.c.Log)
92+
state := patch_exploring.NewState(diff, selectedLineIdx, selectedRealLineIdx, oldState, self.c.Log)
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.GetState(), self.c.Log),
76+
patch_exploring.NewState(mainDiff, mainSelectedLineIdx, mainSelectedRealLineIdx, mainContext.GetState(), self.c.Log),
6777
)
6878

6979
secondaryContext.SetState(
70-
patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondaryContext.GetState(), self.c.Log),
80+
patch_exploring.NewState(secondaryDiff, secondarySelectedLineIdx, secondarySelectedRealLineIdx, secondaryContext.GetState(), self.c.Log),
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
@@ -150,9 +150,15 @@ func (self *PatchExplorerController) GetMouseKeybindings(opts types.KeybindingsO
150150
return self.withRenderAndFocus(self.HandleMouseDown)()
151151
}
152152

153+
_, line, ok := self.c.Helpers().Staging.GetFileAndLineForClickedDiffLine(self.context.GetWindowName(), opts.Y)
154+
if !ok {
155+
line = -1
156+
}
157+
153158
self.c.Context().Push(self.context, types.OnFocusOpts{
154-
ClickedWindowName: self.context.GetWindowName(),
155-
ClickedViewLineIdx: opts.Y,
159+
ClickedWindowName: self.context.GetWindowName(),
160+
ClickedViewLineIdx: opts.Y,
161+
ClickedViewRealLineIdx: line,
156162
})
157163

158164
return nil

pkg/gui/patch_exploring/state.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const (
2929
HUNK
3030
)
3131

32-
func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Entry) *State {
32+
func NewState(diff string, selectedLineIdx int, selectedRealLineIdx int, oldState *State, log *logrus.Entry) *State {
3333
if oldState != nil && diff == oldState.diff && selectedLineIdx == -1 {
3434
// if we're here then we can return the old state. If selectedLineIdx was not -1
3535
// then that would mean we were trying to click and potentiall drag a range, which
@@ -43,6 +43,10 @@ func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Ent
4343
return nil
4444
}
4545

46+
if selectedRealLineIdx != -1 {
47+
selectedLineIdx = patch.PatchLineForLineNumber(selectedRealLineIdx)
48+
}
49+
4650
rangeStartLineIdx := 0
4751
if oldState != nil {
4852
rangeStartLineIdx = oldState.rangeStartLineIdx

pkg/gui/types/context.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ type IViewTrait interface {
209209
type OnFocusOpts struct {
210210
ClickedWindowName string
211211
ClickedViewLineIdx int
212+
213+
// If not -1, takes precedence over ClickedViewLineIdx.
214+
ClickedViewRealLineIdx int
212215
}
213216

214217
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)