├── .github ├── FUNDING.yml └── workflows │ ├── build-package.yml │ └── tests.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── benches └── edit_distance.rs ├── build.rs ├── docs ├── README.md └── img │ └── cyclophosphamide.png ├── src ├── cli.rs ├── langs.rs ├── lib.rs └── main.rs └── tests └── integration_test.rs /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: hisbaan 2 | -------------------------------------------------------------------------------- /.github/workflows/build-package.yml: -------------------------------------------------------------------------------- 1 | name: build-package 2 | on: 3 | workflow_dispatch: 4 | release: 5 | types: [published] 6 | branches: [main] 7 | env: 8 | CARGO_TERM_COLOR: always 9 | RUSTUP_TOOLCHAIN: stable 10 | CARGO_TARGET_DIR: target 11 | jobs: 12 | build: 13 | strategy: 14 | matrix: 15 | os: [ubuntu-latest, macos-latest] 16 | runs-on: ${{ matrix.os }} 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | - name: Build 21 | run: cargo build --locked --release 22 | - name: Strip binary 23 | run: strip target/release/dym 24 | - name: Move the binary 25 | run: cp target/release/dym . 26 | - name: Create TAR package 27 | run: tar -czvf dym-$(target/release/dym --version | cut -d ' ' -f 2)-x86_64-${{ matrix.os == 'macos-latest' && 'apple-darwin' || 'linux-gnu' }}.tar.gz completions docs man dym 28 | - name: Release 29 | uses: softprops/action-gh-release@v1 30 | if: startsWith(github.ref, 'refs/tags/') 31 | with: 32 | files: dym-$(target/release/dym --version | cut -d ' ' -f 2)-x86_64-${{ matrix.os == 'macos-latest' && 'apple-darwin' || 'linux-gnu' }}.tar.gz 33 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: tests 2 | on: 3 | push: 4 | branches: [main] 5 | pull_request: 6 | branches: [main] 7 | env: 8 | CARGO_TERM_COLOR: always 9 | jobs: 10 | build: 11 | runs-on: macos-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - name: Cache build artifacts 15 | uses: actions/cache@v3 16 | with: 17 | path: | 18 | ~/.cargo/registry 19 | ~/.cargo/git 20 | target 21 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} 22 | restore-keys: | 23 | ${{ runner.os }}-cargo- 24 | - name: Build 25 | run: cargo build --verbose 26 | - name: Run tests 27 | run: cargo test --verbose 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/rust,linux 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=rust,linux 3 | 4 | ### Linux ### 5 | *~ 6 | 7 | # temporary files which can be created if a process still has a handle open of a deleted file 8 | .fuse_hidden* 9 | 10 | # KDE directory preferences 11 | .directory 12 | 13 | # Linux trash folder which might appear on any partition or disk 14 | .Trash-* 15 | 16 | # .nfs files are created when an open file is removed but is still being accessed 17 | .nfs* 18 | 19 | ### Rust ### 20 | # Generated by Cargo 21 | # will have compiled files and executables 22 | debug/ 23 | target/ 24 | 25 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 26 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 27 | # Cargo.lock 28 | 29 | # These are backup files generated by rustfmt 30 | **/*.rs.bk 31 | 32 | # MSVC Windows builds of rustc generate these, which store debugging information 33 | *.pdb 34 | 35 | # End of https://www.toptal.com/developers/gitignore/api/rust,linux 36 | 37 | # start of personal gitignore 38 | completions/ 39 | man/ 40 | -------------------------------------------------------------------------------- /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 = "anes" 31 | version = "0.1.6" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" 34 | 35 | [[package]] 36 | name = "anstream" 37 | version = "0.6.11" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" 40 | dependencies = [ 41 | "anstyle", 42 | "anstyle-parse", 43 | "anstyle-query", 44 | "anstyle-wincon", 45 | "colorchoice", 46 | "utf8parse", 47 | ] 48 | 49 | [[package]] 50 | name = "anstyle" 51 | version = "1.0.6" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" 54 | 55 | [[package]] 56 | name = "anstyle-parse" 57 | version = "0.2.3" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" 60 | dependencies = [ 61 | "utf8parse", 62 | ] 63 | 64 | [[package]] 65 | name = "anstyle-query" 66 | version = "1.0.2" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" 69 | dependencies = [ 70 | "windows-sys 0.52.0", 71 | ] 72 | 73 | [[package]] 74 | name = "anstyle-wincon" 75 | version = "3.0.2" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" 78 | dependencies = [ 79 | "anstyle", 80 | "windows-sys 0.52.0", 81 | ] 82 | 83 | [[package]] 84 | name = "atty" 85 | version = "0.2.14" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 88 | dependencies = [ 89 | "hermit-abi 0.1.19", 90 | "libc", 91 | "winapi", 92 | ] 93 | 94 | [[package]] 95 | name = "autocfg" 96 | version = "1.1.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 99 | 100 | [[package]] 101 | name = "backtrace" 102 | version = "0.3.69" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 105 | dependencies = [ 106 | "addr2line", 107 | "cc", 108 | "cfg-if", 109 | "libc", 110 | "miniz_oxide", 111 | "object", 112 | "rustc-demangle", 113 | ] 114 | 115 | [[package]] 116 | name = "base64" 117 | version = "0.21.7" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 120 | 121 | [[package]] 122 | name = "bitflags" 123 | version = "1.3.2" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 126 | 127 | [[package]] 128 | name = "bitflags" 129 | version = "2.4.2" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" 132 | 133 | [[package]] 134 | name = "block" 135 | version = "0.1.6" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 138 | 139 | [[package]] 140 | name = "bumpalo" 141 | version = "3.14.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" 144 | 145 | [[package]] 146 | name = "bytecount" 147 | version = "0.6.7" 148 | source = "registry+https://github.com/rust-lang/crates.io-index" 149 | checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" 150 | 151 | [[package]] 152 | name = "bytes" 153 | version = "1.5.0" 154 | source = "registry+https://github.com/rust-lang/crates.io-index" 155 | checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" 156 | 157 | [[package]] 158 | name = "cast" 159 | version = "0.3.0" 160 | source = "registry+https://github.com/rust-lang/crates.io-index" 161 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" 162 | 163 | [[package]] 164 | name = "cc" 165 | version = "1.0.83" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 168 | dependencies = [ 169 | "libc", 170 | ] 171 | 172 | [[package]] 173 | name = "cfg-if" 174 | version = "1.0.0" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 177 | 178 | [[package]] 179 | name = "ciborium" 180 | version = "0.2.2" 181 | source = "registry+https://github.com/rust-lang/crates.io-index" 182 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" 183 | dependencies = [ 184 | "ciborium-io", 185 | "ciborium-ll", 186 | "serde", 187 | ] 188 | 189 | [[package]] 190 | name = "ciborium-io" 191 | version = "0.2.2" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" 194 | 195 | [[package]] 196 | name = "ciborium-ll" 197 | version = "0.2.2" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" 200 | dependencies = [ 201 | "ciborium-io", 202 | "half", 203 | ] 204 | 205 | [[package]] 206 | name = "clap" 207 | version = "4.4.18" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" 210 | dependencies = [ 211 | "clap_builder", 212 | "clap_derive", 213 | ] 214 | 215 | [[package]] 216 | name = "clap_builder" 217 | version = "4.4.18" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" 220 | dependencies = [ 221 | "anstream", 222 | "anstyle", 223 | "clap_lex", 224 | "strsim", 225 | ] 226 | 227 | [[package]] 228 | name = "clap_complete" 229 | version = "4.4.10" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3" 232 | dependencies = [ 233 | "clap", 234 | ] 235 | 236 | [[package]] 237 | name = "clap_derive" 238 | version = "4.4.7" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" 241 | dependencies = [ 242 | "heck", 243 | "proc-macro2", 244 | "quote", 245 | "syn 2.0.48", 246 | ] 247 | 248 | [[package]] 249 | name = "clap_lex" 250 | version = "0.6.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" 253 | 254 | [[package]] 255 | name = "clap_mangen" 256 | version = "0.2.19" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "8e35a078f3aae828c9b7ad58e1631dab87e9dac40da19418f2219bbf3198aa5c" 259 | dependencies = [ 260 | "clap", 261 | "roff", 262 | ] 263 | 264 | [[package]] 265 | name = "cli-clipboard" 266 | version = "0.4.0" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "04087c1d4a2aa259784a563932aee09cbb0869d490775e051096174b070f3e3d" 269 | dependencies = [ 270 | "clipboard-win", 271 | "objc", 272 | "objc-foundation", 273 | "objc_id", 274 | "wl-clipboard-rs", 275 | "x11-clipboard", 276 | ] 277 | 278 | [[package]] 279 | name = "clipboard-win" 280 | version = "4.5.0" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" 283 | dependencies = [ 284 | "error-code", 285 | "str-buf", 286 | "winapi", 287 | ] 288 | 289 | [[package]] 290 | name = "colorchoice" 291 | version = "1.0.0" 292 | source = "registry+https://github.com/rust-lang/crates.io-index" 293 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 294 | 295 | [[package]] 296 | name = "colored" 297 | version = "2.1.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" 300 | dependencies = [ 301 | "lazy_static", 302 | "windows-sys 0.48.0", 303 | ] 304 | 305 | [[package]] 306 | name = "console" 307 | version = "0.15.8" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" 310 | dependencies = [ 311 | "encode_unicode", 312 | "lazy_static", 313 | "libc", 314 | "unicode-width", 315 | "windows-sys 0.52.0", 316 | ] 317 | 318 | [[package]] 319 | name = "core-foundation" 320 | version = "0.9.4" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" 323 | dependencies = [ 324 | "core-foundation-sys", 325 | "libc", 326 | ] 327 | 328 | [[package]] 329 | name = "core-foundation-sys" 330 | version = "0.8.6" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" 333 | 334 | [[package]] 335 | name = "criterion" 336 | version = "0.5.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" 339 | dependencies = [ 340 | "anes", 341 | "cast", 342 | "ciborium", 343 | "clap", 344 | "criterion-plot", 345 | "is-terminal", 346 | "itertools", 347 | "num-traits", 348 | "once_cell", 349 | "oorandom", 350 | "plotters", 351 | "rayon", 352 | "regex", 353 | "serde", 354 | "serde_derive", 355 | "serde_json", 356 | "tinytemplate", 357 | "walkdir", 358 | ] 359 | 360 | [[package]] 361 | name = "criterion-plot" 362 | version = "0.5.0" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" 365 | dependencies = [ 366 | "cast", 367 | "itertools", 368 | ] 369 | 370 | [[package]] 371 | name = "crossbeam-deque" 372 | version = "0.8.5" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 375 | dependencies = [ 376 | "crossbeam-epoch", 377 | "crossbeam-utils", 378 | ] 379 | 380 | [[package]] 381 | name = "crossbeam-epoch" 382 | version = "0.9.18" 383 | source = "registry+https://github.com/rust-lang/crates.io-index" 384 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 385 | dependencies = [ 386 | "crossbeam-utils", 387 | ] 388 | 389 | [[package]] 390 | name = "crossbeam-utils" 391 | version = "0.8.19" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" 394 | 395 | [[package]] 396 | name = "crunchy" 397 | version = "0.2.2" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 400 | 401 | [[package]] 402 | name = "derive-new" 403 | version = "0.5.9" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535" 406 | dependencies = [ 407 | "proc-macro2", 408 | "quote", 409 | "syn 1.0.109", 410 | ] 411 | 412 | [[package]] 413 | name = "dialoguer" 414 | version = "0.11.0" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" 417 | dependencies = [ 418 | "console", 419 | "shell-words", 420 | "tempfile", 421 | "thiserror", 422 | "zeroize", 423 | ] 424 | 425 | [[package]] 426 | name = "didyoumean" 427 | version = "1.1.4" 428 | dependencies = [ 429 | "atty", 430 | "clap", 431 | "clap_complete", 432 | "clap_mangen", 433 | "cli-clipboard", 434 | "colored", 435 | "criterion", 436 | "dialoguer", 437 | "dirs", 438 | "futures-util", 439 | "indicatif", 440 | "nix 0.27.1", 441 | "phf", 442 | "reqwest", 443 | "tokio", 444 | ] 445 | 446 | [[package]] 447 | name = "dirs" 448 | version = "5.0.1" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" 451 | dependencies = [ 452 | "dirs-sys", 453 | ] 454 | 455 | [[package]] 456 | name = "dirs-sys" 457 | version = "0.4.1" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" 460 | dependencies = [ 461 | "libc", 462 | "option-ext", 463 | "redox_users", 464 | "windows-sys 0.48.0", 465 | ] 466 | 467 | [[package]] 468 | name = "downcast-rs" 469 | version = "1.2.0" 470 | source = "registry+https://github.com/rust-lang/crates.io-index" 471 | checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" 472 | 473 | [[package]] 474 | name = "either" 475 | version = "1.9.0" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 478 | 479 | [[package]] 480 | name = "encode_unicode" 481 | version = "0.3.6" 482 | source = "registry+https://github.com/rust-lang/crates.io-index" 483 | checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" 484 | 485 | [[package]] 486 | name = "encoding_rs" 487 | version = "0.8.33" 488 | source = "registry+https://github.com/rust-lang/crates.io-index" 489 | checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" 490 | dependencies = [ 491 | "cfg-if", 492 | ] 493 | 494 | [[package]] 495 | name = "equivalent" 496 | version = "1.0.1" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 499 | 500 | [[package]] 501 | name = "errno" 502 | version = "0.3.8" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" 505 | dependencies = [ 506 | "libc", 507 | "windows-sys 0.52.0", 508 | ] 509 | 510 | [[package]] 511 | name = "error-code" 512 | version = "2.3.1" 513 | source = "registry+https://github.com/rust-lang/crates.io-index" 514 | checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" 515 | dependencies = [ 516 | "libc", 517 | "str-buf", 518 | ] 519 | 520 | [[package]] 521 | name = "fastrand" 522 | version = "2.0.1" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" 525 | 526 | [[package]] 527 | name = "fixedbitset" 528 | version = "0.4.2" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 531 | 532 | [[package]] 533 | name = "fnv" 534 | version = "1.0.7" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 537 | 538 | [[package]] 539 | name = "foreign-types" 540 | version = "0.3.2" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 543 | dependencies = [ 544 | "foreign-types-shared", 545 | ] 546 | 547 | [[package]] 548 | name = "foreign-types-shared" 549 | version = "0.1.1" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 552 | 553 | [[package]] 554 | name = "form_urlencoded" 555 | version = "1.2.1" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 558 | dependencies = [ 559 | "percent-encoding", 560 | ] 561 | 562 | [[package]] 563 | name = "futures-channel" 564 | version = "0.3.30" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 567 | dependencies = [ 568 | "futures-core", 569 | ] 570 | 571 | [[package]] 572 | name = "futures-core" 573 | version = "0.3.30" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 576 | 577 | [[package]] 578 | name = "futures-io" 579 | version = "0.3.30" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 582 | 583 | [[package]] 584 | name = "futures-macro" 585 | version = "0.3.30" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 588 | dependencies = [ 589 | "proc-macro2", 590 | "quote", 591 | "syn 2.0.48", 592 | ] 593 | 594 | [[package]] 595 | name = "futures-sink" 596 | version = "0.3.30" 597 | source = "registry+https://github.com/rust-lang/crates.io-index" 598 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 599 | 600 | [[package]] 601 | name = "futures-task" 602 | version = "0.3.30" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 605 | 606 | [[package]] 607 | name = "futures-util" 608 | version = "0.3.30" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 611 | dependencies = [ 612 | "futures-core", 613 | "futures-io", 614 | "futures-macro", 615 | "futures-sink", 616 | "futures-task", 617 | "memchr", 618 | "pin-project-lite", 619 | "pin-utils", 620 | "slab", 621 | ] 622 | 623 | [[package]] 624 | name = "gethostname" 625 | version = "0.2.3" 626 | source = "registry+https://github.com/rust-lang/crates.io-index" 627 | checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" 628 | dependencies = [ 629 | "libc", 630 | "winapi", 631 | ] 632 | 633 | [[package]] 634 | name = "getrandom" 635 | version = "0.2.12" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" 638 | dependencies = [ 639 | "cfg-if", 640 | "libc", 641 | "wasi", 642 | ] 643 | 644 | [[package]] 645 | name = "gimli" 646 | version = "0.28.1" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" 649 | 650 | [[package]] 651 | name = "h2" 652 | version = "0.3.26" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 655 | dependencies = [ 656 | "bytes", 657 | "fnv", 658 | "futures-core", 659 | "futures-sink", 660 | "futures-util", 661 | "http", 662 | "indexmap", 663 | "slab", 664 | "tokio", 665 | "tokio-util", 666 | "tracing", 667 | ] 668 | 669 | [[package]] 670 | name = "half" 671 | version = "2.3.1" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" 674 | dependencies = [ 675 | "cfg-if", 676 | "crunchy", 677 | ] 678 | 679 | [[package]] 680 | name = "hashbrown" 681 | version = "0.14.3" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" 684 | 685 | [[package]] 686 | name = "heck" 687 | version = "0.4.1" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 690 | 691 | [[package]] 692 | name = "hermit-abi" 693 | version = "0.1.19" 694 | source = "registry+https://github.com/rust-lang/crates.io-index" 695 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 696 | dependencies = [ 697 | "libc", 698 | ] 699 | 700 | [[package]] 701 | name = "hermit-abi" 702 | version = "0.3.5" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" 705 | 706 | [[package]] 707 | name = "http" 708 | version = "0.2.11" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" 711 | dependencies = [ 712 | "bytes", 713 | "fnv", 714 | "itoa", 715 | ] 716 | 717 | [[package]] 718 | name = "http-body" 719 | version = "0.4.6" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 722 | dependencies = [ 723 | "bytes", 724 | "http", 725 | "pin-project-lite", 726 | ] 727 | 728 | [[package]] 729 | name = "httparse" 730 | version = "1.8.0" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 733 | 734 | [[package]] 735 | name = "httpdate" 736 | version = "1.0.3" 737 | source = "registry+https://github.com/rust-lang/crates.io-index" 738 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 739 | 740 | [[package]] 741 | name = "hyper" 742 | version = "0.14.28" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" 745 | dependencies = [ 746 | "bytes", 747 | "futures-channel", 748 | "futures-core", 749 | "futures-util", 750 | "h2", 751 | "http", 752 | "http-body", 753 | "httparse", 754 | "httpdate", 755 | "itoa", 756 | "pin-project-lite", 757 | "socket2", 758 | "tokio", 759 | "tower-service", 760 | "tracing", 761 | "want", 762 | ] 763 | 764 | [[package]] 765 | name = "hyper-tls" 766 | version = "0.5.0" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 769 | dependencies = [ 770 | "bytes", 771 | "hyper", 772 | "native-tls", 773 | "tokio", 774 | "tokio-native-tls", 775 | ] 776 | 777 | [[package]] 778 | name = "idna" 779 | version = "0.5.0" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 782 | dependencies = [ 783 | "unicode-bidi", 784 | "unicode-normalization", 785 | ] 786 | 787 | [[package]] 788 | name = "indexmap" 789 | version = "2.2.2" 790 | source = "registry+https://github.com/rust-lang/crates.io-index" 791 | checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520" 792 | dependencies = [ 793 | "equivalent", 794 | "hashbrown", 795 | ] 796 | 797 | [[package]] 798 | name = "indicatif" 799 | version = "0.17.7" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" 802 | dependencies = [ 803 | "console", 804 | "instant", 805 | "number_prefix", 806 | "portable-atomic", 807 | "unicode-width", 808 | ] 809 | 810 | [[package]] 811 | name = "instant" 812 | version = "0.1.12" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 815 | dependencies = [ 816 | "cfg-if", 817 | ] 818 | 819 | [[package]] 820 | name = "ipnet" 821 | version = "2.9.0" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" 824 | 825 | [[package]] 826 | name = "is-terminal" 827 | version = "0.4.10" 828 | source = "registry+https://github.com/rust-lang/crates.io-index" 829 | checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" 830 | dependencies = [ 831 | "hermit-abi 0.3.5", 832 | "rustix", 833 | "windows-sys 0.52.0", 834 | ] 835 | 836 | [[package]] 837 | name = "itertools" 838 | version = "0.10.5" 839 | source = "registry+https://github.com/rust-lang/crates.io-index" 840 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 841 | dependencies = [ 842 | "either", 843 | ] 844 | 845 | [[package]] 846 | name = "itoa" 847 | version = "1.0.10" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" 850 | 851 | [[package]] 852 | name = "js-sys" 853 | version = "0.3.67" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" 856 | dependencies = [ 857 | "wasm-bindgen", 858 | ] 859 | 860 | [[package]] 861 | name = "lazy_static" 862 | version = "1.4.0" 863 | source = "registry+https://github.com/rust-lang/crates.io-index" 864 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 865 | 866 | [[package]] 867 | name = "libc" 868 | version = "0.2.153" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" 871 | 872 | [[package]] 873 | name = "libredox" 874 | version = "0.0.1" 875 | source = "registry+https://github.com/rust-lang/crates.io-index" 876 | checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" 877 | dependencies = [ 878 | "bitflags 2.4.2", 879 | "libc", 880 | "redox_syscall", 881 | ] 882 | 883 | [[package]] 884 | name = "linux-raw-sys" 885 | version = "0.4.13" 886 | source = "registry+https://github.com/rust-lang/crates.io-index" 887 | checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" 888 | 889 | [[package]] 890 | name = "log" 891 | version = "0.4.20" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 894 | 895 | [[package]] 896 | name = "malloc_buf" 897 | version = "0.0.6" 898 | source = "registry+https://github.com/rust-lang/crates.io-index" 899 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 900 | dependencies = [ 901 | "libc", 902 | ] 903 | 904 | [[package]] 905 | name = "memchr" 906 | version = "2.7.1" 907 | source = "registry+https://github.com/rust-lang/crates.io-index" 908 | checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" 909 | 910 | [[package]] 911 | name = "memoffset" 912 | version = "0.6.5" 913 | source = "registry+https://github.com/rust-lang/crates.io-index" 914 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 915 | dependencies = [ 916 | "autocfg", 917 | ] 918 | 919 | [[package]] 920 | name = "mime" 921 | version = "0.3.17" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 924 | 925 | [[package]] 926 | name = "minimal-lexical" 927 | version = "0.2.1" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 930 | 931 | [[package]] 932 | name = "miniz_oxide" 933 | version = "0.7.2" 934 | source = "registry+https://github.com/rust-lang/crates.io-index" 935 | checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" 936 | dependencies = [ 937 | "adler", 938 | ] 939 | 940 | [[package]] 941 | name = "mio" 942 | version = "0.8.11" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 945 | dependencies = [ 946 | "libc", 947 | "wasi", 948 | "windows-sys 0.48.0", 949 | ] 950 | 951 | [[package]] 952 | name = "native-tls" 953 | version = "0.2.11" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" 956 | dependencies = [ 957 | "lazy_static", 958 | "libc", 959 | "log", 960 | "openssl", 961 | "openssl-probe", 962 | "openssl-sys", 963 | "schannel", 964 | "security-framework", 965 | "security-framework-sys", 966 | "tempfile", 967 | ] 968 | 969 | [[package]] 970 | name = "nix" 971 | version = "0.24.3" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" 974 | dependencies = [ 975 | "bitflags 1.3.2", 976 | "cfg-if", 977 | "libc", 978 | "memoffset", 979 | ] 980 | 981 | [[package]] 982 | name = "nix" 983 | version = "0.27.1" 984 | source = "registry+https://github.com/rust-lang/crates.io-index" 985 | checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" 986 | dependencies = [ 987 | "bitflags 2.4.2", 988 | "cfg-if", 989 | "libc", 990 | ] 991 | 992 | [[package]] 993 | name = "nom" 994 | version = "7.1.3" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 997 | dependencies = [ 998 | "memchr", 999 | "minimal-lexical", 1000 | ] 1001 | 1002 | [[package]] 1003 | name = "num-traits" 1004 | version = "0.2.17" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" 1007 | dependencies = [ 1008 | "autocfg", 1009 | ] 1010 | 1011 | [[package]] 1012 | name = "num_cpus" 1013 | version = "1.16.0" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 1016 | dependencies = [ 1017 | "hermit-abi 0.3.5", 1018 | "libc", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "number_prefix" 1023 | version = "0.4.0" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 1026 | 1027 | [[package]] 1028 | name = "objc" 1029 | version = "0.2.7" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 1032 | dependencies = [ 1033 | "malloc_buf", 1034 | ] 1035 | 1036 | [[package]] 1037 | name = "objc-foundation" 1038 | version = "0.1.1" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" 1041 | dependencies = [ 1042 | "block", 1043 | "objc", 1044 | "objc_id", 1045 | ] 1046 | 1047 | [[package]] 1048 | name = "objc_id" 1049 | version = "0.1.1" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" 1052 | dependencies = [ 1053 | "objc", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "object" 1058 | version = "0.32.2" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" 1061 | dependencies = [ 1062 | "memchr", 1063 | ] 1064 | 1065 | [[package]] 1066 | name = "once_cell" 1067 | version = "1.19.0" 1068 | source = "registry+https://github.com/rust-lang/crates.io-index" 1069 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 1070 | 1071 | [[package]] 1072 | name = "oorandom" 1073 | version = "11.1.3" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" 1076 | 1077 | [[package]] 1078 | name = "openssl" 1079 | version = "0.10.66" 1080 | source = "registry+https://github.com/rust-lang/crates.io-index" 1081 | checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" 1082 | dependencies = [ 1083 | "bitflags 2.4.2", 1084 | "cfg-if", 1085 | "foreign-types", 1086 | "libc", 1087 | "once_cell", 1088 | "openssl-macros", 1089 | "openssl-sys", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "openssl-macros" 1094 | version = "0.1.1" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" 1097 | dependencies = [ 1098 | "proc-macro2", 1099 | "quote", 1100 | "syn 2.0.48", 1101 | ] 1102 | 1103 | [[package]] 1104 | name = "openssl-probe" 1105 | version = "0.1.5" 1106 | source = "registry+https://github.com/rust-lang/crates.io-index" 1107 | checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" 1108 | 1109 | [[package]] 1110 | name = "openssl-sys" 1111 | version = "0.9.103" 1112 | source = "registry+https://github.com/rust-lang/crates.io-index" 1113 | checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" 1114 | dependencies = [ 1115 | "cc", 1116 | "libc", 1117 | "pkg-config", 1118 | "vcpkg", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "option-ext" 1123 | version = "0.2.0" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 1126 | 1127 | [[package]] 1128 | name = "os_pipe" 1129 | version = "1.1.5" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" 1132 | dependencies = [ 1133 | "libc", 1134 | "windows-sys 0.52.0", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "percent-encoding" 1139 | version = "2.3.1" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 1142 | 1143 | [[package]] 1144 | name = "petgraph" 1145 | version = "0.6.4" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" 1148 | dependencies = [ 1149 | "fixedbitset", 1150 | "indexmap", 1151 | ] 1152 | 1153 | [[package]] 1154 | name = "phf" 1155 | version = "0.11.2" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 1158 | dependencies = [ 1159 | "phf_macros", 1160 | "phf_shared", 1161 | ] 1162 | 1163 | [[package]] 1164 | name = "phf_generator" 1165 | version = "0.11.2" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" 1168 | dependencies = [ 1169 | "phf_shared", 1170 | "rand", 1171 | ] 1172 | 1173 | [[package]] 1174 | name = "phf_macros" 1175 | version = "0.11.2" 1176 | source = "registry+https://github.com/rust-lang/crates.io-index" 1177 | checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" 1178 | dependencies = [ 1179 | "phf_generator", 1180 | "phf_shared", 1181 | "proc-macro2", 1182 | "quote", 1183 | "syn 2.0.48", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "phf_shared" 1188 | version = "0.11.2" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 1191 | dependencies = [ 1192 | "siphasher", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "pin-project-lite" 1197 | version = "0.2.13" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 1200 | 1201 | [[package]] 1202 | name = "pin-utils" 1203 | version = "0.1.0" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1206 | 1207 | [[package]] 1208 | name = "pkg-config" 1209 | version = "0.3.29" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" 1212 | 1213 | [[package]] 1214 | name = "plotters" 1215 | version = "0.3.5" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" 1218 | dependencies = [ 1219 | "num-traits", 1220 | "plotters-backend", 1221 | "plotters-svg", 1222 | "wasm-bindgen", 1223 | "web-sys", 1224 | ] 1225 | 1226 | [[package]] 1227 | name = "plotters-backend" 1228 | version = "0.3.5" 1229 | source = "registry+https://github.com/rust-lang/crates.io-index" 1230 | checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" 1231 | 1232 | [[package]] 1233 | name = "plotters-svg" 1234 | version = "0.3.5" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" 1237 | dependencies = [ 1238 | "plotters-backend", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "portable-atomic" 1243 | version = "1.6.0" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" 1246 | 1247 | [[package]] 1248 | name = "proc-macro2" 1249 | version = "1.0.78" 1250 | source = "registry+https://github.com/rust-lang/crates.io-index" 1251 | checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" 1252 | dependencies = [ 1253 | "unicode-ident", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "quote" 1258 | version = "1.0.35" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" 1261 | dependencies = [ 1262 | "proc-macro2", 1263 | ] 1264 | 1265 | [[package]] 1266 | name = "rand" 1267 | version = "0.8.5" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1270 | dependencies = [ 1271 | "rand_core", 1272 | ] 1273 | 1274 | [[package]] 1275 | name = "rand_core" 1276 | version = "0.6.4" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1279 | 1280 | [[package]] 1281 | name = "rayon" 1282 | version = "1.8.1" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "fa7237101a77a10773db45d62004a272517633fbcc3df19d96455ede1122e051" 1285 | dependencies = [ 1286 | "either", 1287 | "rayon-core", 1288 | ] 1289 | 1290 | [[package]] 1291 | name = "rayon-core" 1292 | version = "1.12.1" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 1295 | dependencies = [ 1296 | "crossbeam-deque", 1297 | "crossbeam-utils", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "redox_syscall" 1302 | version = "0.4.1" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 1305 | dependencies = [ 1306 | "bitflags 1.3.2", 1307 | ] 1308 | 1309 | [[package]] 1310 | name = "redox_users" 1311 | version = "0.4.4" 1312 | source = "registry+https://github.com/rust-lang/crates.io-index" 1313 | checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" 1314 | dependencies = [ 1315 | "getrandom", 1316 | "libredox", 1317 | "thiserror", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "regex" 1322 | version = "1.10.3" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" 1325 | dependencies = [ 1326 | "aho-corasick", 1327 | "memchr", 1328 | "regex-automata", 1329 | "regex-syntax", 1330 | ] 1331 | 1332 | [[package]] 1333 | name = "regex-automata" 1334 | version = "0.4.5" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" 1337 | dependencies = [ 1338 | "aho-corasick", 1339 | "memchr", 1340 | "regex-syntax", 1341 | ] 1342 | 1343 | [[package]] 1344 | name = "regex-syntax" 1345 | version = "0.8.2" 1346 | source = "registry+https://github.com/rust-lang/crates.io-index" 1347 | checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" 1348 | 1349 | [[package]] 1350 | name = "reqwest" 1351 | version = "0.11.24" 1352 | source = "registry+https://github.com/rust-lang/crates.io-index" 1353 | checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" 1354 | dependencies = [ 1355 | "base64", 1356 | "bytes", 1357 | "encoding_rs", 1358 | "futures-core", 1359 | "futures-util", 1360 | "h2", 1361 | "http", 1362 | "http-body", 1363 | "hyper", 1364 | "hyper-tls", 1365 | "ipnet", 1366 | "js-sys", 1367 | "log", 1368 | "mime", 1369 | "native-tls", 1370 | "once_cell", 1371 | "percent-encoding", 1372 | "pin-project-lite", 1373 | "rustls-pemfile", 1374 | "serde", 1375 | "serde_json", 1376 | "serde_urlencoded", 1377 | "sync_wrapper", 1378 | "system-configuration", 1379 | "tokio", 1380 | "tokio-native-tls", 1381 | "tokio-util", 1382 | "tower-service", 1383 | "url", 1384 | "wasm-bindgen", 1385 | "wasm-bindgen-futures", 1386 | "wasm-streams", 1387 | "web-sys", 1388 | "winreg", 1389 | ] 1390 | 1391 | [[package]] 1392 | name = "roff" 1393 | version = "0.2.1" 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" 1395 | checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" 1396 | 1397 | [[package]] 1398 | name = "rustc-demangle" 1399 | version = "0.1.23" 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" 1401 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 1402 | 1403 | [[package]] 1404 | name = "rustix" 1405 | version = "0.38.31" 1406 | source = "registry+https://github.com/rust-lang/crates.io-index" 1407 | checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" 1408 | dependencies = [ 1409 | "bitflags 2.4.2", 1410 | "errno", 1411 | "libc", 1412 | "linux-raw-sys", 1413 | "windows-sys 0.52.0", 1414 | ] 1415 | 1416 | [[package]] 1417 | name = "rustls-pemfile" 1418 | version = "1.0.4" 1419 | source = "registry+https://github.com/rust-lang/crates.io-index" 1420 | checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" 1421 | dependencies = [ 1422 | "base64", 1423 | ] 1424 | 1425 | [[package]] 1426 | name = "ryu" 1427 | version = "1.0.16" 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" 1429 | checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" 1430 | 1431 | [[package]] 1432 | name = "same-file" 1433 | version = "1.0.6" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1436 | dependencies = [ 1437 | "winapi-util", 1438 | ] 1439 | 1440 | [[package]] 1441 | name = "schannel" 1442 | version = "0.1.23" 1443 | source = "registry+https://github.com/rust-lang/crates.io-index" 1444 | checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" 1445 | dependencies = [ 1446 | "windows-sys 0.52.0", 1447 | ] 1448 | 1449 | [[package]] 1450 | name = "security-framework" 1451 | version = "2.9.2" 1452 | source = "registry+https://github.com/rust-lang/crates.io-index" 1453 | checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" 1454 | dependencies = [ 1455 | "bitflags 1.3.2", 1456 | "core-foundation", 1457 | "core-foundation-sys", 1458 | "libc", 1459 | "security-framework-sys", 1460 | ] 1461 | 1462 | [[package]] 1463 | name = "security-framework-sys" 1464 | version = "2.9.1" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" 1467 | dependencies = [ 1468 | "core-foundation-sys", 1469 | "libc", 1470 | ] 1471 | 1472 | [[package]] 1473 | name = "serde" 1474 | version = "1.0.196" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" 1477 | dependencies = [ 1478 | "serde_derive", 1479 | ] 1480 | 1481 | [[package]] 1482 | name = "serde_derive" 1483 | version = "1.0.196" 1484 | source = "registry+https://github.com/rust-lang/crates.io-index" 1485 | checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" 1486 | dependencies = [ 1487 | "proc-macro2", 1488 | "quote", 1489 | "syn 2.0.48", 1490 | ] 1491 | 1492 | [[package]] 1493 | name = "serde_json" 1494 | version = "1.0.113" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" 1497 | dependencies = [ 1498 | "itoa", 1499 | "ryu", 1500 | "serde", 1501 | ] 1502 | 1503 | [[package]] 1504 | name = "serde_urlencoded" 1505 | version = "0.7.1" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1508 | dependencies = [ 1509 | "form_urlencoded", 1510 | "itoa", 1511 | "ryu", 1512 | "serde", 1513 | ] 1514 | 1515 | [[package]] 1516 | name = "shell-words" 1517 | version = "1.1.0" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" 1520 | 1521 | [[package]] 1522 | name = "siphasher" 1523 | version = "0.3.11" 1524 | source = "registry+https://github.com/rust-lang/crates.io-index" 1525 | checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" 1526 | 1527 | [[package]] 1528 | name = "slab" 1529 | version = "0.4.9" 1530 | source = "registry+https://github.com/rust-lang/crates.io-index" 1531 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 1532 | dependencies = [ 1533 | "autocfg", 1534 | ] 1535 | 1536 | [[package]] 1537 | name = "smallvec" 1538 | version = "1.13.1" 1539 | source = "registry+https://github.com/rust-lang/crates.io-index" 1540 | checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" 1541 | 1542 | [[package]] 1543 | name = "socket2" 1544 | version = "0.5.5" 1545 | source = "registry+https://github.com/rust-lang/crates.io-index" 1546 | checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" 1547 | dependencies = [ 1548 | "libc", 1549 | "windows-sys 0.48.0", 1550 | ] 1551 | 1552 | [[package]] 1553 | name = "str-buf" 1554 | version = "1.0.6" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" 1557 | 1558 | [[package]] 1559 | name = "strsim" 1560 | version = "0.10.0" 1561 | source = "registry+https://github.com/rust-lang/crates.io-index" 1562 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1563 | 1564 | [[package]] 1565 | name = "syn" 1566 | version = "1.0.109" 1567 | source = "registry+https://github.com/rust-lang/crates.io-index" 1568 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1569 | dependencies = [ 1570 | "proc-macro2", 1571 | "quote", 1572 | "unicode-ident", 1573 | ] 1574 | 1575 | [[package]] 1576 | name = "syn" 1577 | version = "2.0.48" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" 1580 | dependencies = [ 1581 | "proc-macro2", 1582 | "quote", 1583 | "unicode-ident", 1584 | ] 1585 | 1586 | [[package]] 1587 | name = "sync_wrapper" 1588 | version = "0.1.2" 1589 | source = "registry+https://github.com/rust-lang/crates.io-index" 1590 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 1591 | 1592 | [[package]] 1593 | name = "system-configuration" 1594 | version = "0.5.1" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" 1597 | dependencies = [ 1598 | "bitflags 1.3.2", 1599 | "core-foundation", 1600 | "system-configuration-sys", 1601 | ] 1602 | 1603 | [[package]] 1604 | name = "system-configuration-sys" 1605 | version = "0.5.0" 1606 | source = "registry+https://github.com/rust-lang/crates.io-index" 1607 | checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" 1608 | dependencies = [ 1609 | "core-foundation-sys", 1610 | "libc", 1611 | ] 1612 | 1613 | [[package]] 1614 | name = "tempfile" 1615 | version = "3.10.0" 1616 | source = "registry+https://github.com/rust-lang/crates.io-index" 1617 | checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" 1618 | dependencies = [ 1619 | "cfg-if", 1620 | "fastrand", 1621 | "rustix", 1622 | "windows-sys 0.52.0", 1623 | ] 1624 | 1625 | [[package]] 1626 | name = "thiserror" 1627 | version = "1.0.56" 1628 | source = "registry+https://github.com/rust-lang/crates.io-index" 1629 | checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" 1630 | dependencies = [ 1631 | "thiserror-impl", 1632 | ] 1633 | 1634 | [[package]] 1635 | name = "thiserror-impl" 1636 | version = "1.0.56" 1637 | source = "registry+https://github.com/rust-lang/crates.io-index" 1638 | checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" 1639 | dependencies = [ 1640 | "proc-macro2", 1641 | "quote", 1642 | "syn 2.0.48", 1643 | ] 1644 | 1645 | [[package]] 1646 | name = "tinytemplate" 1647 | version = "1.2.1" 1648 | source = "registry+https://github.com/rust-lang/crates.io-index" 1649 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 1650 | dependencies = [ 1651 | "serde", 1652 | "serde_json", 1653 | ] 1654 | 1655 | [[package]] 1656 | name = "tinyvec" 1657 | version = "1.6.0" 1658 | source = "registry+https://github.com/rust-lang/crates.io-index" 1659 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1660 | dependencies = [ 1661 | "tinyvec_macros", 1662 | ] 1663 | 1664 | [[package]] 1665 | name = "tinyvec_macros" 1666 | version = "0.1.1" 1667 | source = "registry+https://github.com/rust-lang/crates.io-index" 1668 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1669 | 1670 | [[package]] 1671 | name = "tokio" 1672 | version = "1.36.0" 1673 | source = "registry+https://github.com/rust-lang/crates.io-index" 1674 | checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" 1675 | dependencies = [ 1676 | "backtrace", 1677 | "bytes", 1678 | "libc", 1679 | "mio", 1680 | "num_cpus", 1681 | "pin-project-lite", 1682 | "socket2", 1683 | "tokio-macros", 1684 | "windows-sys 0.48.0", 1685 | ] 1686 | 1687 | [[package]] 1688 | name = "tokio-macros" 1689 | version = "2.2.0" 1690 | source = "registry+https://github.com/rust-lang/crates.io-index" 1691 | checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" 1692 | dependencies = [ 1693 | "proc-macro2", 1694 | "quote", 1695 | "syn 2.0.48", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "tokio-native-tls" 1700 | version = "0.3.1" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" 1703 | dependencies = [ 1704 | "native-tls", 1705 | "tokio", 1706 | ] 1707 | 1708 | [[package]] 1709 | name = "tokio-util" 1710 | version = "0.7.10" 1711 | source = "registry+https://github.com/rust-lang/crates.io-index" 1712 | checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" 1713 | dependencies = [ 1714 | "bytes", 1715 | "futures-core", 1716 | "futures-sink", 1717 | "pin-project-lite", 1718 | "tokio", 1719 | "tracing", 1720 | ] 1721 | 1722 | [[package]] 1723 | name = "tower-service" 1724 | version = "0.3.2" 1725 | source = "registry+https://github.com/rust-lang/crates.io-index" 1726 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1727 | 1728 | [[package]] 1729 | name = "tracing" 1730 | version = "0.1.40" 1731 | source = "registry+https://github.com/rust-lang/crates.io-index" 1732 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1733 | dependencies = [ 1734 | "pin-project-lite", 1735 | "tracing-core", 1736 | ] 1737 | 1738 | [[package]] 1739 | name = "tracing-core" 1740 | version = "0.1.32" 1741 | source = "registry+https://github.com/rust-lang/crates.io-index" 1742 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1743 | dependencies = [ 1744 | "once_cell", 1745 | ] 1746 | 1747 | [[package]] 1748 | name = "tree_magic_mini" 1749 | version = "3.0.3" 1750 | source = "registry+https://github.com/rust-lang/crates.io-index" 1751 | checksum = "91adfd0607cacf6e4babdb870e9bec4037c1c4b151cfd279ccefc5e0c7feaa6d" 1752 | dependencies = [ 1753 | "bytecount", 1754 | "fnv", 1755 | "lazy_static", 1756 | "nom", 1757 | "once_cell", 1758 | "petgraph", 1759 | ] 1760 | 1761 | [[package]] 1762 | name = "try-lock" 1763 | version = "0.2.5" 1764 | source = "registry+https://github.com/rust-lang/crates.io-index" 1765 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1766 | 1767 | [[package]] 1768 | name = "unicode-bidi" 1769 | version = "0.3.15" 1770 | source = "registry+https://github.com/rust-lang/crates.io-index" 1771 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1772 | 1773 | [[package]] 1774 | name = "unicode-ident" 1775 | version = "1.0.12" 1776 | source = "registry+https://github.com/rust-lang/crates.io-index" 1777 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1778 | 1779 | [[package]] 1780 | name = "unicode-normalization" 1781 | version = "0.1.22" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1784 | dependencies = [ 1785 | "tinyvec", 1786 | ] 1787 | 1788 | [[package]] 1789 | name = "unicode-width" 1790 | version = "0.1.11" 1791 | source = "registry+https://github.com/rust-lang/crates.io-index" 1792 | checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" 1793 | 1794 | [[package]] 1795 | name = "url" 1796 | version = "2.5.0" 1797 | source = "registry+https://github.com/rust-lang/crates.io-index" 1798 | checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" 1799 | dependencies = [ 1800 | "form_urlencoded", 1801 | "idna", 1802 | "percent-encoding", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "utf8parse" 1807 | version = "0.2.1" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1810 | 1811 | [[package]] 1812 | name = "vcpkg" 1813 | version = "0.2.15" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1816 | 1817 | [[package]] 1818 | name = "walkdir" 1819 | version = "2.4.0" 1820 | source = "registry+https://github.com/rust-lang/crates.io-index" 1821 | checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" 1822 | dependencies = [ 1823 | "same-file", 1824 | "winapi-util", 1825 | ] 1826 | 1827 | [[package]] 1828 | name = "want" 1829 | version = "0.3.1" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1832 | dependencies = [ 1833 | "try-lock", 1834 | ] 1835 | 1836 | [[package]] 1837 | name = "wasi" 1838 | version = "0.11.0+wasi-snapshot-preview1" 1839 | source = "registry+https://github.com/rust-lang/crates.io-index" 1840 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1841 | 1842 | [[package]] 1843 | name = "wasm-bindgen" 1844 | version = "0.2.90" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" 1847 | dependencies = [ 1848 | "cfg-if", 1849 | "wasm-bindgen-macro", 1850 | ] 1851 | 1852 | [[package]] 1853 | name = "wasm-bindgen-backend" 1854 | version = "0.2.90" 1855 | source = "registry+https://github.com/rust-lang/crates.io-index" 1856 | checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" 1857 | dependencies = [ 1858 | "bumpalo", 1859 | "log", 1860 | "once_cell", 1861 | "proc-macro2", 1862 | "quote", 1863 | "syn 2.0.48", 1864 | "wasm-bindgen-shared", 1865 | ] 1866 | 1867 | [[package]] 1868 | name = "wasm-bindgen-futures" 1869 | version = "0.4.40" 1870 | source = "registry+https://github.com/rust-lang/crates.io-index" 1871 | checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" 1872 | dependencies = [ 1873 | "cfg-if", 1874 | "js-sys", 1875 | "wasm-bindgen", 1876 | "web-sys", 1877 | ] 1878 | 1879 | [[package]] 1880 | name = "wasm-bindgen-macro" 1881 | version = "0.2.90" 1882 | source = "registry+https://github.com/rust-lang/crates.io-index" 1883 | checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" 1884 | dependencies = [ 1885 | "quote", 1886 | "wasm-bindgen-macro-support", 1887 | ] 1888 | 1889 | [[package]] 1890 | name = "wasm-bindgen-macro-support" 1891 | version = "0.2.90" 1892 | source = "registry+https://github.com/rust-lang/crates.io-index" 1893 | checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" 1894 | dependencies = [ 1895 | "proc-macro2", 1896 | "quote", 1897 | "syn 2.0.48", 1898 | "wasm-bindgen-backend", 1899 | "wasm-bindgen-shared", 1900 | ] 1901 | 1902 | [[package]] 1903 | name = "wasm-bindgen-shared" 1904 | version = "0.2.90" 1905 | source = "registry+https://github.com/rust-lang/crates.io-index" 1906 | checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" 1907 | 1908 | [[package]] 1909 | name = "wasm-streams" 1910 | version = "0.4.0" 1911 | source = "registry+https://github.com/rust-lang/crates.io-index" 1912 | checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" 1913 | dependencies = [ 1914 | "futures-util", 1915 | "js-sys", 1916 | "wasm-bindgen", 1917 | "wasm-bindgen-futures", 1918 | "web-sys", 1919 | ] 1920 | 1921 | [[package]] 1922 | name = "wayland-client" 1923 | version = "0.29.5" 1924 | source = "registry+https://github.com/rust-lang/crates.io-index" 1925 | checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" 1926 | dependencies = [ 1927 | "bitflags 1.3.2", 1928 | "downcast-rs", 1929 | "libc", 1930 | "nix 0.24.3", 1931 | "wayland-commons", 1932 | "wayland-scanner", 1933 | "wayland-sys", 1934 | ] 1935 | 1936 | [[package]] 1937 | name = "wayland-commons" 1938 | version = "0.29.5" 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" 1940 | checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" 1941 | dependencies = [ 1942 | "nix 0.24.3", 1943 | "once_cell", 1944 | "smallvec", 1945 | "wayland-sys", 1946 | ] 1947 | 1948 | [[package]] 1949 | name = "wayland-protocols" 1950 | version = "0.29.5" 1951 | source = "registry+https://github.com/rust-lang/crates.io-index" 1952 | checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" 1953 | dependencies = [ 1954 | "bitflags 1.3.2", 1955 | "wayland-client", 1956 | "wayland-commons", 1957 | "wayland-scanner", 1958 | ] 1959 | 1960 | [[package]] 1961 | name = "wayland-scanner" 1962 | version = "0.29.5" 1963 | source = "registry+https://github.com/rust-lang/crates.io-index" 1964 | checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" 1965 | dependencies = [ 1966 | "proc-macro2", 1967 | "quote", 1968 | "xml-rs", 1969 | ] 1970 | 1971 | [[package]] 1972 | name = "wayland-sys" 1973 | version = "0.29.5" 1974 | source = "registry+https://github.com/rust-lang/crates.io-index" 1975 | checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" 1976 | dependencies = [ 1977 | "pkg-config", 1978 | ] 1979 | 1980 | [[package]] 1981 | name = "web-sys" 1982 | version = "0.3.67" 1983 | source = "registry+https://github.com/rust-lang/crates.io-index" 1984 | checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" 1985 | dependencies = [ 1986 | "js-sys", 1987 | "wasm-bindgen", 1988 | ] 1989 | 1990 | [[package]] 1991 | name = "winapi" 1992 | version = "0.3.9" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1995 | dependencies = [ 1996 | "winapi-i686-pc-windows-gnu", 1997 | "winapi-x86_64-pc-windows-gnu", 1998 | ] 1999 | 2000 | [[package]] 2001 | name = "winapi-i686-pc-windows-gnu" 2002 | version = "0.4.0" 2003 | source = "registry+https://github.com/rust-lang/crates.io-index" 2004 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2005 | 2006 | [[package]] 2007 | name = "winapi-util" 2008 | version = "0.1.6" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" 2011 | dependencies = [ 2012 | "winapi", 2013 | ] 2014 | 2015 | [[package]] 2016 | name = "winapi-wsapoll" 2017 | version = "0.1.1" 2018 | source = "registry+https://github.com/rust-lang/crates.io-index" 2019 | checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" 2020 | dependencies = [ 2021 | "winapi", 2022 | ] 2023 | 2024 | [[package]] 2025 | name = "winapi-x86_64-pc-windows-gnu" 2026 | version = "0.4.0" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2029 | 2030 | [[package]] 2031 | name = "windows-sys" 2032 | version = "0.48.0" 2033 | source = "registry+https://github.com/rust-lang/crates.io-index" 2034 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 2035 | dependencies = [ 2036 | "windows-targets 0.48.5", 2037 | ] 2038 | 2039 | [[package]] 2040 | name = "windows-sys" 2041 | version = "0.52.0" 2042 | source = "registry+https://github.com/rust-lang/crates.io-index" 2043 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 2044 | dependencies = [ 2045 | "windows-targets 0.52.0", 2046 | ] 2047 | 2048 | [[package]] 2049 | name = "windows-targets" 2050 | version = "0.48.5" 2051 | source = "registry+https://github.com/rust-lang/crates.io-index" 2052 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 2053 | dependencies = [ 2054 | "windows_aarch64_gnullvm 0.48.5", 2055 | "windows_aarch64_msvc 0.48.5", 2056 | "windows_i686_gnu 0.48.5", 2057 | "windows_i686_msvc 0.48.5", 2058 | "windows_x86_64_gnu 0.48.5", 2059 | "windows_x86_64_gnullvm 0.48.5", 2060 | "windows_x86_64_msvc 0.48.5", 2061 | ] 2062 | 2063 | [[package]] 2064 | name = "windows-targets" 2065 | version = "0.52.0" 2066 | source = "registry+https://github.com/rust-lang/crates.io-index" 2067 | checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" 2068 | dependencies = [ 2069 | "windows_aarch64_gnullvm 0.52.0", 2070 | "windows_aarch64_msvc 0.52.0", 2071 | "windows_i686_gnu 0.52.0", 2072 | "windows_i686_msvc 0.52.0", 2073 | "windows_x86_64_gnu 0.52.0", 2074 | "windows_x86_64_gnullvm 0.52.0", 2075 | "windows_x86_64_msvc 0.52.0", 2076 | ] 2077 | 2078 | [[package]] 2079 | name = "windows_aarch64_gnullvm" 2080 | version = "0.48.5" 2081 | source = "registry+https://github.com/rust-lang/crates.io-index" 2082 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 2083 | 2084 | [[package]] 2085 | name = "windows_aarch64_gnullvm" 2086 | version = "0.52.0" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" 2089 | 2090 | [[package]] 2091 | name = "windows_aarch64_msvc" 2092 | version = "0.48.5" 2093 | source = "registry+https://github.com/rust-lang/crates.io-index" 2094 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 2095 | 2096 | [[package]] 2097 | name = "windows_aarch64_msvc" 2098 | version = "0.52.0" 2099 | source = "registry+https://github.com/rust-lang/crates.io-index" 2100 | checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" 2101 | 2102 | [[package]] 2103 | name = "windows_i686_gnu" 2104 | version = "0.48.5" 2105 | source = "registry+https://github.com/rust-lang/crates.io-index" 2106 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 2107 | 2108 | [[package]] 2109 | name = "windows_i686_gnu" 2110 | version = "0.52.0" 2111 | source = "registry+https://github.com/rust-lang/crates.io-index" 2112 | checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" 2113 | 2114 | [[package]] 2115 | name = "windows_i686_msvc" 2116 | version = "0.48.5" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 2119 | 2120 | [[package]] 2121 | name = "windows_i686_msvc" 2122 | version = "0.52.0" 2123 | source = "registry+https://github.com/rust-lang/crates.io-index" 2124 | checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" 2125 | 2126 | [[package]] 2127 | name = "windows_x86_64_gnu" 2128 | version = "0.48.5" 2129 | source = "registry+https://github.com/rust-lang/crates.io-index" 2130 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 2131 | 2132 | [[package]] 2133 | name = "windows_x86_64_gnu" 2134 | version = "0.52.0" 2135 | source = "registry+https://github.com/rust-lang/crates.io-index" 2136 | checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" 2137 | 2138 | [[package]] 2139 | name = "windows_x86_64_gnullvm" 2140 | version = "0.48.5" 2141 | source = "registry+https://github.com/rust-lang/crates.io-index" 2142 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 2143 | 2144 | [[package]] 2145 | name = "windows_x86_64_gnullvm" 2146 | version = "0.52.0" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" 2149 | 2150 | [[package]] 2151 | name = "windows_x86_64_msvc" 2152 | version = "0.48.5" 2153 | source = "registry+https://github.com/rust-lang/crates.io-index" 2154 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 2155 | 2156 | [[package]] 2157 | name = "windows_x86_64_msvc" 2158 | version = "0.52.0" 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" 2160 | checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" 2161 | 2162 | [[package]] 2163 | name = "winreg" 2164 | version = "0.50.0" 2165 | source = "registry+https://github.com/rust-lang/crates.io-index" 2166 | checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" 2167 | dependencies = [ 2168 | "cfg-if", 2169 | "windows-sys 0.48.0", 2170 | ] 2171 | 2172 | [[package]] 2173 | name = "wl-clipboard-rs" 2174 | version = "0.7.0" 2175 | source = "registry+https://github.com/rust-lang/crates.io-index" 2176 | checksum = "981a303dfbb75d659f6612d05a14b2e363c103d24f676a2d44a00d18507a1ad9" 2177 | dependencies = [ 2178 | "derive-new", 2179 | "libc", 2180 | "log", 2181 | "nix 0.24.3", 2182 | "os_pipe", 2183 | "tempfile", 2184 | "thiserror", 2185 | "tree_magic_mini", 2186 | "wayland-client", 2187 | "wayland-protocols", 2188 | ] 2189 | 2190 | [[package]] 2191 | name = "x11-clipboard" 2192 | version = "0.7.1" 2193 | source = "registry+https://github.com/rust-lang/crates.io-index" 2194 | checksum = "980b9aa9226c3b7de8e2adb11bf20124327c054e0e5812d2aac0b5b5a87e7464" 2195 | dependencies = [ 2196 | "x11rb", 2197 | ] 2198 | 2199 | [[package]] 2200 | name = "x11rb" 2201 | version = "0.10.1" 2202 | source = "registry+https://github.com/rust-lang/crates.io-index" 2203 | checksum = "592b4883219f345e712b3209c62654ebda0bb50887f330cbd018d0f654bfd507" 2204 | dependencies = [ 2205 | "gethostname", 2206 | "nix 0.24.3", 2207 | "winapi", 2208 | "winapi-wsapoll", 2209 | "x11rb-protocol", 2210 | ] 2211 | 2212 | [[package]] 2213 | name = "x11rb-protocol" 2214 | version = "0.10.0" 2215 | source = "registry+https://github.com/rust-lang/crates.io-index" 2216 | checksum = "56b245751c0ac9db0e006dc812031482784e434630205a93c73cfefcaabeac67" 2217 | dependencies = [ 2218 | "nix 0.24.3", 2219 | ] 2220 | 2221 | [[package]] 2222 | name = "xml-rs" 2223 | version = "0.8.19" 2224 | source = "registry+https://github.com/rust-lang/crates.io-index" 2225 | checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" 2226 | 2227 | [[package]] 2228 | name = "zeroize" 2229 | version = "1.7.0" 2230 | source = "registry+https://github.com/rust-lang/crates.io-index" 2231 | checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" 2232 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "didyoumean" 3 | authors = ["Hisbaan Noorani"] 4 | version = "1.1.4" 5 | edition = "2021" 6 | license = "GPL-3.0" 7 | description = "A CLI spelling corrector" 8 | documentation = "https://github.com/hisbaan/didyoumean" 9 | homepage = "https://github.com/hisbaan/didyoumean" 10 | repository = "https://github.com/hisbaan/didyoumean" 11 | readme = "docs/README.md" 12 | keywords = ["levenshtein", "damerau", "edit-distance", "spelling"] 13 | categories = ["command-line-utilities"] 14 | 15 | [[bin]] 16 | name = "dym" 17 | path = "src/main.rs" 18 | 19 | [dependencies] 20 | clap = { version = "4.4.18", features = ["derive"] } 21 | colored = "2.1.0" 22 | cli-clipboard = "0.4.0" 23 | dialoguer = "0.11.0" 24 | indicatif = "0.17.7" 25 | atty = "0.2.14" 26 | dirs = "5.0.1" 27 | reqwest = { version = "0.11.24", features = ["stream"] } 28 | tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } 29 | futures-util = "0.3.30" 30 | phf = { version = "0.11.2", features = ["macros"] } 31 | nix = { version = "0.27.1", features = ["process"] } 32 | 33 | [build-dependencies] 34 | clap_complete = "4.4.10" 35 | clap_mangen = "0.2.19" 36 | clap = { version = "4.4.18", features = ["derive"] } 37 | 38 | [target.'cfg(unix)'.dependencies] 39 | nix = "0.27.1" 40 | 41 | [dev-dependencies] 42 | criterion = "0.5.1" 43 | 44 | [[bench]] 45 | name = "edit_distance" 46 | harness = false 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /benches/edit_distance.rs: -------------------------------------------------------------------------------- 1 | use criterion::{criterion_group, criterion_main, Criterion}; 2 | use didyoumean::edit_distance; 3 | 4 | pub fn edit_distance_bench(c: &mut Criterion) { 5 | let arr = vec!["abarthrosis", "abarticular", "abarticulation"]; 6 | let search_chars = "abartclat".chars().collect::>(); 7 | c.bench_function("edit_distance", |b| { 8 | b.iter(|| { 9 | for known_term in arr.iter() { 10 | edit_distance(&search_chars, known_term); 11 | } 12 | }) 13 | }); 14 | } 15 | 16 | criterion_group!(benches, edit_distance_bench); 17 | criterion_main!(benches); 18 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use clap::CommandFactory; 2 | use clap_complete::{ 3 | generate_to, 4 | Shell::{Bash, Elvish, Fish, PowerShell, Zsh}, 5 | }; 6 | 7 | // Include the Cli struct. 8 | include!("src/cli.rs"); 9 | 10 | fn main() { 11 | // Get directories. 12 | let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); 13 | let man_dir = root_dir.join("man"); 14 | let comp_dir = root_dir.join("completions"); 15 | 16 | // Create directories if they don't exist. 17 | std::fs::create_dir_all(&man_dir).unwrap(); 18 | std::fs::create_dir_all(&comp_dir).unwrap(); 19 | 20 | // Setup clap command. 21 | let mut cmd = Cli::command(); 22 | cmd.set_bin_name("dym"); 23 | 24 | // Generate man page. 25 | let man = clap_mangen::Man::new(cmd.to_owned()); 26 | let mut buffer: Vec = Default::default(); 27 | man.render(&mut buffer).expect("Man page generation failed"); 28 | std::fs::write(man_dir.join("dym.1"), buffer).expect("Failed to write man page"); 29 | 30 | // Generate shell completions. 31 | for shell in [Bash, Elvish, Fish, PowerShell, Zsh] { 32 | generate_to(shell, &mut cmd, "dym", &comp_dir).unwrap(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |

DidYouMean

2 | 3 |

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 | 13 | DidYouMean (or `dym`) is a command-line spelling corrector written in rust utilizing a simplified version of [Damerau-Levenshtein distance](https://en.wikipedia.org/wiki/Damerau-Levenshtein_distance). DidYouMean is for those moments when you know what a word sounds like, but you're not quite sure how it's spelled. 14 | 15 |

16 | 17 |

18 | 19 | ## Installation 20 | 21 | ### Arch Linux (and derivatives) 22 | 23 | DidYouMean is available on the AUR as three different packages: 24 | 25 | - [didyoumean](https://aur.archlinux.org/packages/didyoumean): Last stable release, built from source (Thank you [orhun](https://github.com/orhun)!). 26 | - [didyoumean-git](https://aur.archlinux.org/packages/didyoumean-git): Last git commit, built from source. This is the most up to date, but the least stable. 27 | - [didyoumean-bin](https://aur.archlinux.org/packages/didyoumean-bin): Last stable release, distributed as a binary. This is only available for `x86_64` at the moment. 28 | 29 | You can install it using any AUR helper. Using `paru`, the command would be as follows: 30 | 31 | ```sh 32 | paru -S 33 | ``` 34 | 35 | ### Homebrew (macOS) 36 | 37 | Homebrew is a package manager for macOS. Currently, I have only packaged an x86\_64 binary. The command to install it is as follows: 38 | 39 | ```sh 40 | brew tap hisbaan/tap 41 | brew install didyoumean 42 | ``` 43 | 44 | ### NixOS 45 | 46 | [evanjs](https://github.com/evanjs) very kindly packaged `didyoumean` for NixOS. The command to install is as follows: 47 | 48 | ```sh 49 | nix-env install -iA nixpkgs.didyoumean 50 | ``` 51 | 52 | ### Cargo 53 | 54 | Run the following command to build `dym` from source and install it in your home directory. Ensure that you have `$CARGO_HOME/bin/` in your path. 55 | 56 | ```sh 57 | cargo install didyoumean 58 | ``` 59 | 60 | ## Developer Installation 61 | 62 | The build dependencies for this project are `git`, `rust`, `rustc`, and `cargo`. First, clone this repository, then run 63 | 64 | ```sh 65 | cargo run -- 66 | ``` 67 | 68 | where `` are the command-line arguments you would pass the DidYouMean binary. Note that this is an unoptimized build contianing debug information so it runs much, much slower. 69 | -------------------------------------------------------------------------------- /docs/img/cyclophosphamide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hisbaan/didyoumean/b599cb21adb5738f18708fd3590f0df86ec59a9b/docs/img/cyclophosphamide.png -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use clap::Parser; 2 | 3 | // Parse command line arguments to get the search term. 4 | #[derive(Parser)] 5 | #[clap(author = "Hisbaan Noorani", version = "1.1.4", about = "Did You Mean: A cli spelling corrector", long_about = None)] 6 | pub struct Cli { 7 | pub search_term: Option, 8 | #[clap( 9 | short = 'n', 10 | long = "number", 11 | default_value_t = 5, 12 | help = "Change the number of matches printed", 13 | long_help = "Change the number of words the program will print. The default value is five." 14 | )] 15 | pub number: usize, 16 | #[clap( 17 | short = 'c', 18 | long = "clean-output", 19 | help = "Print clean output", 20 | long_help = "Print a clean version of the output without the title, numbers or colour." 21 | )] 22 | pub clean_output: bool, 23 | #[clap( 24 | short = 'v', 25 | long = "verbose", 26 | help = "Print verbose output", 27 | long_help = "Print verbose output including the edit distance of the found word to the queried word." 28 | )] 29 | pub verbose: bool, 30 | #[clap( 31 | short = 'y', 32 | long = "yank", 33 | help = "Yank (copy) to the system cliboard", 34 | long_help = "Yank (copy) the selected word to the system clipboard. If no word is selected, the clipboard will not be altered." 35 | )] 36 | pub yank: bool, 37 | #[clap( 38 | short = 'l', 39 | long = "lang", 40 | help = "Select the desired language using the locale code (en, fr, sp, etc.)", 41 | long_help = "Select the desired language using its locale code. For example, English would have the locale code en and French would have the locale code fr. See --print-langs for a list of locale codes and the corresponding languages.", 42 | default_value = "en" 43 | )] 44 | pub lang: String, 45 | #[clap( 46 | long = "print-langs", 47 | help = "Display a list of supported languages", 48 | long_help = "Display a list of supported languages and their respective locale codes." 49 | )] 50 | pub print_langs: bool, 51 | #[clap( 52 | long = "update-langs", 53 | help = "Update all language files", 54 | long_help = "Update all language files from the repository https://github.com/hisbaan/wordlists." 55 | )] 56 | pub update_langs: bool, 57 | } 58 | -------------------------------------------------------------------------------- /src/langs.rs: -------------------------------------------------------------------------------- 1 | use phf::phf_map; 2 | 3 | pub static LOCALES: phf::Map<&'static str, &'static str> = phf_map! { 4 | "af" => "Afrikaans", 5 | "ar" => "Arabic", 6 | "az" => "Azerbaijani", 7 | "be" => "Belarusian", 8 | "bg" => "Bulgarian", 9 | "br" => "Breton", 10 | "bs" => "Bosnian", 11 | "ca" => "Catalan", 12 | "cs" => "Czech", 13 | "cy" => "Welsh", 14 | "da" => "Danish", 15 | "de" => "German", 16 | "el" => "Greek", 17 | "en" => "English", 18 | "es" => "Spanish", 19 | "et" => "Estonian", 20 | "eu" => "Basque", 21 | "fa" => "Farsi", 22 | "fi" => "Finnish", 23 | "fo" => "Faeroese", 24 | "fr" => "French", 25 | "fy" => "Frisian", 26 | "ga" => "Irish", 27 | "gd" => "Gaelic", 28 | "gl" => "Galician", 29 | "he" => "Hebrew", 30 | "hi" => "Hindi", 31 | "hr" => "Croatian", 32 | "hu" => "Hungarian", 33 | "id" => "Indonesian", 34 | "is" => "Icelandic", 35 | "it" => "Italian", 36 | "ja" => "Japanese", 37 | "ji" => "Yiddish", 38 | "kk" => "Kazach", 39 | "ko" => "Korean", 40 | "la" => "Latin", 41 | "lb" => "Luxembourgish", 42 | "lt" => "Lithuanian", 43 | "lv" => "Latvian", 44 | "mk" => "Macedonian", 45 | "ml" => "Malalyalam", 46 | "ms" => "Malaysian", 47 | "mt" => "Maltese", 48 | "nb" => "Norwegian Bokmal", 49 | "nl" => "Dutch", 50 | "nn" => "Norwegian Nynorsk", 51 | "oc" => "Occitan", 52 | "pa" => "Punjabi", 53 | "pl" => "Polish", 54 | "pt" => "Portugese", 55 | "rm" => "Rhaeto-Romanic", 56 | "ro" => "Romanian", 57 | "ru" => "Russian", 58 | "sb" => "Sorbian", 59 | "se" => "Northern Sami", 60 | "sk" => "Slovak", 61 | "sl" => "Slovenian", 62 | "sq" => "Albanian", 63 | "sr" => "Serbian", 64 | "st" => "Sesotho", 65 | "sv" => "Swedish", 66 | "sw" => "Swahili", 67 | "tg" => "Tajik", 68 | "th" => "Thai", 69 | "tk" => "Turkmen", 70 | "tl" => "Tagalog", 71 | "tn" => "Tswana", 72 | "tr" => "Turkish", 73 | "ts" => "Tsonga", 74 | "uk" => "Ukranian", 75 | "ur" => "Urdu", 76 | "ve" => "Venda", 77 | "vi" => "Vietnamese", 78 | "xh" => "Xhosa", 79 | "yi" => "Yiddish", 80 | "zh" => "Chinese", 81 | "zu" => "Zulu", 82 | }; 83 | 84 | pub static SUPPORTED_LANGS: phf::Map<&'static str, &'static str> = phf_map! { 85 | "af" => "Afrikaans", 86 | "ar" => "Arabic", 87 | "az" => "Azerbaijani", 88 | "be" => "Belarusian", 89 | "bg" => "Bulgarian", 90 | "br" => "Breton", 91 | "bs" => "Bosnian", 92 | "ca" => "Catalan", 93 | "cs" => "Czech", 94 | "cy" => "Welsh", 95 | "da" => "Danish", 96 | "de" => "German", 97 | "el" => "Greek", 98 | "en" => "English", 99 | "es" => "Spanish", 100 | "et" => "Estonian", 101 | "eu" => "Basque", 102 | "fo" => "Faeroese", 103 | "fr" => "French", 104 | "fy" => "Frisian", 105 | "gl" => "Galician", 106 | "hu" => "Hungarian", 107 | "id" => "Indonesian", 108 | "is" => "Icelandic", 109 | "it" => "Italian", 110 | "kk" => "Kazach", 111 | "ko" => "Korean", 112 | "la" => "Latin", 113 | "lb" => "Luxembourgish", 114 | "lt" => "Lithuanian", 115 | "lv" => "Latvian", 116 | "ms" => "Malaysian", 117 | "nb" => "Norwegian Bokmal", 118 | "nl" => "Dutch", 119 | "nn" => "Norwegian Nynorsk", 120 | "oc" => "Occitan", 121 | "pl" => "Polish", 122 | "ro" => "Romanian", 123 | "ru" => "Russian", 124 | "se" => "Northern Sami", 125 | "sk" => "Slovak", 126 | "sl" => "Slovenian", 127 | "sq" => "Albanian", 128 | "sr" => "Serbian", 129 | "st" => "Sesotho", 130 | "sv" => "Swedish", 131 | "sw" => "Swahili", 132 | "tg" => "Tajik", 133 | "tk" => "Turkmen", 134 | "tl" => "Tagalog", 135 | "tn" => "Tswana", 136 | "tr" => "Turkish", 137 | "ts" => "Tsonga", 138 | "tt" => "Tatar", 139 | "uk" => "Ukranian", 140 | "ve" => "Venda", 141 | "vi" => "Vietnamese", 142 | "xh" => "Xhosa", 143 | "yi" => "Yiddish", 144 | "zu" => "Zulu", 145 | }; 146 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | use cli_clipboard::{ClipboardContext, ClipboardProvider}; 2 | use colored::*; 3 | use std::cmp::min; 4 | 5 | #[cfg(unix)] 6 | use nix::unistd::{fork, ForkResult}; 7 | 8 | /// Copy `string` to the system clipboard 9 | /// 10 | /// # Arguments 11 | /// 12 | /// * `string` - the string to be copied. 13 | pub fn yank(string: &str) { 14 | let platform = std::env::consts::OS; 15 | if vec![ 16 | "linux", 17 | "freebsd", 18 | "netbsd", 19 | "dragonfly", 20 | "netbsd", 21 | "openbsd", 22 | "solaris", 23 | ] 24 | .contains(&platform) 25 | { 26 | // The platform is linux/*bsd and is likely using X11 or Wayland. 27 | // There is a fix needed for clipboard use in cases like these. 28 | // The clipboard is cleared on X11/Wayland after the process that set it exist. 29 | // To combat this, we will fork and keep a process around until the clipboard 30 | // is cleared. 31 | // Ideally, this wouldn't be an issue but it was a conscious design decision 32 | // on X11/Wayland 33 | #[cfg(unix)] 34 | match unsafe { fork() } { 35 | Ok(ForkResult::Child) => { 36 | let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap(); 37 | ctx.set_contents(string.to_owned()).unwrap(); 38 | 39 | // Keep the process running until the clipboard changes. 40 | loop { 41 | let clipboard = ctx.get_contents().unwrap(); 42 | std::thread::sleep(std::time::Duration::from_secs(1)); 43 | if clipboard != string { 44 | std::process::exit(0); 45 | } 46 | } 47 | } 48 | Err(_) => { 49 | println!("{}", "Error: Clipboard fork failed".red()); 50 | std::process::exit(1); 51 | } 52 | _ => {} 53 | } 54 | } else { 55 | // The platform is NOT running X11/Wayland and thus, we don't have to handle 56 | // the clipboard clearing behaviour. 57 | let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap(); 58 | ctx.set_contents(string.to_owned()).unwrap(); 59 | } 60 | } 61 | 62 | /// Insert `element` at `index` preserving length. 63 | /// 64 | /// # Arguments 65 | /// 66 | /// * `list` - A vec to be shifted down 67 | /// * `index` - The index at which to insert `element` 68 | /// * `element` - The element to insert at `index` 69 | /// 70 | /// # Examples 71 | /// 72 | /// ``` 73 | /// # use didyoumean::insert_and_shift; 74 | /// let mut to_shift = vec![0, 1, 2, 3, 4]; 75 | /// insert_and_shift(&mut to_shift, 2, 11); 76 | /// 77 | /// assert_eq!(to_shift, vec![0, 1, 11, 2, 3]); 78 | /// ``` 79 | pub fn insert_and_shift(list: &mut Vec, index: usize, element: T) { 80 | if index > list.len() - 1 { 81 | return; 82 | } 83 | 84 | list.insert(index, element); 85 | list.truncate(list.len() - 1); 86 | } 87 | 88 | /// Return the edit distance between `search_term` and `known_term`. 89 | /// Currently implemented using a modified version of 90 | /// [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance). 91 | /// 92 | /// # Arguments 93 | /// 94 | /// * `search_chars` - The first `Vec` to compare, in most time search_term will not change, so 95 | /// we would like to share the same `Vec` between multiple calls. you could use `search_string.chars().collect::>()` to 96 | /// convert a string to a `Vec` 97 | /// * `known_term` - The second string to compare 98 | /// 99 | /// # Examples 100 | /// 101 | /// ``` 102 | /// # use didyoumean::edit_distance; 103 | /// let dist = edit_distance(&"sitting".chars().collect::>(), "kitten"); 104 | /// assert_eq!(dist, 3); 105 | /// assert_eq!(edit_distance(&"geek".chars().collect::>(), "gesek"), 1); 106 | /// assert_eq!(edit_distance(&"cat".chars().collect::>(), "cut"), 1); 107 | /// assert_eq!(edit_distance(&"sunday".chars().collect::>(), "saturday"), 3); 108 | /// assert_eq!(edit_distance(&"tset".chars().collect::>(), "test"), 1); 109 | /// ``` 110 | #[allow(clippy::iter_count, clippy::needless_range_loop)] 111 | pub fn edit_distance(search_chars: &[char], known_term: &str) -> usize { 112 | // Set local constants for repeated use later. 113 | let known_chars: Vec = known_term.chars().collect(); 114 | let n = search_chars.iter().count() + 1; 115 | let m = known_chars.iter().count() + 1; 116 | 117 | // Setup matrix 2D vector. 118 | let mut mat = vec![0; m * n]; 119 | 120 | // Initialize values of the matrix. 121 | for i in 1..n { 122 | mat[i * m] = i; 123 | } 124 | for i in 1..m { 125 | mat[i] = i; 126 | } 127 | 128 | // Run the algorithm. 129 | for i in 1..n { 130 | // let search_char_i_minus_one = search_chars[i - 1]; 131 | // let search_char_i_minus_two = if i > 1 { search_chars[i - 2] } else { ' ' }; 132 | for j in 1..m { 133 | let sub_cost = if search_chars[i - 1] == known_chars[j - 1] { 134 | 0 135 | } else { 136 | 1 137 | }; 138 | 139 | mat[i * m + j] = min( 140 | mat[(i - 1) * m + j - 1] + sub_cost, // substitution cost 141 | min( 142 | mat[(i - 1) * m + j] + 1, // deletion cost 143 | mat[i * m + j - 1] + 1, // insertion cost 144 | ), 145 | ); 146 | if i > 1 147 | && j > 1 148 | && search_chars[i - 1] == known_chars[j - 2] 149 | && search_chars[i - 2] == known_chars[j - 1] 150 | { 151 | mat[i * m + j] = min( 152 | mat[i * m + j], 153 | mat[(i - 2) * m + j - 2] + 1, // transposition cost 154 | ); 155 | } 156 | } 157 | } 158 | 159 | // Return the bottom left corner of the matrix. 160 | mat[m * n - 1] 161 | } 162 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | pub mod cli; 2 | pub mod langs; 3 | 4 | use clap::Parser; 5 | use clap::error::ErrorKind; 6 | use colored::*; 7 | use dialoguer::{theme::ColorfulTheme, Select}; 8 | use dirs::data_dir; 9 | use futures_util::StreamExt; 10 | use indicatif::{ProgressBar, ProgressStyle}; 11 | use reqwest::get; 12 | use std::{ 13 | cmp::min, 14 | fs::{create_dir, read_dir, read_to_string, remove_file, File}, 15 | io::{self, BufRead, Error, Write}, 16 | }; 17 | 18 | use cli::Cli; 19 | use didyoumean::{edit_distance, insert_and_shift, yank}; 20 | use langs::{LOCALES, SUPPORTED_LANGS}; 21 | 22 | fn main() { 23 | std::process::exit(match run_app() { 24 | Ok(_) => 0, 25 | Err(error) => { 26 | eprintln!("Error: {:?}", error); 27 | 1 28 | } 29 | }); 30 | } 31 | 32 | /// Main function to run the application. Return `std::result::Result<(), std::io::Error>`. 33 | fn run_app() -> std::result::Result<(), Error> { 34 | // Correctly output ANSI escape codes on Windows. 35 | #[cfg(windows)] 36 | colored::control::set_virtual_terminal(true).ok(); 37 | 38 | // Parse args using clap. 39 | let args = Cli::parse(); 40 | 41 | // Print all supported languages. 42 | if args.print_langs { 43 | println!("Supported Languages:"); 44 | let mut langs: Vec = vec![]; 45 | 46 | // Add words to vector. 47 | for key in SUPPORTED_LANGS.keys() { 48 | langs.push(format!(" - {}: {}", key, SUPPORTED_LANGS.get(key).unwrap())); 49 | } 50 | 51 | // Sort and print vector. 52 | langs.sort(); 53 | for lang in langs { 54 | println!("{}", lang); 55 | } 56 | 57 | std::process::exit(0); 58 | } 59 | 60 | // Update all downloaded languages. 61 | if args.update_langs { 62 | update_langs(); 63 | std::process::exit(0); 64 | } 65 | 66 | let mut search_term = String::new(); 67 | 68 | // Check if nothing was passed in as the search term. 69 | if args.search_term == None { 70 | // Check if stdin is empty, produce error if so. 71 | if atty::is(atty::Stream::Stdin) { 72 | let mut cmd = clap::Command::new("dym [OPTIONS] "); 73 | let error = cmd.error( 74 | ErrorKind::MissingRequiredArgument, 75 | format!( 76 | "The {} argument was not provided.\n\n\tEither provide it as an argument or pass it in from standard input.", 77 | "".green() 78 | ) 79 | ); 80 | clap::Error::exit(&error); 81 | } else { 82 | // Read search_term from standard input if stdin is not empty. 83 | let stdin = io::stdin(); 84 | stdin.lock().read_line(&mut search_term).unwrap(); 85 | } 86 | } else { 87 | // Unwrap Option that was read from the client. 88 | search_term = args.search_term.unwrap(); 89 | } 90 | 91 | if SUPPORTED_LANGS.contains_key(args.lang.as_str()) { 92 | fetch_word_list(args.lang.to_owned()); 93 | } else { 94 | // Not supported 95 | // Initialize new command. 96 | let mut cmd = clap::Command::new("dym [OPTIONS] "); 97 | 98 | // Whether or not locale code is valid. 99 | let error_string = if LOCALES.contains_key(args.lang.as_str()) { 100 | format!( 101 | "There is currently no word list for {}", 102 | LOCALES.get(args.lang.as_str()).cloned().unwrap() 103 | ) 104 | } else { 105 | format!("{} is not a recognized localed code", args.lang) 106 | }; 107 | 108 | // Set error. 109 | let error = cmd.error(ErrorKind::MissingRequiredArgument, error_string); 110 | 111 | // Exit with error. 112 | clap::Error::exit(&error); 113 | } 114 | 115 | // Get word list. The program will only get here if/when this is a valid word list. 116 | let word_list = read_to_string(dirs::data_dir().unwrap().join("didyoumean").join(args.lang)) 117 | .expect("Error reading file"); 118 | 119 | // Get dictionary of words from words.txt. 120 | let dictionary = word_list.split('\n'); 121 | 122 | // Create mutable vecs for storing the top n words. 123 | let mut top_n_words = vec![""; args.number]; 124 | let mut top_n_dists = vec![search_term.len() * 10; args.number]; 125 | 126 | // Loop over the words in the dictionary, run the algorithm, and 127 | // add to the list if appropriate 128 | let search_chars = search_term.chars().collect::>(); 129 | for word in dictionary { 130 | // Get edit distance. 131 | let dist = edit_distance(&search_chars, word); 132 | 133 | // Add to the list if appropriate. 134 | if dist < top_n_dists[args.number - 1] { 135 | for i in 0..args.number { 136 | if dist < top_n_dists[i] { 137 | insert_and_shift(&mut top_n_dists, i, dist); 138 | insert_and_shift(&mut top_n_words, i, word); 139 | break; 140 | } 141 | } 142 | } 143 | } 144 | 145 | // Print out results. 146 | if !args.clean_output { 147 | if top_n_dists[0] == 0 { 148 | println!("{} is spelled correctly\n", search_term.bold().green()); 149 | } 150 | println!("{}", "Did you mean?".blue().bold()); 151 | } 152 | let mut items = vec!["".to_string(); args.number]; 153 | for i in 0..args.number { 154 | let mut output: String = "".to_string(); 155 | let indent = args.number.to_string().len(); 156 | 157 | // Add numbers if not clean. 158 | if !args.clean_output { 159 | output.push_str(&format!( 160 | "{:>indent$}{} ", 161 | (i + 1).to_string().purple(), 162 | ".".purple() 163 | )); 164 | } 165 | 166 | // Add words in order of edit distance. 167 | output.push_str(top_n_words[i]); 168 | 169 | // Add edit distance if verbose. 170 | if args.verbose { 171 | output.push_str(&format!(" (edit distance: {})", top_n_dists[i])); 172 | } 173 | 174 | // Print concatenated string. 175 | items[i] = output; 176 | } 177 | 178 | // If the yank argument is set, copy the item to the clipboard. 179 | if args.yank { 180 | // Print prompt 181 | println!( 182 | "{} {}", 183 | "?".yellow(), 184 | "[↑↓ to move, ↵ to select, esc/q to cancel]".bold() 185 | ); 186 | // Get the chosen argument. 187 | let chosen = Select::with_theme(&ColorfulTheme::default()) 188 | .items(&items) 189 | .default(0) 190 | .interact_opt() 191 | .unwrap(); 192 | 193 | // Print out items since dialoguer clears. 194 | for item in items { 195 | println!(" {}", item); 196 | } 197 | 198 | match chosen { 199 | // If the chosen arguemnt is valid. 200 | Some(index) => { 201 | yank(top_n_words[index]); 202 | println!( 203 | "{}", 204 | format!("\"{}\" copied to clipboard", top_n_words[index]).green() 205 | ); 206 | } 207 | // If no argument is chosen. 208 | None => { 209 | println!("{}", "No selection made".red()); 210 | std::process::exit(1); 211 | } 212 | } 213 | } else { 214 | // If yank is not set, print out all the items. 215 | for item in items { 216 | println!("{}", item); 217 | } 218 | } 219 | 220 | Ok(()) 221 | } 222 | 223 | /// Fetch the word list specified by `lang` from https://github.com/hisbaan/wordlists 224 | /// 225 | /// # Arguments 226 | /// 227 | /// * `lang` - A locale code string to define the word list file to fetch. 228 | #[tokio::main] 229 | async fn fetch_word_list(lang: String) { 230 | // Get data directory. 231 | let data_dir = dirs::data_dir().unwrap().join("didyoumean"); 232 | 233 | // Create data directory if it doesn't exist. 234 | if !data_dir.is_dir() { 235 | create_dir(data_dir).expect("Failed to create data directory"); 236 | } 237 | 238 | // Get file path. 239 | let file_path = dirs::data_dir().unwrap().join("didyoumean").join(&lang); 240 | 241 | // If the file does not exist, fetch it from the server. 242 | if !file_path.is_file() { 243 | println!( 244 | "Downloading {} word list...", 245 | LOCALES.get(&lang).unwrap().to_string().blue() 246 | ); 247 | 248 | let url = format!( 249 | "https://raw.githubusercontent.com/hisbaan/wordlists/main/{}", 250 | &lang 251 | ); 252 | 253 | // Setup reqwest. 254 | let response = get(&url).await.expect("Request failed"); 255 | let total_size = response.content_length().unwrap(); 256 | let mut file = File::create(file_path).expect("Failed to create file"); 257 | let mut downloaded: u64 = 0; 258 | let mut stream = response.bytes_stream(); 259 | 260 | // Setup indicatif. 261 | let pb = ProgressBar::new(total_size); 262 | pb.set_style( 263 | ProgressStyle::default_bar() 264 | .template( 265 | "[{elapsed_precise}] [{wide_bar:.blue/cyan}] {bytes}/{total_bytes} ({eta})", 266 | ) 267 | .unwrap() 268 | .progress_chars("#>-"), 269 | ); 270 | 271 | // Read from stream into file. 272 | while let Some(item) = stream.next().await { 273 | let chunk = item.expect("Error downloading file"); 274 | file.write_all(&chunk).expect("Error while writing to file"); 275 | let new = min(downloaded + (chunk.len() as u64), total_size); 276 | downloaded = new; 277 | pb.set_position(new); 278 | } 279 | 280 | // Print completed bar. 281 | pb.finish(); 282 | } 283 | } 284 | 285 | /// Update the word list files by deleting and downloading the files from the repository. 286 | fn update_langs() { 287 | let data = data_dir().unwrap().join("didyoumean"); 288 | 289 | // Create data directory if it doesn't exist. 290 | if !data.is_dir() { 291 | create_dir(&data).expect("Failed to create data directory"); 292 | } 293 | 294 | // Get files in data directory. 295 | let data_dir_files = read_dir(&data).unwrap(); 296 | 297 | // Delete and update all files. 298 | for file in data_dir_files { 299 | let file_name = file.unwrap().file_name(); 300 | let string: &str = file_name.to_str().unwrap(); 301 | 302 | // Only delete and download if the language is supported. 303 | if SUPPORTED_LANGS.contains_key(string) { 304 | remove_file(data.join(&string)).expect("Failed to update file (deletion failed)"); 305 | fetch_word_list(string.to_string()); 306 | } 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /tests/integration_test.rs: -------------------------------------------------------------------------------- 1 | use cli_clipboard::{ClipboardContext, ClipboardProvider}; 2 | use didyoumean::yank; 3 | 4 | #[test] 5 | fn yank_test() { 6 | let string = "test"; 7 | let not_string = "not test"; 8 | let mut ctx: ClipboardContext = ClipboardProvider::new().unwrap(); 9 | 10 | // Run the yank function. 11 | yank(string); 12 | 13 | // Sleep to allow the function time to write to the clipboard. 14 | std::thread::sleep(std::time::Duration::from_secs(1)); 15 | 16 | // Get the clipboard contents. 17 | let clipboard = format!("{}", ctx.get_contents().unwrap()); 18 | 19 | assert_eq!(clipboard, string); 20 | 21 | // Set the clipboard contents to something else to get the process to exit. 22 | ctx.set_contents(not_string.to_owned()).unwrap(); 23 | } 24 | --------------------------------------------------------------------------------