Watches a file and prints human-readable, coloured diffs.

Initial commit

nasso.dev 4763cf78

+1
.gitignore
··· 1 + /target
+501
Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "anstream" 7 + version = "0.6.21" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" 10 + dependencies = [ 11 + "anstyle", 12 + "anstyle-parse", 13 + "anstyle-query", 14 + "anstyle-wincon", 15 + "colorchoice", 16 + "is_terminal_polyfill", 17 + "utf8parse", 18 + ] 19 + 20 + [[package]] 21 + name = "anstyle" 22 + version = "1.0.13" 23 + source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" 25 + 26 + [[package]] 27 + name = "anstyle-parse" 28 + version = "0.2.7" 29 + source = "registry+https://github.com/rust-lang/crates.io-index" 30 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 31 + dependencies = [ 32 + "utf8parse", 33 + ] 34 + 35 + [[package]] 36 + name = "anstyle-query" 37 + version = "1.1.4" 38 + source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 40 + dependencies = [ 41 + "windows-sys 0.60.2", 42 + ] 43 + 44 + [[package]] 45 + name = "anstyle-wincon" 46 + version = "3.0.10" 47 + source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 49 + dependencies = [ 50 + "anstyle", 51 + "once_cell_polyfill", 52 + "windows-sys 0.60.2", 53 + ] 54 + 55 + [[package]] 56 + name = "anyhow" 57 + version = "1.0.100" 58 + source = "registry+https://github.com/rust-lang/crates.io-index" 59 + checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 60 + 61 + [[package]] 62 + name = "bitflags" 63 + version = "1.3.2" 64 + source = "registry+https://github.com/rust-lang/crates.io-index" 65 + checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 66 + 67 + [[package]] 68 + name = "bitflags" 69 + version = "2.9.4" 70 + source = "registry+https://github.com/rust-lang/crates.io-index" 71 + checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 72 + 73 + [[package]] 74 + name = "clap" 75 + version = "4.5.49" 76 + source = "registry+https://github.com/rust-lang/crates.io-index" 77 + checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" 78 + dependencies = [ 79 + "clap_builder", 80 + "clap_derive", 81 + ] 82 + 83 + [[package]] 84 + name = "clap_builder" 85 + version = "4.5.49" 86 + source = "registry+https://github.com/rust-lang/crates.io-index" 87 + checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" 88 + dependencies = [ 89 + "anstream", 90 + "anstyle", 91 + "clap_lex", 92 + "strsim", 93 + ] 94 + 95 + [[package]] 96 + name = "clap_derive" 97 + version = "4.5.49" 98 + source = "registry+https://github.com/rust-lang/crates.io-index" 99 + checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" 100 + dependencies = [ 101 + "heck", 102 + "proc-macro2", 103 + "quote", 104 + "syn", 105 + ] 106 + 107 + [[package]] 108 + name = "clap_lex" 109 + version = "0.7.6" 110 + source = "registry+https://github.com/rust-lang/crates.io-index" 111 + checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" 112 + 113 + [[package]] 114 + name = "colorchoice" 115 + version = "1.0.4" 116 + source = "registry+https://github.com/rust-lang/crates.io-index" 117 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 118 + 119 + [[package]] 120 + name = "diff" 121 + version = "0.1.13" 122 + source = "registry+https://github.com/rust-lang/crates.io-index" 123 + checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" 124 + 125 + [[package]] 126 + name = "diffwatch" 127 + version = "0.1.0" 128 + dependencies = [ 129 + "anyhow", 130 + "clap", 131 + "diff", 132 + "notify", 133 + "termcolor", 134 + ] 135 + 136 + [[package]] 137 + name = "fsevent-sys" 138 + version = "4.1.0" 139 + source = "registry+https://github.com/rust-lang/crates.io-index" 140 + checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" 141 + dependencies = [ 142 + "libc", 143 + ] 144 + 145 + [[package]] 146 + name = "heck" 147 + version = "0.5.0" 148 + source = "registry+https://github.com/rust-lang/crates.io-index" 149 + checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 150 + 151 + [[package]] 152 + name = "inotify" 153 + version = "0.11.0" 154 + source = "registry+https://github.com/rust-lang/crates.io-index" 155 + checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" 156 + dependencies = [ 157 + "bitflags 2.9.4", 158 + "inotify-sys", 159 + "libc", 160 + ] 161 + 162 + [[package]] 163 + name = "inotify-sys" 164 + version = "0.1.5" 165 + source = "registry+https://github.com/rust-lang/crates.io-index" 166 + checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" 167 + dependencies = [ 168 + "libc", 169 + ] 170 + 171 + [[package]] 172 + name = "is_terminal_polyfill" 173 + version = "1.70.1" 174 + source = "registry+https://github.com/rust-lang/crates.io-index" 175 + checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 176 + 177 + [[package]] 178 + name = "kqueue" 179 + version = "1.1.1" 180 + source = "registry+https://github.com/rust-lang/crates.io-index" 181 + checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" 182 + dependencies = [ 183 + "kqueue-sys", 184 + "libc", 185 + ] 186 + 187 + [[package]] 188 + name = "kqueue-sys" 189 + version = "1.0.4" 190 + source = "registry+https://github.com/rust-lang/crates.io-index" 191 + checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" 192 + dependencies = [ 193 + "bitflags 1.3.2", 194 + "libc", 195 + ] 196 + 197 + [[package]] 198 + name = "libc" 199 + version = "0.2.177" 200 + source = "registry+https://github.com/rust-lang/crates.io-index" 201 + checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" 202 + 203 + [[package]] 204 + name = "log" 205 + version = "0.4.28" 206 + source = "registry+https://github.com/rust-lang/crates.io-index" 207 + checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 208 + 209 + [[package]] 210 + name = "mio" 211 + version = "1.0.4" 212 + source = "registry+https://github.com/rust-lang/crates.io-index" 213 + checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" 214 + dependencies = [ 215 + "libc", 216 + "log", 217 + "wasi", 218 + "windows-sys 0.59.0", 219 + ] 220 + 221 + [[package]] 222 + name = "notify" 223 + version = "8.2.0" 224 + source = "registry+https://github.com/rust-lang/crates.io-index" 225 + checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" 226 + dependencies = [ 227 + "bitflags 2.9.4", 228 + "fsevent-sys", 229 + "inotify", 230 + "kqueue", 231 + "libc", 232 + "log", 233 + "mio", 234 + "notify-types", 235 + "walkdir", 236 + "windows-sys 0.60.2", 237 + ] 238 + 239 + [[package]] 240 + name = "notify-types" 241 + version = "2.0.0" 242 + source = "registry+https://github.com/rust-lang/crates.io-index" 243 + checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" 244 + 245 + [[package]] 246 + name = "once_cell_polyfill" 247 + version = "1.70.1" 248 + source = "registry+https://github.com/rust-lang/crates.io-index" 249 + checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 250 + 251 + [[package]] 252 + name = "proc-macro2" 253 + version = "1.0.101" 254 + source = "registry+https://github.com/rust-lang/crates.io-index" 255 + checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 256 + dependencies = [ 257 + "unicode-ident", 258 + ] 259 + 260 + [[package]] 261 + name = "quote" 262 + version = "1.0.41" 263 + source = "registry+https://github.com/rust-lang/crates.io-index" 264 + checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" 265 + dependencies = [ 266 + "proc-macro2", 267 + ] 268 + 269 + [[package]] 270 + name = "same-file" 271 + version = "1.0.6" 272 + source = "registry+https://github.com/rust-lang/crates.io-index" 273 + checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 274 + dependencies = [ 275 + "winapi-util", 276 + ] 277 + 278 + [[package]] 279 + name = "strsim" 280 + version = "0.11.1" 281 + source = "registry+https://github.com/rust-lang/crates.io-index" 282 + checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 283 + 284 + [[package]] 285 + name = "syn" 286 + version = "2.0.106" 287 + source = "registry+https://github.com/rust-lang/crates.io-index" 288 + checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 289 + dependencies = [ 290 + "proc-macro2", 291 + "quote", 292 + "unicode-ident", 293 + ] 294 + 295 + [[package]] 296 + name = "termcolor" 297 + version = "1.4.1" 298 + source = "registry+https://github.com/rust-lang/crates.io-index" 299 + checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" 300 + dependencies = [ 301 + "winapi-util", 302 + ] 303 + 304 + [[package]] 305 + name = "unicode-ident" 306 + version = "1.0.19" 307 + source = "registry+https://github.com/rust-lang/crates.io-index" 308 + checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" 309 + 310 + [[package]] 311 + name = "utf8parse" 312 + version = "0.2.2" 313 + source = "registry+https://github.com/rust-lang/crates.io-index" 314 + checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 315 + 316 + [[package]] 317 + name = "walkdir" 318 + version = "2.5.0" 319 + source = "registry+https://github.com/rust-lang/crates.io-index" 320 + checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 321 + dependencies = [ 322 + "same-file", 323 + "winapi-util", 324 + ] 325 + 326 + [[package]] 327 + name = "wasi" 328 + version = "0.11.1+wasi-snapshot-preview1" 329 + source = "registry+https://github.com/rust-lang/crates.io-index" 330 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 331 + 332 + [[package]] 333 + name = "winapi-util" 334 + version = "0.1.11" 335 + source = "registry+https://github.com/rust-lang/crates.io-index" 336 + checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" 337 + dependencies = [ 338 + "windows-sys 0.61.2", 339 + ] 340 + 341 + [[package]] 342 + name = "windows-link" 343 + version = "0.2.1" 344 + source = "registry+https://github.com/rust-lang/crates.io-index" 345 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 346 + 347 + [[package]] 348 + name = "windows-sys" 349 + version = "0.59.0" 350 + source = "registry+https://github.com/rust-lang/crates.io-index" 351 + checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 352 + dependencies = [ 353 + "windows-targets 0.52.6", 354 + ] 355 + 356 + [[package]] 357 + name = "windows-sys" 358 + version = "0.60.2" 359 + source = "registry+https://github.com/rust-lang/crates.io-index" 360 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 361 + dependencies = [ 362 + "windows-targets 0.53.5", 363 + ] 364 + 365 + [[package]] 366 + name = "windows-sys" 367 + version = "0.61.2" 368 + source = "registry+https://github.com/rust-lang/crates.io-index" 369 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 370 + dependencies = [ 371 + "windows-link", 372 + ] 373 + 374 + [[package]] 375 + name = "windows-targets" 376 + version = "0.52.6" 377 + source = "registry+https://github.com/rust-lang/crates.io-index" 378 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 379 + dependencies = [ 380 + "windows_aarch64_gnullvm 0.52.6", 381 + "windows_aarch64_msvc 0.52.6", 382 + "windows_i686_gnu 0.52.6", 383 + "windows_i686_gnullvm 0.52.6", 384 + "windows_i686_msvc 0.52.6", 385 + "windows_x86_64_gnu 0.52.6", 386 + "windows_x86_64_gnullvm 0.52.6", 387 + "windows_x86_64_msvc 0.52.6", 388 + ] 389 + 390 + [[package]] 391 + name = "windows-targets" 392 + version = "0.53.5" 393 + source = "registry+https://github.com/rust-lang/crates.io-index" 394 + checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 395 + dependencies = [ 396 + "windows-link", 397 + "windows_aarch64_gnullvm 0.53.1", 398 + "windows_aarch64_msvc 0.53.1", 399 + "windows_i686_gnu 0.53.1", 400 + "windows_i686_gnullvm 0.53.1", 401 + "windows_i686_msvc 0.53.1", 402 + "windows_x86_64_gnu 0.53.1", 403 + "windows_x86_64_gnullvm 0.53.1", 404 + "windows_x86_64_msvc 0.53.1", 405 + ] 406 + 407 + [[package]] 408 + name = "windows_aarch64_gnullvm" 409 + version = "0.52.6" 410 + source = "registry+https://github.com/rust-lang/crates.io-index" 411 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 412 + 413 + [[package]] 414 + name = "windows_aarch64_gnullvm" 415 + version = "0.53.1" 416 + source = "registry+https://github.com/rust-lang/crates.io-index" 417 + checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 418 + 419 + [[package]] 420 + name = "windows_aarch64_msvc" 421 + version = "0.52.6" 422 + source = "registry+https://github.com/rust-lang/crates.io-index" 423 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 424 + 425 + [[package]] 426 + name = "windows_aarch64_msvc" 427 + version = "0.53.1" 428 + source = "registry+https://github.com/rust-lang/crates.io-index" 429 + checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 430 + 431 + [[package]] 432 + name = "windows_i686_gnu" 433 + version = "0.52.6" 434 + source = "registry+https://github.com/rust-lang/crates.io-index" 435 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 436 + 437 + [[package]] 438 + name = "windows_i686_gnu" 439 + version = "0.53.1" 440 + source = "registry+https://github.com/rust-lang/crates.io-index" 441 + checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 442 + 443 + [[package]] 444 + name = "windows_i686_gnullvm" 445 + version = "0.52.6" 446 + source = "registry+https://github.com/rust-lang/crates.io-index" 447 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 448 + 449 + [[package]] 450 + name = "windows_i686_gnullvm" 451 + version = "0.53.1" 452 + source = "registry+https://github.com/rust-lang/crates.io-index" 453 + checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 454 + 455 + [[package]] 456 + name = "windows_i686_msvc" 457 + version = "0.52.6" 458 + source = "registry+https://github.com/rust-lang/crates.io-index" 459 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 460 + 461 + [[package]] 462 + name = "windows_i686_msvc" 463 + version = "0.53.1" 464 + source = "registry+https://github.com/rust-lang/crates.io-index" 465 + checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 466 + 467 + [[package]] 468 + name = "windows_x86_64_gnu" 469 + version = "0.52.6" 470 + source = "registry+https://github.com/rust-lang/crates.io-index" 471 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 472 + 473 + [[package]] 474 + name = "windows_x86_64_gnu" 475 + version = "0.53.1" 476 + source = "registry+https://github.com/rust-lang/crates.io-index" 477 + checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 478 + 479 + [[package]] 480 + name = "windows_x86_64_gnullvm" 481 + version = "0.52.6" 482 + source = "registry+https://github.com/rust-lang/crates.io-index" 483 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 484 + 485 + [[package]] 486 + name = "windows_x86_64_gnullvm" 487 + version = "0.53.1" 488 + source = "registry+https://github.com/rust-lang/crates.io-index" 489 + checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 490 + 491 + [[package]] 492 + name = "windows_x86_64_msvc" 493 + version = "0.52.6" 494 + source = "registry+https://github.com/rust-lang/crates.io-index" 495 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 496 + 497 + [[package]] 498 + name = "windows_x86_64_msvc" 499 + version = "0.53.1" 500 + source = "registry+https://github.com/rust-lang/crates.io-index" 501 + checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
+11
Cargo.toml
··· 1 + [package] 2 + name = "diffwatch" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies] 7 + anyhow = "1.0.100" 8 + clap = { version = "4.5.49", features = ["derive"] } 9 + diff = "0.1.13" 10 + notify = "8.2.0" 11 + termcolor = "1.4.1"
+3
README.md
··· 1 + # `diffwatch` 2 + 3 + Watches a file and prints human-readable, coloured diffs.
+126
src/main.rs
··· 1 + use std::{fs::read_to_string, io::Write as _, path::PathBuf, sync::mpsc}; 2 + 3 + use clap::{Parser, ValueEnum}; 4 + use notify::{RecursiveMode, Watcher}; 5 + use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; 6 + 7 + /// Watch a file and print diffs of changes. 8 + #[derive(Debug, Parser)] 9 + #[command(version, about, long_about = None)] 10 + pub struct Args { 11 + /// Path to the file to watch. 12 + file: PathBuf, 13 + 14 + /// Whether to enable color output. 15 + #[arg(long, value_enum, default_value_t = ColorMode::Auto)] 16 + color: ColorMode, 17 + 18 + /// Show unchanged lines. 19 + #[arg(long, default_value_t = false)] 20 + show_unchanged: bool, 21 + } 22 + 23 + #[derive(Debug, Copy, Clone, PartialEq, Eq, ValueEnum)] 24 + enum ColorMode { 25 + Auto, 26 + Always, 27 + Never, 28 + } 29 + 30 + impl From<ColorMode> for ColorChoice { 31 + fn from(value: ColorMode) -> Self { 32 + match value { 33 + ColorMode::Auto => Self::Auto, 34 + ColorMode::Always => Self::Always, 35 + ColorMode::Never => Self::Never, 36 + } 37 + } 38 + } 39 + 40 + fn main() -> anyhow::Result<()> { 41 + let args = Args::parse(); 42 + let (tx, rx) = mpsc::channel(); 43 + let mut stdout = StandardStream::stdout(args.color.into()); 44 + 45 + let mut watcher = notify::recommended_watcher(tx)?; 46 + watcher.watch(&args.file, RecursiveMode::NonRecursive)?; 47 + 48 + let mut old_content = read_to_string(&args.file)?; 49 + 50 + for evt in rx { 51 + let evt = evt?; 52 + 53 + match evt.kind { 54 + notify::EventKind::Create(_) | notify::EventKind::Modify(_) => { 55 + let new_content = read_to_string(&args.file)?; 56 + 57 + if old_content == new_content { 58 + // ignore 59 + continue; 60 + } 61 + 62 + on_update(&mut stdout, &old_content, &new_content, args.show_unchanged)?; 63 + old_content = new_content; 64 + } 65 + notify::EventKind::Remove(_) => { 66 + stdout.reset()?; 67 + writeln!(&mut stdout, "................ file deleted!")?; 68 + break; 69 + } 70 + _ => {} 71 + } 72 + } 73 + 74 + stdout.reset()?; 75 + 76 + Ok(()) 77 + } 78 + 79 + fn on_update( 80 + out: &mut impl WriteColor, 81 + old_content: &str, 82 + new_content: &str, 83 + show_unchanged: bool, 84 + ) -> std::io::Result<()> { 85 + let color_deleted = { 86 + let mut color = ColorSpec::new(); 87 + color.set_fg(Some(Color::Red)); 88 + color 89 + }; 90 + let color_unchanged = ColorSpec::new(); 91 + let color_added = { 92 + let mut color = ColorSpec::new(); 93 + color.set_fg(Some(Color::Green)); 94 + color 95 + }; 96 + let (mut left_line, mut right_line) = (0, 0); 97 + 98 + out.reset()?; 99 + writeln!(out, "................ file modified!")?; 100 + for line in diff::lines(old_content, new_content) { 101 + match line { 102 + diff::Result::Left(l) => { 103 + left_line += 1; 104 + 105 + out.set_color(&color_deleted)?; 106 + writeln!(out, "{left_line:>5} - {l}")?; 107 + } 108 + diff::Result::Both(l, _) => { 109 + left_line += 1; 110 + right_line += 1; 111 + if show_unchanged { 112 + out.set_color(&color_unchanged)?; 113 + writeln!(out, "{left_line:>5} {right_line:>5} | {l}")?; 114 + } 115 + } 116 + diff::Result::Right(l) => { 117 + right_line += 1; 118 + out.set_color(&color_added)?; 119 + writeln!(out, " {right_line:>5} + {l}")?; 120 + } 121 + } 122 + } 123 + out.reset()?; 124 + 125 + Ok(()) 126 + }