forked from mirrors/jj
diff: split color-words diffing to line-based and refinement stages
This allows us to select rendering function hunk by hunk. For example, a hunk with lots of small changes could be rendered without interleaving left/right words. Another good thing is that context line handling can be simplified as the whole context hunk is available.
This commit is contained in:
parent
59745fb67f
commit
9beb57018a
1 changed files with 49 additions and 29 deletions
|
@ -16,7 +16,7 @@ use std::cmp::max;
|
||||||
use std::collections::{HashSet, VecDeque};
|
use std::collections::{HashSet, VecDeque};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{io, mem};
|
use std::{io, iter, mem};
|
||||||
|
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -26,7 +26,7 @@ use jj_lib::conflicts::{
|
||||||
materialized_diff_stream, MaterializedTreeDiffEntry, MaterializedTreeValue,
|
materialized_diff_stream, MaterializedTreeDiffEntry, MaterializedTreeValue,
|
||||||
};
|
};
|
||||||
use jj_lib::diff::{Diff, DiffHunk};
|
use jj_lib::diff::{Diff, DiffHunk};
|
||||||
use jj_lib::files::{DiffLine, DiffLineHunkSide, DiffLineIterator};
|
use jj_lib::files::{DiffLine, DiffLineHunkSide, DiffLineIterator, DiffLineNumber};
|
||||||
use jj_lib::matchers::Matcher;
|
use jj_lib::matchers::Matcher;
|
||||||
use jj_lib::merge::MergedTreeValue;
|
use jj_lib::merge::MergedTreeValue;
|
||||||
use jj_lib::merged_tree::{MergedTree, TreeDiffEntry, TreeDiffStream};
|
use jj_lib::merged_tree::{MergedTree, TreeDiffEntry, TreeDiffStream};
|
||||||
|
@ -401,13 +401,21 @@ fn show_color_words_diff_hunks(
|
||||||
formatter: &mut dyn Formatter,
|
formatter: &mut dyn Formatter,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
const SKIPPED_CONTEXT_LINE: &str = " ...\n";
|
const SKIPPED_CONTEXT_LINE: &str = " ...\n";
|
||||||
|
let mut line_number = DiffLineNumber { left: 1, right: 1 };
|
||||||
let mut context = VecDeque::new();
|
let mut context = VecDeque::new();
|
||||||
// Have we printed "..." for any skipped context?
|
// Have we printed "..." for any skipped context?
|
||||||
let mut skipped_context = false;
|
let mut skipped_context = false;
|
||||||
// Are the lines in `context` to be printed before the next modified line?
|
// Are the lines in `context` to be printed before the next modified line?
|
||||||
let mut context_before = true;
|
let mut context_before = true;
|
||||||
for diff_line in DiffLineIterator::new(Diff::default_refinement([left, right]).hunks()) {
|
for hunk in Diff::by_line([left, right]).hunks() {
|
||||||
if diff_line.is_unmodified() {
|
match hunk {
|
||||||
|
DiffHunk::Matching(content) => {
|
||||||
|
// TODO: just split by "\n"
|
||||||
|
let mut diff_line_iter = DiffLineIterator::with_line_number(
|
||||||
|
iter::once(DiffHunk::matching(content)),
|
||||||
|
line_number,
|
||||||
|
);
|
||||||
|
for diff_line in diff_line_iter.by_ref() {
|
||||||
context.push_back(diff_line.clone());
|
context.push_back(diff_line.clone());
|
||||||
let mut start_skipping_context = false;
|
let mut start_skipping_context = false;
|
||||||
if context_before {
|
if context_before {
|
||||||
|
@ -428,16 +436,28 @@ fn show_color_words_diff_hunks(
|
||||||
skipped_context = true;
|
skipped_context = true;
|
||||||
context_before = true;
|
context_before = true;
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
line_number = diff_line_iter.next_line_number();
|
||||||
|
}
|
||||||
|
DiffHunk::Different(contents) => {
|
||||||
for line in &context {
|
for line in &context {
|
||||||
show_color_words_diff_line(formatter, line)?;
|
show_color_words_diff_line(formatter, line)?;
|
||||||
}
|
}
|
||||||
context.clear();
|
context.clear();
|
||||||
|
|
||||||
|
let word_diff = Diff::by_word(&contents);
|
||||||
|
let mut diff_line_iter =
|
||||||
|
DiffLineIterator::with_line_number(word_diff.hunks(), line_number);
|
||||||
|
for diff_line in diff_line_iter.by_ref() {
|
||||||
show_color_words_diff_line(formatter, &diff_line)?;
|
show_color_words_diff_line(formatter, &diff_line)?;
|
||||||
|
}
|
||||||
|
line_number = diff_line_iter.next_line_number();
|
||||||
|
|
||||||
context_before = false;
|
context_before = false;
|
||||||
skipped_context = false;
|
skipped_context = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if !context_before {
|
if !context_before {
|
||||||
if context.len() > num_context_lines + 1 {
|
if context.len() > num_context_lines + 1 {
|
||||||
context.truncate(num_context_lines);
|
context.truncate(num_context_lines);
|
||||||
|
|
Loading…
Reference in a new issue