Skip to content

Commit

Permalink
diff: buffer color-words context lines
Browse files Browse the repository at this point in the history
I'm testing simple conflicts diffs locally, and we'll probably need to handle
consecutive context hunks when we add some form of unmaterialized conflicts
diffs. Let's buffer context hunks (up to 1 right now.) The new code looks
simpler.
  • Loading branch information
yuja committed Sep 19, 2024
1 parent 9f5ce93 commit 0c9bc37
Showing 1 changed file with 21 additions and 34 deletions.
55 changes: 21 additions & 34 deletions cli/src/diff_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,65 +461,52 @@ fn show_color_words_diff_hunks(
options: &ColorWordsOptions,
) -> io::Result<()> {
let line_diff = Diff::by_line([left, right]);
let mut line_diff_hunks = line_diff.hunks().peekable();
let mut line_number = DiffLineNumber { left: 1, right: 1 };
// Matching entries shouldn't appear consecutively in diff of two inputs.
// However, if the inputs have conflicts, there may be a hunk that can be
// resolved, resulting [matching, resolved, matching] sequence.
let mut contexts = Vec::new();
let mut emitted = false;

// First "before" context
if let Some(DiffHunk::Matching(content)) =
line_diff_hunks.next_if(|hunk| matches!(hunk, DiffHunk::Matching(_)))
{
if line_diff_hunks.peek().is_some() {
line_number = show_color_words_context_lines(
formatter,
content,
line_number,
0,
options.context,
)?;
}
}
while let Some(hunk) = line_diff_hunks.next() {
for hunk in line_diff.hunks() {
match hunk {
// Middle "after"/"before" context
DiffHunk::Matching(content) if line_diff_hunks.peek().is_some() => {
line_number = show_color_words_context_lines(
formatter,
content,
line_number,
options.context,
options.context,
)?;
}
// Last "after" context
DiffHunk::Matching(content) => {
DiffHunk::Matching(content) => contexts.push(content),
DiffHunk::Different(contents) => {
let num_after = if emitted { options.context } else { 0 };
line_number = show_color_words_context_lines(
formatter,
content,
&contexts,
line_number,
num_after,
options.context,
0,
)?;
}
DiffHunk::Different(contents) => {
contexts.clear();
emitted = true;
line_number =
show_color_words_diff_lines(formatter, &contents, line_number, options)?;
}
}
}

if emitted {
show_color_words_context_lines(formatter, &contexts, line_number, options.context, 0)?;
}
Ok(())
}

/// Prints `num_after` lines, ellipsis, and `num_before` lines.
fn show_color_words_context_lines(
formatter: &mut dyn Formatter,
content: &[u8],
contents: &[&BStr],
mut line_number: DiffLineNumber,
num_after: usize,
num_before: usize,
) -> io::Result<DiffLineNumber> {
const SKIPPED_CONTEXT_LINE: &str = " ...\n";
let mut lines = content.split_inclusive(|b| *b == b'\n').fuse();
let mut lines = contents
.iter()
.flat_map(|content| content.split_inclusive(|b| *b == b'\n'))
.fuse();
for line in lines.by_ref().take(num_after) {
show_color_words_line_number(formatter, Some(line_number.left), Some(line_number.right))?;
show_color_words_inline_hunks(formatter, &[(DiffLineHunkSide::Both, line.as_ref())])?;
Expand Down

0 comments on commit 0c9bc37

Please sign in to comment.