Merge adjacent spans to normalise output in regression tests

pull/919/head
Wilfred Hughes 2025-11-15 02:40:43 +07:00
parent 57bcd173a7
commit 0a3f8c2f92
2 changed files with 123 additions and 77 deletions

@ -1,14 +1,14 @@
sample_files/Session_1.kt sample_files/Session_2.kt
a5899a29b0ebb0800923ac368b95fa1e -
fec9f5421c5bdb3cb485c2cfd2f336a6 -
sample_files/ada_1.adb sample_files/ada_2.adb
0f5fafa73393305ea0d6aba11149efd2 -
7498a465384992689732536fcf6ec19b -
sample_files/added_line_1.txt sample_files/added_line_2.txt
8a1587e6b5fc53f2ec2ac665a5d00372 -
sample_files/align_footer_1.txt sample_files/align_footer_2.txt
0c2a263268f6c1dd27aa5e6aed686b6c -
a7ed15e00ccc8094621e2a9d3c29449c -
sample_files/all_changed_1.js sample_files/all_changed_2.js
6f6cbd4d2ed1045e3883143787dbd75b -
@ -17,94 +17,97 @@ sample_files/apex_1.cls sample_files/apex_2.cls
8e477350907734ac4d5201752523dff3 -
sample_files/b2_math_1.h sample_files/b2_math_2.h
1ab24165d072f91be11893b92bc0943f -
ea7421bd7970a6edf2897f8785053ce4 -
sample_files/bad_combine_1.rs sample_files/bad_combine_2.rs
dabc6d2f9df43eeaebdbbb44e23a73bb -
a6d674bd88d54f085c22c70c2d5a4c80 -
sample_files/big_text_hunk_1.txt sample_files/big_text_hunk_2.txt
fc26d41a5ff771670e04033b177973d2 -
sample_files/change_outer_1.el sample_files/change_outer_2.el
13d4673474ea6c7ee980f8a955fff26b -
ae93896664a63c1f0d4a5f9c4d26dd70 -
sample_files/chinese_1.po sample_files/chinese_2.po
0c40e3f3093cdda64ac9c9674ded3bce -
582b2c28cca7a60b7c6b0410dfa436bc -
sample_files/clojure_1.clj sample_files/clojure_2.clj
cdc99aad6117c0cfc2e6896fe629876e -
f1a045dfa78cac71d355951fe0b363a0 -
sample_files/comma_1.js sample_files/comma_2.js
0e29285c944ffe768790ffbbf9542470 -
dfd18ec953d29545380fa656e54ff70e -
sample_files/comma_and_comment_1.js sample_files/comma_and_comment_2.js
0a5ccbcd368607e62eaff0c4ae25049f -
sample_files/comments_1.rs sample_files/comments_2.rs
a75827163654d6aed8f837bb586e733c -
d8c3c256de454bc23944cf1a4300c66e -
sample_files/context_1.rs sample_files/context_2.rs
1a1633bcf672a582867c815381ae1609 -
9b84c492d07d125912de77002bcaad9a -
sample_files/contiguous_1.js sample_files/contiguous_2.js
22da862378dbee68e55ecba8b0fcec42 -
7ac6081dee02e3529a88defca194bc00 -
sample_files/css_1.css sample_files/css_2.css
3d911704ac4d76697c748e1dcd40eece -
43a2bbc8dc2f4b4733ecb5a888d10dfc -
sample_files/dart_1.dart sample_files/dart_2.dart
107d073c2922ff14e9ba66ee0f489592 -
sample_files/devicetree_1.dts sample_files/devicetree_2.dts
7ab2bd26334b6729a481665e5566cf97 -
100d21f4d762db8991757b489c794db1 -
sample_files/elisp_1.el sample_files/elisp_2.el
d7bdaf5f87e1c44475774c6e7ba70822 -
3e8c8abcb65a5141a2fb54bae4a9ca06 -
sample_files/elisp_contiguous_1.el sample_files/elisp_contiguous_2.el
4a5a33873a4f84ee055d95e1448fba35 -
sample_files/elixir_1.ex sample_files/elixir_2.ex
85494310196ac5065b3b4ce1d4b350fd -
5ab1a845f7cb3ca6db1fdef7bc4a042f -
sample_files/elm_1.elm sample_files/elm_2.elm
ccc1f4bb568cd72781dbcd623b612c43 -
8a67269f2dd2e4913f885b3b6e6d6a07 -
sample_files/elvish_1.elv sample_files/elvish_2.elv
93af1d46752d57db84011ca7482ae842 -
sample_files/erlang_1.erl sample_files/erlang_2.erl
4c3e2bd1f0918ed339e87a5f8e0b05cb -
268056b80b3311309a17a6c5485f68cd -
sample_files/f_sharp_1.fs sample_files/f_sharp_2.fs
25253b18ef64469c67cf9a7131c8c125 -
f6c90edd5c4fb81b793f3b7c9b367845 -
sample_files/hack_1.php sample_files/hack_2.php
c2bb0aa7d7b07d6ced79f6a5363e878b -
sample_files/hare_1.ha sample_files/hare_2.ha
ef6fd59edc55241311a97d21dd81e4c0 -
b0d0b2c446b46285c585a8eca75e6dd3 -
sample_files/haskell_1.hs sample_files/haskell_2.hs
68fd7f9865c2b1defe05ffd509e08b93 -
e47ca7a69c6f90d9ed9e8b9d47eb2cd4 -
sample_files/hcl_1.hcl sample_files/hcl_2.hcl
7c2aaa3a8b401bc007817f5dd608946d -
b4de7a8269018e05c0eba247d8097111 -
sample_files/hello_world_1.smali sample_files/hello_world_2.smali
c6a0a04710c1dbf30cec4ebed4a35ec9 -
bb8463618fcb7f263bd2dafeef7a8b06 -
sample_files/helpful_1.el sample_files/helpful_2.el
295640aa4cbc23640658a80ad2393ce4 -
6eda1c77cb5dc13bc321e90e41a6b64d -
sample_files/html_1.html sample_files/html_2.html
3cc8b445a56b74f05e1d7bb84874edab -
2b873fd1ea8f77d2463ceb08aa23967c -
sample_files/html_simple_1.html sample_files/html_simple_2.html
bb129dce38cd26eac81ca52d2016bade -
4122689b7d2e3d59d822d2a5d93ebdd0 -
sample_files/huge_cpp_1.cpp sample_files/huge_cpp_2.cpp
09e8a30ad7be5686e4d03a3e6b2588aa -
05d96cce94db8ebdfaf4f2d52239470c -
sample_files/hyphen_subwords_1.json sample_files/hyphen_subwords_2.json
d0728537a824a0404a910b5b8dc05b1b -
sample_files/identical_1.scala sample_files/identical_2.scala
15c5a789e644348cb7e0de051ff4b63e -
@ -116,61 +119,61 @@ sample_files/insert_blank_1.txt sample_files/insert_blank_2.txt
a5fd75afcc99aa7b2b285f1f9ced8607 -
sample_files/janet_1.janet sample_files/janet_2.janet
4dba18ec3a9eeee68da7dcccba0fe5a5 -
7dc0f1a3ce49f489fa4b64edefebb3c5 -
sample_files/java_1.java sample_files/java_2.java
028c9176ac031eb3859f3d04bc43ed10 -
f4b15ddf3283e6c14d200efd06c0e85a -
sample_files/javascript_1.js sample_files/javascript_2.js
96bc1817594be11dfba02ad675aba076 -
7fc853454d1133da215c646732ac67f3 -
sample_files/javascript_simple_1.js sample_files/javascript_simple_2.js
449a5a824892da502f7211714214684e -
1a2fdfb7210a93c80a7ce7c0768920c3 -
sample_files/json_1.json sample_files/json_2.json
133c9224b47a5ee9940536a6ad70fd2e -
2ac602e995cdcb4bbbc1be6f4622e296 -
sample_files/jsx_1.jsx sample_files/jsx_2.jsx
712ef0cf61b469bbacc84b53b944e5ff -
89832bde34f9c54c99a1bfb0f68291a9 -
sample_files/julia_1.jl sample_files/julia_2.jl
532405b3959d8864c06d2fb3548df119 -
10ac32ea1bd1d48b20386f1deeca40a0 -
sample_files/load_1.js sample_files/load_2.js
289f061e6f36e009f646fb927335326a -
2e47b7908951ff8390058856edbaf715 -
sample_files/long_line_1.txt sample_files/long_line_2.txt
7fc50bd547f0c20fda89a1931e5eb61e -
sample_files/lua_1.lua sample_files/lua_2.lua
81ad9478e64494320e96284cb7632ced -
11693bb34168541f2ac9f4154d246038 -
sample_files/makefile_1.mk sample_files/makefile_2.mk
4759883325ade33566f2c8afa09e2d82 -
1a132d165294d0325f9b0dae5569a4d0 -
sample_files/many_newlines_1.txt sample_files/many_newlines_2.txt
52ca05855e520876479e6f608c5e7831 -
sample_files/metadata_1.clj sample_files/metadata_2.clj
fd0fee4a660e938c44182e6f77746d0e -
b788a546c4ccc5662e98ed30473dd776 -
sample_files/modules_1.ml sample_files/modules_2.ml
8584f755c99a93dd744a6722596a4418 -
d0a10fce6354902c0a1708571ab17ffc -
sample_files/multibyte_1.py sample_files/multibyte_2.py
f761255d521267ace4f4887a21664a12 -
222fad0d771916afb86dfede9906895b -
sample_files/multiline_string_1.ml sample_files/multiline_string_2.ml
ed80815053ba156505d156277d0f4195 -
sample_files/multiline_string_eof_1.yml sample_files/multiline_string_eof_2.yml
cd9cfd627c28b8ecd7c990adc683281a -
79f24009a062f256054cf36e0317dc5d -
sample_files/nest_1.rs sample_files/nest_2.rs
d3a799fe2cd9d81aa251c96af5cd9711 -
bb3c526d9400776ffae5bf78631fa0c3 -
sample_files/nested_slider_1.el sample_files/nested_slider_2.el
0880b11fd8a2e1245622f1f2a908e0c4 -
7691443ec4ab9d35837f7caa5bfad2de -
sample_files/nested_slider_1.rs sample_files/nested_slider_2.rs
342df46db959e8c90925ff4400c0fa63 -
@ -179,31 +182,31 @@ sample_files/nesting_1.el sample_files/nesting_2.el
cf32f6b798a080a2bf14a430337ac4a6 -
sample_files/newick_1.nwk sample_files/newick_2.nwk
4244a6609827bae5dabb01b91c9cbd37 -
bbc830fc20d60c5fdca7a99edc3fde78 -
sample_files/nix_1.nix sample_files/nix_2.nix
6f9bea063047d66e9f857123dfe95e10 -
5f591ced7633a07f13cdda9766110715 -
sample_files/nullable_1.kt sample_files/nullable_2.kt
d0a51e7201cc16dc6bcb99cbad64f6be -
sample_files/objc_header_1.h sample_files/objc_header_2.h
122f030f33e779fb60d0ee83d5a187f4 -
37267814a3d241a8f1497ef3239b360c -
sample_files/objc_module_1.m sample_files/objc_module_2.m
f6c69d2b8b283619f5e093b689e7eb23 -
63d3b15c53dfcb54c5cf6ff10c22a965 -
sample_files/ocaml_1.ml sample_files/ocaml_2.ml
20586eb6dedffb55c7a9e264ed3739c9 -
e99bb9f1f789bce0e9a1d4e5205b8139 -
sample_files/outer_delimiter_1.el sample_files/outer_delimiter_2.el
971c3ddebfae222ded24f7a97ec7b5d7 -
sample_files/pascal_1.pascal sample_files/pascal_2.pascal
4e8dbdc95cbaba358cbc5dfa4cb22a55 -
de04f7fdb7af7bd70ca62f1868504f11 -
sample_files/perl_1.pl sample_files/perl_2.pl
e90ef13054f1e541addcac5ee4bad880 -
2cd2638b2b6d07248911f1f2e5ad1b25 -
sample_files/prefer_outer_1.el sample_files/prefer_outer_2.el
991038c9988cccc2c824652e33f772a2 -
@ -212,25 +215,25 @@ sample_files/preprocessor_1.h sample_files/preprocessor_2.h
d94f452bbf7cb3accc8d538fdd7ab5e4 -
sample_files/qml_1.qml sample_files/qml_2.qml
26fed88e46817e49c59fe466701ee574 -
ec69003436e7780633b6224861c3cccf -
sample_files/r_1.R sample_files/r_2.R
f9ee6c271d614bfcd510633bddc9e49d -
f86f4d5f494756079a4ccfdc17521ef3 -
sample_files/racket_1.rkt sample_files/racket_2.rkt
ba1164af47f67d0865a4ba7706096bbc -
4debb7e7af49678aa19726acb5c55d7d -
sample_files/repeated_line_no_eol_1.txt sample_files/repeated_line_no_eol_2.txt
b63c743f2133480de3ba42ecdec5eb93 -
sample_files/ruby_1.rb sample_files/ruby_2.rb
af0b05e67f4338db6be0fd21454c6a08 -
a0a7121421e3d57acadc08519275dcce -
sample_files/scala_1.scala sample_files/scala_2.scala
13181dc30f15675747ce5315cd8073e6 -
2304bea82a6dae573964afdaeb47f845 -
sample_files/scheme_1.scm sample_files/scheme_2.scm
09f8683219a8491c22d9a2fa1ce98c16 -
2d18a48f788361085a05812c2446de91 -
sample_files/simple_1.js sample_files/simple_2.js
1d49d0e440067284015eb5621f4a6adf -
@ -242,13 +245,13 @@ sample_files/simple_1.txt sample_files/simple_2.txt
7df04bd5dbc68a2392b2f0b375c4413e -
sample_files/slider_1.rs sample_files/slider_2.rs
346155adadb1340c026bbfa5cfd5669d -
ebdc9db32892d1d74f7e745f45fbaba6 -
sample_files/slider_at_end_1.json sample_files/slider_at_end_2.json
cb370f1c0ccc5e155743330629f899f0 -
6c994cd99226f6584f74f531bb27d54f -
sample_files/slow_1.rs sample_files/slow_2.rs
74dcf4792d2dc7d7e03ee367aadc3b3c -
4eabdb287f5fa31f5765117f4874d218 -
sample_files/small_1.js sample_files/small_2.js
86b1132b6c17fcc2cbec65b1c248baa9 -
@ -257,65 +260,65 @@ sample_files/sql_1.sql sample_files/sql_2.sql
ee54ee3f974aa54c8bdfc2b9075824f2 -
sample_files/string_subwords_1.el sample_files/string_subwords_2.el
b66e960672189960c2d35ef68b47a195 -
5c72eae6a018e26189868bcc28747c72 -
sample_files/strings_1.el sample_files/strings_2.el
26ea57243abb16043088b17bfee482a4 -
ae3b58de9c115cac8a1044e6cdf77723 -
sample_files/swift_1.swift sample_files/swift_2.swift
73830b14bd8aacac8d4590a3bed61c40 -
sample_files/syntax_error_1.js sample_files/syntax_error_2.js
5bbd81f688bdcfbdbdf69d870f0c1357 -
c3b918adc3e37f06c65e76fdd4f967e3 -
sample_files/tab_1.c sample_files/tab_2.c
a7f9bce0ca76ce356413fb218d82d686 -
3e19a5dfb37bcda0fbc20e0446c65692 -
sample_files/tab_1.txt sample_files/tab_2.txt
a17e978720fe4c1b25614402910cc695 -
10e9a853917dc9d92d2867e3453269b2 -
sample_files/tailwind_1.css sample_files/tailwind_2.css
132f217659bf9dac8b82feabf5643f47 -
sample_files/text_1.txt sample_files/text_2.txt
f8f81946284fc625ac8e9ae441f31e6d -
caa98983e0fc26ae2bc833ae90fb0a1c -
sample_files/todomvc_1.gleam sample_files/todomvc_2.gleam
6b3b8c9f1e813617819b97144cc5cc4a -
sample_files/toml_1.toml sample_files/toml_2.toml
c331bdb54c00b0a5b5a622dbd250042a -
e1002ceba14d973fcc8abc23619e65b0 -
sample_files/trailling_newline_1.yaml sample_files/trailling_newline_2.yaml
8e37febfec957288576f9c2020cfc4f2 -
sample_files/typescript_1.ts sample_files/typescript_2.ts
fee7ee33d2037ad1941ba6bb5532a1db -
e15ceae53da7cfb308960f8c3f30b891 -
sample_files/typing_1.ml sample_files/typing_2.ml
975a97f2a6798abd1e4c0ce219e183fd -
ae41c3f5aa1ba13c2a424d3afa7ece6c -
sample_files/utf16_1.py sample_files/utf16_2.py
3bcee785d4cebc38a42eafe49a198b52 -
58f2fd906a5ed1b7c5d933bb380c5a1c -
sample_files/verilog_1.sv sample_files/verilog_2.sv
2f59632b5a4e5addfa7b4d5274da72cc -
0fbb9bd8ff99b8ee852741860d2c25d0 -
sample_files/vhdl_1.vhd sample_files/vhdl_2.vhd
ca98b4d14fc21e0f04cf24aeb3d2526c -
d23ea3d27a4cba037729adf485c84afa -
sample_files/whitespace_1.tsx sample_files/whitespace_2.tsx
6449f177ecbaadbbf97d2eedfbf26f16 -
789689b170b80ef280a322b3a6c7363b -
sample_files/windows1251_1.txt sample_files/windows1251_2.txt
9ebe6bb440ac2e630f889827b98d4714 -
28cb8832f6b172c34a28082012512269 -
sample_files/xml_1.xml sample_files/xml_2.xml
e629cbd2e721fd249c7ce1626f17e953 -
d943cb3ae6ea5a5b933ceb1b9987c06b -
sample_files/yaml_1.yaml sample_files/yaml_2.yaml
521a2075e4f8b0ea9fb74436e0445b52 -
a539973fd87b6f1fe1391ce73a9b9f90 -
sample_files/zig_1.zig sample_files/zig_2.zig
2cb2ce5bcb62c02a29da7ce8a33c6265 -
f548aaa131854792fe3b72bc283f1280 -

@ -324,6 +324,48 @@ pub(crate) fn novel_style(style: Style, side: Side, background: BackgroundColor)
}
}
/// Merge spans where the end of one span matches the start of the
/// next span.
///
/// This reduces the number of ANSI character codes in the
/// output. This is negligible for performance, but makes regression
/// testing easier for difftastic.
///
/// The file compare.expected contains hashes of the output, so it
/// considers `<green>ab</green>` to be distinct from
/// `<green>a</green><green>b</green>`. Merging the spans normalises
/// the output to `<green>ab</green>`.
fn merge_adjacent(items: &[(SingleLineSpan, Style)]) -> Vec<(SingleLineSpan, Style)> {
let mut merged: Vec<(SingleLineSpan, Style)> = vec![];
let mut prev_item: Option<(SingleLineSpan, Style)> = None;
for (span, style) in items.iter().copied() {
match prev_item.take() {
Some((mut prev_span, prev_style)) => {
if prev_style == style
&& prev_span.line == span.line
&& prev_span.end_col == span.start_col
{
prev_span.end_col = span.end_col;
prev_item = Some((prev_span, style));
} else {
merged.push((prev_span, prev_style));
prev_item = Some((span, style));
}
}
None => {
prev_item = Some((span, style));
}
}
}
if let Some(last_item) = prev_item {
merged.push(last_item);
}
merged
}
pub(crate) fn color_positions(
side: Side,
background: BackgroundColor,
@ -402,7 +444,8 @@ pub(crate) fn color_positions(
};
styles.push((mp.pos, style));
}
styles
merge_adjacent(&styles)
}
pub(crate) fn apply_colors(