1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-01-02 03:37:14 +02:00

refactor line by line panel

This commit is contained in:
Jesse Duffield 2021-04-18 16:30:34 +10:00
parent b28b2d05bd
commit e73de332a1
7 changed files with 295 additions and 219 deletions

View File

@ -182,11 +182,8 @@ func (p *PatchManager) RenderPatchForFile(filename string, plain bool, reverse b
if plain {
return patch
}
parser, err := NewPatchParser(p.Log, patch)
if err != nil {
// swallowing for now
return ""
}
parser := NewPatchParser(p.Log, patch)
// not passing included lines because we don't want to see them in the secondary panel
return parser.Render(-1, -1, nil)
}

View File

@ -39,11 +39,8 @@ type PatchParser struct {
}
// NewPatchParser builds a new branch list builder
func NewPatchParser(log *logrus.Entry, patch string) (*PatchParser, error) {
hunkStarts, stageableLines, patchLines, err := parsePatch(patch)
if err != nil {
return nil, err
}
func NewPatchParser(log *logrus.Entry, patch string) *PatchParser {
hunkStarts, stageableLines, patchLines := parsePatch(patch)
patchHunks := GetHunksFromDiff(patch)
@ -53,7 +50,7 @@ func NewPatchParser(log *logrus.Entry, patch string) (*PatchParser, error) {
StageableLines: stageableLines,
PatchLines: patchLines,
PatchHunks: patchHunks,
}, nil
}
}
// GetHunkContainingLine takes a line index and an offset and finds the hunk
@ -139,7 +136,7 @@ func coloredString(colorAttr color.Attribute, str string, selected bool, include
return utils.ColoredStringDirect(str[:1], clIncluded) + utils.ColoredStringDirect(str[1:], cl)
}
func parsePatch(patch string) ([]int, []int, []*PatchLine, error) {
func parsePatch(patch string) ([]int, []int, []*PatchLine) {
lines := strings.Split(patch, "\n")
hunkStarts := []int{}
stageableLines := []int{}
@ -185,7 +182,7 @@ func parsePatch(patch string) ([]int, []int, []*PatchLine, error) {
}
patchLines[index] = &PatchLine{Kind: lineKind, Content: line}
}
return hunkStarts, stageableLines, patchLines, nil
return hunkStarts, stageableLines, patchLines
}
// Render returns the coloured string of the diff with any selected lines highlighted

View File

@ -18,9 +18,9 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands"
"github.com/jesseduffield/lazygit/pkg/commands/models"
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/config"
"github.com/jesseduffield/lazygit/pkg/gui/filetree"
"github.com/jesseduffield/lazygit/pkg/gui/lbl"
"github.com/jesseduffield/lazygit/pkg/gui/modes/filtering"
"github.com/jesseduffield/lazygit/pkg/gui/types"
"github.com/jesseduffield/lazygit/pkg/i18n"
@ -133,13 +133,8 @@ func (h *listPanelState) GetSelectedLineIdx() int {
// for now the staging panel state, unlike the other panel states, is going to be
// non-mutative, so that we don't accidentally end up
// with mismatches of data. We might change this in the future
type lBlPanelState struct {
SelectedLineIdx int
FirstLineIdx int
LastLineIdx int
Diff string
PatchParser *patch.PatchParser
SelectMode SelectMode
type LblPanelState struct {
*lbl.State
SecondaryFocused bool // this is for if we show the left or right panel
}
@ -230,7 +225,7 @@ type panelStates struct {
SubCommits *subCommitPanelState
Stash *stashPanelState
Menu *menuPanelState
LineByLine *lBlPanelState
LineByLine *LblPanelState
Merging *mergingPanelState
CommitFiles *commitFilesPanelState
Submodules *submodulePanelState

191
pkg/gui/lbl/line_by_line.go Normal file
View File

@ -0,0 +1,191 @@
package lbl
import (
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/sirupsen/logrus"
)
type State struct {
selectedLineIdx int
rangeStartLineIdx int
diff string
patchParser *patch.PatchParser
selectMode selectMode
}
// these represent what select mode we're in
type selectMode int
const (
LINE selectMode = iota
RANGE
HUNK
)
func NewState(diff string, selectedLineIdx int, oldState *State, log *logrus.Entry) *State {
patchParser := patch.NewPatchParser(log, diff)
if len(patchParser.StageableLines) == 0 {
return nil
}
rangeStartLineIdx := 0
if oldState != nil {
rangeStartLineIdx = oldState.rangeStartLineIdx
}
selectMode := LINE
// if we have clicked from the outside to focus the main view we'll pass in a non-negative line index so that we can instantly select that line
if selectedLineIdx >= 0 {
selectMode = RANGE
rangeStartLineIdx = selectedLineIdx
} else if oldState != nil {
// if we previously had a selectMode of RANGE, we want that to now be line again
if oldState.selectMode == HUNK {
selectMode = HUNK
}
selectedLineIdx = patchParser.GetNextStageableLineIndex(oldState.selectedLineIdx)
} else {
selectedLineIdx = patchParser.StageableLines[0]
}
return &State{
patchParser: patchParser,
selectedLineIdx: selectedLineIdx,
selectMode: selectMode,
rangeStartLineIdx: rangeStartLineIdx,
diff: diff,
}
}
func (s *State) GetSelectedLineIdx() int {
return s.selectedLineIdx
}
func (s *State) GetDiff() string {
return s.diff
}
func (s *State) ToggleSelectHunk() {
if s.selectMode == HUNK {
s.selectMode = LINE
} else {
s.selectMode = HUNK
}
}
func (s *State) ToggleSelectRange() {
if s.selectMode == RANGE {
s.selectMode = LINE
} else {
s.selectMode = RANGE
s.rangeStartLineIdx = s.selectedLineIdx
}
}
func (s *State) SelectingHunk() bool {
return s.selectMode == HUNK
}
func (s *State) SelectingRange() bool {
return s.selectMode == RANGE
}
func (s *State) SelectingLine() bool {
return s.selectMode == LINE
}
func (s *State) SetLineSelectMode() {
s.selectMode = LINE
}
func (s *State) SelectLine(newSelectedLineIdx int) {
if newSelectedLineIdx < 0 {
newSelectedLineIdx = 0
} else if newSelectedLineIdx > len(s.patchParser.PatchLines)-1 {
newSelectedLineIdx = len(s.patchParser.PatchLines) - 1
}
s.selectedLineIdx = newSelectedLineIdx
}
func (s *State) SelectNewLineForRange(newSelectedLineIdx int) {
s.rangeStartLineIdx = newSelectedLineIdx
s.selectMode = RANGE
s.SelectLine(newSelectedLineIdx)
}
func (s *State) CycleSelection(forward bool) {
if s.SelectingHunk() {
s.CycleHunk(forward)
} else {
s.CycleLine(forward)
}
}
func (s *State) CycleHunk(forward bool) {
change := 1
if !forward {
change = -1
}
newHunk := s.patchParser.GetHunkContainingLine(s.selectedLineIdx, change)
s.selectedLineIdx = s.patchParser.GetNextStageableLineIndex(newHunk.FirstLineIdx)
}
func (s *State) CycleLine(forward bool) {
change := 1
if !forward {
change = -1
}
s.SelectLine(s.selectedLineIdx + change)
}
func (s *State) CurrentHunk() *patch.PatchHunk {
return s.patchParser.GetHunkContainingLine(s.selectedLineIdx, 0)
}
func (s *State) SelectedRange() (int, int) {
switch s.selectMode {
case HUNK:
hunk := s.CurrentHunk()
return hunk.FirstLineIdx, hunk.LastLineIdx()
case RANGE:
if s.rangeStartLineIdx > s.selectedLineIdx {
return s.selectedLineIdx, s.rangeStartLineIdx
} else {
return s.rangeStartLineIdx, s.selectedLineIdx
}
case LINE:
return s.selectedLineIdx, s.selectedLineIdx
default:
// should never happen
return 0, 0
}
}
func (s *State) CurrentLineNumber() int {
return s.CurrentHunk().LineNumberOfLine(s.selectedLineIdx)
}
func (s *State) AdjustSelectedLineIdx(change int) {
s.SelectLine(s.selectedLineIdx + change)
}
func (s *State) RenderForLineIndices(includedLineIndices []int) string {
firstLineIdx, lastLineIdx := s.SelectedRange()
return s.patchParser.Render(firstLineIdx, lastLineIdx, includedLineIndices)
}
func (s *State) SelectBottom() {
s.SetLineSelectMode()
s.SelectLine(len(s.patchParser.PatchLines) - 1)
}
func (s *State) SelectTop() {
s.SetLineSelectMode()
s.SelectLine(0)
}

View File

@ -6,6 +6,7 @@ import (
"github.com/go-errors/errors"
"github.com/jesseduffield/gocui"
"github.com/jesseduffield/lazygit/pkg/commands/patch"
"github.com/jesseduffield/lazygit/pkg/gui/lbl"
)
// Currently there are two 'pseudo-panels' that make use of this 'pseudo-panel'.
@ -15,82 +16,38 @@ import (
// staging_panel.go and patch_building_panel.go have functions specific to their
// use cases
// these represent what select mode we're in
type SelectMode int
const (
LINE SelectMode = iota
RANGE
HUNK
)
// returns whether the patch is empty so caller can escape if necessary
// both diffs should be non-coloured because we'll parse them and colour them here
func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int, state *lBlPanelState) (bool, error) {
func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, secondaryFocused bool, selectedLineIdx int) (bool, error) {
gui.splitMainPanel(true)
patchParser, err := patch.NewPatchParser(gui.Log, diff)
if err != nil {
return false, nil
var oldState *lbl.State
if gui.State.Panels.LineByLine != nil {
oldState = gui.State.Panels.LineByLine.State
}
if len(patchParser.StageableLines) == 0 {
state := lbl.NewState(diff, selectedLineIdx, oldState, gui.Log)
if state == nil {
return true, nil
}
var firstLineIdx int
var lastLineIdx int
selectMode := LINE
// if we have clicked from the outside to focus the main view we'll pass in a non-negative line index so that we can instantly select that line
if selectedLineIdx >= 0 {
selectMode = RANGE
firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx
} else if state != nil {
if state.SelectMode == HUNK {
// this is tricky: we need to find out which hunk we just staged based on our old `state.PatchParser` (as opposed to the new `patchParser`)
// we do this by getting the first line index of the original hunk, then
// finding the next stageable line, then getting its containing hunk
// in the new diff
selectMode = HUNK
prevNewHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 0)
selectedLineIdx = patchParser.GetNextStageableLineIndex(prevNewHunk.FirstLineIdx)
newHunk := patchParser.GetHunkContainingLine(selectedLineIdx, 0)
firstLineIdx, lastLineIdx = newHunk.FirstLineIdx, newHunk.LastLineIdx()
} else {
selectedLineIdx = patchParser.GetNextStageableLineIndex(state.SelectedLineIdx)
firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx
}
} else {
selectedLineIdx = patchParser.StageableLines[0]
firstLineIdx, lastLineIdx = selectedLineIdx, selectedLineIdx
}
state = &lBlPanelState{
PatchParser: patchParser,
SelectedLineIdx: selectedLineIdx,
SelectMode: selectMode,
FirstLineIdx: firstLineIdx,
LastLineIdx: lastLineIdx,
Diff: diff,
gui.State.Panels.LineByLine = &LblPanelState{
State: state,
SecondaryFocused: secondaryFocused,
}
gui.State.Panels.LineByLine = state
if err := gui.refreshMainViewForLineByLine(state); err != nil {
if err := gui.refreshMainViewForLineByLine(gui.State.Panels.LineByLine); err != nil {
return false, err
}
if err := gui.focusSelection(selectMode == HUNK, state); err != nil {
if err := gui.focusSelection(gui.State.Panels.LineByLine); err != nil {
return false, err
}
gui.Views.Secondary.Highlight = true
gui.Views.Secondary.Wrap = false
secondaryPatchParser, err := patch.NewPatchParser(gui.Log, secondaryDiff)
if err != nil {
return false, nil
}
secondaryPatchParser := patch.NewPatchParser(gui.Log, secondaryDiff)
gui.setViewContent(gui.Views.Secondary, secondaryPatchParser.Render(-1, -1, nil))
@ -98,107 +55,66 @@ func (gui *Gui) refreshLineByLinePanel(diff string, secondaryDiff string, second
}
func (gui *Gui) handleSelectPrevLine() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.LBLCycleLine(-1, state)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.CycleSelection(false)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleSelectNextLine() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.LBLCycleLine(+1, state)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.CycleSelection(true)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleSelectPrevHunk() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, -1)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.CycleHunk(false)
return gui.selectNewHunk(newHunk, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleSelectNextHunk() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 1)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.CycleHunk(true)
return gui.selectNewHunk(newHunk, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) selectNewHunk(newHunk *patch.PatchHunk, state *lBlPanelState) error {
state.SelectedLineIdx = state.PatchParser.GetNextStageableLineIndex(newHunk.FirstLineIdx)
if state.SelectMode == HUNK {
state.FirstLineIdx, state.LastLineIdx = newHunk.FirstLineIdx, newHunk.LastLineIdx()
} else {
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
}
func (gui *Gui) refreshAndFocusLblPanel(state *LblPanelState) error {
if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err
}
return gui.focusSelection(true, state)
}
func (gui *Gui) LBLCycleLine(change int, state *lBlPanelState) error {
if state.SelectMode == HUNK {
newHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, change)
return gui.selectNewHunk(newHunk, state)
}
return gui.LBLSelectLine(state.SelectedLineIdx+change, state)
}
func (gui *Gui) LBLSelectLine(newSelectedLineIdx int, state *lBlPanelState) error {
if newSelectedLineIdx < 0 {
newSelectedLineIdx = 0
} else if newSelectedLineIdx > len(state.PatchParser.PatchLines)-1 {
newSelectedLineIdx = len(state.PatchParser.PatchLines) - 1
}
state.SelectedLineIdx = newSelectedLineIdx
if state.SelectMode == RANGE {
if state.SelectedLineIdx < state.FirstLineIdx {
state.FirstLineIdx = state.SelectedLineIdx
} else {
state.LastLineIdx = state.SelectedLineIdx
}
} else {
state.LastLineIdx = state.SelectedLineIdx
state.FirstLineIdx = state.SelectedLineIdx
}
if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err
}
return gui.focusSelection(false, state)
return gui.focusSelection(state)
}
func (gui *Gui) handleLBLMouseDown() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
if gui.popupPanelFocused() {
return nil
}
newSelectedLineIdx := gui.Views.Main.SelectedLineIdx()
state.FirstLineIdx = newSelectedLineIdx
state.LastLineIdx = newSelectedLineIdx
state.SelectNewLineForRange(gui.Views.Main.SelectedLineIdx())
state.SelectMode = RANGE
return gui.LBLSelectLine(newSelectedLineIdx, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleMouseDrag() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
if gui.popupPanelFocused() {
return nil
}
return gui.LBLSelectLine(gui.Views.Main.SelectedLineIdx(), state)
state.SelectLine(gui.Views.Main.SelectedLineIdx())
return gui.refreshAndFocusLblPanel(state)
})
}
@ -208,7 +124,7 @@ func (gui *Gui) getSelectedCommitFileName() string {
return gui.State.CommitFileManager.GetItemAtIndex(idx).GetPath()
}
func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
func (gui *Gui) refreshMainViewForLineByLine(state *LblPanelState) error {
var includedLineIndices []int
// I'd prefer not to have knowledge of contexts using this file but I'm not sure
// how to get around this
@ -220,7 +136,7 @@ func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
return err
}
}
colorDiff := state.PatchParser.Render(state.FirstLineIdx, state.LastLineIdx, includedLineIndices)
colorDiff := state.RenderForLineIndices(includedLineIndices)
gui.Views.Main.Highlight = true
gui.Views.Main.Wrap = false
@ -232,21 +148,14 @@ func (gui *Gui) refreshMainViewForLineByLine(state *lBlPanelState) error {
// focusSelection works out the best focus for the staging panel given the
// selected line and size of the hunk
func (gui *Gui) focusSelection(includeCurrentHunk bool, state *lBlPanelState) error {
func (gui *Gui) focusSelection(state *LblPanelState) error {
stagingView := gui.Views.Main
_, viewHeight := stagingView.Size()
bufferHeight := viewHeight - 1
_, origin := stagingView.Origin()
firstLineIdx := state.SelectedLineIdx
lastLineIdx := state.SelectedLineIdx
if includeCurrentHunk {
hunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 0)
firstLineIdx = hunk.FirstLineIdx
lastLineIdx = hunk.LastLineIdx()
}
firstLineIdx, lastLineIdx := state.SelectedRange()
margin := 0 // we may want to have a margin in place to show context but right now I'm thinking we keep this at zero
@ -264,41 +173,25 @@ func (gui *Gui) focusSelection(includeCurrentHunk bool, state *lBlPanelState) er
return err
}
return stagingView.SetCursor(0, state.SelectedLineIdx-newOrigin)
return stagingView.SetCursor(0, state.GetSelectedLineIdx()-newOrigin)
})
return nil
}
func (gui *Gui) handleToggleSelectRange() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if state.SelectMode == RANGE {
state.SelectMode = LINE
} else {
state.SelectMode = RANGE
}
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.ToggleSelectRange()
return gui.refreshMainViewForLineByLine(state)
})
}
func (gui *Gui) handleToggleSelectHunk() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
if state.SelectMode == HUNK {
state.SelectMode = LINE
state.FirstLineIdx, state.LastLineIdx = state.SelectedLineIdx, state.SelectedLineIdx
} else {
state.SelectMode = HUNK
selectedHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 0)
state.FirstLineIdx, state.LastLineIdx = selectedHunk.FirstLineIdx, selectedHunk.LastLineIdx()
}
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.ToggleSelectHunk()
if err := gui.refreshMainViewForLineByLine(state); err != nil {
return err
}
return gui.focusSelection(state.SelectMode == HUNK, state)
return gui.refreshAndFocusLblPanel(state)
})
}
@ -307,7 +200,7 @@ func (gui *Gui) escapeLineByLinePanel() {
}
func (gui *Gui) handleOpenFileAtLine() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
// again, would be good to use inheritance here (or maybe even composition)
var filename string
switch gui.State.MainContext {
@ -324,8 +217,7 @@ func (gui *Gui) handleOpenFileAtLine() error {
}
// need to look at current index, then work out what my hunk's header information is, and see how far my line is away from the hunk header
selectedHunk := state.PatchParser.GetHunkContainingLine(state.SelectedLineIdx, 0)
lineNumber := selectedHunk.LineNumberOfLine(state.SelectedLineIdx)
lineNumber := state.CurrentLineNumber()
filenameWithLineNum := fmt.Sprintf("%s:%d", filename, lineNumber)
if err := gui.OSCommand.OpenFile(filenameWithLineNum); err != nil {
return err
@ -336,48 +228,49 @@ func (gui *Gui) handleOpenFileAtLine() error {
}
func (gui *Gui) handleLineByLineNextPage() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := state.SelectedLineIdx + gui.pageDelta(gui.Views.Main)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SetLineSelectMode()
state.AdjustSelectedLineIdx(gui.pageDelta(gui.Views.Main))
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleLineByLinePrevPage() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := state.SelectedLineIdx - gui.pageDelta(gui.Views.Main)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SetLineSelectMode()
state.AdjustSelectedLineIdx(-gui.pageDelta(gui.Views.Main))
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleLineByLineGotoBottom() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
newSelectedLineIdx := len(state.PatchParser.PatchLines) - 1
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SelectBottom()
return gui.lineByLineNavigateTo(newSelectedLineIdx, state)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handleLineByLineGotoTop() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.lineByLineNavigateTo(0, state)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SelectTop()
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) handlelineByLineNavigateTo(selectedLineIdx int) error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.lineByLineNavigateTo(selectedLineIdx, state)
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SetLineSelectMode()
state.SelectLine(selectedLineIdx)
return gui.refreshAndFocusLblPanel(state)
})
}
func (gui *Gui) lineByLineNavigateTo(selectedLineIdx int, state *lBlPanelState) error {
state.SelectMode = LINE
return gui.LBLSelectLine(selectedLineIdx, state)
}
func (gui *Gui) withLBLActiveCheck(f func(*lBlPanelState) error) error {
func (gui *Gui) withLBLActiveCheck(f func(*LblPanelState) error) error {
gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock()

View File

@ -17,7 +17,7 @@ func (gui *Gui) getFromAndReverseArgsForDiff(to string) (string, bool) {
return from, reverse
}
func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *lBlPanelState) error {
func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *LblPanelState) error {
if !gui.GitCommand.PatchManager.Active() {
return gui.handleEscapePatchBuildingPanel()
}
@ -43,7 +43,7 @@ func (gui *Gui) refreshPatchBuildingPanel(selectedLineIdx int, state *lBlPanelSt
return err
}
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx, state)
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, false, selectedLineIdx)
if err != nil {
return err
}
@ -63,14 +63,14 @@ func (gui *Gui) handleRefreshPatchBuildingPanel(selectedLineIdx int) error {
}
func (gui *Gui) handleToggleSelectionForPatch() error {
err := gui.withLBLActiveCheck(func(state *lBlPanelState) error {
err := gui.withLBLActiveCheck(func(state *LblPanelState) error {
toggleFunc := gui.GitCommand.PatchManager.AddFileLineRange
filename := gui.getSelectedCommitFileName()
includedLineIndices, err := gui.GitCommand.PatchManager.GetFileIncLineIndices(filename)
if err != nil {
return err
}
currentLineIsStaged := utils.IncludesInt(includedLineIndices, state.SelectedLineIdx)
currentLineIsStaged := utils.IncludesInt(includedLineIndices, state.GetSelectedLineIdx())
if currentLineIsStaged {
toggleFunc = gui.GitCommand.PatchManager.RemoveFileLineRange
}
@ -81,7 +81,9 @@ func (gui *Gui) handleToggleSelectionForPatch() error {
return nil
}
if err := toggleFunc(node.GetPath(), state.FirstLineIdx, state.LastLineIdx); err != nil {
firstLineIdx, lastLineIdx := state.SelectedRange()
if err := toggleFunc(node.GetPath(), firstLineIdx, lastLineIdx); err != nil {
// might actually want to return an error here
gui.Log.Error(err)
}

View File

@ -6,7 +6,7 @@ import (
"github.com/jesseduffield/lazygit/pkg/commands/patch"
)
func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int, state *lBlPanelState) error {
func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx int) error {
gui.splitMainPanel(true)
file := gui.getSelectedFile()
@ -17,8 +17,8 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
secondaryFocused := false
if forceSecondaryFocused {
secondaryFocused = true
} else if state != nil {
secondaryFocused = state.SecondaryFocused
} else if gui.State.Panels.LineByLine != nil {
secondaryFocused = gui.State.Panels.LineByLine.SecondaryFocused
}
if (secondaryFocused && !file.HasStagedChanges) || (!secondaryFocused && !file.HasUnstagedChanges) {
@ -47,7 +47,7 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
diff, secondaryDiff = secondaryDiff, diff
}
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx, state)
empty, err := gui.refreshLineByLinePanel(diff, secondaryDiff, secondaryFocused, selectedLineIdx)
if err != nil {
return err
}
@ -60,10 +60,10 @@ func (gui *Gui) refreshStagingPanel(forceSecondaryFocused bool, selectedLineIdx
}
func (gui *Gui) handleTogglePanelClick() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SecondaryFocused = !state.SecondaryFocused
return gui.refreshStagingPanel(false, gui.Views.Secondary.SelectedLineIdx(), state)
return gui.refreshStagingPanel(false, gui.Views.Secondary.SelectedLineIdx())
})
}
@ -71,13 +71,13 @@ func (gui *Gui) handleRefreshStagingPanel(forceSecondaryFocused bool, selectedLi
gui.Mutexes.LineByLinePanelMutex.Lock()
defer gui.Mutexes.LineByLinePanelMutex.Unlock()
return gui.refreshStagingPanel(forceSecondaryFocused, selectedLineIdx, gui.State.Panels.LineByLine)
return gui.refreshStagingPanel(forceSecondaryFocused, selectedLineIdx)
}
func (gui *Gui) handleTogglePanel() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
state.SecondaryFocused = !state.SecondaryFocused
return gui.refreshStagingPanel(false, -1, state)
return gui.refreshStagingPanel(false, -1)
})
}
@ -88,13 +88,13 @@ func (gui *Gui) handleStagingEscape() error {
}
func (gui *Gui) handleToggleStagedSelection() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
return gui.applySelection(state.SecondaryFocused, state)
})
}
func (gui *Gui) handleResetSelection() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
if state.SecondaryFocused {
// for backwards compatibility
return gui.applySelection(true, state)
@ -106,7 +106,7 @@ func (gui *Gui) handleResetSelection() error {
prompt: gui.Tr.UnstageLinesPrompt,
handlersManageFocus: true,
handleConfirm: func() error {
return gui.withLBLActiveCheck(func(state *lBlPanelState) error {
return gui.withLBLActiveCheck(func(state *LblPanelState) error {
if err := gui.pushContext(gui.State.Contexts.Staging); err != nil {
return err
}
@ -124,13 +124,14 @@ func (gui *Gui) handleResetSelection() error {
})
}
func (gui *Gui) applySelection(reverse bool, state *lBlPanelState) error {
func (gui *Gui) applySelection(reverse bool, state *LblPanelState) error {
file := gui.getSelectedFile()
if file == nil {
return nil
}
patch := patch.ModifiedPatchForRange(gui.Log, file.Name, state.Diff, state.FirstLineIdx, state.LastLineIdx, reverse, false)
firstLineIdx, lastLineIdx := state.SelectedRange()
patch := patch.ModifiedPatchForRange(gui.Log, file.Name, state.GetDiff(), firstLineIdx, lastLineIdx, reverse, false)
if patch == "" {
return nil
@ -147,14 +148,14 @@ func (gui *Gui) applySelection(reverse bool, state *lBlPanelState) error {
return gui.surfaceError(err)
}
if state.SelectMode == RANGE {
state.SelectMode = LINE
if state.SelectingRange() {
state.SetLineSelectMode()
}
if err := gui.refreshSidePanels(refreshOptions{scope: []RefreshableView{FILES}}); err != nil {
return err
}
if err := gui.refreshStagingPanel(false, -1, state); err != nil {
if err := gui.refreshStagingPanel(false, -1); err != nil {
return err
}
return nil