Skip to content

Commit

Permalink
Merge branch 'johan/conflict-context'
Browse files Browse the repository at this point in the history
  • Loading branch information
walles committed May 19, 2024
2 parents 2425c5f + ac5a713 commit 645462f
Show file tree
Hide file tree
Showing 3 changed files with 196 additions and 19 deletions.
47 changes: 28 additions & 19 deletions src/conflicts_highlighter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,33 +86,42 @@ impl LinesHighlighter for ConflictsHighlighter {
});
}

let (maybe_prefix, destination) = if !self.c2_header.is_empty() {
("+ ", &mut self.c2)
//
// All header lines handled, this is a content line
//

let destination = if !self.c2_header.is_empty() {
&mut self.c2
} else if !self.base_header.is_empty() {
("++", &mut self.base)
&mut self.base
} else {
(" +", &mut self.c1)
&mut self.c1
};

let prefix = if self.c1_header.starts_with("++") {
maybe_prefix
let prefixes = if self.c1_header.starts_with("++") {
// Possible content line prefixes when doing "git diff"
vec!["+ ", "++", " +"]
} else {
""
vec![""]
};

if let Some(line) = line.strip_prefix(prefix) {
destination.push_str(line);
destination.push('\n');
return Ok(Response {
line_accepted: LineAcceptance::AcceptedWantMore,
highlighted: vec![],
});
} else {
return Ok(Response {
line_accepted: LineAcceptance::RejectedDone,
highlighted: vec![self.render_plain()],
});
for prefix in prefixes {
if let Some(line) = line.strip_prefix(prefix) {
// Handle the context line
destination.push_str(line);
destination.push('\n');
return Ok(Response {
line_accepted: LineAcceptance::AcceptedWantMore,
highlighted: vec![],
});
}
}

// Not a context line, just give up and do a simple render
return Ok(Response {
line_accepted: LineAcceptance::RejectedDone,
highlighted: vec![self.render_plain()],
});
}

fn consume_eof(&mut self, _thread_pool: &ThreadPool) -> Result<Vec<StringFuture>, String> {
Expand Down
84 changes: 84 additions & 0 deletions testdata/conflict-with-context.diff
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
diff --cc m/search.go
index 5b67346,e5b580f..0000000
--- m/search.go
+++ m/search.go
@@@ -10,45 -6,9 +10,79 @@@ import
"github.com/walles/moar/m/linenumbers"
)

++<<<<<<< HEAD
+func (p *Pager) scrollToSearchHits() {
+ if p.searchPattern == nil {
+ // This is not a search
+ return
+ }
+
+ lineNumber := p.scrollPosition.lineNumber(p)
+ if lineNumber == nil {
+ // No lines to search
+ return
+ }
+
+ firstHitPosition := p.findFirstHit(*lineNumber, nil, false)
+ if firstHitPosition == nil && (*lineNumber != linenumbers.LineNumber{}) {
+ // Try again from the top
+ firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, lineNumber, false)
+ }
+ if firstHitPosition == nil {
+ // No match, give up
+ return
+ }
+
+ if firstHitPosition.isVisible(p) {
+ // Already on-screen, never mind
+ return
+ }
+
+ p.scrollPosition = *firstHitPosition
+}
+
+// NOTE: When we search, we do that by looping over the *input lines*, not the
+// screen lines. That's why startPosition is a LineNumber rather than a
+// scrollPosition.
+//
+// The `beforePosition` parameter is exclusive, meaning that line will not be
+// searched.
+//
+// For the actual searching, this method will call _findFirstHit() in parallel
+// on multiple cores, to help large file search performance.
++||||||| parent of b835e9a (Fix the warnings)
++func (p *Pager) scrollToSearchHits() {
++ if p.searchPattern == nil {
++ // This is not a search
++ return
++ }
++
++ firstHitPosition := p.findFirstHit(*p.scrollPosition.lineNumber(p), nil, false)
++ if firstHitPosition == nil {
++ // Try again from the top
++ firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, p.scrollPosition.lineNumber(p), false)
++ }
++ if firstHitPosition == nil {
++ // No match, give up
++ return
++ }
++
++ if firstHitPosition.isVisible(p) {
++ // Already on-screen, never mind
++ return
++ }
++
++ p.scrollPosition = *firstHitPosition
++}
++
+ // NOTE: When we search, we do that by looping over the *input lines*, not
+ // the screen lines. That's why we're using a line number rather than a
+ // scrollPosition for searching.
++=======
++// NOTE: When we search, we do that by looping over the *input lines*, not
++// the screen lines. That's why we're using a line number rather than a
++// scrollPosition for searching.
++>>>>>>> b835e9a (Fix the warnings)
//
// FIXME: We should take startPosition.deltaScreenLines into account as well!
func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, beforePosition *linenumbers.LineNumber, backwards bool) *scrollPosition {
84 changes: 84 additions & 0 deletions testdata/conflict-with-context.riff-output
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
diff --cc m/search.go
index 5b67346,e5b580f..0000000
--- m/search.go
+++ m/search.go
@@@ -10,45 -6,9 +10,79 @@@ import 
"github.com/walles/moar/m/linenumbers"
)

++<<<<<<< HEAD
 +func (p *Pager) scrollToSearchHits() {
 + if p.searchPattern == nil {
 + // This is not a search
 + return
 + }
 +
 + lineNumber := p.scrollPosition.lineNumber(p)
 + if lineNumber == nil {
 + // No lines to search
 + return
 + }
 +
 + firstHitPosition := p.findFirstHit(*lineNumber, nil, false)
 + if firstHitPosition == nil && (*lineNumber != linenumbers.LineNumber{}) {
 + // Try again from the top
 + firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, lineNumber, false)
 + }
 + if firstHitPosition == nil {
 + // No match, give up
 + return
 + }
 +
 + if firstHitPosition.isVisible(p) {
 + // Already on-screen, never mind
 + return
 + }
 +
 + p.scrollPosition = *firstHitPosition
 +}
 +
 +// NOTE: When we search, we do that by looping over the *input lines*, not the
 +// screen lines. That's why startPosition is a LineNumber rather than a
 +// scrollPosition.
 +//
 +// The `beforePosition` parameter is exclusive, meaning that line will not be
 +// searched.
 +//
 +// For the actual searching, this method will call _findFirstHit() in parallel
 +// on multiple cores, to help large file search performance.
++||||||| parent of b835e9a (Fix the warnings)
++func (p *Pager) scrollToSearchHits() {
++ if p.searchPattern == nil {
++ // This is not a search
++ return
++ }
++
++ firstHitPosition := p.findFirstHit(*p.scrollPosition.lineNumber(p), nil, false)
++ if firstHitPosition == nil {
++ // Try again from the top
++ firstHitPosition = p.findFirstHit(linenumbers.LineNumber{}, p.scrollPosition.lineNumber(p), false)
++ }
++ if firstHitPosition == nil {
++ // No match, give up
++ return
++ }
++
++ if firstHitPosition.isVisible(p) {
++ // Already on-screen, never mind
++ return
++ }
++
++ p.scrollPosition = *firstHitPosition
++}
++
++// NOTE: When we search, we do that by looping over the *input lines*, not
++// the screen lines. That's why we're using a line number rather than a
++// scrollPosition for searching.
++=======
+ // NOTE: When we search, we do that by looping over the *input lines*, not
+ // the screen lines. That's why we're using a line number rather than a
+ // scrollPosition for searching.
++>>>>>>> b835e9a (Fix the warnings)
//
// FIXME: We should take startPosition.deltaScreenLines into account as well!
func (p *Pager) findFirstHit(startPosition linenumbers.LineNumber, beforePosition *linenumbers.LineNumber, backwards bool) *scrollPosition {

0 comments on commit 645462f

Please sign in to comment.