files: make DiffLineIterator accept generic DiffLine iterator

I'm thinking of adding some heuristics to render hunks containing lots of
small word changes differently, in a similar manner to the unified diffs. This
patch might help add some pre/post-processing at consumer.

files::diff() is inlined to caller to get around 'self borrowing.
This commit is contained in:
Yuya Nishihara 2024-08-14 14:20:19 +09:00
parent f85792288f
commit 78c0128ec3
2 changed files with 21 additions and 18 deletions

View File

@ -25,8 +25,8 @@ use jj_lib::commit::Commit;
use jj_lib::conflicts::{
materialized_diff_stream, MaterializedTreeDiffEntry, MaterializedTreeValue,
};
use jj_lib::diff::{Diff, DiffHunk};
use jj_lib::files::DiffLine;
use jj_lib::diff::{self, Diff, DiffHunk};
use jj_lib::files::{DiffLine, DiffLineIterator};
use jj_lib::matchers::Matcher;
use jj_lib::merge::MergedTreeValue;
use jj_lib::merged_tree::{MergedTree, TreeDiffEntry, TreeDiffStream};
@ -35,7 +35,6 @@ use jj_lib::repo::Repo;
use jj_lib::repo_path::{RepoPath, RepoPathUiConverter};
use jj_lib::settings::{ConfigResultExt as _, UserSettings};
use jj_lib::store::Store;
use jj_lib::{diff, files};
use pollster::FutureExt;
use thiserror::Error;
use tracing::instrument;
@ -401,7 +400,7 @@ fn show_color_words_diff_hunks(
let mut skipped_context = false;
// Are the lines in `context` to be printed before the next modified line?
let mut context_before = true;
for diff_line in files::diff(left, right) {
for diff_line in DiffLineIterator::new(Diff::default_refinement([left, right]).hunks()) {
if diff_line.is_unmodified() {
context.push_back(diff_line.clone());
let mut start_skipping_context = false;

View File

@ -14,11 +14,11 @@
#![allow(missing_docs)]
use std::borrow::Borrow;
use std::collections::VecDeque;
use std::fmt::{Debug, Error, Formatter};
use std::{iter, vec};
use std::iter;
use crate::diff;
use crate::diff::{Diff, DiffHunk};
use crate::merge::{trivial_merge, Merge};
@ -45,19 +45,19 @@ impl DiffLine<'_> {
}
}
pub fn diff<'a>(left: &'a [u8], right: &'a [u8]) -> DiffLineIterator<'a> {
let diff_hunks = diff::diff(left, right);
DiffLineIterator::new(diff_hunks)
}
pub struct DiffLineIterator<'a> {
diff_hunks: iter::Fuse<vec::IntoIter<DiffHunk<'a>>>,
pub struct DiffLineIterator<'a, I> {
diff_hunks: iter::Fuse<I>,
current_line: DiffLine<'a>,
queued_lines: VecDeque<DiffLine<'a>>,
}
impl<'a> DiffLineIterator<'a> {
fn new(diff_hunks: Vec<DiffHunk<'a>>) -> Self {
impl<'a, I> DiffLineIterator<'a, I>
where
I: Iterator,
I::Item: Borrow<DiffHunk<'a>>,
{
/// Iterates `diff_hunks` by line. Each hunk should have exactly two inputs.
pub fn new(diff_hunks: I) -> Self {
let current_line = DiffLine {
left_line_number: 1,
right_line_number: 1,
@ -66,14 +66,18 @@ impl<'a> DiffLineIterator<'a> {
hunks: vec![],
};
DiffLineIterator {
diff_hunks: diff_hunks.into_iter().fuse(),
diff_hunks: diff_hunks.fuse(),
current_line,
queued_lines: VecDeque::new(),
}
}
}
impl<'a> Iterator for DiffLineIterator<'a> {
impl<'a, I> Iterator for DiffLineIterator<'a, I>
where
I: Iterator,
I::Item: Borrow<DiffHunk<'a>>,
{
type Item = DiffLine<'a>;
fn next(&mut self) -> Option<Self::Item> {
@ -83,7 +87,7 @@ impl<'a> Iterator for DiffLineIterator<'a> {
let Some(hunk) = self.diff_hunks.next() else {
break;
};
match &hunk {
match hunk.borrow() {
DiffHunk::Matching(text) => {
let lines = text.split_inclusive(|b| *b == b'\n');
for line in lines {