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:
parent
b28b2d05bd
commit
e73de332a1
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
191
pkg/gui/lbl/line_by_line.go
Normal 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)
|
||||
}
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user