├── .envrc ├── .github └── workflows │ └── build_nix.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── default.nix ├── flake.lock ├── flake.nix ├── shell.nix └── src ├── main.rs └── utils.rs /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.github/workflows/build_nix.yml: -------------------------------------------------------------------------------- 1 | name: "Build Nix package on Ubuntu" 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: cachix/install-nix-action@v23 12 | - name: Building package 13 | run: nix build 14 | - name: Get repository name 15 | run: echo "REPO_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV 16 | - name: Get commit hash 17 | run: echo "COMMIT_HASH=${GITHUB_SHA::6}" >> $GITHUB_ENV 18 | - uses: actions/upload-artifact@v3 19 | with: 20 | name: ${{ env.REPO_NAME }}-${{ env.COMMIT_HASH }}-x86_64-linux 21 | path: result/bin/${{ env.REPO_NAME }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .direnv -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "1.1.2" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anstream" 31 | version = "0.6.4" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" 34 | dependencies = [ 35 | "anstyle", 36 | "anstyle-parse", 37 | "anstyle-query", 38 | "anstyle-wincon", 39 | "colorchoice", 40 | "utf8parse", 41 | ] 42 | 43 | [[package]] 44 | name = "anstyle" 45 | version = "1.0.4" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" 48 | 49 | [[package]] 50 | name = "anstyle-parse" 51 | version = "0.2.2" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" 54 | dependencies = [ 55 | "utf8parse", 56 | ] 57 | 58 | [[package]] 59 | name = "anstyle-query" 60 | version = "1.0.0" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 63 | dependencies = [ 64 | "windows-sys", 65 | ] 66 | 67 | [[package]] 68 | name = "anstyle-wincon" 69 | version = "3.0.1" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" 72 | dependencies = [ 73 | "anstyle", 74 | "windows-sys", 75 | ] 76 | 77 | [[package]] 78 | name = "approx" 79 | version = "0.5.1" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" 82 | dependencies = [ 83 | "num-traits", 84 | ] 85 | 86 | [[package]] 87 | name = "atty" 88 | version = "0.2.14" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 91 | dependencies = [ 92 | "hermit-abi 0.1.19", 93 | "libc", 94 | "winapi", 95 | ] 96 | 97 | [[package]] 98 | name = "autocfg" 99 | version = "1.1.0" 100 | source = "registry+https://github.com/rust-lang/crates.io-index" 101 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 102 | 103 | [[package]] 104 | name = "backtrace" 105 | version = "0.3.69" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 108 | dependencies = [ 109 | "addr2line", 110 | "cc", 111 | "cfg-if", 112 | "libc", 113 | "miniz_oxide", 114 | "object", 115 | "rustc-demangle", 116 | ] 117 | 118 | [[package]] 119 | name = "backtrace-ext" 120 | version = "0.2.1" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50" 123 | dependencies = [ 124 | "backtrace", 125 | ] 126 | 127 | [[package]] 128 | name = "bit_field" 129 | version = "0.10.2" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" 132 | 133 | [[package]] 134 | name = "bitflags" 135 | version = "1.3.2" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 138 | 139 | [[package]] 140 | name = "bitflags" 141 | version = "2.4.1" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" 144 | 145 | [[package]] 146 | name = "bytemuck" 147 | version = "1.14.0" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" 150 | 151 | [[package]] 152 | name = "byteorder" 153 | version = "1.5.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 156 | 157 | [[package]] 158 | name = "cc" 159 | version = "1.0.83" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 162 | dependencies = [ 163 | "libc", 164 | ] 165 | 166 | [[package]] 167 | name = "cfg-if" 168 | version = "1.0.0" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 171 | 172 | [[package]] 173 | name = "clap" 174 | version = "3.2.25" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" 177 | dependencies = [ 178 | "atty", 179 | "bitflags 1.3.2", 180 | "clap_lex 0.2.4", 181 | "indexmap", 182 | "once_cell", 183 | "strsim", 184 | "termcolor", 185 | "terminal_size 0.2.6", 186 | "textwrap 0.16.0", 187 | ] 188 | 189 | [[package]] 190 | name = "clap" 191 | version = "4.4.8" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" 194 | dependencies = [ 195 | "clap_builder", 196 | "clap_derive", 197 | ] 198 | 199 | [[package]] 200 | name = "clap_builder" 201 | version = "4.4.8" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" 204 | dependencies = [ 205 | "anstream", 206 | "anstyle", 207 | "clap_lex 0.6.0", 208 | "strsim", 209 | ] 210 | 211 | [[package]] 212 | name = "clap_complete" 213 | version = "3.2.5" 214 | source = "registry+https://github.com/rust-lang/crates.io-index" 215 | checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8" 216 | dependencies = [ 217 | "clap 3.2.25", 218 | ] 219 | 220 | [[package]] 221 | name = "clap_derive" 222 | version = "4.4.7" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" 225 | dependencies = [ 226 | "heck", 227 | "proc-macro2", 228 | "quote", 229 | "syn", 230 | ] 231 | 232 | [[package]] 233 | name = "clap_lex" 234 | version = "0.2.4" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 237 | dependencies = [ 238 | "os_str_bytes", 239 | ] 240 | 241 | [[package]] 242 | name = "clap_lex" 243 | version = "0.6.0" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" 246 | 247 | [[package]] 248 | name = "color-thief" 249 | version = "0.2.2" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "e6460d760cf38ce67c9e0318f896538820acc54f2d0a3bfc5b2c557211066c98" 252 | dependencies = [ 253 | "rgb", 254 | ] 255 | 256 | [[package]] 257 | name = "color_quant" 258 | version = "1.1.0" 259 | source = "registry+https://github.com/rust-lang/crates.io-index" 260 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 261 | 262 | [[package]] 263 | name = "colorchoice" 264 | version = "1.0.0" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 267 | 268 | [[package]] 269 | name = "colorpickle" 270 | version = "0.2.0" 271 | dependencies = [ 272 | "clap 4.4.8", 273 | "color-thief", 274 | "image", 275 | "miette", 276 | "okolors", 277 | "pastel", 278 | ] 279 | 280 | [[package]] 281 | name = "crc32fast" 282 | version = "1.3.2" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 285 | dependencies = [ 286 | "cfg-if", 287 | ] 288 | 289 | [[package]] 290 | name = "crossbeam-deque" 291 | version = "0.8.3" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" 294 | dependencies = [ 295 | "cfg-if", 296 | "crossbeam-epoch", 297 | "crossbeam-utils", 298 | ] 299 | 300 | [[package]] 301 | name = "crossbeam-epoch" 302 | version = "0.9.15" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" 305 | dependencies = [ 306 | "autocfg", 307 | "cfg-if", 308 | "crossbeam-utils", 309 | "memoffset", 310 | "scopeguard", 311 | ] 312 | 313 | [[package]] 314 | name = "crossbeam-utils" 315 | version = "0.8.16" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 318 | dependencies = [ 319 | "cfg-if", 320 | ] 321 | 322 | [[package]] 323 | name = "crunchy" 324 | version = "0.2.2" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 327 | 328 | [[package]] 329 | name = "either" 330 | version = "1.9.0" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 333 | 334 | [[package]] 335 | name = "errno" 336 | version = "0.3.7" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" 339 | dependencies = [ 340 | "libc", 341 | "windows-sys", 342 | ] 343 | 344 | [[package]] 345 | name = "exr" 346 | version = "1.71.0" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" 349 | dependencies = [ 350 | "bit_field", 351 | "flume", 352 | "half", 353 | "lebe", 354 | "miniz_oxide", 355 | "rayon-core", 356 | "smallvec", 357 | "zune-inflate", 358 | ] 359 | 360 | [[package]] 361 | name = "fast-srgb8" 362 | version = "1.0.0" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" 365 | 366 | [[package]] 367 | name = "fdeflate" 368 | version = "0.3.1" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" 371 | dependencies = [ 372 | "simd-adler32", 373 | ] 374 | 375 | [[package]] 376 | name = "flate2" 377 | version = "1.0.28" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" 380 | dependencies = [ 381 | "crc32fast", 382 | "miniz_oxide", 383 | ] 384 | 385 | [[package]] 386 | name = "flume" 387 | version = "0.11.0" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" 390 | dependencies = [ 391 | "spin", 392 | ] 393 | 394 | [[package]] 395 | name = "getrandom" 396 | version = "0.2.11" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" 399 | dependencies = [ 400 | "cfg-if", 401 | "libc", 402 | "wasi", 403 | ] 404 | 405 | [[package]] 406 | name = "gif" 407 | version = "0.12.0" 408 | source = "registry+https://github.com/rust-lang/crates.io-index" 409 | checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" 410 | dependencies = [ 411 | "color_quant", 412 | "weezl", 413 | ] 414 | 415 | [[package]] 416 | name = "gimli" 417 | version = "0.28.1" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 420 | 421 | [[package]] 422 | name = "half" 423 | version = "2.2.1" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" 426 | dependencies = [ 427 | "crunchy", 428 | ] 429 | 430 | [[package]] 431 | name = "hashbrown" 432 | version = "0.12.3" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 435 | 436 | [[package]] 437 | name = "heck" 438 | version = "0.4.1" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 441 | 442 | [[package]] 443 | name = "hermit-abi" 444 | version = "0.1.19" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 447 | dependencies = [ 448 | "libc", 449 | ] 450 | 451 | [[package]] 452 | name = "hermit-abi" 453 | version = "0.3.3" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" 456 | 457 | [[package]] 458 | name = "image" 459 | version = "0.24.7" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" 462 | dependencies = [ 463 | "bytemuck", 464 | "byteorder", 465 | "color_quant", 466 | "exr", 467 | "gif", 468 | "jpeg-decoder", 469 | "num-rational", 470 | "num-traits", 471 | "png", 472 | "qoi", 473 | "tiff", 474 | ] 475 | 476 | [[package]] 477 | name = "indexmap" 478 | version = "1.9.3" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 481 | dependencies = [ 482 | "autocfg", 483 | "hashbrown", 484 | ] 485 | 486 | [[package]] 487 | name = "io-lifetimes" 488 | version = "1.0.11" 489 | source = "registry+https://github.com/rust-lang/crates.io-index" 490 | checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" 491 | dependencies = [ 492 | "hermit-abi 0.3.3", 493 | "libc", 494 | "windows-sys", 495 | ] 496 | 497 | [[package]] 498 | name = "is-terminal" 499 | version = "0.4.9" 500 | source = "registry+https://github.com/rust-lang/crates.io-index" 501 | checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" 502 | dependencies = [ 503 | "hermit-abi 0.3.3", 504 | "rustix 0.38.25", 505 | "windows-sys", 506 | ] 507 | 508 | [[package]] 509 | name = "is_ci" 510 | version = "1.1.1" 511 | source = "registry+https://github.com/rust-lang/crates.io-index" 512 | checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb" 513 | 514 | [[package]] 515 | name = "jpeg-decoder" 516 | version = "0.3.0" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" 519 | dependencies = [ 520 | "rayon", 521 | ] 522 | 523 | [[package]] 524 | name = "lebe" 525 | version = "0.5.2" 526 | source = "registry+https://github.com/rust-lang/crates.io-index" 527 | checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" 528 | 529 | [[package]] 530 | name = "libc" 531 | version = "0.2.150" 532 | source = "registry+https://github.com/rust-lang/crates.io-index" 533 | checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" 534 | 535 | [[package]] 536 | name = "linux-raw-sys" 537 | version = "0.3.8" 538 | source = "registry+https://github.com/rust-lang/crates.io-index" 539 | checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" 540 | 541 | [[package]] 542 | name = "linux-raw-sys" 543 | version = "0.4.11" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" 546 | 547 | [[package]] 548 | name = "lock_api" 549 | version = "0.4.11" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" 552 | dependencies = [ 553 | "autocfg", 554 | "scopeguard", 555 | ] 556 | 557 | [[package]] 558 | name = "memchr" 559 | version = "2.6.4" 560 | source = "registry+https://github.com/rust-lang/crates.io-index" 561 | checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" 562 | 563 | [[package]] 564 | name = "memoffset" 565 | version = "0.9.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" 568 | dependencies = [ 569 | "autocfg", 570 | ] 571 | 572 | [[package]] 573 | name = "miette" 574 | version = "5.10.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" 577 | dependencies = [ 578 | "backtrace", 579 | "backtrace-ext", 580 | "is-terminal", 581 | "miette-derive", 582 | "once_cell", 583 | "owo-colors", 584 | "supports-color", 585 | "supports-hyperlinks", 586 | "supports-unicode", 587 | "terminal_size 0.1.17", 588 | "textwrap 0.15.2", 589 | "thiserror", 590 | "unicode-width", 591 | ] 592 | 593 | [[package]] 594 | name = "miette-derive" 595 | version = "5.10.0" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" 598 | dependencies = [ 599 | "proc-macro2", 600 | "quote", 601 | "syn", 602 | ] 603 | 604 | [[package]] 605 | name = "minimal-lexical" 606 | version = "0.2.1" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 609 | 610 | [[package]] 611 | name = "miniz_oxide" 612 | version = "0.7.1" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 615 | dependencies = [ 616 | "adler", 617 | "simd-adler32", 618 | ] 619 | 620 | [[package]] 621 | name = "nom" 622 | version = "7.1.3" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 625 | dependencies = [ 626 | "memchr", 627 | "minimal-lexical", 628 | ] 629 | 630 | [[package]] 631 | name = "num-integer" 632 | version = "0.1.45" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 635 | dependencies = [ 636 | "autocfg", 637 | "num-traits", 638 | ] 639 | 640 | [[package]] 641 | name = "num-rational" 642 | version = "0.4.1" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 645 | dependencies = [ 646 | "autocfg", 647 | "num-integer", 648 | "num-traits", 649 | ] 650 | 651 | [[package]] 652 | name = "num-traits" 653 | version = "0.2.17" 654 | source = "registry+https://github.com/rust-lang/crates.io-index" 655 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" 656 | dependencies = [ 657 | "autocfg", 658 | ] 659 | 660 | [[package]] 661 | name = "object" 662 | version = "0.32.1" 663 | source = "registry+https://github.com/rust-lang/crates.io-index" 664 | checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" 665 | dependencies = [ 666 | "memchr", 667 | ] 668 | 669 | [[package]] 670 | name = "okolors" 671 | version = "0.4.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "5228a8897788133261d9552bebd76bebc6b10d3c1c2e5b48df5771574ab521f6" 674 | dependencies = [ 675 | "image", 676 | "palette", 677 | "rand", 678 | "rand_xoshiro", 679 | "rayon", 680 | ] 681 | 682 | [[package]] 683 | name = "once_cell" 684 | version = "1.18.0" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 687 | 688 | [[package]] 689 | name = "os_str_bytes" 690 | version = "6.6.1" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" 693 | 694 | [[package]] 695 | name = "output_vt100" 696 | version = "0.1.3" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" 699 | dependencies = [ 700 | "winapi", 701 | ] 702 | 703 | [[package]] 704 | name = "owo-colors" 705 | version = "3.5.0" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" 708 | 709 | [[package]] 710 | name = "palette" 711 | version = "0.7.3" 712 | source = "registry+https://github.com/rust-lang/crates.io-index" 713 | checksum = "b2e2f34147767aa758aa649415b50a69eeb46a67f9dc7db8011eeb3d84b351dc" 714 | dependencies = [ 715 | "approx", 716 | "fast-srgb8", 717 | "palette_derive", 718 | ] 719 | 720 | [[package]] 721 | name = "palette_derive" 722 | version = "0.7.3" 723 | source = "registry+https://github.com/rust-lang/crates.io-index" 724 | checksum = "b7db010ec5ff3d4385e4f133916faacd9dad0f6a09394c92d825b3aed310fa0a" 725 | dependencies = [ 726 | "proc-macro2", 727 | "quote", 728 | "syn", 729 | ] 730 | 731 | [[package]] 732 | name = "pastel" 733 | version = "0.9.0" 734 | source = "git+https://github.com/sharkdp/pastel.git?rev=f205dec1952808ed3c33e9bc5ad98d0dccb19f74#f205dec1952808ed3c33e9bc5ad98d0dccb19f74" 735 | dependencies = [ 736 | "atty", 737 | "clap 3.2.25", 738 | "clap_complete", 739 | "nom", 740 | "once_cell", 741 | "output_vt100", 742 | "rand", 743 | "regex", 744 | ] 745 | 746 | [[package]] 747 | name = "png" 748 | version = "0.17.10" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" 751 | dependencies = [ 752 | "bitflags 1.3.2", 753 | "crc32fast", 754 | "fdeflate", 755 | "flate2", 756 | "miniz_oxide", 757 | ] 758 | 759 | [[package]] 760 | name = "ppv-lite86" 761 | version = "0.2.17" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 764 | 765 | [[package]] 766 | name = "proc-macro2" 767 | version = "1.0.69" 768 | source = "registry+https://github.com/rust-lang/crates.io-index" 769 | checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" 770 | dependencies = [ 771 | "unicode-ident", 772 | ] 773 | 774 | [[package]] 775 | name = "qoi" 776 | version = "0.4.1" 777 | source = "registry+https://github.com/rust-lang/crates.io-index" 778 | checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" 779 | dependencies = [ 780 | "bytemuck", 781 | ] 782 | 783 | [[package]] 784 | name = "quote" 785 | version = "1.0.33" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 788 | dependencies = [ 789 | "proc-macro2", 790 | ] 791 | 792 | [[package]] 793 | name = "rand" 794 | version = "0.8.5" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 797 | dependencies = [ 798 | "libc", 799 | "rand_chacha", 800 | "rand_core", 801 | ] 802 | 803 | [[package]] 804 | name = "rand_chacha" 805 | version = "0.3.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 808 | dependencies = [ 809 | "ppv-lite86", 810 | "rand_core", 811 | ] 812 | 813 | [[package]] 814 | name = "rand_core" 815 | version = "0.6.4" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 818 | dependencies = [ 819 | "getrandom", 820 | ] 821 | 822 | [[package]] 823 | name = "rand_xoshiro" 824 | version = "0.6.0" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" 827 | dependencies = [ 828 | "rand_core", 829 | ] 830 | 831 | [[package]] 832 | name = "rayon" 833 | version = "1.8.0" 834 | source = "registry+https://github.com/rust-lang/crates.io-index" 835 | checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" 836 | dependencies = [ 837 | "either", 838 | "rayon-core", 839 | ] 840 | 841 | [[package]] 842 | name = "rayon-core" 843 | version = "1.12.0" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" 846 | dependencies = [ 847 | "crossbeam-deque", 848 | "crossbeam-utils", 849 | ] 850 | 851 | [[package]] 852 | name = "regex" 853 | version = "1.10.2" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" 856 | dependencies = [ 857 | "aho-corasick", 858 | "memchr", 859 | "regex-automata", 860 | "regex-syntax", 861 | ] 862 | 863 | [[package]] 864 | name = "regex-automata" 865 | version = "0.4.3" 866 | source = "registry+https://github.com/rust-lang/crates.io-index" 867 | checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" 868 | dependencies = [ 869 | "aho-corasick", 870 | "memchr", 871 | "regex-syntax", 872 | ] 873 | 874 | [[package]] 875 | name = "regex-syntax" 876 | version = "0.8.2" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 879 | 880 | [[package]] 881 | name = "rgb" 882 | version = "0.8.37" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" 885 | dependencies = [ 886 | "bytemuck", 887 | ] 888 | 889 | [[package]] 890 | name = "rustc-demangle" 891 | version = "0.1.23" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 894 | 895 | [[package]] 896 | name = "rustix" 897 | version = "0.37.27" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" 900 | dependencies = [ 901 | "bitflags 1.3.2", 902 | "errno", 903 | "io-lifetimes", 904 | "libc", 905 | "linux-raw-sys 0.3.8", 906 | "windows-sys", 907 | ] 908 | 909 | [[package]] 910 | name = "rustix" 911 | version = "0.38.25" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" 914 | dependencies = [ 915 | "bitflags 2.4.1", 916 | "errno", 917 | "libc", 918 | "linux-raw-sys 0.4.11", 919 | "windows-sys", 920 | ] 921 | 922 | [[package]] 923 | name = "scopeguard" 924 | version = "1.2.0" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 927 | 928 | [[package]] 929 | name = "simd-adler32" 930 | version = "0.3.7" 931 | source = "registry+https://github.com/rust-lang/crates.io-index" 932 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 933 | 934 | [[package]] 935 | name = "smallvec" 936 | version = "1.11.2" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" 939 | 940 | [[package]] 941 | name = "smawk" 942 | version = "0.3.2" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" 945 | 946 | [[package]] 947 | name = "spin" 948 | version = "0.9.8" 949 | source = "registry+https://github.com/rust-lang/crates.io-index" 950 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 951 | dependencies = [ 952 | "lock_api", 953 | ] 954 | 955 | [[package]] 956 | name = "strsim" 957 | version = "0.10.0" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 960 | 961 | [[package]] 962 | name = "supports-color" 963 | version = "2.1.0" 964 | source = "registry+https://github.com/rust-lang/crates.io-index" 965 | checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" 966 | dependencies = [ 967 | "is-terminal", 968 | "is_ci", 969 | ] 970 | 971 | [[package]] 972 | name = "supports-hyperlinks" 973 | version = "2.1.0" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "f84231692eb0d4d41e4cdd0cabfdd2e6cd9e255e65f80c9aa7c98dd502b4233d" 976 | dependencies = [ 977 | "is-terminal", 978 | ] 979 | 980 | [[package]] 981 | name = "supports-unicode" 982 | version = "2.0.0" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "4b6c2cb240ab5dd21ed4906895ee23fe5a48acdbd15a3ce388e7b62a9b66baf7" 985 | dependencies = [ 986 | "is-terminal", 987 | ] 988 | 989 | [[package]] 990 | name = "syn" 991 | version = "2.0.39" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" 994 | dependencies = [ 995 | "proc-macro2", 996 | "quote", 997 | "unicode-ident", 998 | ] 999 | 1000 | [[package]] 1001 | name = "termcolor" 1002 | version = "1.4.0" 1003 | source = "registry+https://github.com/rust-lang/crates.io-index" 1004 | checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" 1005 | dependencies = [ 1006 | "winapi-util", 1007 | ] 1008 | 1009 | [[package]] 1010 | name = "terminal_size" 1011 | version = "0.1.17" 1012 | source = "registry+https://github.com/rust-lang/crates.io-index" 1013 | checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" 1014 | dependencies = [ 1015 | "libc", 1016 | "winapi", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "terminal_size" 1021 | version = "0.2.6" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "8e6bf6f19e9f8ed8d4048dc22981458ebcf406d67e94cd422e5ecd73d63b3237" 1024 | dependencies = [ 1025 | "rustix 0.37.27", 1026 | "windows-sys", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "textwrap" 1031 | version = "0.15.2" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "b7b3e525a49ec206798b40326a44121291b530c963cfb01018f63e135bac543d" 1034 | dependencies = [ 1035 | "smawk", 1036 | "unicode-linebreak", 1037 | "unicode-width", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "textwrap" 1042 | version = "0.16.0" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" 1045 | dependencies = [ 1046 | "terminal_size 0.2.6", 1047 | ] 1048 | 1049 | [[package]] 1050 | name = "thiserror" 1051 | version = "1.0.50" 1052 | source = "registry+https://github.com/rust-lang/crates.io-index" 1053 | checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" 1054 | dependencies = [ 1055 | "thiserror-impl", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "thiserror-impl" 1060 | version = "1.0.50" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" 1063 | dependencies = [ 1064 | "proc-macro2", 1065 | "quote", 1066 | "syn", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "tiff" 1071 | version = "0.9.0" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" 1074 | dependencies = [ 1075 | "flate2", 1076 | "jpeg-decoder", 1077 | "weezl", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "unicode-ident" 1082 | version = "1.0.12" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1085 | 1086 | [[package]] 1087 | name = "unicode-linebreak" 1088 | version = "0.1.5" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" 1091 | 1092 | [[package]] 1093 | name = "unicode-width" 1094 | version = "0.1.11" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" 1097 | 1098 | [[package]] 1099 | name = "utf8parse" 1100 | version = "0.2.1" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1103 | 1104 | [[package]] 1105 | name = "wasi" 1106 | version = "0.11.0+wasi-snapshot-preview1" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1109 | 1110 | [[package]] 1111 | name = "weezl" 1112 | version = "0.1.7" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" 1115 | 1116 | [[package]] 1117 | name = "winapi" 1118 | version = "0.3.9" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1121 | dependencies = [ 1122 | "winapi-i686-pc-windows-gnu", 1123 | "winapi-x86_64-pc-windows-gnu", 1124 | ] 1125 | 1126 | [[package]] 1127 | name = "winapi-i686-pc-windows-gnu" 1128 | version = "0.4.0" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1131 | 1132 | [[package]] 1133 | name = "winapi-util" 1134 | version = "0.1.6" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" 1137 | dependencies = [ 1138 | "winapi", 1139 | ] 1140 | 1141 | [[package]] 1142 | name = "winapi-x86_64-pc-windows-gnu" 1143 | version = "0.4.0" 1144 | source = "registry+https://github.com/rust-lang/crates.io-index" 1145 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1146 | 1147 | [[package]] 1148 | name = "windows-sys" 1149 | version = "0.48.0" 1150 | source = "registry+https://github.com/rust-lang/crates.io-index" 1151 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1152 | dependencies = [ 1153 | "windows-targets", 1154 | ] 1155 | 1156 | [[package]] 1157 | name = "windows-targets" 1158 | version = "0.48.5" 1159 | source = "registry+https://github.com/rust-lang/crates.io-index" 1160 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1161 | dependencies = [ 1162 | "windows_aarch64_gnullvm", 1163 | "windows_aarch64_msvc", 1164 | "windows_i686_gnu", 1165 | "windows_i686_msvc", 1166 | "windows_x86_64_gnu", 1167 | "windows_x86_64_gnullvm", 1168 | "windows_x86_64_msvc", 1169 | ] 1170 | 1171 | [[package]] 1172 | name = "windows_aarch64_gnullvm" 1173 | version = "0.48.5" 1174 | source = "registry+https://github.com/rust-lang/crates.io-index" 1175 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1176 | 1177 | [[package]] 1178 | name = "windows_aarch64_msvc" 1179 | version = "0.48.5" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1182 | 1183 | [[package]] 1184 | name = "windows_i686_gnu" 1185 | version = "0.48.5" 1186 | source = "registry+https://github.com/rust-lang/crates.io-index" 1187 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1188 | 1189 | [[package]] 1190 | name = "windows_i686_msvc" 1191 | version = "0.48.5" 1192 | source = "registry+https://github.com/rust-lang/crates.io-index" 1193 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1194 | 1195 | [[package]] 1196 | name = "windows_x86_64_gnu" 1197 | version = "0.48.5" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1200 | 1201 | [[package]] 1202 | name = "windows_x86_64_gnullvm" 1203 | version = "0.48.5" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1206 | 1207 | [[package]] 1208 | name = "windows_x86_64_msvc" 1209 | version = "0.48.5" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1212 | 1213 | [[package]] 1214 | name = "zune-inflate" 1215 | version = "0.2.54" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" 1218 | dependencies = [ 1219 | "simd-adler32", 1220 | ] 1221 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "colorpickle" 3 | version = "0.2.0" 4 | edition = "2021" 5 | authors = ["Agatha V. Lovelace "] 6 | description = "A colorscheme generator" 7 | license = "NVPLv7+" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | clap = { version = "4.4.6", features = ["derive"] } 13 | color-thief = "0.2.2" 14 | image = "0.24.7" 15 | miette = { version = "5.10.0", features = ["fancy"] } 16 | okolors = "0.4.0" 17 | pastel = { git = "https://github.com/sharkdp/pastel.git", rev = "f205dec1952808ed3c33e9bc5ad98d0dccb19f74" } 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS 2 | COOPERATIVE NON-VIOLENT PUBLIC LICENSE (\"LICENSE\"). THE WORK IS 3 | PROTECTED BY COPYRIGHT AND ALL OTHER APPLICABLE LAWS. ANY USE OF THE 4 | WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS 5 | PROHIBITED. BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED IN THIS 6 | LICENSE, YOU AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE 7 | EXTENT THIS LICENSE MAY BE CONSIDERED TO BE A CONTRACT, THE LICENSOR 8 | GRANTS YOU THE RIGHTS CONTAINED HERE IN AS CONSIDERATION FOR ACCEPTING 9 | THE TERMS AND CONDITIONS OF THIS LICENSE AND FOR AGREEING TO BE BOUND BY 10 | THE TERMS AND CONDITIONS OF THIS LICENSE. 11 | 12 | # Definitions 13 | 14 | An Act of War is any action of one country against any group either with 15 | an intention to provoke a conflict or an action that occurs during a 16 | declared war or during armed conflict between military forces of any 17 | origin. This includes but is not limited to enforcing sanctions or 18 | sieges, supplying armed forces, or profiting from the manufacture of 19 | tools or weaponry used in military conflict. 20 | 21 | An Adaptation is a work based upon the Work, or upon the Work and other 22 | pre-existing works, such as a translation, adaptation, derivative work, 23 | arrangement of music or other alterations of a literary or artistic 24 | work, or phonogram or performance and includes cinematographic 25 | adaptations or any other form in which the Work may be recast, 26 | transformed, or adapted including in any form recognizably derived from 27 | the original, except that a work that constitutes a Collection will not 28 | be considered an Adaptation for the purpose of this License. For the 29 | avoidance of doubt, where the Work is a musical work, performance or 30 | phonogram, the synchronization of the Work in timed-relation with a 31 | moving image (\"synching\") will be considered an Adaptation for the 32 | purpose of this License. In addition, where the Work is designed to 33 | output a neural network the output of the neural network will be 34 | considered an Adaptation for the purpose of this license. 35 | 36 | Bodily Harm is any physical hurt or injury to a person that interferes 37 | with the health or comfort of the person and that is more than merely 38 | transient or trifling in nature. 39 | 40 | Distribute is to make available to the public the original and copies of 41 | the Work or Adaptation, as appropriate, through sale, gift or any other 42 | transfer of possession or ownership. 43 | 44 | Incarceration is Confinement in a jail, prison, or any other place where 45 | individuals of any kind are held against either their will or (if their 46 | will cannot be determined) the will of their legal guardian or 47 | guardians. In the case of a conflict between the will of the individual 48 | and the will of their legal guardian or guardians, the will of the 49 | individual will take precedence. 50 | 51 | Licensor is The individual, individuals, entity, or entities that 52 | offer(s) the Work under the terms of this License 53 | 54 | Original Author is in the case of a literary or artistic work, the 55 | individual, individuals, entity or entities who created the Work or if 56 | no individual or entity can be identified, the publisher; and in 57 | addition 58 | 59 | - in the case of a performance the actors, singers, musicians, 60 | dancers, and other persons who act, sing, deliver, declaim, play in, 61 | interpret or otherwise perform literary or artistic works or 62 | expressions of folklore; 63 | 64 | - in the case of a phonogram the producer being the person or legal 65 | entity who first fixes the sounds of a performance or other sounds; 66 | and, 67 | 68 | - in the case of broadcasts, the organization that transmits the 69 | broadcast. 70 | 71 | Work is the literary and/or artistic work offered under the terms of 72 | this License including without limitation any production in the 73 | literary, scientific and artistic domain, whatever may be the mode or 74 | form of its expression including digital form, such as a book, pamphlet 75 | and other writing; a lecture, address, sermon or other work of the same 76 | nature; a dramatic or dramatico-musical work; a choreographic work or 77 | entertainment in dumb show; a musical composition with or without words; 78 | a cinematographic work to which are assimilated works expressed by a 79 | process analogous to cinematography; a work of drawing, painting, 80 | architecture, sculpture, engraving or lithography; a photographic work 81 | to which are assimilated works expressed by a process analogous to 82 | photography; a work of applied art; an illustration, map, plan, sketch 83 | or three-dimensional work relative to geography, topography, 84 | architecture or science; a performance; a broadcast; a phonogram; a 85 | compilation of data to the extent it is protected as a copyrightable 86 | work; or a work performed by a variety or circus performer to the extent 87 | it is not otherwise considered a literary or artistic work. 88 | 89 | You means an individual or entity exercising rights under this License 90 | who has not previously violated the terms of this License with respect 91 | to the Work, or who has received express permission from the Licensor to 92 | exercise rights under this License despite a previous violation. 93 | 94 | Publicly Perform means to perform public recitations of the Work and to 95 | communicate to the public those public recitations, by any means or 96 | process, including by wire or wireless means or public digital 97 | performances; to make available to the public Works in such a way that 98 | members of the public may access these Works from a place and at a place 99 | individually chosen by them; to perform the Work to the public by any 100 | means or process and the communication to the public of the performances 101 | of the Work, including by public digital performance; to broadcast and 102 | rebroadcast the Work by any means including signs, sounds or images. 103 | 104 | Reproduce is to make copies of the Work by any means including without 105 | limitation by sound or visual recordings and the right of fixation and 106 | reproducing fixations of the Work, including storage of a protected 107 | performance or phonogram in digital form or other electronic medium. 108 | 109 | Software is any digital Work which, through use of a third-party piece 110 | of Software or through the direct usage of itself on a computer system, 111 | the memory of the computer is modified dynamically or semi-dynamically. 112 | \"Software\", secondly, processes or interprets information. 113 | 114 | Source Code is Any digital Work which, through use of a third-party 115 | piece of Software or through the direct usage of itself on a computer 116 | system, the memory of the computer is modified dynamically or 117 | semi-dynamically. \"Software\", secondly, processes or interprets 118 | information. 119 | 120 | Surveilling is the use of the Work to either overtly or covertly observe 121 | and record persons and or their activities. 122 | 123 | A Network Service is the use of a piece of Software to interpret or 124 | modify information that is subsequently and directly served to users 125 | over the Internet. 126 | 127 | To Discriminate is use of a work to differentiate between humans in a 128 | such a way which prioritizes some above others on the basis of percieved 129 | membership within certain groups. 130 | 131 | Hate Speech is Communication or any form of expression which is solely 132 | for the purpose of expressing hatred for some group or advocating a form 133 | of Discrimination between humans. 134 | 135 | Coercion is leveraging of the threat of force or use of force to 136 | intimidate a person in order to gain compliance, or to offer large 137 | incentives which aim to entice a person to act against their will. 138 | 139 | # Fair Dealing Rights 140 | 141 | Nothing in this License is intended to reduce, limit, or restrict any 142 | uses free from copyright or rights arising from limitations or 143 | exceptions that are provided for in connection with the copyright 144 | protection under copyright law or other applicable laws. 145 | 146 | # License Grant 147 | 148 | Subject to the terms and conditions of this License, Licensor hereby 149 | grants You a worldwide, royalty-free, non-exclusive, perpetual (for the 150 | duration of the applicable copyright) license to exercise the rights in 151 | the Work as stated below: 152 | 153 | To Reproduce the Work, to incorporate the Work into one or more 154 | Collections, and to Reproduce the Work as incorporated in the 155 | Collections 156 | 157 | To create and Reproduce Adaptations provided that any such Adaptation, 158 | including any translation in any medium, takes reasonable steps to 159 | clearly label, demarcate or otherwise identify that changes were made to 160 | the original Work. For example, a translation could be marked \"The 161 | original work was translated from English to Spanish,\" or a 162 | modification could indicate \"The original work has been modified.\" 163 | 164 | To Distribute and Publicly Perform the Work including as incorporated in 165 | Collections. 166 | 167 | To Distribute and Publicly Perform Adaptations. The above rights may be 168 | exercised in all media and formats whether now known or hereafter 169 | devised. The above rights include the right to make such modifications 170 | as are technically necessary to exercise the rights in other media and 171 | formats. This License constitutes the entire agreement between the 172 | parties with respect to the Work licensed here. There are no 173 | understandings, agreements or representations with respect to the Work 174 | not specified here. Licensor shall not be bound by any additional 175 | provisions that may appear in any communication from You. This License 176 | may not be modified without the mutual written agreement of the Licensor 177 | and You. All rights not expressly granted by Licensor are hereby 178 | reserved, including but not limited to the rights set forth in 179 | Non-waivable Compulsory License Schemes, Waivable Compulsory License 180 | Schemes, and Voluntary License Schemes in the restrictions. 181 | 182 | # Restrictions 183 | 184 | The license granted in the license grant above is expressly made subject 185 | to and limited by the following restrictions: 186 | 187 | You may Distribute or Publicly Perform the Work only under the terms of 188 | this License. You must include a copy of, or the Uniform Resource 189 | Identifier (URI) for, this License with every copy of the Work You 190 | Distribute or Publicly Perform. You may not offer or impose any terms on 191 | the Work that restrict the terms of this License or the ability of the 192 | recipient of the Work to exercise the rights granted to that recipient 193 | under the terms of the License. You may not sublicense the Work. You 194 | must keep intact all notices that refer to this License and to the 195 | disclaimer of warranties with every copy of the Work You Distribute or 196 | Publicly Perform. When You Distribute or Publicly Perform the Work, You 197 | may not impose any effective technological measures on the Work that 198 | restrict the ability of a recipient of the Work from You to exercise the 199 | rights granted to that recipient under the terms of the License. This 200 | Section applies to the Work as incorporated in a Collection, but this 201 | does not require the Collection apart from the Work itself to be made 202 | subject to the terms of this License. If You create a Collection, upon 203 | notice from any Licensor You must, to the extent practicable, remove 204 | from the Collection any credit as requested. If You create an 205 | Adaptation, upon notice from any Licensor You must, to the extent 206 | practicable, remove from the Adaptation any credit as requested. 207 | 208 | If the Work meets the definition of Software, You may exercise the 209 | rights granted in the license grant only if You provide a copy of the 210 | corresponding Source Code from which the Work was derived in digital 211 | form, or You provide a URI for the corresponding Source Code of the 212 | Work, to any recipients upon request. 213 | 214 | If the Work is used as or for a Network Service, You may exercise the 215 | rights granted in the license grant only if You provide a copy of the 216 | corresponding Source Code from which the Work was derived in digital 217 | form, or You provide a URI for the corresponding Source Code to the 218 | Work, to any recipients of the data served or modified by the Web 219 | Service. 220 | 221 | ## 222 | 223 | You may exercise the rights granted in the license grant for any 224 | purposes only if: 225 | 226 | i. You do not use the Work for the purpose of inflicting Bodily Harm on 227 | human beings (subject to criminal prosecution or otherwise) outside 228 | of providing medical aid or undergoing a voluntary procedure under 229 | no form of Coercion. 230 | 231 | ii. You do not use the Work for the purpose of Surveilling or tracking 232 | individuals for financial gain. 233 | 234 | iii. You do not use the Work in an Act of War. 235 | 236 | iv. You do not use the Work for the purpose of supporting or profiting 237 | from an Act of War. 238 | 239 | v. You do not use the Work for the purpose of Incarceration. 240 | 241 | vi. You do not use the Work for the purpose of extracting, processing, 242 | or refining, oil, gas, or coal. Or to in any other way to 243 | deliberately pollute the environment as a byproduct of manufacturing 244 | or irresponsible disposal of hazardous materials. 245 | 246 | vii. You do not use the Work for the purpose of expediting, 247 | coordinating, or facilitating paid work undertaken by individuals 248 | under the age of 12 years. 249 | 250 | viii. You do not use the Work to either Discriminate or spread Hate 251 | Speech on the basis of sex, sexual orientation, gender identity, 252 | race, age, disability, color, national origin, religion, caste, or 253 | lower economic status. 254 | 255 | ## 256 | 257 | If You Distribute, or Publicly Perform the Work or any Adaptations or 258 | Collections, You must, unless a request has been made by any Licensor to 259 | remove credit from a Collection or Adaptation, keep intact all copyright 260 | notices for the Work and provide, reasonable to the medium or means You 261 | are utilizing: 262 | 263 | i. the name of the Original Author (or pseudonym, if applicable) if 264 | supplied, and/or if the Original Author and/or Licensor designate 265 | another party or parties (e.g., a sponsor institute, publishing 266 | entity, journal) for attribution (\"Attribution Parties\") in 267 | Licensor\'s copyright notice, terms of service or by other 268 | reasonable means, the name of such party or parties; 269 | 270 | ii. the title of the Work if supplied; 271 | 272 | iii. to the extent reasonably practicable, the URI, if any, that 273 | Licensor to be associated with the Work, unless such URI does not 274 | refer to the copyright notice or licensing information for the 275 | Work; and, 276 | 277 | iv. in the case of an Adaptation, a credit identifying the use of the 278 | Work in the Adaptation (e.g., \"French translation of the Work by 279 | Original Author,\" or \"Screenplay based on original Work by 280 | Original Author\"). 281 | 282 | If any Licensor has sent notice to request removing credit, You must, to 283 | the extent practicable, remove any credit as requested. The credit 284 | required by this Section may be implemented in any reasonable manner; 285 | provided, however, that in the case of an Adaptation or Collection, at a 286 | minimum such credit will appear, if a credit for all contributing 287 | authors of the Adaptation or Collection appears, then as part of these 288 | credits and in a manner at least as prominent as the credits for the 289 | other contributing authors. For the avoidance of doubt, You may only use 290 | the credit required by this Section for the purpose of attribution in 291 | the manner set out above and, by exercising Your rights under this 292 | License, You may not implicitly or explicitly assert or imply any 293 | connection with, sponsorship or endorsement by the Original Author, 294 | Licensor and/or Attribution Parties, as appropriate, of You or Your use 295 | of the Work, without the separate, express prior written permission of 296 | the Original Author, Licensor and/or Attribution Parties. 297 | 298 | Except as otherwise agreed in writing by the Licensor or as may be 299 | otherwise permitted by applicable law, if You Reproduce, Distribute or 300 | Publicly Perform the Work either by itself or as part of any Adaptations 301 | or Collections, You must not distort, mutilate, modify or take other 302 | derogatory action in relation to the Work which would be prejudicial to 303 | the Original Author\'s honor or reputation. Licensor agrees that in 304 | those jurisdictions (e.g. Japan), in which any exercise of the right 305 | granted in the license grant of this License (the right to make 306 | Adaptations) would be deemed to be a distortion, mutilation, 307 | modification or other derogatory action prejudicial to the Original 308 | Author\'s honor and reputation, the Licensor will waive or not assert, 309 | as appropriate, this Section, to the fullest extent permitted by the 310 | applicable national law, to enable You to reasonably exercise Your right 311 | under the license grant of this License (right to make Adaptations) but 312 | not otherwise. 313 | 314 | Do not make any legal claim against anyone accusing the Work, with or 315 | without changes, alone or with other works, of infringing any patent 316 | claim. 317 | 318 | # Representations Warranties and Disclaimer 319 | 320 | UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR 321 | OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY 322 | KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, 323 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, 324 | FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF 325 | LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, 326 | WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE 327 | EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 328 | 329 | # Limitation on Liability 330 | 331 | EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL 332 | LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, 333 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF 334 | THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED 335 | OF THE POSSIBILITY OF SUCH DAMAGES. 336 | 337 | # Termination 338 | 339 | This License and the rights granted hereunder will terminate 340 | automatically upon any breach by You of the terms of this License. 341 | Individuals or entities who have received Adaptations or Collections 342 | from You under this License, however, will not have their licenses 343 | terminated provided such individuals or entities remain in full 344 | compliance with those licenses. The Sections on definitions, fair 345 | dealing rights, representations, warranties, and disclaimer, limitation 346 | on liability, termination, and revised license versions will survive any 347 | termination of this License. 348 | 349 | Subject to the above terms and conditions, the license granted here is 350 | perpetual (for the duration of the applicable copyright in the Work). 351 | Notwithstanding the above, Licensor reserves the right to release the 352 | Work under different license terms or to stop distributing the Work at 353 | any time; provided, however that any such election will not serve to 354 | withdraw this License (or any other license that has been, or is 355 | required to be, granted under the terms of this License), and this 356 | License will continue in full force and effect unless terminated as 357 | stated above. 358 | 359 | # Revised License Versions 360 | 361 | This License may receive future revisions in the original spirit of the 362 | license intended to strengthen This License. Each version of This 363 | License has an incrementing version number. 364 | 365 | Unless otherwise specified like in the below subsection The Licensor has 366 | only granted this current version of This License for The Work. In this 367 | case future revisions do not apply. 368 | 369 | The Licensor may specify that the latest available revision of This 370 | License be used for The Work by either explicitly writing so or by 371 | suffixing the License URI with a \"+\" symbol. 372 | 373 | The Licensor may specify that The Work is also available under the terms 374 | of This License\'s current revision as well as specific future 375 | revisions. The Licensor may do this by writing it explicitly or 376 | suffixing the License URI with any additional version numbers each 377 | separated by a comma. 378 | 379 | # Miscellaneous 380 | 381 | Each time You Distribute or Publicly Perform the Work or a Collection, 382 | the Licensor offers to the recipient a license to the Work on the same 383 | terms and conditions as the license granted to You under this License. 384 | 385 | Each time You Distribute or Publicly Perform an Adaptation, Licensor 386 | offers to the recipient a license to the original Work on the same terms 387 | and conditions as the license granted to You under this License. 388 | 389 | If the Work is classified as Software, each time You Distribute or 390 | Publicly Perform an Adaptation, Licensor offers to the recipient a copy 391 | and/or URI of the corresponding Source Code on the same terms and 392 | conditions as the license granted to You under this License. 393 | 394 | If the Work is used as a Network Service, each time You Distribute or 395 | Publicly Perform an Adaptation, or serve data derived from the Software, 396 | the Licensor offers to any recipients of the data a copy and/or URI of 397 | the corresponding Source Code on the same terms and conditions as the 398 | license granted to You under this License. 399 | 400 | If any provision of this License is invalid or unenforceable under 401 | applicable law, it shall not affect the validity or enforceability of 402 | the remainder of the terms of this License, and without further action 403 | by the parties to this agreement, such provision shall be reformed to 404 | the minimum extent necessary to make such provision valid and 405 | enforceable. 406 | 407 | No term or provision of this License shall be deemed waived and no 408 | breach consented to unless such waiver or consent shall be in writing 409 | and signed by the party to be charged with such waiver or consent. 410 | 411 | This License constitutes the entire agreement between the parties with 412 | respect to the Work licensed here. There are no understandings, 413 | agreements or representations with respect to the Work not specified 414 | here. Licensor shall not be bound by any additional provisions that may 415 | appear in any communication from You. This License may not be modified 416 | without the mutual written agreement of the Licensor and You. 417 | 418 | The rights granted under, and the subject matter referenced, in this 419 | License were drafted utilizing the terminology of the Berne Convention 420 | for the Protection of Literary and Artistic Works (as amended on 421 | September 28, 1979), the Rome Convention of 1961, the WIPO Copyright 422 | Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and 423 | the Universal Copyright Convention (as revised on July 24, 1971). These 424 | rights and subject matter take effect in the relevant jurisdiction in 425 | which the License terms are sought to be enforced according to the 426 | corresponding provisions of the implementation of those treaty 427 | provisions in the applicable national law. If the standard suite of 428 | rights granted under applicable copyright law includes additional rights 429 | not granted under this License, such additional rights are deemed to be 430 | included in the License; this License is not intended to restrict the 431 | license of any rights under applicable law. 432 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Colorpickle 2 | 3 | ![Screenshot of a colorscheme output in a terminal, next to the wallpaper it was generated from](https://i.imgur.com/D7o3zMC.png) 4 | 5 | A colorscheme generator. 6 | 7 | ## Building 8 | Clone this repository, then run: 9 | ```sh 10 | cargo build --release 11 | ``` 12 | The output binary will be in `target/release/colorpickle` 13 | 14 | Alternatively, 15 | ```sh 16 | nix build github:AgathaSorceress/colorpickle 17 | ``` 18 | A binary for linux-x86_64 is built on [each commit](https://github.com/AgathaSorceress/colorpickle/actions) and uploaded to Artifacts. 19 | 20 | ## Usage 21 | ``` 22 | Usage: colorpickle [OPTIONS] 23 | 24 | Arguments: 25 | Path to image to pick colors from 26 | 27 | Options: 28 | -c, --colors Number of colors to generate (excluding bold colors) [default: 8] 29 | -l, --light Generate a light colorscheme 30 | -b, --no-bold Skip generating bold color variants 31 | --bold-delta How much lightness should be added to bold colors [default: 0.2] 32 | --rotate-hue Rotate colors along the hue axis [default: 0] 33 | --saturate Saturate/desaturate colors [default: 0] 34 | --lighten Lighten/darken colors [default: 0] 35 | --no-adjust Do not darken the background and lighten the foreground colors 36 | --backend Which algorithm to use [default: okolors] [possible values: color-thief, okolors] 37 | -h, --help Print help 38 | -V, --version Print version 39 | ``` 40 | 41 | ## Using the NixOS module 42 | 43 | After importing the NixOS module exposed by this flake, a colorscheme can be defined like this: 44 | ```nix 45 | environment.graphical.colorschemes.purple = { 46 | image = ../../../external/6.png; 47 | params = [ "--lighten" "0.05" "--bold-delta" "0.1" ]; 48 | }; 49 | ``` 50 | The generated colors will be accessible from `environment.graphical.colors.purple` 51 | as an attribute set of hex color strings: 52 | ``` 53 | nix-repl> nodes.ritual.config.environment.graphical.colors.purple 54 | { "0" = "#19172b"; "1" = "#453354"; "10" = "#90629a"; "11" = "#7a6d98"; "12" = "#9a79ab"; "13" = "#a6a1bc"; "14" = "#b69dba"; "15" = "#d0c5dc"; "16" = ""; "2" = "#734e7b"; "3" = "#62577b"; "4" = "#825d94"; "5" = "#8a83a7"; "6" = "#a07fa5"; "7" = "#b7a5c9"; "8" = "#2c294c"; "9" = "#5f4674"; } 55 | ``` 56 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import ( 2 | fetchTarball { 3 | url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; 4 | sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; } 5 | ) { 6 | src = ./.; 7 | }).defaultNix 8 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "naersk": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs" 6 | }, 7 | "locked": { 8 | "lastModified": 1694081375, 9 | "narHash": "sha256-vzJXOUnmkMCm3xw8yfPP5m8kypQ3BhAIRe4RRCWpzy8=", 10 | "owner": "nix-community", 11 | "repo": "naersk", 12 | "rev": "3f976d822b7b37fc6fb8e6f157c2dd05e7e94e89", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "nix-community", 17 | "ref": "master", 18 | "repo": "naersk", 19 | "type": "github" 20 | } 21 | }, 22 | "nixpkgs": { 23 | "locked": { 24 | "lastModified": 1696234590, 25 | "narHash": "sha256-mgOzQYTvaTT4bFopVOadlndy2RPwLy60rDjIWOGujwo=", 26 | "owner": "NixOS", 27 | "repo": "nixpkgs", 28 | "rev": "f902cb49892d300ff15cb237e48aa1cad79d68c3", 29 | "type": "github" 30 | }, 31 | "original": { 32 | "id": "nixpkgs", 33 | "type": "indirect" 34 | } 35 | }, 36 | "nixpkgs_2": { 37 | "locked": { 38 | "lastModified": 1696234590, 39 | "narHash": "sha256-mgOzQYTvaTT4bFopVOadlndy2RPwLy60rDjIWOGujwo=", 40 | "owner": "NixOS", 41 | "repo": "nixpkgs", 42 | "rev": "f902cb49892d300ff15cb237e48aa1cad79d68c3", 43 | "type": "github" 44 | }, 45 | "original": { 46 | "owner": "NixOS", 47 | "ref": "nixpkgs-unstable", 48 | "repo": "nixpkgs", 49 | "type": "github" 50 | } 51 | }, 52 | "root": { 53 | "inputs": { 54 | "naersk": "naersk", 55 | "nixpkgs": "nixpkgs_2", 56 | "utils": "utils" 57 | } 58 | }, 59 | "systems": { 60 | "locked": { 61 | "lastModified": 1681028828, 62 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 63 | "owner": "nix-systems", 64 | "repo": "default", 65 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 66 | "type": "github" 67 | }, 68 | "original": { 69 | "owner": "nix-systems", 70 | "repo": "default", 71 | "type": "github" 72 | } 73 | }, 74 | "utils": { 75 | "inputs": { 76 | "systems": "systems" 77 | }, 78 | "locked": { 79 | "lastModified": 1694529238, 80 | "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", 81 | "owner": "numtide", 82 | "repo": "flake-utils", 83 | "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", 84 | "type": "github" 85 | }, 86 | "original": { 87 | "owner": "numtide", 88 | "repo": "flake-utils", 89 | "type": "github" 90 | } 91 | } 92 | }, 93 | "root": "root", 94 | "version": 7 95 | } 96 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | naersk.url = "github:nix-community/naersk/master"; 4 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 5 | utils.url = "github:numtide/flake-utils"; 6 | }; 7 | 8 | outputs = { self, nixpkgs, utils, naersk }: 9 | utils.lib.eachDefaultSystem (system: 10 | let 11 | pkgs = import nixpkgs { inherit system; }; 12 | naersk-lib = pkgs.callPackage naersk { }; 13 | in { 14 | packages.default = naersk-lib.buildPackage ./.; 15 | devShells.default = with pkgs; 16 | mkShell { 17 | buildInputs = [ 18 | cargo 19 | rustc 20 | rustfmt 21 | pre-commit 22 | rustPackages.clippy 23 | rust-analyzer 24 | ]; 25 | RUST_SRC_PATH = rustPlatform.rustLibSrc; 26 | }; 27 | }) // { 28 | nixosModules.default = { config, lib, pkgs, ... }: 29 | with lib; { 30 | options.environment.graphical = with types; { 31 | colorschemes = mkOption { 32 | default = { }; 33 | type = attrsOf (submodule { 34 | options = { 35 | image = mkOption { 36 | type = either str path; 37 | description = 38 | "Path to image that will be used as input for colorscheme generation"; 39 | }; 40 | params = mkOption { 41 | type = listOf str; 42 | default = [ ]; 43 | description = 44 | mdDoc "list of parameters to pass to `colorpickle`"; 45 | example = [ 46 | "--colors" 47 | "8" 48 | "--lighten" 49 | "0.05" 50 | "--bold-delta" 51 | "0.1" 52 | ]; 53 | }; 54 | }; 55 | }); 56 | }; 57 | colors = mkOption { 58 | default = { }; 59 | type = attrsOf (attrsOf str); 60 | }; 61 | }; 62 | 63 | config = let 64 | generate = name: image: args: 65 | pkgs.runCommand "colors-${name}" { 66 | nativeBuildInputs = [ self.packages.${pkgs.system}.default ]; 67 | } '' 68 | colorpickle ${image} ${ 69 | lib.strings.concatStringsSep " " args 70 | } > $out 71 | ''; 72 | formattedColors = name: image: args: 73 | builtins.listToAttrs (lib.lists.imap0 (i: v: { 74 | name = builtins.toString i; 75 | value = v; 76 | }) (lib.strings.splitString "\n" (lib.strings.removeSuffix "\n" 77 | (builtins.readFile (generate name image args))))); 78 | in { 79 | environment.graphical.colors = lib.attrsets.mapAttrs 80 | (name: value: formattedColors name value.image value.params) 81 | config.environment.graphical.colorschemes; 82 | }; 83 | }; 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import ( 2 | fetchTarball { 3 | url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; 4 | sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; } 5 | ) { 6 | src = ./.; 7 | }).shellNix 8 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | use miette::{IntoDiagnostic, Result}; 3 | use pastel::ansi::{self, Brush, ToAnsiStyle}; 4 | use std::io::{stdout, IsTerminal}; 5 | use utils::{generate_palette, validate_color_delta, Backend}; 6 | 7 | mod utils; 8 | 9 | #[derive(Parser, Debug)] 10 | #[command(author, version, about)] 11 | pub struct Args { 12 | /// Path to image to pick colors from 13 | image: String, 14 | /// Number of colors to generate (excluding bold colors) 15 | #[arg(short, long, default_value_t = 8)] 16 | colors: u8, 17 | /// Generate a light colorscheme 18 | #[arg(short, long)] 19 | light: bool, 20 | /// Skip generating bold color variants 21 | #[arg(short = 'b', long)] 22 | no_bold: bool, 23 | /// How much lightness should be added to bold colors 24 | #[arg(long, default_value_t = 0.2, value_parser = validate_color_delta, allow_hyphen_values = true)] 25 | bold_delta: f64, 26 | /// Rotate colors along the hue axis 27 | #[arg(long, default_value_t = 0.0, allow_hyphen_values = true)] 28 | rotate_hue: f64, 29 | /// Saturate/desaturate colors 30 | #[arg(long, default_value_t = 0.0, value_parser = validate_color_delta, allow_hyphen_values = true)] 31 | saturate: f64, 32 | /// Lighten/darken colors 33 | #[arg(long, default_value_t = 0.0, value_parser = validate_color_delta, allow_hyphen_values = true)] 34 | lighten: f64, 35 | /// Do not darken the background and lighten the foreground colors 36 | #[arg(long)] 37 | no_adjust: bool, 38 | /// Which algorithm to use 39 | #[arg(long, value_enum, rename_all = "PascalCase", default_value_t = Backend::Okolors)] 40 | backend: Backend, 41 | } 42 | 43 | fn main() -> Result<()> { 44 | let args = Args::parse(); 45 | 46 | // Open image file 47 | let image = image::open(&args.image).into_diagnostic()?; 48 | 49 | // Generate the colorscheme from image 50 | let colors = generate_palette(&image, &args)?; 51 | 52 | // Print colors with formatting turned off for pipes 53 | let brush = Brush::from_mode(Some(ansi::Mode::TrueColor)); 54 | colors.iter().for_each(|c| { 55 | println!( 56 | "{}", 57 | if stdout().is_terminal() { 58 | brush.paint(c.to_rgb_hex_string(true), c.text_color().ansi_style().on(c)) 59 | } else { 60 | c.to_rgb_hex_string(true) 61 | } 62 | ) 63 | }); 64 | 65 | Ok(()) 66 | } 67 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use clap::ValueEnum; 2 | 3 | use color_thief::ColorFormat; 4 | use image::DynamicImage; 5 | use miette::{IntoDiagnostic, Result}; 6 | use okolors::OklabCounts; 7 | use pastel::{Color, Fraction}; 8 | 9 | use crate::Args; 10 | 11 | #[derive(ValueEnum, Clone, Debug)] 12 | pub enum Backend { 13 | ColorThief, 14 | Okolors, 15 | } 16 | 17 | /// Make sure that input value is between -1.0 and 1.0 18 | pub fn validate_color_delta(s: &str) -> Result { 19 | let num = s 20 | .parse() 21 | .map_err(|_| format!("`{s}` is not a valid floating point number"))?; 22 | if (-1.0..=1.0).contains(&num) { 23 | Ok(num) 24 | } else { 25 | Err(format!("{num} is not in range [-1.0,1.0]")) 26 | } 27 | } 28 | 29 | pub fn generate_palette(image: &DynamicImage, args: &Args) -> Result> { 30 | match args.backend { 31 | Backend::ColorThief => generate_color_thief(image, args), 32 | Backend::Okolors => generate_okolors(image, args), 33 | } 34 | .map(|mut c| transform_colors(&mut c, args)) 35 | } 36 | 37 | /// Generate a palette using the color-thief algorithm 38 | fn generate_color_thief(image: &DynamicImage, args: &Args) -> Result> { 39 | let pixels = image.to_rgb8(); 40 | 41 | let colors: Vec<_> = 42 | color_thief::get_palette(pixels.as_ref(), ColorFormat::Rgb, 5, args.colors + 1) 43 | .into_diagnostic()? 44 | .into_iter() 45 | .map(|c| Color::from_rgb(c.r, c.g, c.b)) 46 | .collect(); 47 | 48 | Ok(colors) 49 | } 50 | 51 | /// Generate a palette using `okolors` 52 | fn generate_okolors(image: &DynamicImage, args: &Args) -> Result> { 53 | let oklab = OklabCounts::try_from_image(image, u8::MAX).into_diagnostic()?; 54 | 55 | let colors: Vec<_> = okolors::run(&oklab, 5, args.colors, 0.05, 128, 0) 56 | .centroids 57 | .into_iter() 58 | .map(|c| Color::from_oklab(c.l as f64, c.a as f64, c.b as f64, 1.0)) 59 | .collect(); 60 | 61 | Ok(colors) 62 | } 63 | 64 | fn transform_colors(colors: &mut Vec, args: &Args) -> Vec { 65 | // Sort colors by luminance 66 | colors.sort_by_key(|c| (c.luminance() * 1000.0) as i32); 67 | 68 | if !args.no_adjust { 69 | // Darken the darkest color 70 | colors[0] = colors[0].mix::(&Color::black(), Fraction::from(0.9)); 71 | // Lighten the lightest color 72 | if let Some(c) = colors.last_mut() { 73 | *c = c.mix::(&Color::white(), Fraction::from(0.9)) 74 | } 75 | } 76 | 77 | if !args.no_bold { 78 | // Create second pairs of lighter colors 79 | let bold_colors = colors.clone(); 80 | let bold_colors = bold_colors.iter().map(|c| c.lighten(args.bold_delta)); 81 | colors.extend(bold_colors); 82 | } 83 | 84 | // Apply color transformations, if any 85 | let mut colors: Vec<_> = colors 86 | .iter_mut() 87 | .map(|c| c.saturate(args.saturate)) 88 | .collect(); 89 | 90 | // Light theme transformations 91 | if args.light { 92 | colors.reverse(); 93 | } 94 | 95 | colors 96 | } 97 | --------------------------------------------------------------------------------