summaryrefslogtreecommitdiffstats
path: root/vendor/prettydiff
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/prettydiff
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/prettydiff')
-rw-r--r--vendor/prettydiff/.cargo-checksum.json1
-rw-r--r--vendor/prettydiff/Cargo.lock622
-rw-r--r--vendor/prettydiff/Cargo.toml53
-rw-r--r--vendor/prettydiff/LICENSE21
-rw-r--r--vendor/prettydiff/README.md135
-rw-r--r--vendor/prettydiff/src/basic.rs169
-rw-r--r--vendor/prettydiff/src/format_table.rs38
-rw-r--r--vendor/prettydiff/src/lcs.rs227
-rw-r--r--vendor/prettydiff/src/lib.rs20
-rw-r--r--vendor/prettydiff/src/main.rs51
-rw-r--r--vendor/prettydiff/src/text.rs877
11 files changed, 2214 insertions, 0 deletions
diff --git a/vendor/prettydiff/.cargo-checksum.json b/vendor/prettydiff/.cargo-checksum.json
new file mode 100644
index 000000000..ecd9fa9dd
--- /dev/null
+++ b/vendor/prettydiff/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"87cb860de6bc0d894deaf44641c4034ebec8f0ae8a283f160ae6d7b875deb343","Cargo.toml":"a769bd8cdeb6fb5bf404b07d43b33f143509fe0e68f8f883ac87001d0f8d3999","LICENSE":"95b7a3611fd946d5a09aaa5f5270dc97632980e394fe749e1e5b6a5156716a3f","README.md":"7c3efef58b23289741daab7f048b26d758a0418cb304d24ea78f2db37a780c33","screens/app.png":"2f6c9cc5dd759920789b23d228125d2aab4f4ff59de43e418e92f8a645a88a1b","screens/diff_chars.png":"74adc717d599b53ffd1460a7c381d9be366d04308c4eb0672c9baf09cbffef0b","screens/diff_lines.png":"9e003be6b27837a08d38d216c381d16ecd3dc1cf3abcb387b72f7455e3b23263","screens/diff_slice.png":"5c5f0fde321b4c18db923bd0d53db6097ae673c9d5bc5f1748ea81f0010196ae","src/basic.rs":"4a312f1b541bc252efbdb42a5887d23d6351b2445c157becc7729ef8987460de","src/format_table.rs":"09faa7f16c0bb9db61cc63044e008ee86e88c479f3254dfd2af81f7679e6f726","src/lcs.rs":"91e6afc5e0a28354cf20446f8a308c0a37d1c7849fb564e5355b01141f0b89a9","src/lib.rs":"ad47c5609a4036579f86399c42dd48aec18ca683d77ebf8468fa01b8c4d42b53","src/main.rs":"3f95441205e1021c337abbb56ec40e31e1161a7c6eefe0e19e745004c48e5bb8","src/text.rs":"6dc399b32c32e6607f4c4e3556dede049c7b7e33e685b056c1c44176ec0e917a"},"package":"8ff1fec61082821f8236cf6c0c14e8172b62ce8a72a0eedc30d3b247bb68dc11"} \ No newline at end of file
diff --git a/vendor/prettydiff/Cargo.lock b/vendor/prettydiff/Cargo.lock
new file mode 100644
index 000000000..3eab886cc
--- /dev/null
+++ b/vendor/prettydiff/Cargo.lock
@@ -0,0 +1,622 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "ansi_term"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi 0.1.19",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "ansi_term",
+ "atty",
+ "bitflags",
+ "strsim",
+ "textwrap",
+ "unicode-width",
+ "vec_map",
+]
+
+[[package]]
+name = "csv"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad"
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "dirs-next"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
+dependencies = [
+ "cfg-if",
+ "dirs-sys-next",
+]
+
+[[package]]
+name = "dirs-sys-next"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
+name = "errno"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "256017f749ab3117e93acb91063009e1f1bb56d03965b14c2c8df4eb02c524d8"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.141"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "pad"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ad9b889f1b12e0b9ee24db044b5129150d5eada288edc800f789928dc8c0e3"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "prettydiff"
+version = "0.6.4"
+dependencies = [
+ "ansi_term",
+ "pad",
+ "prettytable-rs",
+ "structopt",
+]
+
+[[package]]
+name = "prettytable-rs"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a"
+dependencies = [
+ "csv",
+ "encode_unicode",
+ "is-terminal",
+ "lazy_static",
+ "term",
+ "unicode-width",
+]
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
+name = "rustix"
+version = "0.37.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aae838e49b3d63e9274e1c01833cc8139d3fec468c3b84688c628f44b1ae11d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.45.0",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
+
+[[package]]
+name = "ryu"
+version = "1.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+
+[[package]]
+name = "serde"
+version = "1.0.159"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065"
+
+[[package]]
+name = "strsim"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+
+[[package]]
+name = "structopt"
+version = "0.3.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
+dependencies = [
+ "clap",
+ "lazy_static",
+ "structopt-derive",
+]
+
+[[package]]
+name = "structopt-derive"
+version = "0.4.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
+dependencies = [
+ "heck",
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "term"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
+dependencies = [
+ "dirs-next",
+ "rustversion",
+ "winapi",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.13",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
+name = "version_check"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
+dependencies = [
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/vendor/prettydiff/Cargo.toml b/vendor/prettydiff/Cargo.toml
new file mode 100644
index 000000000..6b398dcaf
--- /dev/null
+++ b/vendor/prettydiff/Cargo.toml
@@ -0,0 +1,53 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "prettydiff"
+version = "0.6.4"
+authors = ["Roman Koblov <penpen938@me.com>"]
+description = "Side-by-side diff for two files"
+homepage = "https://github.com/romankoblov/prettydiff"
+readme = "README.md"
+keywords = [
+ "diff",
+ "text",
+ "compare",
+ "changes",
+]
+categories = ["text-processing"]
+license = "MIT"
+repository = "https://github.com/romankoblov/prettydiff"
+
+[[bin]]
+name = "prettydiff"
+required-features = ["cli"]
+
+[dependencies.ansi_term]
+version = "0.12"
+
+[dependencies.pad]
+version = "0.1.6"
+
+[dependencies.prettytable-rs]
+version = "0.10.0"
+optional = true
+
+[dependencies.structopt]
+version = "0.3"
+optional = true
+
+[features]
+cli = [
+ "prettytable-rs",
+ "structopt",
+]
+default = ["cli"]
diff --git a/vendor/prettydiff/LICENSE b/vendor/prettydiff/LICENSE
new file mode 100644
index 000000000..86ace6afc
--- /dev/null
+++ b/vendor/prettydiff/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2019 Roman Koblov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/prettydiff/README.md b/vendor/prettydiff/README.md
new file mode 100644
index 000000000..3d2aa64ee
--- /dev/null
+++ b/vendor/prettydiff/README.md
@@ -0,0 +1,135 @@
+# prettydiff
+
+[![Crate](https://img.shields.io/crates/v/prettydiff.svg)](https://crates.io/crates/prettydiff)
+[![docs.rs](https://docs.rs/prettydiff/badge.svg)](https://docs.rs/prettydiff)
+
+Side-by-side diff for two files in Rust. App && Library.
+
+## Examples
+
+### Slice diff
+
+```rust
+use prettydiff::diff_slice;
+
+println!("Diff: {}", diff_slice(&[1, 2, 3, 4, 5, 6], &[2, 3, 5, 7]));
+println!(
+ "Diff: {}",
+ diff_slice(&["q", "a", "b", "x", "c", "d"], &["a", "b", "y", "c", "d", "f"])
+);
+println!(
+ "Diff: {}",
+ diff_slice(&["a", "c", "d", "b"], &["a", "e", "b"])
+);
+ ```
+
+ ![diff_slice](https://raw.githubusercontent.com/romankoblov/prettydiff/master/screens/diff_slice.png)
+
+Get vector of changes:
+
+```rust
+use prettydiff::diff_slice;
+
+assert_eq!(
+ diff_slice(&["q", "a", "b", "x", "c", "d"], &["a", "b", "y", "c", "d", "f"]).diff,
+ vec![
+ DiffOp::Remove(&["q"]),
+ DiffOp::Equal(&["a", "b"]),
+ DiffOp::Replace(&["x"], &["y"]),
+ DiffOp::Equal(&["c", "d"]),
+ DiffOp::Insert(&["f"]),
+ ]
+);
+```
+
+### Diff line by chars or words
+
+![diff_chars](https://raw.githubusercontent.com/romankoblov/prettydiff/master/screens/diff_chars.png)
+
+```rust
+use prettydiff::{diff_chars, diff_words};
+
+println!("diff_chars: {}", diff_chars("abefcd", "zadqwc"));
+println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The quick brown fox jumps over the lazy dog",
+ "The quick brown dog leaps over the lazy cat"
+ )
+);
+println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+);
+println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+ .set_highlight_whitespace(true)
+);
+println!(
+ "diff_words: {}",
+ diff_words(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+);
+println!(
+ "diff_words: {}",
+ diff_words(
+ "The quick brown fox jumps over the lazy dog",
+ "The quick, brown dog leaps over the lazy cat"
+ )
+);
+```
+
+### Diff lines
+
+![diff_lines](https://raw.githubusercontent.com/romankoblov/prettydiff/master/screens/diff_lines.png)
+
+```rust
+use prettydiff::diff_lines;
+
+let code1_a = r#"
+void func1() {
+ x += 1
+}
+
+void func2() {
+ x += 2
+}
+ "#;
+let code1_b = r#"
+void func1(a: u32) {
+ x += 1
+}
+
+void functhreehalves() {
+ x += 1.5
+}
+
+void func2() {
+ x += 2
+}
+
+void func3(){}
+"#;
+println!("diff_lines:");
+println!("{}", diff_lines(code1_a, code1_b));
+```
+
+## App
+
+This crate also provides app for side-by-side diff:
+
+```sh
+cargo install prettydiff
+prettydiff left_file.txt right_file.txt
+```
+
+![App](https://raw.githubusercontent.com/romankoblov/prettydiff/master/screens/app.png) \ No newline at end of file
diff --git a/vendor/prettydiff/src/basic.rs b/vendor/prettydiff/src/basic.rs
new file mode 100644
index 000000000..d35392a7b
--- /dev/null
+++ b/vendor/prettydiff/src/basic.rs
@@ -0,0 +1,169 @@
+//! Basic diff functions
+use crate::lcs;
+use ansi_term::Colour;
+use std::fmt;
+
+/// Single change in original slice needed to get new slice
+#[derive(Debug, PartialEq, Eq)]
+pub enum DiffOp<'a, T: 'a> {
+ /// Appears only in second slice
+ Insert(&'a [T]),
+ /// Appears in both slices, but changed
+ Replace(&'a [T], &'a [T]),
+ /// Appears only in first slice
+ Remove(&'a [T]),
+ /// Appears on both slices
+ Equal(&'a [T]),
+}
+
+/// Diffs any slices which implements PartialEq
+pub fn diff<'a, T: PartialEq>(x: &'a [T], y: &'a [T]) -> Vec<DiffOp<'a, T>> {
+ let mut ops: Vec<DiffOp<T>> = Vec::new();
+ let table = lcs::Table::new(x, y);
+
+ let mut i = 0;
+ let mut j = 0;
+
+ for m in table.matches_zero() {
+ let x_seq = &x[i..m.x];
+ let y_seq = &y[j..m.y];
+
+ if i < m.x && j < m.y {
+ ops.push(DiffOp::Replace(x_seq, y_seq));
+ } else if i < m.x {
+ ops.push(DiffOp::Remove(x_seq));
+ } else if j < m.y {
+ ops.push(DiffOp::Insert(y_seq));
+ }
+
+ i = m.x + m.len;
+ j = m.y + m.len;
+
+ if m.len > 0 {
+ ops.push(DiffOp::Equal(&x[m.x..i]));
+ }
+ }
+ ops
+}
+
+/// Container for slice diff result. Can be pretty-printed by Display trait.
+#[derive(Debug, PartialEq, Eq)]
+pub struct SliceChangeset<'a, T> {
+ pub diff: Vec<DiffOp<'a, T>>,
+}
+
+impl<'a, T: fmt::Display> SliceChangeset<'a, T> {
+ pub fn format(&self, skip_same: bool) -> String {
+ let mut out: Vec<String> = Vec::with_capacity(self.diff.len());
+ for op in &self.diff {
+ match op {
+ DiffOp::Equal(a) => {
+ if !skip_same || a.len() == 1 {
+ for i in a.iter() {
+ out.push(format!(" {}", i))
+ }
+ } else if a.len() > 1 {
+ out.push(format!(" ... skip({}) ...", a.len()));
+ }
+ }
+
+ DiffOp::Insert(a) => {
+ for i in a.iter() {
+ out.push(Colour::Green.paint(format!("+ {}", i)).to_string());
+ }
+ }
+
+ DiffOp::Remove(a) => {
+ for i in a.iter() {
+ out.push(Colour::Red.paint(format!("- {}", i)).to_string());
+ }
+ }
+ DiffOp::Replace(a, b) => {
+ let min_len = std::cmp::min(a.len(), b.len());
+ let max_len = std::cmp::max(a.len(), b.len());
+
+ for i in 0..min_len {
+ out.push(
+ Colour::Yellow
+ .paint(format!("~ {} -> {}", a[i], b[i]))
+ .to_string(),
+ );
+ }
+ for i in min_len..max_len {
+ if max_len == a.len() {
+ out.push(Colour::Red.paint(format!("- {}", a[i])).to_string());
+ } else {
+ out.push(Colour::Green.paint(format!("+ {}", b[i])).to_string());
+ }
+ }
+ }
+ }
+ }
+ format!("[\n{}\n]", out.join(",\n"))
+ }
+}
+
+impl<'a, T: fmt::Display> fmt::Display for SliceChangeset<'a, T> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "{}", self.format(true))
+ }
+}
+
+/// Diff two arbitary slices with elements that support Display trait
+pub fn diff_slice<'a, T: PartialEq + std::fmt::Display>(
+ x: &'a [T],
+ y: &'a [T],
+) -> SliceChangeset<'a, T> {
+ let diff = diff(x, y);
+ SliceChangeset { diff }
+}
+
+#[test]
+fn test_basic() {
+ assert_eq!(
+ diff(&[1, 2, 3, 4, 5, 6], &[2, 3, 5, 7]),
+ vec![
+ DiffOp::Remove(&[1]),
+ DiffOp::Equal(&[2, 3]),
+ DiffOp::Remove(&[4]),
+ DiffOp::Equal(&[5]),
+ DiffOp::Replace(&[6], &[7]),
+ ]
+ );
+
+ assert_eq!(
+ diff_slice(
+ &["q", "a", "b", "x", "c", "d"],
+ &["a", "b", "y", "c", "d", "f"],
+ )
+ .diff,
+ vec![
+ DiffOp::Remove(&["q"]),
+ DiffOp::Equal(&["a", "b"]),
+ DiffOp::Replace(&["x"], &["y"]),
+ DiffOp::Equal(&["c", "d"]),
+ DiffOp::Insert(&["f"]),
+ ]
+ );
+
+ assert_eq!(
+ diff(&["a", "c", "d", "b"], &["a", "e", "b"]),
+ vec![
+ DiffOp::Equal(&["a"]),
+ DiffOp::Replace(&["c", "d"], &["e"]),
+ DiffOp::Equal(&["b"]),
+ ]
+ );
+ println!("Diff: {}", diff_slice(&[1, 2, 3, 4, 5, 6], &[2, 3, 5, 7]));
+ println!(
+ "Diff: {}",
+ diff_slice(
+ &["q", "a", "b", "x", "c", "d"],
+ &["a", "b", "y", "c", "d", "f"]
+ )
+ );
+ println!(
+ "Diff: {}",
+ diff_slice(&["a", "c", "d", "b"], &["a", "e", "b"])
+ );
+}
diff --git a/vendor/prettydiff/src/format_table.rs b/vendor/prettydiff/src/format_table.rs
new file mode 100644
index 000000000..7293faefd
--- /dev/null
+++ b/vendor/prettydiff/src/format_table.rs
@@ -0,0 +1,38 @@
+//! Setup unicode-formatted table for prettytable
+//!
+//! TODO: Move to separate crate
+
+use prettytable::format;
+use prettytable::Table;
+
+fn format_table(table: &mut Table) {
+ table.set_format(
+ format::FormatBuilder::new()
+ .column_separator('│')
+ .borders('│')
+ .separators(
+ &[format::LinePosition::Top],
+ format::LineSeparator::new('─', '┬', '┌', '┐'),
+ )
+ .separators(
+ &[format::LinePosition::Title],
+ format::LineSeparator::new('─', '┼', '├', '┤'),
+ )
+ .separators(
+ &[format::LinePosition::Intern],
+ format::LineSeparator::new('─', '┼', '├', '┤'),
+ )
+ .separators(
+ &[format::LinePosition::Bottom],
+ format::LineSeparator::new('─', '┴', '└', '┘'),
+ )
+ .padding(1, 1)
+ .build(),
+ );
+}
+/// Returns Table with unicode formatter
+pub fn new() -> Table {
+ let mut table = Table::new();
+ format_table(&mut table);
+ table
+}
diff --git a/vendor/prettydiff/src/lcs.rs b/vendor/prettydiff/src/lcs.rs
new file mode 100644
index 000000000..fc57edc77
--- /dev/null
+++ b/vendor/prettydiff/src/lcs.rs
@@ -0,0 +1,227 @@
+//! Common functions for [Longest common subsequences](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)
+//! on slice.
+
+cfg_prettytable! {
+ use crate::format_table;
+ use prettytable::{Cell, Row};
+}
+use std::cmp::max;
+
+#[derive(Debug)]
+pub struct Table<'a, T: 'a> {
+ x: &'a [T],
+ y: &'a [T],
+ table: Vec<Vec<usize>>,
+}
+
+/// Implements Longest Common Subsequences Table
+/// Memory requirement: O(N^2)
+///
+/// Based on [Wikipedia article](https://en.wikipedia.org/wiki/Longest_common_subsequence_problem)
+impl<'a, T> Table<'a, T>
+where
+ T: PartialEq,
+{
+ /// Creates new table for search common subsequences in x and y
+ pub fn new(x: &'a [T], y: &'a [T]) -> Table<'a, T> {
+ let x_len = x.len() + 1;
+ let y_len = y.len() + 1;
+ let mut table = vec![vec![0; y_len]; x_len];
+
+ for i in 1..x_len {
+ for j in 1..y_len {
+ table[i][j] = if x[i - 1] == y[j - 1] {
+ table[i - 1][j - 1] + 1
+ } else {
+ max(table[i][j - 1], table[i - 1][j])
+ };
+ }
+ }
+
+ Table { x, y, table }
+ }
+
+ fn seq_iter(&self) -> TableIter<T> {
+ TableIter {
+ x: self.x.len(),
+ y: self.y.len(),
+ table: self,
+ }
+ }
+ fn get_match(&self, x: usize, y: usize, len: usize) -> Match<T> {
+ Match {
+ x,
+ y,
+ len,
+ table: self,
+ }
+ }
+
+ /// Returns matches between X and Y
+ pub fn matches(&self) -> Vec<Match<T>> {
+ let mut matches: Vec<Match<T>> = Vec::new();
+ for (x, y) in self.seq_iter() {
+ if let Some(last) = matches.last_mut() {
+ if last.x == x + 1 && last.y == y + 1 {
+ last.x = x;
+ last.y = y;
+ last.len += 1;
+ continue;
+ }
+ }
+ matches.push(self.get_match(x, y, 1));
+ }
+ matches.reverse();
+ matches
+ }
+
+ /// Returns matches between X and Y with zero-len match at the end
+ pub fn matches_zero(&self) -> Vec<Match<T>> {
+ let mut matches = self.matches();
+ matches.push(self.get_match(self.x.len(), self.y.len(), 0));
+ matches
+ }
+
+ /// Find longest sequence
+ pub fn longest_seq(&self) -> Vec<&T> {
+ self.matches();
+ let mut common: Vec<_> = self.seq_iter().map(|(x, _y)| &self.x[x]).collect();
+ common.reverse();
+ common
+ }
+}
+
+#[cfg(feature = "prettytable-rs")]
+/// Prints pretty-table for LCS
+impl<'a, T> std::fmt::Display for Table<'a, T>
+where
+ T: std::fmt::Display,
+{
+ fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
+ let mut table = format_table::new();
+ let mut header = vec!["".to_string(), "Ø".to_string()];
+ for i in self.x {
+ header.push(format!("{}", i));
+ }
+
+ table.set_titles(Row::new(
+ header.into_iter().map(|i| Cell::new(&i)).collect(),
+ ));
+ for j in 0..=self.y.len() {
+ let mut row = vec![if j == 0 {
+ "Ø".to_string()
+ } else {
+ format!("{}", self.y[j - 1])
+ }];
+ for i in 0..=self.x.len() {
+ row.push(format!("{}", self.table[i][j]));
+ }
+ table.add_row(row.into_iter().map(|i| Cell::new(&i)).collect());
+ }
+ write!(formatter, "\n{}", table)
+ }
+}
+
+struct TableIter<'a, T: 'a> {
+ x: usize,
+ y: usize,
+ table: &'a Table<'a, T>,
+}
+
+impl<'a, T> Iterator for TableIter<'a, T> {
+ type Item = (usize, usize);
+ fn next(&mut self) -> Option<Self::Item> {
+ let table = &self.table.table;
+
+ while self.x != 0 && self.y != 0 {
+ let cur = table[self.x][self.y];
+
+ if cur == table[self.x - 1][self.y] {
+ self.x -= 1;
+ continue;
+ }
+ self.y -= 1;
+ if cur == table[self.x][self.y] {
+ continue;
+ }
+ self.x -= 1;
+ return Some((self.x, self.y));
+ }
+ None
+ }
+}
+
+pub struct Match<'a, T: 'a> {
+ pub x: usize,
+ pub y: usize,
+ pub len: usize,
+ table: &'a Table<'a, T>,
+}
+
+impl<'a, T> Match<'a, T> {
+ /// Returns matched sequence
+ pub fn seq(&self) -> &[T] {
+ &self.table.x[self.x..(self.x + self.len)]
+ }
+}
+
+#[test]
+fn test_table() {
+ let x = vec!["A", "G", "C", "A", "T"];
+ let y = vec!["G", "A", "C"];
+
+ let table = Table::new(&x, &y);
+ assert_eq!(
+ format!("{}", table),
+ r#"
+┌───┬───┬───┬───┬───┬───┬───┐
+│ │ Ø │ A │ G │ C │ A │ T │
+├───┼───┼───┼───┼───┼───┼───┤
+│ Ø │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │
+├───┼───┼───┼───┼───┼───┼───┤
+│ G │ 0 │ 0 │ 1 │ 1 │ 1 │ 1 │
+├───┼───┼───┼───┼───┼───┼───┤
+│ A │ 0 │ 1 │ 1 │ 1 │ 2 │ 2 │
+├───┼───┼───┼───┼───┼───┼───┤
+│ C │ 0 │ 1 │ 1 │ 2 │ 2 │ 2 │
+└───┴───┴───┴───┴───┴───┴───┘
+"#
+ );
+ assert_eq!(table.longest_seq(), vec![&"A", &"C"]);
+}
+
+#[test]
+
+fn test_table_match() {
+ let test_v = vec![
+ (
+ "The quick brown fox jumps over the lazy dog",
+ "The quick brown dog leaps over the lazy cat",
+ "The quick brown o ps over the lazy ",
+ vec!["The quick brown ", "o", " ", "ps over the lazy "],
+ ),
+ ("ab:c", "ba:b:c", "ab:c", vec!["a", "b:c"]),
+ (
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log",
+ "The brown fox ped over the rolling log",
+ vec!["The ", "brown ", "fox ", "ped over the rolling log"],
+ ),
+ ];
+ for (x_str, y_str, exp_str, match_exp) in test_v {
+ let x: Vec<_> = x_str.split("").collect();
+ let y: Vec<_> = y_str.split("").collect();
+
+ // Trim empty elements
+ let table = Table::new(&x[1..(x.len() - 1)], &y[1..(y.len() - 1)]);
+ let seq = table
+ .longest_seq()
+ .iter()
+ .map(|i| i.to_string())
+ .collect::<Vec<String>>()
+ .join("");
+ assert_eq!(seq, exp_str);
+ let matches: Vec<_> = table.matches().iter().map(|m| m.seq().join("")).collect();
+ assert_eq!(matches, match_exp);
+ }
+}
diff --git a/vendor/prettydiff/src/lib.rs b/vendor/prettydiff/src/lib.rs
new file mode 100644
index 000000000..ff9dae6ce
--- /dev/null
+++ b/vendor/prettydiff/src/lib.rs
@@ -0,0 +1,20 @@
+macro_rules! cfg_prettytable {( $($item:item)* ) => (
+ $(
+ #[cfg(feature = "prettytable-rs")]
+ $item
+ )*
+)}
+
+#[cfg(feature = "prettytable-rs")]
+#[macro_use]
+extern crate prettytable;
+
+pub mod basic;
+cfg_prettytable! {
+ pub mod format_table;
+}
+pub mod lcs;
+pub mod text;
+
+pub use crate::basic::diff_slice;
+pub use crate::text::{diff_chars, diff_lines, diff_words};
diff --git a/vendor/prettydiff/src/main.rs b/vendor/prettydiff/src/main.rs
new file mode 100644
index 000000000..9b6a59bbd
--- /dev/null
+++ b/vendor/prettydiff/src/main.rs
@@ -0,0 +1,51 @@
+use std::fs::File;
+use std::io::prelude::*;
+use std::path::PathBuf;
+use structopt::StructOpt;
+
+/// Side-by-side diff for two files
+#[derive(StructOpt, Debug)]
+#[structopt(name = "prettydiff")]
+struct Opt {
+ /// Left file
+ #[structopt(name = "LEFT", parse(from_os_str))]
+ left: PathBuf,
+ /// Right file
+ #[structopt(name = "RIGHT", parse(from_os_str))]
+ right: PathBuf,
+ /// Don't show lines numbers
+ #[structopt(long = "disable_lines")]
+ disable_lines: bool,
+ /// Show non-changed blocks
+ #[structopt(long = "show_same")]
+ show_same: bool,
+ /// Align new lines inside change block
+ #[structopt(long = "disable_align")]
+ disable_align: bool,
+}
+
+fn read_file(path: &PathBuf) -> std::io::Result<String> {
+ let mut file = File::open(path)?;
+ let mut contents = String::new();
+ file.read_to_string(&mut contents)?;
+ Ok(contents)
+}
+
+fn main() -> std::io::Result<()> {
+ let opt = Opt::from_args();
+
+ let left_data = read_file(&opt.left)?;
+ let left_name = opt.left.into_os_string().into_string().unwrap();
+
+ let right_data = read_file(&opt.right)?;
+ let right_name = opt.right.into_os_string().into_string().unwrap();
+
+ prettydiff::diff_lines(&left_data, &right_data)
+ .names(&left_name, &right_name)
+ .set_show_lines(!opt.disable_lines)
+ .set_diff_only(!opt.show_same)
+ .set_align_new_lines(!opt.disable_align)
+ .prettytable();
+
+ Ok(())
+}
diff --git a/vendor/prettydiff/src/text.rs b/vendor/prettydiff/src/text.rs
new file mode 100644
index 000000000..0d5fc03c3
--- /dev/null
+++ b/vendor/prettydiff/src/text.rs
@@ -0,0 +1,877 @@
+//! Utils for diff text
+pub use ansi_term::Style;
+
+use crate::basic;
+cfg_prettytable! {
+ use crate::format_table;
+ use prettytable::{Cell, Row};
+}
+use ansi_term::Colour;
+use pad::{Alignment, PadStr};
+use std::{
+ cmp::{max, min},
+ fmt,
+};
+
+pub struct StringSplitIter<'a, F>
+where
+ F: Fn(char) -> bool,
+{
+ last: usize,
+ text: &'a str,
+ matched: Option<&'a str>,
+ iter: std::str::MatchIndices<'a, F>,
+}
+
+impl<'a, F> Iterator for StringSplitIter<'a, F>
+where
+ F: Fn(char) -> bool,
+{
+ type Item = &'a str;
+ fn next(&mut self) -> Option<Self::Item> {
+ if let Some(m) = self.matched {
+ self.matched = None;
+ Some(m)
+ } else if let Some((idx, matched)) = self.iter.next() {
+ let res = if self.last != idx {
+ self.matched = Some(matched);
+ &self.text[self.last..idx]
+ } else {
+ matched
+ };
+ self.last = idx + matched.len();
+ Some(res)
+ } else if self.last < self.text.len() {
+ let res = &self.text[self.last..];
+ self.last = self.text.len();
+ Some(res)
+ } else {
+ None
+ }
+ }
+}
+
+pub fn collect_strings<T: ToString>(it: impl Iterator<Item = T>) -> Vec<String> {
+ it.map(|s| s.to_string()).collect::<Vec<String>>()
+}
+
+/// Split string by clousure (Fn(char)->bool) keeping delemiters
+pub fn split_by_char_fn<F>(text: &'_ str, pat: F) -> StringSplitIter<'_, F>
+where
+ F: Fn(char) -> bool,
+{
+ StringSplitIter {
+ last: 0,
+ text,
+ matched: None,
+ iter: text.match_indices(pat),
+ }
+}
+
+/// Split string by non-alphanumeric characters keeping delemiters
+pub fn split_words(text: &str) -> impl Iterator<Item = &str> {
+ split_by_char_fn(text, |c: char| !c.is_alphanumeric())
+}
+
+/// Container for inline text diff result. Can be pretty-printed by Display trait.
+#[derive(Debug, PartialEq)]
+pub struct InlineChangeset<'a> {
+ old: Vec<&'a str>,
+ new: Vec<&'a str>,
+ separator: &'a str,
+ highlight_whitespace: bool,
+ insert_style: Style,
+ insert_whitespace_style: Style,
+ remove_style: Style,
+ remove_whitespace_style: Style,
+}
+
+impl<'a> InlineChangeset<'a> {
+ pub fn new(old: Vec<&'a str>, new: Vec<&'a str>) -> InlineChangeset<'a> {
+ InlineChangeset {
+ old,
+ new,
+ separator: "",
+ highlight_whitespace: true,
+ insert_style: Colour::Green.normal(),
+ insert_whitespace_style: Colour::White.on(Colour::Green),
+ remove_style: Colour::Red.strikethrough(),
+ remove_whitespace_style: Colour::White.on(Colour::Red),
+ }
+ }
+ /// Highlight whitespaces in case of insert/remove?
+ pub fn set_highlight_whitespace(mut self, val: bool) -> Self {
+ self.highlight_whitespace = val;
+ self
+ }
+
+ /// Style of inserted text
+ pub fn set_insert_style(mut self, val: Style) -> Self {
+ self.insert_style = val;
+ self
+ }
+
+ /// Style of inserted whitespace
+ pub fn set_insert_whitespace_style(mut self, val: Style) -> Self {
+ self.insert_whitespace_style = val;
+ self
+ }
+
+ /// Style of removed text
+ pub fn set_remove_style(mut self, val: Style) -> Self {
+ self.remove_style = val;
+ self
+ }
+
+ /// Style of removed whitespace
+ pub fn set_remove_whitespace_style(mut self, val: Style) -> Self {
+ self.remove_whitespace_style = val;
+ self
+ }
+
+ /// Set output separator
+ pub fn set_separator(mut self, val: &'a str) -> Self {
+ self.separator = val;
+ self
+ }
+
+ /// Returns Vec of changes
+ pub fn diff(&self) -> Vec<basic::DiffOp<'a, &str>> {
+ basic::diff(&self.old, &self.new)
+ }
+
+ fn apply_style(&self, style: Style, whitespace_style: Style, a: &[&str]) -> String {
+ let s = a.join(self.separator);
+ if self.highlight_whitespace {
+ collect_strings(split_by_char_fn(&s, |c| c.is_whitespace()).map(|s| {
+ let style = if s
+ .chars()
+ .next()
+ .map_or_else(|| false, |c| c.is_whitespace())
+ {
+ whitespace_style
+ } else {
+ style
+ };
+ style.paint(s)
+ }))
+ .join("")
+ } else {
+ style.paint(s).to_string()
+ }
+ }
+
+ fn remove_color(&self, a: &[&str]) -> String {
+ self.apply_style(self.remove_style, self.remove_whitespace_style, a)
+ }
+
+ fn insert_color(&self, a: &[&str]) -> String {
+ self.apply_style(self.insert_style, self.insert_whitespace_style, a)
+ }
+ /// Returns formatted string with colors
+ pub fn format(&self) -> String {
+ let diff = self.diff();
+ let mut out: Vec<String> = Vec::with_capacity(diff.len());
+ for op in diff {
+ match op {
+ basic::DiffOp::Equal(a) => out.push(a.join(self.separator)),
+ basic::DiffOp::Insert(a) => out.push(self.insert_color(a)),
+ basic::DiffOp::Remove(a) => out.push(self.remove_color(a)),
+ basic::DiffOp::Replace(a, b) => {
+ out.push(self.remove_color(a));
+ out.push(self.insert_color(b));
+ }
+ }
+ }
+ out.join(self.separator)
+ }
+}
+
+impl<'a> fmt::Display for InlineChangeset<'a> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "{}", self.format())
+ }
+}
+
+pub fn diff_chars<'a>(old: &'a str, new: &'a str) -> InlineChangeset<'a> {
+ let old: Vec<&str> = old.split("").filter(|&i| i != "").collect();
+ let new: Vec<&str> = new.split("").filter(|&i| i != "").collect();
+
+ InlineChangeset::new(old, new)
+}
+
+/// Diff two strings by words (contiguous)
+pub fn diff_words<'a>(old: &'a str, new: &'a str) -> InlineChangeset<'a> {
+ InlineChangeset::new(split_words(old).collect(), split_words(new).collect())
+}
+
+#[cfg(feature = "prettytable-rs")]
+fn color_multilines(color: Colour, s: &str) -> String {
+ collect_strings(s.split('\n').map(|i| color.paint(i))).join("\n")
+}
+
+#[derive(Debug)]
+pub struct ContextConfig<'a> {
+ pub context_size: usize,
+ pub skipping_marker: &'a str,
+}
+
+/// Container for line-by-line text diff result. Can be pretty-printed by Display trait.
+#[derive(Debug, PartialEq, Eq)]
+pub struct LineChangeset<'a> {
+ old: Vec<&'a str>,
+ new: Vec<&'a str>,
+
+ names: Option<(&'a str, &'a str)>,
+ diff_only: bool,
+ show_lines: bool,
+ trim_new_lines: bool,
+ aling_new_lines: bool,
+}
+
+impl<'a> LineChangeset<'a> {
+ pub fn new(old: Vec<&'a str>, new: Vec<&'a str>) -> LineChangeset<'a> {
+ LineChangeset {
+ old,
+ new,
+ names: None,
+ diff_only: false,
+ show_lines: true,
+ trim_new_lines: true,
+ aling_new_lines: false,
+ }
+ }
+
+ /// Sets names for side-by-side diff
+ pub fn names(mut self, old: &'a str, new: &'a str) -> Self {
+ self.names = Some((old, new));
+ self
+ }
+ /// Show only differences for side-by-side diff
+ pub fn set_diff_only(mut self, val: bool) -> Self {
+ self.diff_only = val;
+ self
+ }
+ /// Show lines in side-by-side diff
+ pub fn set_show_lines(mut self, val: bool) -> Self {
+ self.show_lines = val;
+ self
+ }
+ /// Trim new lines in side-by-side diff
+ pub fn set_trim_new_lines(mut self, val: bool) -> Self {
+ self.trim_new_lines = val;
+ self
+ }
+ /// Align new lines inside diff
+ pub fn set_align_new_lines(mut self, val: bool) -> Self {
+ self.aling_new_lines = val;
+ self
+ }
+ /// Returns Vec of changes
+ pub fn diff(&self) -> Vec<basic::DiffOp<'a, &str>> {
+ basic::diff(&self.old, &self.new)
+ }
+
+ #[cfg(feature = "prettytable-rs")]
+ fn prettytable_process(&self, a: &[&str], color: Option<Colour>) -> (String, usize) {
+ let mut start = 0;
+ let mut stop = a.len();
+ if self.trim_new_lines {
+ for (index, element) in a.iter().enumerate() {
+ if *element != "" {
+ break;
+ }
+ start = index + 1;
+ }
+ for (index, element) in a.iter().enumerate().rev() {
+ if *element != "" {
+ stop = index + 1;
+ break;
+ }
+ }
+ }
+ let out = &a[start..stop];
+ if let Some(color) = color {
+ (
+ collect_strings(out.iter().map(|i| color.paint(*i).to_string()))
+ .join("\n")
+ .replace("\t", " "),
+ start,
+ )
+ } else {
+ (out.join("\n").replace("\t", " "), start)
+ }
+ }
+
+ #[cfg(feature = "prettytable-rs")]
+ fn prettytable_process_replace(
+ &self,
+ old: &[&str],
+ new: &[&str],
+ ) -> ((String, String), (usize, usize)) {
+ let (old, old_offset) = self.prettytable_process(old, None);
+ let (new, new_offset) = self.prettytable_process(new, None);
+
+ let mut old_out = String::new();
+ let mut new_out = String::new();
+
+ for op in diff_words(&old, &new).diff() {
+ match op {
+ basic::DiffOp::Equal(a) => {
+ old_out.push_str(&a.join(""));
+ new_out.push_str(&a.join(""));
+ }
+ basic::DiffOp::Insert(a) => {
+ new_out.push_str(&color_multilines(Colour::Green, &a.join("")));
+ }
+ basic::DiffOp::Remove(a) => {
+ old_out.push_str(&color_multilines(Colour::Red, &a.join("")));
+ }
+ basic::DiffOp::Replace(a, b) => {
+ old_out.push_str(&color_multilines(Colour::Red, &a.join("")));
+ new_out.push_str(&color_multilines(Colour::Green, &b.join("")));
+ }
+ }
+ }
+
+ ((old_out, new_out), (old_offset, new_offset))
+ }
+
+ #[cfg(feature = "prettytable-rs")]
+ /// Prints side-by-side diff in table
+ pub fn prettytable(&self) {
+ let mut table = format_table::new();
+ if let Some((old, new)) = &self.names {
+ let mut header = vec![];
+ if self.show_lines {
+ header.push(Cell::new(""));
+ }
+ header.push(Cell::new(&Colour::Cyan.paint(old.to_string()).to_string()));
+ if self.show_lines {
+ header.push(Cell::new(""));
+ }
+ header.push(Cell::new(&Colour::Cyan.paint(new.to_string()).to_string()));
+ table.set_titles(Row::new(header));
+ }
+ let mut old_lines = 1;
+ let mut new_lines = 1;
+ let mut out: Vec<(usize, String, usize, String)> = Vec::new();
+ for op in &self.diff() {
+ match op {
+ basic::DiffOp::Equal(a) => {
+ let (old, offset) = self.prettytable_process(a, None);
+ if !self.diff_only {
+ out.push((old_lines + offset, old.clone(), new_lines + offset, old));
+ }
+ old_lines += a.len();
+ new_lines += a.len();
+ }
+ basic::DiffOp::Insert(a) => {
+ let (new, offset) = self.prettytable_process(a, Some(Colour::Green));
+ out.push((old_lines, "".to_string(), new_lines + offset, new));
+ new_lines += a.len();
+ }
+ basic::DiffOp::Remove(a) => {
+ let (old, offset) = self.prettytable_process(a, Some(Colour::Red));
+ out.push((old_lines + offset, old, new_lines, "".to_string()));
+ old_lines += a.len();
+ }
+ basic::DiffOp::Replace(a, b) => {
+ let ((old, new), (old_offset, new_offset)) =
+ self.prettytable_process_replace(a, b);
+ out.push((old_lines + old_offset, old, new_lines + new_offset, new));
+ old_lines += a.len();
+ new_lines += b.len();
+ }
+ };
+ }
+ for (old_lines, old, new_lines, new) in out {
+ if self.trim_new_lines && old.trim() == "" && new.trim() == "" {
+ continue;
+ }
+ if self.show_lines {
+ table.add_row(row![old_lines, old, new_lines, new]);
+ } else {
+ table.add_row(row![old, new]);
+ }
+ }
+ table.printstd();
+ }
+
+ fn remove_color(&self, a: &str) -> String {
+ Colour::Red.strikethrough().paint(a).to_string()
+ }
+
+ fn insert_color(&self, a: &str) -> String {
+ Colour::Green.paint(a).to_string()
+ }
+
+ /// Returns formatted string with colors
+ pub fn format(&self) -> String {
+ self.format_with_context(None, false)
+ }
+
+ /// Formats lines in DiffOp::Equal
+ fn format_equal(
+ &self,
+ lines: &[&str],
+ display_line_numbers: bool,
+ prefix_size: usize,
+ line_counter: &mut usize,
+ ) -> Option<String> {
+ lines
+ .iter()
+ .map(|line| {
+ let res = if display_line_numbers {
+ format!("{} ", *line_counter)
+ .pad_to_width_with_alignment(prefix_size, Alignment::Right)
+ + line
+ } else {
+ "".pad_to_width(prefix_size) + line
+ };
+ *line_counter += 1;
+ res
+ })
+ .reduce(|acc, line| acc + "\n" + &line)
+ }
+
+ /// Formats lines in DiffOp::Remove
+ fn format_remove(
+ &self,
+ lines: &[&str],
+ display_line_numbers: bool,
+ prefix_size: usize,
+ line_counter: &mut usize,
+ ) -> String {
+ lines
+ .iter()
+ .map(|line| {
+ let res = if display_line_numbers {
+ format!("{} ", *line_counter)
+ .pad_to_width_with_alignment(prefix_size, Alignment::Right)
+ + &self.remove_color(line)
+ } else {
+ "".pad_to_width(prefix_size) + &self.remove_color(line)
+ };
+ *line_counter += 1;
+ res
+ })
+ .reduce(|acc, line| acc + "\n" + &line)
+ .unwrap()
+ }
+
+ /// Formats lines in DiffOp::Insert
+ fn format_insert(&self, lines: &[&str], prefix_size: usize) -> String {
+ lines
+ .iter()
+ .map(|line| "".pad_to_width(prefix_size) + &self.insert_color(line))
+ .reduce(|acc, line| acc + "\n" + &line)
+ .unwrap()
+ }
+
+ /// Returns formatted string with colors.
+ /// May omit identical lines, if `context_size` is `Some(k)`.
+ /// In this case, only print identical lines if they are within `k` lines
+ /// of a changed line (as in `diff -C`).
+ pub fn format_with_context(
+ &self,
+ context_config: Option<ContextConfig>,
+ display_line_numbers: bool,
+ ) -> String {
+ let line_number_size = if display_line_numbers {
+ (self.old.len() as f64).log10().ceil() as usize
+ } else {
+ 0
+ };
+ let skipping_marker_size = if let Some(ContextConfig {
+ skipping_marker, ..
+ }) = context_config
+ {
+ skipping_marker.len()
+ } else {
+ 0
+ };
+ let prefix_size = max(line_number_size, skipping_marker_size) + 1;
+
+ let mut next_line = 1;
+
+ let mut diff = self.diff().into_iter().peekable();
+ let mut out: Vec<String> = Vec::with_capacity(diff.len());
+ let mut at_beginning = true;
+ while let Some(op) = diff.next() {
+ match op {
+ basic::DiffOp::Equal(a) => match context_config {
+ None => out.push(a.join("\n")),
+ Some(ContextConfig {
+ context_size,
+ skipping_marker,
+ }) => {
+ let mut lines = a;
+ if !at_beginning {
+ let upper_bound = min(context_size, lines.len());
+ if let Some(newlines) = self.format_equal(
+ &lines[..upper_bound],
+ display_line_numbers,
+ prefix_size,
+ &mut next_line,
+ ) {
+ out.push(newlines)
+ }
+ lines = &lines[upper_bound..];
+ }
+ if lines.len() == 0 {
+ continue;
+ }
+ let lower_bound = if lines.len() > context_size {
+ lines.len() - context_size
+ } else {
+ 0
+ };
+ if lower_bound > 0 {
+ out.push(skipping_marker.to_string());
+ next_line += lower_bound
+ }
+ if diff.peek().is_none() {
+ continue;
+ }
+ if let Some(newlines) = self.format_equal(
+ &lines[lower_bound..],
+ display_line_numbers,
+ prefix_size,
+ &mut next_line,
+ ) {
+ out.push(newlines)
+ }
+ }
+ },
+ basic::DiffOp::Insert(a) => out.push(self.format_insert(a, prefix_size)),
+ basic::DiffOp::Remove(a) => out.push(self.format_remove(
+ a,
+ display_line_numbers,
+ prefix_size,
+ &mut next_line,
+ )),
+ basic::DiffOp::Replace(a, b) => {
+ out.push(self.format_remove(
+ a,
+ display_line_numbers,
+ prefix_size,
+ &mut next_line,
+ ));
+ out.push(self.format_insert(b, prefix_size));
+ }
+ }
+ at_beginning = false;
+ }
+ out.join("\n")
+ }
+}
+
+impl<'a> fmt::Display for LineChangeset<'a> {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "{}", self.format())
+ }
+}
+
+pub fn diff_lines<'a>(old: &'a str, new: &'a str) -> LineChangeset<'a> {
+ let old: Vec<&str> = old.lines().collect();
+ let new: Vec<&str> = new.lines().collect();
+
+ LineChangeset::new(old, new)
+}
+
+fn _test_splitter_basic(text: &str, exp: &[&str]) {
+ let res = collect_strings(
+ split_by_char_fn(&text, |c: char| c.is_whitespace()).map(|s| s.to_string()),
+ );
+ assert_eq!(res, exp)
+}
+
+#[test]
+fn test_splitter() {
+ _test_splitter_basic(
+ " blah test2 test3 ",
+ &[" ", " ", "blah", " ", "test2", " ", "test3", " ", " "],
+ );
+ _test_splitter_basic(
+ "\tblah test2 test3 ",
+ &["\t", "blah", " ", "test2", " ", "test3", " ", " "],
+ );
+ _test_splitter_basic(
+ "\tblah test2 test3 t",
+ &["\t", "blah", " ", "test2", " ", "test3", " ", " ", "t"],
+ );
+ _test_splitter_basic(
+ "\tblah test2 test3 tt",
+ &["\t", "blah", " ", "test2", " ", "test3", " ", " ", "tt"],
+ );
+}
+
+#[test]
+fn test_basic() {
+ println!("diff_chars: {}", diff_chars("abefcd", "zadqwc"));
+ println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The quick brown fox jumps over the lazy dog",
+ "The quick brown dog leaps over the lazy cat"
+ )
+ );
+ println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+ );
+ println!(
+ "diff_chars: {}",
+ diff_chars(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+ .set_highlight_whitespace(true)
+ );
+ println!(
+ "diff_words: {}",
+ diff_words(
+ "The red brown fox jumped over the rolling log",
+ "The brown spotted fox leaped over the rolling log"
+ )
+ );
+ println!(
+ "diff_words: {}",
+ diff_words(
+ "The quick brown fox jumps over the lazy dog",
+ "The quick, brown dog leaps over the lazy cat"
+ )
+ );
+}
+
+#[test]
+fn test_split_words() {
+ assert_eq!(
+ collect_strings(split_words("Hello World")),
+ ["Hello", " ", "World"]
+ );
+ assert_eq!(
+ collect_strings(split_words("Hello😋World")),
+ ["Hello", "😋", "World"]
+ );
+ assert_eq!(
+ collect_strings(split_words(
+ "The red brown fox\tjumped, over the rolling log"
+ )),
+ [
+ "The", " ", "red", " ", "brown", " ", "fox", "\t", "jumped", ",", " ", "over", " ",
+ "the", " ", "rolling", " ", "log"
+ ]
+ );
+}
+
+#[test]
+fn test_diff_lines() {
+ let code1_a = r#"
+void func1() {
+ x += 1
+}
+
+void func2() {
+ x += 2
+}
+ "#;
+ let code1_b = r#"
+void func1(a: u32) {
+ x += 1
+}
+
+void functhreehalves() {
+ x += 1.5
+}
+
+void func2() {
+ x += 2
+}
+
+void func3(){}
+"#;
+ println!("diff_lines:");
+ println!("{}", diff_lines(code1_a, code1_b));
+ println!("====");
+ diff_lines(code1_a, code1_b)
+ .names("left", "right")
+ .set_align_new_lines(true)
+ .prettytable();
+}
+
+fn _test_colors(changeset: &InlineChangeset, exp: &[(Option<Style>, &str)]) {
+ let color_s: String = collect_strings(exp.iter().map(|(style_opt, s)| {
+ if let Some(style) = style_opt {
+ style.paint(s.to_string()).to_string()
+ } else {
+ s.to_string()
+ }
+ }))
+ .join("");
+ assert_eq!(format!("{}", changeset), color_s);
+}
+
+#[test]
+fn test_diff_words_issue_1() {
+ let insert_style = Colour::Green.normal();
+ let insert_whitespace_style = Colour::White.on(Colour::Green);
+ let remove_style = Colour::Red.strikethrough();
+ let remove_whitespace_style = Colour::White.on(Colour::Red);
+ let d1 = diff_words(
+ "und meine Unschuld beweisen!",
+ "und ich werde meine Unschuld beweisen!",
+ )
+ .set_insert_style(insert_style)
+ .set_insert_whitespace_style(insert_whitespace_style)
+ .set_remove_style(remove_style)
+ .set_remove_whitespace_style(remove_whitespace_style);
+
+ println!("diff_words: {} {:?}", d1, d1.diff());
+
+ _test_colors(
+ &d1,
+ &[
+ (None, "und "),
+ (Some(insert_style), "ich"),
+ (Some(insert_whitespace_style), " "),
+ (Some(insert_style), "werde"),
+ (Some(insert_whitespace_style), " "),
+ (None, "meine Unschuld beweisen!"),
+ ],
+ );
+ _test_colors(
+ &d1.set_highlight_whitespace(false),
+ &[
+ (None, "und "),
+ (Some(insert_style), "ich werde "),
+ (None, "meine Unschuld beweisen!"),
+ ],
+ );
+ let d2 = diff_words(
+ "Campaignings aus dem Ausland gegen meine Person ausfindig",
+ "Campaignings ausfindig",
+ );
+ println!("diff_words: {} {:?}", d2, d2.diff());
+ _test_colors(
+ &d2,
+ &[
+ (None, "Campaignings "),
+ (Some(remove_style), "aus"),
+ (Some(remove_whitespace_style), " "),
+ (Some(remove_style), "dem"),
+ (Some(remove_whitespace_style), " "),
+ (Some(remove_style), "Ausland"),
+ (Some(remove_whitespace_style), " "),
+ (Some(remove_style), "gegen"),
+ (Some(remove_whitespace_style), " "),
+ (Some(remove_style), "meine"),
+ (Some(remove_whitespace_style), " "),
+ (Some(remove_style), "Person"),
+ (Some(remove_whitespace_style), " "),
+ (None, "ausfindig"),
+ ],
+ );
+ let d3 = diff_words("des kriminellen Videos", "des kriminell erstellten Videos");
+ println!("diff_words: {} {:?}", d3, d3.diff());
+ _test_colors(
+ &d3,
+ &[
+ (None, "des "),
+ (Some(remove_style), "kriminellen"),
+ (Some(insert_style), "kriminell"),
+ (None, " "),
+ (Some(insert_style), "erstellten"),
+ (Some(insert_whitespace_style), " "),
+ (None, "Videos"),
+ ],
+ );
+}
+
+#[test]
+fn test_prettytable_process() {
+ let d1 = diff_lines(
+ r#"line1
+ line2
+ line3
+ "#,
+ r#"line1
+ line2
+ line2.5
+ line3
+ "#,
+ );
+
+ println!("diff_lines: {} {:?}", d1, d1.diff());
+ assert_eq!(d1.prettytable_process(&["a", "b", "c"], None), (String::from("a\nb\nc"), 0));
+ assert_eq!(d1.prettytable_process(&["a", "b", "c", ""], None), (String::from("a\nb\nc"), 0));
+ assert_eq!(d1.prettytable_process(&["", "a", "b", "c"], None), (String::from("a\nb\nc"), 1));
+ assert_eq!(d1.prettytable_process(&["", "a", "b", "c", ""], None), (String::from("a\nb\nc"), 1));
+}
+
+#[test]
+fn test_format_with_context() {
+ let d = diff_lines(
+ r#"line1
+ line2
+ line3
+ line4
+ line5
+ line6
+ line7
+ line8
+ line9
+ line10
+ line11
+ line12"#,
+ r#"line1
+ line2
+ line4
+ line5
+ line6.5
+ line7
+ line8
+ line9
+ line10
+ line11.5
+ line12"#,
+ );
+ let context = |n| ContextConfig {
+ context_size: n,
+ skipping_marker: "...",
+ };
+ println!(
+ "diff_lines:\n{}\n{:?}",
+ d.format_with_context(Some(context(0)), true),
+ d.diff()
+ );
+ let formatted_none = d.format_with_context(None, true);
+ let formatted_some_0 = d.format_with_context(Some(context(0)), true);
+ let formatted_some_1 = d.format_with_context(Some(context(1)), true);
+ let formatted_some_2 = d.format_with_context(Some(context(2)), true);
+ // With a context of size 2, every line is present
+ assert_eq!(
+ formatted_none.lines().count(),
+ formatted_some_2.lines().count()
+ );
+ // with a context of size 1:
+ // * line 1 is replaced by '...' (-0 lines)
+ // * line 8-9 are replaced by '...' (-1 line)
+ assert_eq!(
+ formatted_none.lines().count() - 1,
+ formatted_some_1.lines().count()
+ );
+ // with a context of size 0:
+ // * lines 1-2 are replaced by '...' (-1 line)
+ // * lines 4-5 are replaced by '...' (-1 line)
+ // * lines 7-10 are replaced by '...' (-3 lines)
+ // * line 12 is replaced by '...' (-0 lines)
+ assert_eq!(
+ formatted_none.lines().count() - 5,
+ formatted_some_0.lines().count()
+ );
+}