mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-03-17 21:18:31 +02:00
Minor refactor
This commit is contained in:
parent
df4eb70ba2
commit
f08fdb2873
79
pkg/gui/mergeconflicts/merge_conflict.go
Normal file
79
pkg/gui/mergeconflicts/merge_conflict.go
Normal 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}
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user