A file-based task manager

Compare changes

Choose any two refs to compare.

+400 -273
+8
.tsk/archive/tsk-31.tsk
···
··· 1 + DO THE THING 2 + 3 + 4 + remember to do part1 5 + 6 + and part2 7 + 8 + and part3
+3 -3
.tsk/index
··· 1 - tsk-30 Add flag to only print IDs in list command 1735007126 2 tsk-28 Add tool to clean up old tasks not in index 1735006519 3 tsk-10 foreign workspaces 1732594198 4 tsk-21 Add command to setup git stuff 1732594198 5 - tsk-8 IMAP4-based sync 1732594198 6 tsk-17 Add reopen command 1732594198 7 - tsk-16 Add ability to search archived tasks with find command 1732594198 8 tsk-15 Add link identification to tasks 1732594198 9 tsk-9 fix timestamp storage and parsing 1732594198 10 tsk-7 allow for creating tasks that don't go to top of stack 1732594198
··· 1 + tsk-30 Add flag to only print IDs in list command 1763257109 2 tsk-28 Add tool to clean up old tasks not in index 1735006519 3 tsk-10 foreign workspaces 1732594198 4 tsk-21 Add command to setup git stuff 1732594198 5 + tsk-8 IMAP4-based sync 1767469318 6 tsk-17 Add reopen command 1732594198 7 + tsk-16 Add ability to search archived tasks with find command 1767466011 8 tsk-15 Add link identification to tasks 1732594198 9 tsk-9 fix timestamp storage and parsing 1732594198 10 tsk-7 allow for creating tasks that don't go to top of stack 1732594198
+1 -1
.tsk/next
··· 1 - 31
··· 1 + 32
+228 -168
Cargo.lock
··· 4 5 [[package]] 6 name = "anstream" 7 - version = "0.6.18" 8 source = "registry+https://github.com/rust-lang/crates.io-index" 9 - checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 10 dependencies = [ 11 "anstyle", 12 "anstyle-parse", ··· 19 20 [[package]] 21 name = "anstyle" 22 - version = "1.0.10" 23 source = "registry+https://github.com/rust-lang/crates.io-index" 24 - checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 25 26 [[package]] 27 name = "anstyle-parse" 28 - version = "0.2.6" 29 source = "registry+https://github.com/rust-lang/crates.io-index" 30 - checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 31 dependencies = [ 32 "utf8parse", 33 ] 34 35 [[package]] 36 name = "anstyle-query" 37 - version = "1.1.2" 38 source = "registry+https://github.com/rust-lang/crates.io-index" 39 - checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 40 dependencies = [ 41 - "windows-sys", 42 ] 43 44 [[package]] 45 name = "anstyle-wincon" 46 - version = "3.0.7" 47 source = "registry+https://github.com/rust-lang/crates.io-index" 48 - checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 49 dependencies = [ 50 "anstyle", 51 - "once_cell", 52 - "windows-sys", 53 ] 54 55 [[package]] 56 name = "bitflags" 57 - version = "2.9.0" 58 source = "registry+https://github.com/rust-lang/crates.io-index" 59 - checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 60 61 [[package]] 62 name = "cfg-if" 63 - version = "1.0.0" 64 source = "registry+https://github.com/rust-lang/crates.io-index" 65 - checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 66 67 [[package]] 68 name = "cfg_aliases" ··· 72 73 [[package]] 74 name = "clap" 75 - version = "4.5.37" 76 source = "registry+https://github.com/rust-lang/crates.io-index" 77 - checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" 78 dependencies = [ 79 "clap_builder", 80 "clap_derive", ··· 82 83 [[package]] 84 name = "clap_builder" 85 - version = "4.5.37" 86 source = "registry+https://github.com/rust-lang/crates.io-index" 87 - checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" 88 dependencies = [ 89 "anstream", 90 "anstyle", ··· 94 95 [[package]] 96 name = "clap_complete" 97 - version = "4.5.49" 98 source = "registry+https://github.com/rust-lang/crates.io-index" 99 - checksum = "07ae023020f3bbb76bfd6c7b9dd3f903b40f60e4dc60696c303457c5c01e6cbe" 100 dependencies = [ 101 "clap", 102 ] 103 104 [[package]] 105 name = "clap_derive" 106 - version = "4.5.32" 107 source = "registry+https://github.com/rust-lang/crates.io-index" 108 - checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 109 dependencies = [ 110 "heck", 111 "proc-macro2", ··· 115 116 [[package]] 117 name = "clap_lex" 118 - version = "0.7.4" 119 source = "registry+https://github.com/rust-lang/crates.io-index" 120 - checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 121 122 [[package]] 123 name = "clap_mangen" 124 - version = "0.2.26" 125 source = "registry+https://github.com/rust-lang/crates.io-index" 126 - checksum = "724842fa9b144f9b89b3f3d371a89f3455eea660361d13a554f68f8ae5d6c13a" 127 dependencies = [ 128 "clap", 129 "roff", ··· 131 132 [[package]] 133 name = "colorchoice" 134 - version = "1.0.3" 135 source = "registry+https://github.com/rust-lang/crates.io-index" 136 - checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 137 138 [[package]] 139 name = "colored" ··· 141 source = "registry+https://github.com/rust-lang/crates.io-index" 142 checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" 143 dependencies = [ 144 - "windows-sys", 145 ] 146 147 [[package]] ··· 173 174 [[package]] 175 name = "errno" 176 - version = "0.3.11" 177 source = "registry+https://github.com/rust-lang/crates.io-index" 178 - checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" 179 dependencies = [ 180 "libc", 181 - "windows-sys", 182 ] 183 184 [[package]] ··· 189 190 [[package]] 191 name = "form_urlencoded" 192 - version = "1.2.1" 193 source = "registry+https://github.com/rust-lang/crates.io-index" 194 - checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 195 dependencies = [ 196 "percent-encoding", 197 ] 198 199 [[package]] 200 name = "getrandom" 201 - version = "0.3.2" 202 source = "registry+https://github.com/rust-lang/crates.io-index" 203 - checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 204 dependencies = [ 205 "cfg-if", 206 "libc", ··· 220 source = "registry+https://github.com/rust-lang/crates.io-index" 221 checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 222 dependencies = [ 223 - "windows-sys", 224 ] 225 226 [[package]] 227 name = "icu_collections" 228 - version = "1.5.0" 229 source = "registry+https://github.com/rust-lang/crates.io-index" 230 - checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 231 dependencies = [ 232 "displaydoc", 233 "yoke", 234 "zerofrom", 235 "zerovec", 236 ] 237 238 [[package]] 239 - name = "icu_locid" 240 - version = "1.5.0" 241 source = "registry+https://github.com/rust-lang/crates.io-index" 242 - checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 243 dependencies = [ 244 "displaydoc", 245 "litemap", ··· 249 ] 250 251 [[package]] 252 - name = "icu_locid_transform" 253 - version = "1.5.0" 254 - source = "registry+https://github.com/rust-lang/crates.io-index" 255 - checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 256 - dependencies = [ 257 - "displaydoc", 258 - "icu_locid", 259 - "icu_locid_transform_data", 260 - "icu_provider", 261 - "tinystr", 262 - "zerovec", 263 - ] 264 - 265 - [[package]] 266 - name = "icu_locid_transform_data" 267 - version = "1.5.1" 268 - source = "registry+https://github.com/rust-lang/crates.io-index" 269 - checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" 270 - 271 - [[package]] 272 name = "icu_normalizer" 273 - version = "1.5.0" 274 source = "registry+https://github.com/rust-lang/crates.io-index" 275 - checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 276 dependencies = [ 277 "displaydoc", 278 "icu_collections", ··· 280 "icu_properties", 281 "icu_provider", 282 "smallvec", 283 - "utf16_iter", 284 - "utf8_iter", 285 - "write16", 286 "zerovec", 287 ] 288 289 [[package]] 290 name = "icu_normalizer_data" 291 - version = "1.5.1" 292 source = "registry+https://github.com/rust-lang/crates.io-index" 293 - checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" 294 295 [[package]] 296 name = "icu_properties" 297 - version = "1.5.1" 298 source = "registry+https://github.com/rust-lang/crates.io-index" 299 - checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 300 dependencies = [ 301 "displaydoc", 302 "icu_collections", 303 - "icu_locid_transform", 304 "icu_properties_data", 305 "icu_provider", 306 - "tinystr", 307 "zerovec", 308 ] 309 310 [[package]] 311 name = "icu_properties_data" 312 - version = "1.5.1" 313 source = "registry+https://github.com/rust-lang/crates.io-index" 314 - checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" 315 316 [[package]] 317 name = "icu_provider" 318 - version = "1.5.0" 319 source = "registry+https://github.com/rust-lang/crates.io-index" 320 - checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 321 dependencies = [ 322 "displaydoc", 323 - "icu_locid", 324 - "icu_provider_macros", 325 "stable_deref_trait", 326 "tinystr", 327 "writeable", 328 "yoke", 329 "zerofrom", 330 "zerovec", 331 ] 332 333 [[package]] 334 - name = "icu_provider_macros" 335 - version = "1.5.0" 336 - source = "registry+https://github.com/rust-lang/crates.io-index" 337 - checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 338 - dependencies = [ 339 - "proc-macro2", 340 - "quote", 341 - "syn", 342 - ] 343 - 344 - [[package]] 345 name = "idna" 346 - version = "1.0.3" 347 source = "registry+https://github.com/rust-lang/crates.io-index" 348 - checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 349 dependencies = [ 350 "idna_adapter", 351 "smallvec", ··· 354 355 [[package]] 356 name = "idna_adapter" 357 - version = "1.2.0" 358 source = "registry+https://github.com/rust-lang/crates.io-index" 359 - checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 360 dependencies = [ 361 "icu_normalizer", 362 "icu_properties", ··· 398 399 [[package]] 400 name = "libc" 401 - version = "0.2.172" 402 source = "registry+https://github.com/rust-lang/crates.io-index" 403 - checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 404 405 [[package]] 406 name = "linux-raw-sys" ··· 416 417 [[package]] 418 name = "litemap" 419 - version = "0.7.5" 420 source = "registry+https://github.com/rust-lang/crates.io-index" 421 - checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" 422 423 [[package]] 424 name = "nix" ··· 439 checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 440 441 [[package]] 442 name = "open" 443 version = "5.3.2" 444 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 457 458 [[package]] 459 name = "percent-encoding" 460 - version = "2.3.1" 461 source = "registry+https://github.com/rust-lang/crates.io-index" 462 - checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 463 464 [[package]] 465 name = "proc-macro2" 466 - version = "1.0.95" 467 source = "registry+https://github.com/rust-lang/crates.io-index" 468 - checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 469 dependencies = [ 470 "unicode-ident", 471 ] ··· 481 482 [[package]] 483 name = "r-efi" 484 - version = "5.2.0" 485 source = "registry+https://github.com/rust-lang/crates.io-index" 486 - checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 487 488 [[package]] 489 name = "roff" ··· 501 "errno", 502 "libc", 503 "linux-raw-sys 0.4.15", 504 - "windows-sys", 505 ] 506 507 [[package]] 508 name = "rustix" 509 - version = "1.0.7" 510 source = "registry+https://github.com/rust-lang/crates.io-index" 511 - checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" 512 dependencies = [ 513 "bitflags", 514 "errno", 515 "libc", 516 "linux-raw-sys 0.9.4", 517 - "windows-sys", 518 ] 519 520 [[package]] ··· 539 540 [[package]] 541 name = "smallvec" 542 - version = "1.15.0" 543 source = "registry+https://github.com/rust-lang/crates.io-index" 544 - checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 545 546 [[package]] 547 name = "stable_deref_trait" ··· 557 558 [[package]] 559 name = "syn" 560 - version = "2.0.101" 561 source = "registry+https://github.com/rust-lang/crates.io-index" 562 - checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" 563 dependencies = [ 564 "proc-macro2", 565 "quote", ··· 579 580 [[package]] 581 name = "tempfile" 582 - version = "3.19.1" 583 source = "registry+https://github.com/rust-lang/crates.io-index" 584 - checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" 585 dependencies = [ 586 "fastrand", 587 "getrandom", 588 "once_cell", 589 - "rustix 1.0.7", 590 - "windows-sys", 591 ] 592 593 [[package]] 594 name = "thiserror" 595 - version = "2.0.12" 596 source = "registry+https://github.com/rust-lang/crates.io-index" 597 - checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" 598 dependencies = [ 599 "thiserror-impl", 600 ] 601 602 [[package]] 603 name = "thiserror-impl" 604 - version = "2.0.12" 605 source = "registry+https://github.com/rust-lang/crates.io-index" 606 - checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" 607 dependencies = [ 608 "proc-macro2", 609 "quote", ··· 612 613 [[package]] 614 name = "tinystr" 615 - version = "0.7.6" 616 source = "registry+https://github.com/rust-lang/crates.io-index" 617 - checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 618 dependencies = [ 619 "displaydoc", 620 "zerovec", ··· 622 623 [[package]] 624 name = "tsk-cli" 625 - version = "0.2.6" 626 dependencies = [ 627 "clap", 628 "clap_complete", ··· 645 646 [[package]] 647 name = "url" 648 - version = "2.5.4" 649 source = "registry+https://github.com/rust-lang/crates.io-index" 650 - checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 651 dependencies = [ 652 "form_urlencoded", 653 "idna", 654 "percent-encoding", 655 ] 656 - 657 - [[package]] 658 - name = "utf16_iter" 659 - version = "1.0.5" 660 - source = "registry+https://github.com/rust-lang/crates.io-index" 661 - checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 662 663 [[package]] 664 name = "utf8_iter" ··· 674 675 [[package]] 676 name = "wasi" 677 - version = "0.14.2+wasi-0.2.4" 678 source = "registry+https://github.com/rust-lang/crates.io-index" 679 - checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 680 dependencies = [ 681 - "wit-bindgen-rt", 682 ] 683 684 [[package]] ··· 694 ] 695 696 [[package]] 697 name = "windows-sys" 698 version = "0.59.0" 699 source = "registry+https://github.com/rust-lang/crates.io-index" 700 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 701 dependencies = [ 702 - "windows-targets", 703 ] 704 705 [[package]] ··· 708 source = "registry+https://github.com/rust-lang/crates.io-index" 709 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 710 dependencies = [ 711 - "windows_aarch64_gnullvm", 712 - "windows_aarch64_msvc", 713 - "windows_i686_gnu", 714 - "windows_i686_gnullvm", 715 - "windows_i686_msvc", 716 - "windows_x86_64_gnu", 717 - "windows_x86_64_gnullvm", 718 - "windows_x86_64_msvc", 719 ] 720 721 [[package]] ··· 725 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 726 727 [[package]] 728 name = "windows_aarch64_msvc" 729 version = "0.52.6" 730 source = "registry+https://github.com/rust-lang/crates.io-index" 731 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 732 733 [[package]] 734 name = "windows_i686_gnu" 735 version = "0.52.6" 736 source = "registry+https://github.com/rust-lang/crates.io-index" 737 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 738 739 [[package]] 740 name = "windows_i686_gnullvm" 741 version = "0.52.6" 742 source = "registry+https://github.com/rust-lang/crates.io-index" 743 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 744 745 [[package]] 746 name = "windows_i686_msvc" 747 version = "0.52.6" 748 source = "registry+https://github.com/rust-lang/crates.io-index" 749 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 750 751 [[package]] 752 name = "windows_x86_64_gnu" 753 version = "0.52.6" 754 source = "registry+https://github.com/rust-lang/crates.io-index" 755 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 756 757 [[package]] 758 name = "windows_x86_64_gnullvm" 759 version = "0.52.6" 760 source = "registry+https://github.com/rust-lang/crates.io-index" 761 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 762 763 [[package]] 764 name = "windows_x86_64_msvc" 765 version = "0.52.6" 766 source = "registry+https://github.com/rust-lang/crates.io-index" 767 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 768 769 [[package]] 770 - name = "wit-bindgen-rt" 771 - version = "0.39.0" 772 source = "registry+https://github.com/rust-lang/crates.io-index" 773 - checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 774 - dependencies = [ 775 - "bitflags", 776 - ] 777 778 [[package]] 779 - name = "write16" 780 - version = "1.0.0" 781 source = "registry+https://github.com/rust-lang/crates.io-index" 782 - checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 783 784 [[package]] 785 name = "writeable" 786 - version = "0.5.5" 787 source = "registry+https://github.com/rust-lang/crates.io-index" 788 - checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 789 790 [[package]] 791 name = "xattr" 792 - version = "1.5.0" 793 source = "registry+https://github.com/rust-lang/crates.io-index" 794 - checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" 795 dependencies = [ 796 "libc", 797 - "rustix 1.0.7", 798 ] 799 800 [[package]] 801 name = "yoke" 802 - version = "0.7.5" 803 source = "registry+https://github.com/rust-lang/crates.io-index" 804 - checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 805 dependencies = [ 806 "serde", 807 "stable_deref_trait", ··· 811 812 [[package]] 813 name = "yoke-derive" 814 - version = "0.7.5" 815 source = "registry+https://github.com/rust-lang/crates.io-index" 816 - checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 817 dependencies = [ 818 "proc-macro2", 819 "quote", ··· 843 ] 844 845 [[package]] 846 name = "zerovec" 847 - version = "0.10.4" 848 source = "registry+https://github.com/rust-lang/crates.io-index" 849 - checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 850 dependencies = [ 851 "yoke", 852 "zerofrom", ··· 855 856 [[package]] 857 name = "zerovec-derive" 858 - version = "0.10.3" 859 source = "registry+https://github.com/rust-lang/crates.io-index" 860 - checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 861 dependencies = [ 862 "proc-macro2", 863 "quote",
··· 4 5 [[package]] 6 name = "anstream" 7 + version = "0.6.20" 8 source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" 10 dependencies = [ 11 "anstyle", 12 "anstyle-parse", ··· 19 20 [[package]] 21 name = "anstyle" 22 + version = "1.0.11" 23 source = "registry+https://github.com/rust-lang/crates.io-index" 24 + checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" 25 26 [[package]] 27 name = "anstyle-parse" 28 + version = "0.2.7" 29 source = "registry+https://github.com/rust-lang/crates.io-index" 30 + checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" 31 dependencies = [ 32 "utf8parse", 33 ] 34 35 [[package]] 36 name = "anstyle-query" 37 + version = "1.1.4" 38 source = "registry+https://github.com/rust-lang/crates.io-index" 39 + checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 40 dependencies = [ 41 + "windows-sys 0.60.2", 42 ] 43 44 [[package]] 45 name = "anstyle-wincon" 46 + version = "3.0.10" 47 source = "registry+https://github.com/rust-lang/crates.io-index" 48 + checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 49 dependencies = [ 50 "anstyle", 51 + "once_cell_polyfill", 52 + "windows-sys 0.60.2", 53 ] 54 55 [[package]] 56 name = "bitflags" 57 + version = "2.9.4" 58 source = "registry+https://github.com/rust-lang/crates.io-index" 59 + checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" 60 61 [[package]] 62 name = "cfg-if" 63 + version = "1.0.3" 64 source = "registry+https://github.com/rust-lang/crates.io-index" 65 + checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" 66 67 [[package]] 68 name = "cfg_aliases" ··· 72 73 [[package]] 74 name = "clap" 75 + version = "4.5.47" 76 source = "registry+https://github.com/rust-lang/crates.io-index" 77 + checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" 78 dependencies = [ 79 "clap_builder", 80 "clap_derive", ··· 82 83 [[package]] 84 name = "clap_builder" 85 + version = "4.5.47" 86 source = "registry+https://github.com/rust-lang/crates.io-index" 87 + checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" 88 dependencies = [ 89 "anstream", 90 "anstyle", ··· 94 95 [[package]] 96 name = "clap_complete" 97 + version = "4.5.57" 98 source = "registry+https://github.com/rust-lang/crates.io-index" 99 + checksum = "4d9501bd3f5f09f7bbee01da9a511073ed30a80cd7a509f1214bb74eadea71ad" 100 dependencies = [ 101 "clap", 102 ] 103 104 [[package]] 105 name = "clap_derive" 106 + version = "4.5.47" 107 source = "registry+https://github.com/rust-lang/crates.io-index" 108 + checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" 109 dependencies = [ 110 "heck", 111 "proc-macro2", ··· 115 116 [[package]] 117 name = "clap_lex" 118 + version = "0.7.5" 119 source = "registry+https://github.com/rust-lang/crates.io-index" 120 + checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" 121 122 [[package]] 123 name = "clap_mangen" 124 + version = "0.2.29" 125 source = "registry+https://github.com/rust-lang/crates.io-index" 126 + checksum = "27b4c3c54b30f0d9adcb47f25f61fcce35c4dd8916638c6b82fbd5f4fb4179e2" 127 dependencies = [ 128 "clap", 129 "roff", ··· 131 132 [[package]] 133 name = "colorchoice" 134 + version = "1.0.4" 135 source = "registry+https://github.com/rust-lang/crates.io-index" 136 + checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" 137 138 [[package]] 139 name = "colored" ··· 141 source = "registry+https://github.com/rust-lang/crates.io-index" 142 checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" 143 dependencies = [ 144 + "windows-sys 0.59.0", 145 ] 146 147 [[package]] ··· 173 174 [[package]] 175 name = "errno" 176 + version = "0.3.13" 177 source = "registry+https://github.com/rust-lang/crates.io-index" 178 + checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" 179 dependencies = [ 180 "libc", 181 + "windows-sys 0.60.2", 182 ] 183 184 [[package]] ··· 189 190 [[package]] 191 name = "form_urlencoded" 192 + version = "1.2.2" 193 source = "registry+https://github.com/rust-lang/crates.io-index" 194 + checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" 195 dependencies = [ 196 "percent-encoding", 197 ] 198 199 [[package]] 200 name = "getrandom" 201 + version = "0.3.3" 202 source = "registry+https://github.com/rust-lang/crates.io-index" 203 + checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 204 dependencies = [ 205 "cfg-if", 206 "libc", ··· 220 source = "registry+https://github.com/rust-lang/crates.io-index" 221 checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 222 dependencies = [ 223 + "windows-sys 0.59.0", 224 ] 225 226 [[package]] 227 name = "icu_collections" 228 + version = "2.0.0" 229 source = "registry+https://github.com/rust-lang/crates.io-index" 230 + checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" 231 dependencies = [ 232 "displaydoc", 233 + "potential_utf", 234 "yoke", 235 "zerofrom", 236 "zerovec", 237 ] 238 239 [[package]] 240 + name = "icu_locale_core" 241 + version = "2.0.0" 242 source = "registry+https://github.com/rust-lang/crates.io-index" 243 + checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" 244 dependencies = [ 245 "displaydoc", 246 "litemap", ··· 250 ] 251 252 [[package]] 253 name = "icu_normalizer" 254 + version = "2.0.0" 255 source = "registry+https://github.com/rust-lang/crates.io-index" 256 + checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" 257 dependencies = [ 258 "displaydoc", 259 "icu_collections", ··· 261 "icu_properties", 262 "icu_provider", 263 "smallvec", 264 "zerovec", 265 ] 266 267 [[package]] 268 name = "icu_normalizer_data" 269 + version = "2.0.0" 270 source = "registry+https://github.com/rust-lang/crates.io-index" 271 + checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" 272 273 [[package]] 274 name = "icu_properties" 275 + version = "2.0.1" 276 source = "registry+https://github.com/rust-lang/crates.io-index" 277 + checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" 278 dependencies = [ 279 "displaydoc", 280 "icu_collections", 281 + "icu_locale_core", 282 "icu_properties_data", 283 "icu_provider", 284 + "potential_utf", 285 + "zerotrie", 286 "zerovec", 287 ] 288 289 [[package]] 290 name = "icu_properties_data" 291 + version = "2.0.1" 292 source = "registry+https://github.com/rust-lang/crates.io-index" 293 + checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" 294 295 [[package]] 296 name = "icu_provider" 297 + version = "2.0.0" 298 source = "registry+https://github.com/rust-lang/crates.io-index" 299 + checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" 300 dependencies = [ 301 "displaydoc", 302 + "icu_locale_core", 303 "stable_deref_trait", 304 "tinystr", 305 "writeable", 306 "yoke", 307 "zerofrom", 308 + "zerotrie", 309 "zerovec", 310 ] 311 312 [[package]] 313 name = "idna" 314 + version = "1.1.0" 315 source = "registry+https://github.com/rust-lang/crates.io-index" 316 + checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" 317 dependencies = [ 318 "idna_adapter", 319 "smallvec", ··· 322 323 [[package]] 324 name = "idna_adapter" 325 + version = "1.2.1" 326 source = "registry+https://github.com/rust-lang/crates.io-index" 327 + checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" 328 dependencies = [ 329 "icu_normalizer", 330 "icu_properties", ··· 366 367 [[package]] 368 name = "libc" 369 + version = "0.2.175" 370 source = "registry+https://github.com/rust-lang/crates.io-index" 371 + checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" 372 373 [[package]] 374 name = "linux-raw-sys" ··· 384 385 [[package]] 386 name = "litemap" 387 + version = "0.8.0" 388 source = "registry+https://github.com/rust-lang/crates.io-index" 389 + checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" 390 391 [[package]] 392 name = "nix" ··· 407 checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 408 409 [[package]] 410 + name = "once_cell_polyfill" 411 + version = "1.70.1" 412 + source = "registry+https://github.com/rust-lang/crates.io-index" 413 + checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" 414 + 415 + [[package]] 416 name = "open" 417 version = "5.3.2" 418 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 431 432 [[package]] 433 name = "percent-encoding" 434 + version = "2.3.2" 435 source = "registry+https://github.com/rust-lang/crates.io-index" 436 + checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 437 + 438 + [[package]] 439 + name = "potential_utf" 440 + version = "0.1.3" 441 + source = "registry+https://github.com/rust-lang/crates.io-index" 442 + checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" 443 + dependencies = [ 444 + "zerovec", 445 + ] 446 447 [[package]] 448 name = "proc-macro2" 449 + version = "1.0.101" 450 source = "registry+https://github.com/rust-lang/crates.io-index" 451 + checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" 452 dependencies = [ 453 "unicode-ident", 454 ] ··· 464 465 [[package]] 466 name = "r-efi" 467 + version = "5.3.0" 468 source = "registry+https://github.com/rust-lang/crates.io-index" 469 + checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 470 471 [[package]] 472 name = "roff" ··· 484 "errno", 485 "libc", 486 "linux-raw-sys 0.4.15", 487 + "windows-sys 0.59.0", 488 ] 489 490 [[package]] 491 name = "rustix" 492 + version = "1.0.8" 493 source = "registry+https://github.com/rust-lang/crates.io-index" 494 + checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" 495 dependencies = [ 496 "bitflags", 497 "errno", 498 "libc", 499 "linux-raw-sys 0.9.4", 500 + "windows-sys 0.60.2", 501 ] 502 503 [[package]] ··· 522 523 [[package]] 524 name = "smallvec" 525 + version = "1.15.1" 526 source = "registry+https://github.com/rust-lang/crates.io-index" 527 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 528 529 [[package]] 530 name = "stable_deref_trait" ··· 540 541 [[package]] 542 name = "syn" 543 + version = "2.0.106" 544 source = "registry+https://github.com/rust-lang/crates.io-index" 545 + checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" 546 dependencies = [ 547 "proc-macro2", 548 "quote", ··· 562 563 [[package]] 564 name = "tempfile" 565 + version = "3.21.0" 566 source = "registry+https://github.com/rust-lang/crates.io-index" 567 + checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" 568 dependencies = [ 569 "fastrand", 570 "getrandom", 571 "once_cell", 572 + "rustix 1.0.8", 573 + "windows-sys 0.60.2", 574 ] 575 576 [[package]] 577 name = "thiserror" 578 + version = "2.0.16" 579 source = "registry+https://github.com/rust-lang/crates.io-index" 580 + checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" 581 dependencies = [ 582 "thiserror-impl", 583 ] 584 585 [[package]] 586 name = "thiserror-impl" 587 + version = "2.0.16" 588 source = "registry+https://github.com/rust-lang/crates.io-index" 589 + checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" 590 dependencies = [ 591 "proc-macro2", 592 "quote", ··· 595 596 [[package]] 597 name = "tinystr" 598 + version = "0.8.1" 599 source = "registry+https://github.com/rust-lang/crates.io-index" 600 + checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" 601 dependencies = [ 602 "displaydoc", 603 "zerovec", ··· 605 606 [[package]] 607 name = "tsk-cli" 608 + version = "0.4.0" 609 dependencies = [ 610 "clap", 611 "clap_complete", ··· 628 629 [[package]] 630 name = "url" 631 + version = "2.5.7" 632 source = "registry+https://github.com/rust-lang/crates.io-index" 633 + checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" 634 dependencies = [ 635 "form_urlencoded", 636 "idna", 637 "percent-encoding", 638 + "serde", 639 ] 640 641 [[package]] 642 name = "utf8_iter" ··· 652 653 [[package]] 654 name = "wasi" 655 + version = "0.14.4+wasi-0.2.4" 656 source = "registry+https://github.com/rust-lang/crates.io-index" 657 + checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" 658 dependencies = [ 659 + "wit-bindgen", 660 ] 661 662 [[package]] ··· 672 ] 673 674 [[package]] 675 + name = "windows-link" 676 + version = "0.1.3" 677 + source = "registry+https://github.com/rust-lang/crates.io-index" 678 + checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" 679 + 680 + [[package]] 681 name = "windows-sys" 682 version = "0.59.0" 683 source = "registry+https://github.com/rust-lang/crates.io-index" 684 checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 685 dependencies = [ 686 + "windows-targets 0.52.6", 687 + ] 688 + 689 + [[package]] 690 + name = "windows-sys" 691 + version = "0.60.2" 692 + source = "registry+https://github.com/rust-lang/crates.io-index" 693 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 694 + dependencies = [ 695 + "windows-targets 0.53.3", 696 ] 697 698 [[package]] ··· 701 source = "registry+https://github.com/rust-lang/crates.io-index" 702 checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 703 dependencies = [ 704 + "windows_aarch64_gnullvm 0.52.6", 705 + "windows_aarch64_msvc 0.52.6", 706 + "windows_i686_gnu 0.52.6", 707 + "windows_i686_gnullvm 0.52.6", 708 + "windows_i686_msvc 0.52.6", 709 + "windows_x86_64_gnu 0.52.6", 710 + "windows_x86_64_gnullvm 0.52.6", 711 + "windows_x86_64_msvc 0.52.6", 712 + ] 713 + 714 + [[package]] 715 + name = "windows-targets" 716 + version = "0.53.3" 717 + source = "registry+https://github.com/rust-lang/crates.io-index" 718 + checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" 719 + dependencies = [ 720 + "windows-link", 721 + "windows_aarch64_gnullvm 0.53.0", 722 + "windows_aarch64_msvc 0.53.0", 723 + "windows_i686_gnu 0.53.0", 724 + "windows_i686_gnullvm 0.53.0", 725 + "windows_i686_msvc 0.53.0", 726 + "windows_x86_64_gnu 0.53.0", 727 + "windows_x86_64_gnullvm 0.53.0", 728 + "windows_x86_64_msvc 0.53.0", 729 ] 730 731 [[package]] ··· 735 checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 736 737 [[package]] 738 + name = "windows_aarch64_gnullvm" 739 + version = "0.53.0" 740 + source = "registry+https://github.com/rust-lang/crates.io-index" 741 + checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" 742 + 743 + [[package]] 744 name = "windows_aarch64_msvc" 745 version = "0.52.6" 746 source = "registry+https://github.com/rust-lang/crates.io-index" 747 checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 748 749 [[package]] 750 + name = "windows_aarch64_msvc" 751 + version = "0.53.0" 752 + source = "registry+https://github.com/rust-lang/crates.io-index" 753 + checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" 754 + 755 + [[package]] 756 name = "windows_i686_gnu" 757 version = "0.52.6" 758 source = "registry+https://github.com/rust-lang/crates.io-index" 759 checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 760 761 [[package]] 762 + name = "windows_i686_gnu" 763 + version = "0.53.0" 764 + source = "registry+https://github.com/rust-lang/crates.io-index" 765 + checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" 766 + 767 + [[package]] 768 name = "windows_i686_gnullvm" 769 version = "0.52.6" 770 source = "registry+https://github.com/rust-lang/crates.io-index" 771 checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 772 773 [[package]] 774 + name = "windows_i686_gnullvm" 775 + version = "0.53.0" 776 + source = "registry+https://github.com/rust-lang/crates.io-index" 777 + checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" 778 + 779 + [[package]] 780 name = "windows_i686_msvc" 781 version = "0.52.6" 782 source = "registry+https://github.com/rust-lang/crates.io-index" 783 checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 784 785 [[package]] 786 + name = "windows_i686_msvc" 787 + version = "0.53.0" 788 + source = "registry+https://github.com/rust-lang/crates.io-index" 789 + checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" 790 + 791 + [[package]] 792 name = "windows_x86_64_gnu" 793 version = "0.52.6" 794 source = "registry+https://github.com/rust-lang/crates.io-index" 795 checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 796 797 [[package]] 798 + name = "windows_x86_64_gnu" 799 + version = "0.53.0" 800 + source = "registry+https://github.com/rust-lang/crates.io-index" 801 + checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" 802 + 803 + [[package]] 804 name = "windows_x86_64_gnullvm" 805 version = "0.52.6" 806 source = "registry+https://github.com/rust-lang/crates.io-index" 807 checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 808 809 [[package]] 810 + name = "windows_x86_64_gnullvm" 811 + version = "0.53.0" 812 + source = "registry+https://github.com/rust-lang/crates.io-index" 813 + checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" 814 + 815 + [[package]] 816 name = "windows_x86_64_msvc" 817 version = "0.52.6" 818 source = "registry+https://github.com/rust-lang/crates.io-index" 819 checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 820 821 [[package]] 822 + name = "windows_x86_64_msvc" 823 + version = "0.53.0" 824 source = "registry+https://github.com/rust-lang/crates.io-index" 825 + checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" 826 827 [[package]] 828 + name = "wit-bindgen" 829 + version = "0.45.1" 830 source = "registry+https://github.com/rust-lang/crates.io-index" 831 + checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" 832 833 [[package]] 834 name = "writeable" 835 + version = "0.6.1" 836 source = "registry+https://github.com/rust-lang/crates.io-index" 837 + checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" 838 839 [[package]] 840 name = "xattr" 841 + version = "1.5.1" 842 source = "registry+https://github.com/rust-lang/crates.io-index" 843 + checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" 844 dependencies = [ 845 "libc", 846 + "rustix 1.0.8", 847 ] 848 849 [[package]] 850 name = "yoke" 851 + version = "0.8.0" 852 source = "registry+https://github.com/rust-lang/crates.io-index" 853 + checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" 854 dependencies = [ 855 "serde", 856 "stable_deref_trait", ··· 860 861 [[package]] 862 name = "yoke-derive" 863 + version = "0.8.0" 864 source = "registry+https://github.com/rust-lang/crates.io-index" 865 + checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" 866 dependencies = [ 867 "proc-macro2", 868 "quote", ··· 892 ] 893 894 [[package]] 895 + name = "zerotrie" 896 + version = "0.2.2" 897 + source = "registry+https://github.com/rust-lang/crates.io-index" 898 + checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" 899 + dependencies = [ 900 + "displaydoc", 901 + "yoke", 902 + "zerofrom", 903 + ] 904 + 905 + [[package]] 906 name = "zerovec" 907 + version = "0.11.4" 908 source = "registry+https://github.com/rust-lang/crates.io-index" 909 + checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" 910 dependencies = [ 911 "yoke", 912 "zerofrom", ··· 915 916 [[package]] 917 name = "zerovec-derive" 918 + version = "0.11.1" 919 source = "registry+https://github.com/rust-lang/crates.io-index" 920 + checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" 921 dependencies = [ 922 "proc-macro2", 923 "quote",
+2 -2
Cargo.toml
··· 1 [package] 2 name = "tsk-cli" 3 - version = "0.2.6" 4 - edition = "2021" 5 publish = true 6 license-file = "LICENSE" 7 description = "A command-line first, file-system based task manager"
··· 1 [package] 2 name = "tsk-cli" 3 + version = "0.4.0" 4 + edition = "2024" 5 publish = true 6 license-file = "LICENSE" 7 description = "A command-line first, file-system based task manager"
+25 -6
flake.nix
··· 5 utils.url = "github:numtide/flake-utils"; 6 }; 7 8 - outputs = { self, nixpkgs, utils, naersk }: 9 - utils.lib.eachDefaultSystem (system: 10 let 11 pkgs = import nixpkgs { inherit system; }; 12 naersk-lib = pkgs.callPackage naersk { }; 13 in 14 { 15 defaultPackage = naersk-lib.buildPackage ./.; 16 - devShell = with pkgs; mkShell { 17 - buildInputs = [ libiconv cargo rustc rustfmt rust-analyzer rustPackages.clippy plan9port pandoc ]; 18 - RUST_SRC_PATH = rustPlatform.rustLibSrc; 19 - }; 20 } 21 ); 22 }
··· 5 utils.url = "github:numtide/flake-utils"; 6 }; 7 8 + outputs = 9 + { 10 + self, 11 + nixpkgs, 12 + utils, 13 + naersk, 14 + }: 15 + utils.lib.eachDefaultSystem ( 16 + system: 17 let 18 pkgs = import nixpkgs { inherit system; }; 19 naersk-lib = pkgs.callPackage naersk { }; 20 in 21 { 22 defaultPackage = naersk-lib.buildPackage ./.; 23 + devShell = 24 + with pkgs; 25 + mkShell { 26 + buildInputs = [ 27 + libiconv 28 + cargo 29 + rustc 30 + rustfmt 31 + rust-analyzer 32 + rustPackages.clippy 33 + plan9port 34 + pandoc 35 + codeberg-cli 36 + ]; 37 + RUST_SRC_PATH = rustPlatform.rustLibSrc; 38 + }; 39 } 40 ); 41 }
+5 -2
readme
··· 184 A quick overview of the format: 185 186 - \!Bolded\! text is surrounded by exclamation marks (!) 187 - - \*Italicized\* text is surrouneded by single asterists (*) 188 - \_Underlined\_ text is surrounded by underscores (_) 189 - - \~Strikenthrough\~ text is surrounded by tildes (~) 190 191 Links like in Markdown, along with the wiki-style links documented above. 192 193 Misc 194 ----
··· 184 A quick overview of the format: 185 186 - \!Bolded\! text is surrounded by exclamation marks (!) 187 + - \*Italicized\* text is surrounded by single asterisks (*) 188 - \_Underlined\_ text is surrounded by underscores (_) 189 + - \~Strikethrough\~ text is surrounded by tildes (~) 190 + - \=Highlighted\= text is surrounded by equals signs (=) 191 + - \`Inline code\` is surrounded by backticks (`) 192 193 Links like in Markdown, along with the wiki-style links documented above. 194 + Raw links can also be written as \<https://example.com\>. 195 196 Misc 197 ----
+1 -1
src/attrs.rs
··· 1 use std::collections::btree_map::Entry; 2 use std::collections::btree_map::{IntoIter as BTreeIntoIter, Iter as BTreeMapIter}; 3 - use std::collections::BTreeMap; 4 use std::iter::Chain; 5 6 type Map = BTreeMap<String, String>;
··· 1 + use std::collections::BTreeMap; 2 use std::collections::btree_map::Entry; 3 use std::collections::btree_map::{IntoIter as BTreeIntoIter, Iter as BTreeMapIter}; 4 use std::iter::Chain; 5 6 type Map = BTreeMap<String, String>;
+14 -6
src/fzf.rs
··· 1 use crate::errors::{Error, Result}; 2 use std::fmt::Display; 3 use std::io::Write; 4 use std::process::{Command, Stdio}; ··· 6 7 /// Sends each item as a line to stdin to the `fzf` command and returns the selected item's string 8 /// representation as output 9 - pub fn select<I>(input: impl IntoIterator<Item = I>) -> Result<Option<I>> 10 where 11 - I: Display + FromStr, 12 - Error: From<<I as FromStr>::Err>, 13 { 14 - let mut child = Command::new("fzf") 15 - .args(["-d", "\t"]) 16 .stderr(Stdio::inherit()) 17 .stdin(Stdio::piped()) 18 .stdout(Stdio::piped()) ··· 20 // unwrap: this can never fail 21 let child_in = child.stdin.as_mut().unwrap(); 22 for item in input.into_iter() { 23 - writeln!(child_in, "{item}")?; 24 } 25 let output = child.wait_with_output()?; 26 if output.stdout.is_empty() {
··· 1 use crate::errors::{Error, Result}; 2 + use std::ffi::OsStr; 3 use std::fmt::Display; 4 use std::io::Write; 5 use std::process::{Command, Stdio}; ··· 7 8 /// Sends each item as a line to stdin to the `fzf` command and returns the selected item's string 9 /// representation as output 10 + pub fn select<I, O, S>( 11 + input: impl IntoIterator<Item = I>, 12 + extra: impl IntoIterator<Item = S>, 13 + ) -> Result<Option<O>> 14 where 15 + O: FromStr, 16 + I: Display, 17 + Error: From<<O as FromStr>::Err>, 18 + S: AsRef<OsStr>, 19 { 20 + let mut command = Command::new("fzf"); 21 + let mut child = command 22 + .args(extra) 23 + .arg("--read0") 24 .stderr(Stdio::inherit()) 25 .stdin(Stdio::piped()) 26 .stdout(Stdio::piped()) ··· 28 // unwrap: this can never fail 29 let child_in = child.stdin.as_mut().unwrap(); 30 for item in input.into_iter() { 31 + write!(child_in, "{item}\0")?; 32 } 33 let output = child.wait_with_output()?; 34 if output.stdout.is_empty() {
+31 -22
src/main.rs
··· 5 mod task; 6 mod util; 7 mod workspace; 8 - use clap_complete::{generate, Shell}; 9 use errors::Result; 10 use std::io::{self, Write}; 11 use std::path::PathBuf; ··· 86 all: bool, 87 #[arg(short = 'c', default_value_t = 10)] 88 count: usize, 89 - #[arg(short = 'i', default_value_t = false)] 90 - ids: bool 91 }, 92 93 /// Swaps the top two tasks on the stack. If there are less than 2 tasks on the stack, there is ··· 222 #[derive(Args)] 223 #[group(required = false, multiple = false)] 224 struct FindArgs { 225 - /// Include the contents of tasks in the search criteria. 226 #[arg(short = 'b', default_value_t = false)] 227 - search_body: bool, 228 /* TODO: implement this 229 /// Include archived tasks in the search criteria. Combine with `-b` to include archived 230 /// bodies in the search criteria. ··· 239 TaskIdentifier::Id(id) 240 } else if value.find.find { 241 TaskIdentifier::Find { 242 - search_body: value.find.args.search_body, 243 archived: false, 244 } 245 } else { ··· 255 Commands::Init => command_init(dir), 256 Commands::Push { edit, body, title } => command_push(dir, edit, body, title), 257 Commands::Append { edit, body, title } => command_append(dir, edit, body, title), 258 - Commands::List { all, count, ids } => command_list(dir, all, ids, count), 259 Commands::Swap => command_swap(dir), 260 Commands::Show { 261 task_id, ··· 293 relative_id: 0, 294 find: Find { 295 find: false, 296 - args: FindArgs { search_body: false }, 297 }, 298 } 299 } ··· 315 } else { 316 "".to_string() 317 }; 318 - let mut body = body.unwrap_or_default(); 319 if body == "-" { 320 // add newline so you can type directly in the shell 321 //eprintln!(""); ··· 329 body = content.1.to_string(); 330 } 331 } 332 let task = workspace.new_task(title, body)?; 333 workspace.handle_metadata(&task, None)?; 334 Ok(task) ··· 346 workspace.append_task(task) 347 } 348 349 - fn command_list(dir: PathBuf, all: bool, only_print_ids: bool, count: usize) -> Result<()> { 350 let workspace = Workspace::from_path(dir)?; 351 let stack = workspace.read_stack()?; 352 ··· 360 .enumerate() 361 .take_while(|(idx, _)| all || idx < &count) 362 { 363 - match (task::parse(&stack_item.title), only_print_ids) { 364 - (None, false) => { 365 - println!("{stack_item}"); 366 - }, 367 - (Some(parsed), false) => { 368 - println!("{}\t{}", stack_item.id, parsed.content.trim()) 369 - }, 370 - (None, true) | (Some(_), true) => { 371 - println!("{}", stack_item.id) 372 - }, 373 } 374 } 375 Ok(()) ··· 388 let pre_links = task::parse(&task.to_string()).map(|pt| pt.intenal_links()); 389 let new_content = open_editor(format!("{}\n\n{}", task.title.trim(), task.body.trim()))?; 390 if let Some((title, body)) = new_content.split_once("\n") { 391 - task.title = title.to_string(); 392 task.body = body.to_string(); 393 workspace.handle_metadata(&task, pre_links)?; 394 task.save()?; ··· 413 } 414 415 fn command_find(dir: PathBuf, short_id: bool, find_args: FindArgs) -> Result<()> { 416 - let id = Workspace::from_path(dir)?.search(None, find_args.search_body, false)?; 417 if let Some(id) = id { 418 if short_id { 419 // print as integer
··· 5 mod task; 6 mod util; 7 mod workspace; 8 + use clap_complete::{Shell, generate}; 9 use errors::Result; 10 use std::io::{self, Write}; 11 use std::path::PathBuf; ··· 86 all: bool, 87 #[arg(short = 'c', default_value_t = 10)] 88 count: usize, 89 }, 90 91 /// Swaps the top two tasks on the stack. If there are less than 2 tasks on the stack, there is ··· 220 #[derive(Args)] 221 #[group(required = false, multiple = false)] 222 struct FindArgs { 223 + /// Exclude the contents of tasks in the search criteria. 224 #[arg(short = 'b', default_value_t = false)] 225 + exclude_body: bool, 226 /* TODO: implement this 227 /// Include archived tasks in the search criteria. Combine with `-b` to include archived 228 /// bodies in the search criteria. ··· 237 TaskIdentifier::Id(id) 238 } else if value.find.find { 239 TaskIdentifier::Find { 240 + exclude_body: value.find.args.exclude_body, 241 archived: false, 242 } 243 } else { ··· 253 Commands::Init => command_init(dir), 254 Commands::Push { edit, body, title } => command_push(dir, edit, body, title), 255 Commands::Append { edit, body, title } => command_append(dir, edit, body, title), 256 + Commands::List { all, count } => command_list(dir, all, count), 257 Commands::Swap => command_swap(dir), 258 Commands::Show { 259 task_id, ··· 291 relative_id: 0, 292 find: Find { 293 find: false, 294 + args: FindArgs { exclude_body: true }, 295 }, 296 } 297 } ··· 313 } else { 314 "".to_string() 315 }; 316 + // If no body was explicitly provided and the title contains newlines, 317 + // treat the first line as the title and the rest as the body (like git commit -m) 318 + let mut body = if body.is_none() { 319 + if let Some((first_line, rest)) = title.split_once('\n') { 320 + let extracted_body = rest.to_string(); 321 + title = first_line.to_string(); 322 + extracted_body 323 + } else { 324 + String::new() 325 + } 326 + } else { 327 + // Body was explicitly provided, so strip any newlines from title 328 + title = title.replace(['\n', '\r'], " "); 329 + body.unwrap_or_default() 330 + }; 331 if body == "-" { 332 // add newline so you can type directly in the shell 333 //eprintln!(""); ··· 341 body = content.1.to_string(); 342 } 343 } 344 + // Ensure title never contains newlines (invariant for index file format) 345 + title = title.replace(['\n', '\r'], " "); 346 let task = workspace.new_task(title, body)?; 347 workspace.handle_metadata(&task, None)?; 348 Ok(task) ··· 360 workspace.append_task(task) 361 } 362 363 + fn command_list(dir: PathBuf, all: bool, count: usize) -> Result<()> { 364 let workspace = Workspace::from_path(dir)?; 365 let stack = workspace.read_stack()?; 366 ··· 374 .enumerate() 375 .take_while(|(idx, _)| all || idx < &count) 376 { 377 + if let Some(parsed) = task::parse(&stack_item.title) { 378 + println!("{}\t{}", stack_item.id, parsed.content.trim()); 379 + } else { 380 + println!("{stack_item}"); 381 } 382 } 383 Ok(()) ··· 396 let pre_links = task::parse(&task.to_string()).map(|pt| pt.intenal_links()); 397 let new_content = open_editor(format!("{}\n\n{}", task.title.trim(), task.body.trim()))?; 398 if let Some((title, body)) = new_content.split_once("\n") { 399 + // Ensure title never contains newlines (invariant for index file format) 400 + task.title = title.replace(['\n', '\r'], " "); 401 task.body = body.to_string(); 402 workspace.handle_metadata(&task, pre_links)?; 403 task.save()?; ··· 422 } 423 424 fn command_find(dir: PathBuf, short_id: bool, find_args: FindArgs) -> Result<()> { 425 + let id = Workspace::from_path(dir)?.search(None, !find_args.exclude_body, false)?; 426 if let Some(id) = id { 427 if short_id { 428 // print as integer
+2 -2
src/stack.rs
··· 4 5 use crate::errors::{Error, Result}; 6 use crate::util; 7 - use std::collections::vec_deque::Iter; 8 use std::collections::VecDeque; 9 use std::fmt::Display; 10 use std::fs::File; 11 use std::io::{self, BufRead, BufReader, Seek, Write}; ··· 179 self.all.remove(index) 180 } 181 182 - pub fn iter(&self) -> Iter<StackItem> { 183 self.all.iter() 184 } 185
··· 4 5 use crate::errors::{Error, Result}; 6 use crate::util; 7 use std::collections::VecDeque; 8 + use std::collections::vec_deque::Iter; 9 use std::fmt::Display; 10 use std::fs::File; 11 use std::io::{self, BufRead, BufReader, Seek, Write}; ··· 179 self.all.remove(index) 180 } 181 182 + pub fn iter(&self) -> Iter<'_, StackItem> { 183 self.all.iter() 184 } 185
+27 -24
src/task.rs
··· 6 use crate::workspace::Id; 7 use colored::Colorize; 8 9 #[derive(Debug, Eq, PartialEq, Clone, Copy)] 10 enum ParserState { 11 // Started by ` =`, terminated by `= ··· 98 panic!("Internal link is not a valid id: {contents}"); 99 } 100 } 101 - (' ' | '\r' | '\n', '[', _) => { 102 state.push(Linktext(end, char_pos)); 103 } 104 (']', '(', Some(Linktext(_, _))) => { 105 state.push(Link(end, char_pos)); 106 } 107 - (')', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Link(_, _))) => { 108 // TODO: this needs to be updated to use `s` instead of `out` for position 109 // parsing 110 let linkpos = if let Link(lp, _) = state.pop().unwrap() { ··· 130 out.replace_range(linktextpos..end, &linktext); 131 } 132 } 133 - ('>', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(RawLink(hl, s_pos))) 134 - if s_pos != char_pos - 1 => 135 { 136 state.pop(); 137 let link = s.get(s_pos + 1..char_pos - 1)?; ··· 142 out.replace_range(hl..end, &linktext); 143 } 144 } 145 - (' ' | '\r' | '\n', '<', _) => { 146 state.push(RawLink(end, char_pos)); 147 } 148 - ('=', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Highlight(hl, s_pos))) 149 - if s_pos != char_pos - 1 => 150 { 151 state.pop(); 152 out.replace_range( ··· 154 &s.get(s_pos + 1..char_pos - 1)?.reversed().to_string(), 155 ); 156 } 157 - (' ' | '\r' | '\n', '=', _) => { 158 state.push(Highlight(end, char_pos)); 159 } 160 - (' ' | '\r' | '\n', '*', _) => { 161 state.push(Italics(end, char_pos)); 162 } 163 - ('*', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Italics(il, s_pos))) 164 - if s_pos != char_pos - 1 => 165 { 166 state.pop(); 167 out.replace_range( ··· 169 &s.get(s_pos + 1..char_pos - 1)?.italic().to_string(), 170 ); 171 } 172 - (' ' | '\r' | '\n', '!', _) => { 173 state.push(Bold(end, char_pos)); 174 } 175 - ('!', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Bold(il, s_pos))) 176 - if s_pos != char_pos - 1 => 177 - { 178 state.pop(); 179 out.replace_range( 180 il..end, 181 &s.get(s_pos + 1..char_pos - 1)?.bold().to_string(), 182 ); 183 } 184 - (' ' | '\r' | '\n', '_', _) => { 185 state.push(Underline(end, char_pos)); 186 } 187 - ('_', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Underline(il, s_pos))) 188 - if s_pos != char_pos - 1 => 189 { 190 state.pop(); 191 out.replace_range( ··· 193 &s.get(s_pos + 1..char_pos - 1)?.underline().to_string(), 194 ); 195 } 196 - (' ' | '\r' | '\n', '~', _) => { 197 state.push(Strikethrough(end, char_pos)); 198 } 199 - ('~', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(Strikethrough(il, s_pos))) 200 - if s_pos != char_pos - 1 => 201 { 202 state.pop(); 203 out.replace_range( ··· 205 &s.get(s_pos + 1..char_pos - 1)?.strikethrough().to_string(), 206 ); 207 } 208 - ('`', ' ' | '\n' | '\r' | '.' | '!' | '?', Some(InlineBlock(hl, s_pos))) 209 - if s_pos != char_pos - 1 => 210 { 211 out.replace_range( 212 hl..end, 213 &s.get(s_pos + 1..char_pos - 1)?.green().to_string(), 214 ); 215 } 216 - (' ' | '\n' | '\r' | '.' | '!' | '?', '`', _) => { 217 state.push(InlineBlock(end, char_pos)); 218 } 219 _ => (),
··· 6 use crate::workspace::Id; 7 use colored::Colorize; 8 9 + /// Returns true if the character is a word boundary (whitespace or punctuation) 10 + fn is_boundary(c: char) -> bool { 11 + c.is_whitespace() || c.is_ascii_punctuation() 12 + } 13 + 14 #[derive(Debug, Eq, PartialEq, Clone, Copy)] 15 enum ParserState { 16 // Started by ` =`, terminated by `= ··· 103 panic!("Internal link is not a valid id: {contents}"); 104 } 105 } 106 + (last, '[', _) if is_boundary(last) => { 107 state.push(Linktext(end, char_pos)); 108 } 109 (']', '(', Some(Linktext(_, _))) => { 110 state.push(Link(end, char_pos)); 111 } 112 + (')', c, Some(Link(_, _))) if is_boundary(c) => { 113 // TODO: this needs to be updated to use `s` instead of `out` for position 114 // parsing 115 let linkpos = if let Link(lp, _) = state.pop().unwrap() { ··· 135 out.replace_range(linktextpos..end, &linktext); 136 } 137 } 138 + ('>', c, Some(RawLink(hl, s_pos))) 139 + if is_boundary(c) && s_pos != char_pos - 1 => 140 { 141 state.pop(); 142 let link = s.get(s_pos + 1..char_pos - 1)?; ··· 147 out.replace_range(hl..end, &linktext); 148 } 149 } 150 + (last, '<', _) if is_boundary(last) => { 151 state.push(RawLink(end, char_pos)); 152 } 153 + ('=', c, Some(Highlight(hl, s_pos))) 154 + if is_boundary(c) && s_pos != char_pos - 1 => 155 { 156 state.pop(); 157 out.replace_range( ··· 159 &s.get(s_pos + 1..char_pos - 1)?.reversed().to_string(), 160 ); 161 } 162 + (last, '=', _) if is_boundary(last) => { 163 state.push(Highlight(end, char_pos)); 164 } 165 + (last, '*', _) if is_boundary(last) => { 166 state.push(Italics(end, char_pos)); 167 } 168 + ('*', c, Some(Italics(il, s_pos))) 169 + if is_boundary(c) && s_pos != char_pos - 1 => 170 { 171 state.pop(); 172 out.replace_range( ··· 174 &s.get(s_pos + 1..char_pos - 1)?.italic().to_string(), 175 ); 176 } 177 + (last, '!', _) if is_boundary(last) => { 178 state.push(Bold(end, char_pos)); 179 } 180 + ('!', c, Some(Bold(il, s_pos))) if is_boundary(c) && s_pos != char_pos - 1 => { 181 state.pop(); 182 out.replace_range( 183 il..end, 184 &s.get(s_pos + 1..char_pos - 1)?.bold().to_string(), 185 ); 186 } 187 + (last, '_', _) if is_boundary(last) => { 188 state.push(Underline(end, char_pos)); 189 } 190 + ('_', c, Some(Underline(il, s_pos))) 191 + if is_boundary(c) && s_pos != char_pos - 1 => 192 { 193 state.pop(); 194 out.replace_range( ··· 196 &s.get(s_pos + 1..char_pos - 1)?.underline().to_string(), 197 ); 198 } 199 + (last, '~', _) if is_boundary(last) => { 200 state.push(Strikethrough(end, char_pos)); 201 } 202 + ('~', c, Some(Strikethrough(il, s_pos))) 203 + if is_boundary(c) && s_pos != char_pos - 1 => 204 { 205 state.pop(); 206 out.replace_range( ··· 208 &s.get(s_pos + 1..char_pos - 1)?.strikethrough().to_string(), 209 ); 210 } 211 + ('`', c, Some(InlineBlock(hl, s_pos))) 212 + if is_boundary(c) && s_pos != char_pos - 1 => 213 { 214 out.replace_range( 215 hl..end, 216 &s.get(s_pos + 1..char_pos - 1)?.green().to_string(), 217 ); 218 } 219 + (last, '`', _) if is_boundary(last) => { 220 state.push(InlineBlock(end, char_pos)); 221 } 222 _ => (),
+53 -36
src/workspace.rs
··· 7 use crate::stack::{StackItem, TaskStack}; 8 use crate::task::parse as parse_task; 9 use crate::{fzf, util}; 10 - use std::collections::{vec_deque, BTreeMap, HashSet}; 11 use std::ffi::OsString; 12 use std::fmt::Display; 13 - use std::fs::{remove_file, File}; 14 use std::io::{BufRead as _, BufReader, Read, Seek, SeekFrom}; 15 use std::ops::Deref; 16 use std::os::unix::fs::symlink; 17 use std::path::PathBuf; 18 use std::str::FromStr; 19 use std::{fs::OpenOptions, io::Write}; 20 ··· 30 type Err = Error; 31 32 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { 33 - let s = s 34 .trim() 35 - .strip_prefix("tsk-") 36 .ok_or(Self::Err::Parse(format!("expected tsk- prefix. Got {s}")))?; 37 Ok(Self(s.parse()?)) 38 } ··· 60 pub enum TaskIdentifier { 61 Id(Id), 62 Relative(u32), 63 - Find { search_body: bool, archived: bool }, 64 } 65 66 impl From<Id> for TaskIdentifier { ··· 93 .create(true) 94 .truncate(true) 95 .open(tsk_dir.join("next"))?; 96 next.write_all(b"1\n")?; 97 Ok(()) 98 } ··· 111 Ok(stack_item.id) 112 } 113 TaskIdentifier::Find { 114 - search_body, 115 archived, 116 } => self 117 - .search(None, search_body, archived)? 118 .ok_or(Error::NotSelected), 119 } 120 } ··· 347 workspace: self, 348 }; 349 // search the entirety of a task 350 - Ok(fzf::select(loader)?.map(|bt| bt.id)) 351 } else { 352 // just search the stack 353 - Ok(fzf::select(stack)?.map(|si| si.id)) 354 } 355 } 356 ··· 406 Ok(()) 407 } 408 409 fn bare(self) -> SearchTask { 410 SearchTask { 411 id: self.id, ··· 422 pub body: String, 423 } 424 425 - impl FromStr for SearchTask { 426 - type Err = Error; 427 - 428 - fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { 429 - let (tsk_id, task_content) = s.split_once('\t').ok_or(Error::Parse( 430 - "Missing TSK-ID or content or task parse.".to_owned(), 431 - ))?; 432 - let (title, body) = task_content 433 - .split_once('\t') 434 - .ok_or(Error::Parse("Missing body for task parse.".to_owned()))?; 435 - Ok(Self { 436 - id: tsk_id.parse()?, 437 - title: title.to_string(), 438 - body: body.to_string(), 439 - }) 440 - } 441 - } 442 - 443 impl Display for SearchTask { 444 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 445 - write!( 446 - f, 447 - "{}\t{}\t{}", 448 - self.id, 449 - self.title.trim(), 450 - self.body.replace('\n', " ").replace('\r', "") 451 - ) 452 } 453 } 454 ··· 470 } 471 } 472 473 #[cfg(test)] 474 mod test { 475 use super::*; ··· 479 let task = SearchTask { 480 id: Id(123), 481 title: "Hello, world".to_string(), 482 - body: "The body of the task.\nAnother line\r\nis here.".to_string(), 483 }; 484 assert_eq!( 485 - "tsk-123\tHello, world\tThe body of the task. Another line is here.", 486 task.to_string() 487 ); 488 }
··· 7 use crate::stack::{StackItem, TaskStack}; 8 use crate::task::parse as parse_task; 9 use crate::{fzf, util}; 10 + use std::collections::{BTreeMap, HashSet, vec_deque}; 11 use std::ffi::OsString; 12 use std::fmt::Display; 13 + use std::fs::{File, remove_file}; 14 use std::io::{BufRead as _, BufReader, Read, Seek, SeekFrom}; 15 use std::ops::Deref; 16 use std::os::unix::fs::symlink; 17 use std::path::PathBuf; 18 + use std::process::{Command, Stdio}; 19 use std::str::FromStr; 20 use std::{fs::OpenOptions, io::Write}; 21 ··· 31 type Err = Error; 32 33 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> { 34 + let upper = s.to_uppercase(); 35 + let s = upper 36 .trim() 37 + .strip_prefix("TSK-") 38 .ok_or(Self::Err::Parse(format!("expected tsk- prefix. Got {s}")))?; 39 Ok(Self(s.parse()?)) 40 } ··· 62 pub enum TaskIdentifier { 63 Id(Id), 64 Relative(u32), 65 + Find { exclude_body: bool, archived: bool }, 66 } 67 68 impl From<Id> for TaskIdentifier { ··· 95 .create(true) 96 .truncate(true) 97 .open(tsk_dir.join("next"))?; 98 + // initialize the next file with ID 1 99 next.write_all(b"1\n")?; 100 Ok(()) 101 } ··· 114 Ok(stack_item.id) 115 } 116 TaskIdentifier::Find { 117 + exclude_body, 118 archived, 119 } => self 120 + .search(None, !exclude_body, archived)? 121 .ok_or(Error::NotSelected), 122 } 123 } ··· 350 workspace: self, 351 }; 352 // search the entirety of a task 353 + Ok(fzf::select::<_, Id, _>( 354 + loader, 355 + [ 356 + "--no-multi-line", 357 + "--accept-nth=1", 358 + "--delimiter=\t", 359 + "--preview=tsk show -T {1}", 360 + "--preview-window=top", 361 + "--ansi", 362 + "--info-command=tsk show -T {1} | head -n1", 363 + "--info=inline-right", 364 + ], 365 + )?) 366 } else { 367 // just search the stack 368 + Ok(fzf::select::<_, Id, _>( 369 + stack, 370 + ["--delimiter=\t", "--accept-nth=1"], 371 + )?) 372 } 373 } 374 ··· 424 Ok(()) 425 } 426 427 + /// Returns a [`SearchTas`] which is plain task data with no file or attrs 428 fn bare(self) -> SearchTask { 429 SearchTask { 430 id: self.id, ··· 441 pub body: String, 442 } 443 444 impl Display for SearchTask { 445 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 446 + write!(f, "{}\t{}", self.id, self.title.trim())?; 447 + if !self.body.is_empty() { 448 + write!(f, "\n\n{}", self.body)?; 449 + } 450 + Ok(()) 451 } 452 } 453 ··· 469 } 470 } 471 472 + fn select_task(input: impl IntoIterator<Item = SearchTask>) -> Result<Option<Id>> { 473 + let mut child = Command::new("cat") 474 + .stderr(Stdio::inherit()) 475 + .stdin(Stdio::piped()) 476 + .stdout(Stdio::piped()) 477 + .spawn()?; 478 + let child_in = child.stdin.as_mut().unwrap(); 479 + for item in input.into_iter() { 480 + writeln!(child_in, "{item}\0")?; 481 + } 482 + let output = child.wait_with_output()?; 483 + if output.stdout.is_empty() { 484 + Ok(None) 485 + } else { 486 + Ok(Some(String::from_utf8(output.stdout)?.parse()?)) 487 + } 488 + } 489 + 490 #[cfg(test)] 491 mod test { 492 use super::*; ··· 496 let task = SearchTask { 497 id: Id(123), 498 title: "Hello, world".to_string(), 499 + body: "The body of the task.\nAnother line is here.".to_string(), 500 }; 501 assert_eq!( 502 + "tsk-123\tHello, world\n\nThe body of the task.\nAnother line is here.", 503 task.to_string() 504 ); 505 }