1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-03-17 21:18:31 +02:00

Minor refactor

This commit is contained in:
Jesse Duffield 2021-08-25 20:43:57 +10:00
parent df4eb70ba2
commit f08fdb2873
3 changed files with 106 additions and 89 deletions

View File

@ -0,0 +1,79 @@
package mergeconflicts
// mergeConflict : A git conflict with a start, ancestor (if exists), target, and end corresponding to line
// numbers in the file where the conflict markers appear.
// If no ancestor is present (i.e. we're not using the diff3 algorithm), then
// the `ancestor` field's value will be -1
type mergeConflict struct {
start int
ancestor int
target int
end int
}
func (c *mergeConflict) hasAncestor() bool {
return c.ancestor >= 0
}
func (c *mergeConflict) isMarkerLine(i int) bool {
return i == c.start ||
i == c.ancestor ||
i == c.target ||
i == c.end
}
type Selection int
const (
TOP Selection = iota
MIDDLE
BOTTOM
ALL
)
func (s Selection) isIndexToKeep(conflict *mergeConflict, i int) bool {
// we're only handling one conflict at a time so any lines outside this
// conflict we'll keep
if i < conflict.start || conflict.end < i {
return true
}
if conflict.isMarkerLine(i) {
return false
}
selectionStart, selectionEnd := s.bounds(conflict)
return selectionStart < i && i < selectionEnd
}
func (s Selection) bounds(c *mergeConflict) (int, int) {
switch s {
case TOP:
if c.hasAncestor() {
return c.start, c.ancestor
} else {
return c.start, c.target
}
case MIDDLE:
return c.ancestor, c.target
case BOTTOM:
return c.target, c.end
case ALL:
return c.start, c.end
}
panic("unexpected selection for merge conflict")
}
func (s Selection) selected(c *mergeConflict, idx int) bool {
start, end := s.bounds(c)
return start < idx && idx < end
}
func availableSelections(c *mergeConflict) []Selection {
if c.hasAncestor() {
return []Selection{TOP, MIDDLE, BOTTOM}
} else {
return []Selection{TOP, BOTTOM}
}
}

View File

@ -16,7 +16,7 @@ func ColoredConflictFile(content string, state *State, hasFocus bool) string {
var outputBuffer bytes.Buffer
for i, line := range utils.SplitLines(content) {
textStyle := theme.DefaultTextColor
if i == conflict.start || i == conflict.ancestor || i == conflict.target || i == conflict.end {
if conflict.isMarkerLine(i) {
textStyle = style.FgRed
}
@ -36,18 +36,6 @@ func shiftConflict(conflicts []*mergeConflict) (*mergeConflict, []*mergeConflict
}
func shouldHighlightLine(index int, conflict *mergeConflict, selection Selection) bool {
switch selection {
case TOP:
if conflict.hasAncestor() {
return index >= conflict.start && index <= conflict.ancestor
} else {
return index >= conflict.start && index <= conflict.target
}
case MIDDLE:
return index >= conflict.ancestor && index <= conflict.target
case BOTTOM:
return index >= conflict.target && index <= conflict.end
default:
return false
}
selectionStart, selectionEnd := selection.bounds(conflict)
return index >= selectionStart && index <= selectionEnd
}

View File

@ -7,51 +7,19 @@ import (
"github.com/jesseduffield/lazygit/pkg/utils"
)
func clamp(x int, min int, max int) int {
if x < min {
return min
} else if x > max {
return max
}
return x
}
type Selection int
const (
TOP Selection = iota
MIDDLE
BOTTOM
ALL
)
// mergeConflict : A git conflict with a start, ancestor (if exists), target, and end corresponding to line
// numbers in the file where the conflict markers appear
type mergeConflict struct {
start int
ancestor int
target int
end int
}
func (c *mergeConflict) hasAncestor() bool {
return c.ancestor >= 0
}
func (c *mergeConflict) availableSelections() []Selection {
if c.hasAncestor() {
return []Selection{TOP, MIDDLE, BOTTOM}
} else {
return []Selection{TOP, BOTTOM}
}
}
type State struct {
sync.Mutex
conflictIndex int
conflicts []*mergeConflict
// this is the index of the above `conflicts` field which is currently selected
conflictIndex int
// this is the index of the selected conflict's available selections slice e.g. [TOP, MIDDLE, BOTTOM]
// We use this to know which hunk of the conflict is selected.
selectionIndex int
conflicts []*mergeConflict
EditHistory *stack.Stack
// this allows us to undo actions
EditHistory *stack.Stack
}
func NewState() *State {
@ -66,9 +34,9 @@ func NewState() *State {
func (s *State) setConflictIndex(index int) {
if len(s.conflicts) == 0 {
s.conflictIndex = clamp(index, 0, len(s.conflicts)-1)
} else {
s.conflictIndex = 0
} else {
s.conflictIndex = clamp(index, 0, len(s.conflicts)-1)
}
s.setSelectionIndex(s.selectionIndex)
}
@ -137,7 +105,7 @@ func (s *State) Selection() Selection {
func (s *State) availableSelections() []Selection {
if conflict := s.currentConflict(); conflict != nil {
return conflict.availableSelections()
return availableSelections(conflict)
}
return nil
}
@ -154,7 +122,10 @@ func (s *State) GetConflictMiddle() int {
return s.currentConflict().target
}
func (s *State) ContentAfterConflictResolve(path string, selection Selection) (bool, string, error) {
func (s *State) ContentAfterConflictResolve(
path string,
selection Selection,
) (bool, string, error) {
conflict := s.currentConflict()
if conflict == nil {
return false, "", nil
@ -162,7 +133,7 @@ func (s *State) ContentAfterConflictResolve(path string, selection Selection) (b
content := ""
err := utils.ForEachLineInFile(path, func(line string, i int) {
if !isIndexToDelete(i, conflict, selection) {
if selection.isIndexToKeep(conflict, i) {
content += line
}
})
@ -174,32 +145,11 @@ func (s *State) ContentAfterConflictResolve(path string, selection Selection) (b
return true, content, nil
}
func isIndexToDelete(i int, conflict *mergeConflict, selection Selection) bool {
if i < conflict.start || conflict.end < i {
return false
func clamp(x int, min int, max int) int {
if x < min {
return min
} else if x > max {
return max
}
isMarkerLine :=
i == conflict.start ||
i == conflict.ancestor ||
i == conflict.target ||
i == conflict.end
var isWantedContent bool
switch selection {
case TOP:
if conflict.hasAncestor() {
isWantedContent = conflict.start < i && i < conflict.ancestor
} else {
isWantedContent = conflict.start < i && i < conflict.target
}
case MIDDLE:
isWantedContent = conflict.ancestor < i && i < conflict.target
case BOTTOM:
isWantedContent = conflict.target < i && i < conflict.end
case ALL:
isWantedContent = true
}
return isMarkerLine || !isWantedContent
return x
}