jj/cli/src
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
..
commands next/prev: Add config flag to control prev/next edit behaviour. 2024-08-20 15:46:00 +01:00
config diff: add option to display complex color-words diffs without inlining 2024-08-21 17:48:52 +09:00
merge_tools merged_tree: remove TreeDiffEntry::source 2024-08-18 22:16:41 -07:00
cleanup_guard.rs
cli_util.rs config: expand tilde in ssh key filepaths 2024-08-13 08:06:43 -07:00
command_error.rs describe: allow updating the description of multiple commits 2024-08-05 02:06:40 +08:00
commit_templater.rs diff: add option to display complex color-words diffs without inlining 2024-08-21 17:48:52 +09:00
config-schema.json diff: add option to display complex color-words diffs without inlining 2024-08-21 17:48:52 +09:00
config.rs config: do not parse TOML value expression by write_config_value_to_file() 2024-08-09 22:39:16 +09:00
description_util.rs describe: warn user of limitations when describing multiple commits 2024-08-06 11:28:21 -07:00
diff_util.rs diff: add option to display complex color-words diffs without inlining 2024-08-21 17:48:52 +09:00
formatter.rs formatter: make error type of with_label() callback generic 2024-08-01 22:56:36 +09:00
generic_templater.rs templater: implement expect_*_arguments() as methods 2024-05-22 10:18:05 +09:00
git_util.rs config: expand tilde in ssh key filepaths 2024-08-13 08:06:43 -07:00
graphlog.rs
lib.rs next/prev: refactor movement utilities into cli/src/movement_utils.rs 2024-08-16 23:21:00 +01:00
main.rs
movement_util.rs next/prev: Add config flag to control prev/next edit behaviour. 2024-08-20 15:46:00 +01:00
operation_templater.rs templater: implement expect_*_arguments() as methods 2024-05-22 10:18:05 +09:00
progress.rs cli: clear line after writing 2024-05-30 12:27:11 -05:00
revset_util.rs Define builtin_immutable_heads() as a default revset alias. 2024-08-14 11:32:16 +01:00
template.pest fileset, revset, templater: add support for single-quoted raw string literals 2024-04-25 11:14:33 +09:00
template_builder.rs dsl_util: add keyword arguments and parsing helper to FunctionCallNode 2024-05-29 22:36:15 +09:00
template_parser.rs revset, templater: implement arity-based alias overloading 2024-06-14 23:11:29 +09:00
templater.rs templater: add SizeHint type to represent revset.count_estimate() value 2024-05-09 08:51:34 +09:00
text_util.rs cli: add ui.color = "debug" 2024-05-11 10:16:09 +02:00
time_util.rs
ui.rs ui: do not write() to channel if builtin pager has terminated 2024-08-05 10:34:33 +09:00