jj/docs
Yuya Nishihara a83dadd5a9 diff: add option to display complex color-words diffs without inlining
In this patch, I use the number of adds<->removes alternation as a threshold,
which approximates the visual complexity of diff hunks. I don't think user can
choose the threshold intuitively, but we need a config knob to try out some.
I set `max-inline-alternation = 3` locally. 0 and 1 mean "disable inlining"
and "inline adds-only/removes-only lines" respectively.

I've added "diff.<format>" config namespace assuming "ui.diff" will be
reorganized as "ui.diff-formatter" or something. #3327

Some other metrics I've tried:
```
// Per-line alternation. This also works well, but can't measure complexity of
// changes across lines.
fn count_max_diff_alternation_per_line(diff_lines: &[DiffLine]) -> usize {
    diff_lines
        .iter()
        .map(|line| {
            let sides = line.hunks.iter().map(|&(side, _)| side);
            sides
                .filter(|&side| side != DiffLineHunkSide::Both)
                .dedup() // omit e.g. left->both->left
                .count()
        })
        .max()
        .unwrap_or(0)
}

// Per-line occupancy of changes. Large diffs don't always look complex.
fn max_diff_token_ratio_per_line(diff_lines: &[DiffLine]) -> f32 {
    diff_lines
        .iter()
        .filter_map(|line| {
            let [both_len, left_len, right_len] =
                line.hunks.iter().fold([0, 0, 0], |mut acc, (side, data)| {
                    let index = match side {
                        DiffLineHunkSide::Both => 0,
                        DiffLineHunkSide::Left => 1,
                        DiffLineHunkSide::Right => 2,
                    };
                    acc[index] += data.len();
                    acc
                });
            // left/right-only change is readable
            (left_len != 0 && right_len != 0).then(|| {
                let diff_len = left_len + right_len;
                let total_len = both_len + left_len + right_len;
                (diff_len as f32) / (total_len as f32)
            })
        })
        .reduce(f32::max)
        .unwrap_or(0.0)
}

// Total occupancy of changes. Large diffs don't always look complex.
fn total_change_ratio(diff_lines: &[DiffLine]) -> f32 {
    let (diff_len, total_len) = diff_lines
        .iter()
        .flat_map(|line| &line.hunks)
        .fold((0, 0), |(diff_len, total_len), (side, data)| {
            let l = data.len();
            match side {
                DiffLineHunkSide::Both => (diff_len, total_len + l),
                DiffLineHunkSide::Left => (diff_len + l, total_len + l),
                DiffLineHunkSide::Right => (diff_len + l, total_len + l),
            }
        });
    (diff_len as f32) / (total_len as f32)
}
```
2024-08-21 17:48:52 +09:00
..
design
technical
branches.md
cli-reference.md
code-of-conduct.md
community_tools.md
config.md diff: add option to display complex color-words diffs without inlining 2024-08-21 17:48:52 +09:00
config.toml
conflicts.md
contributing.md
design_doc_blueprint.md
design_docs.md
FAQ.md
filesets.md
git-comparison.md
git-compatibility.md
github.md
glossary.md
index.md
install-and-setup.md
operation-log.md
related-work.md
revsets.md
sapling-comparison.md
templates.md
testimonials.md
tutorial.md
windows.md
working-copy.md