diff --git a/sample_files/compare.expected b/sample_files/compare.expected index db0c2b663..950947509 100644 --- a/sample_files/compare.expected +++ b/sample_files/compare.expected @@ -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 - diff --git a/src/display/style.rs b/src/display/style.rs index 28d480e31..7a6e54179 100644 --- a/src/display/style.rs +++ b/src/display/style.rs @@ -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 `ab` to be distinct from +/// `ab`. Merging the spans normalises +/// the output to `ab`. +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(