commit 1b28b30fdd665bfc327ff6021d4b58d1d0d7fc02 Author: Madeleine Date: Tue Feb 21 22:14:29 2023 +0000 🌟 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d81f12e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +/.idea diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..72fcd46 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,833 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "serde", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "clap" +version = "4.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "colored" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" +dependencies = [ + "atty", + "lazy_static", + "winapi", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "csv" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af91f40b7355f82b0a891f50e70399475945bb0b0da4f1700ce60761c9d3e359" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + +[[package]] +name = "cxx" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "itoa" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "csv", + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall", + "thiserror", +] + +[[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + +[[package]] +name = "ryu" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" + +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + +[[package]] +name = "serde" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tasks" +version = "0.1.0" +dependencies = [ + "chrono", + "clap", + "colored", + "dirs", + "prettytable-rs", + "serde", + "serde_json", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] +name = "unicode-ident" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..babfaf3 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "agenda" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde = { version = "1.0.152", features = ["derive"] } +serde_json = { version = "1.0.93" } + +clap = { version = "4.1.1", features = ["derive", "cargo"] } +chrono = { version = "0.4.23", features = ["serde"] } +dirs = "4.0.0" +colored = "2.0.0" +prettytable-rs = "0.10.0" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..32a7992 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Agenda +> Rust command-line task manager for nerds. +⚠️ **Warning:** In progress - however somewhat usable at the moment. The name of this project is also subject to change. diff --git a/src/args.rs b/src/args.rs new file mode 100644 index 0000000..67288d6 --- /dev/null +++ b/src/args.rs @@ -0,0 +1,122 @@ +use clap::{Args, Parser, Subcommand}; + +#[derive(Parser, Debug)] +#[clap(author, version, about)] +pub struct TasksArgs { + #[clap(subcommand)] + pub command: Commands, +} + +#[derive(Subcommand, PartialEq, Debug)] +pub enum Commands { + /// Creates a new task + Add(CreateTask), + /// Deletes a task without completing it + Del(DeleteTask), + /// Deletes all tasks + Clear, + /// Shows info about a task + Show(ShowTask), + /// Marks a task as completed + Done(CompleteTask), + /// Marks a task as active + Start(StartTask), + /// Marks a task as pending + Stop(StopTask), + /// Edit a task with $EDITOR + Edit(EditTask), + /// Modify a task at the cli + Modify(ModifyTask), + /// Passes git commands to the repository + Git(GitExecute), + /// Pull then push to git remote and merge commits + Sync(SyncTasks), + /// Undo a number of commits + Undo(UndoExecute), +} + +#[derive(Args, PartialEq, Debug)] +pub struct CreateTask { + /// Title of the task + pub title: String, + + /// Any notes to help explain/remember the task + #[arg(short, long)] + #[clap(default_value=None)] + pub notes: Option, + + /// Tags for organisation, separated by commas + #[arg(short, long)] + #[clap(default_value=None)] + pub tags: Option, + + /// Date when you want to do the task + #[arg(short, long)] + #[clap(default_value=None)] + pub when: Option, + + /// Deadline when the task has to be in + #[arg(short, long)] + #[clap(default_value=None)] + pub deadline: Option, + + /// The date and time when you want to be reminded + #[arg(short, long)] + #[clap(default_value=None)] + pub reminder: Option, +} +#[derive(Args, PartialEq, Debug)] +pub struct DeleteTask { + /// ID of the task + pub id: usize, +} +#[derive(Args, PartialEq, Debug)] +pub struct ShowTask { + /// ID of the task + #[clap(default_value=None)] + pub id: Option, +} +#[derive(Args, PartialEq, Debug)] +pub struct CompleteTask { + /// ID of the task + pub id: usize, +} +#[derive(Args, PartialEq, Debug)] +pub struct StartTask { + /// ID of the task + pub id: usize, +} +#[derive(Args, PartialEq, Debug)] +pub struct StopTask { + /// ID of the task + pub id: usize, +} +#[derive(Args, PartialEq, Debug)] +pub struct EditTask { + /// ID of the task + pub id: usize, +} +#[derive(Args, PartialEq, Debug)] +pub struct ModifyTask { + /// ID of the task + pub id: usize, + /// Summary of the task + pub summary: String, +} +#[derive(Args, PartialEq, Debug)] +pub struct GitExecute { + /// Git command to run + pub command: String, +} +#[derive(Args, PartialEq, Debug)] +pub struct SyncTasks { + /// Git remote to use + #[clap(default_value="origin")] + pub remote: String, +} +#[derive(Args, PartialEq, Debug)] +pub struct UndoExecute { + /// Number of times to undo + #[clap(default_value="1")] + pub number: String, +} \ No newline at end of file diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..01c0505 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,124 @@ +use crate::args::{TasksArgs, Commands}; +use crate::args::{CreateTask, DeleteTask, ShowTask, StartTask, StopTask, CompleteTask}; +use crate::tasks::{Tasks, Task, Status}; +use prettytable::{Table, Row, row, format}; +use colored::*; + +fn success(msg: String) { + println!("{} {}", "success:".green().bold(), msg); +} + +fn warning(msg: &str) { + println!("{} {}", "warning:".yellow().bold(), msg); +} + +#[allow(dead_code)] +fn error(msg: String) { + println!("{} {}", "error:".red().bold(), msg); + panic!(); +} + +fn task_msg(msg: &str, task: &Task, id: usize) -> String { + format!("{} task: {}({})", msg, task.title.blue(), id.to_string().cyan()) +} + +fn get_task(tasks: &mut Tasks, id: usize) -> Task { + match tasks.get_task(id) { + Ok(task) => task.clone(), + Err(error) => panic!("error: {}", error), + } +} + +fn calc_row(task: &Task, id: usize) -> Row { + if task.status == Status::Complete { + // Generate greyed out rows for complete tasks + Row::from([id.to_string().bright_black().italic(), + task.status.as_string().bright_black().italic(), + task.title.clone().bright_black().italic()]) + } else { + // Generate normal colored rows for uncompleted tasks + Row::from([id.to_string().cyan(), task.status.as_string(), task.title.clone().white()]) + } +} + +pub fn execute(tasks: &mut Tasks, arguments: TasksArgs) -> &mut Tasks { + match arguments.command { + Commands::Add(CreateTask { title, .. }) => { + let task = Task::new(title); + tasks.add(task.clone()); + + let id = tasks.len() - 1; + success(task_msg("created", &task, id)); + } + Commands::Del(DeleteTask { id }) => { + let mut binding = tasks.clone(); + let task = match binding.get_task(id) { + Ok(task) => task, + Err(error) => panic!("error: {}", error), + }; + + tasks.del(id); + success(task_msg("deleted", task, id)); + } + Commands::Show(ShowTask { id }) => { + if id.is_none() { + if tasks.tasks.is_none() { + warning("no tasks available to show") + } else { + // Create the table for printing + let mut table = Table::new(); + table.set_titles(row!["ID".magenta().bold(), "Status".magenta().bold(), "Title".magenta().bold()]); + table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + + // Iterate through each task + let mut id = 0; + for task in tasks.tasks.as_ref().unwrap() { + table.add_row(calc_row(task, id)); + id += 1; + } + + // Print the table + println!("{}", table); + }; + } else { + let id = id.unwrap(); + let task = get_task(&mut tasks.clone(), id); + + // Generate and print the table + let mut table = Table::new(); + table.set_titles(row!["ID".magenta().bold(), "Status".magenta().bold(), "Title".magenta().bold()]); + table.set_format(*format::consts::FORMAT_NO_BORDER_LINE_SEPARATOR); + table.add_row(calc_row(&task, id)); + println!("{}", table) + }; + } + Commands::Done(CompleteTask { id }) => { + let task = get_task(&mut tasks.clone(), id); + + tasks.set_status(id, Status::Complete); + success(task_msg("completed", &task, id)); + } + Commands::Start(StartTask { id }) => { + let task = get_task(&mut tasks.clone(), id); + + tasks.set_status(id, Status::Active); + success(task_msg("started", &task, id)); + } + Commands::Stop(StopTask { id }) => { + let task = get_task(&mut tasks.clone(), id); + + if task.when.is_none() { + tasks.set_status(id, Status::Inbox); + } else { + tasks.set_status(id, Status::Pending); + }; + success(task_msg("stopped", &task, id)); + } + Commands::Clear => { + tasks.clear(); + success(String::from("cleared all tasks")); + } + _ => todo!() + }; + tasks +} \ No newline at end of file diff --git a/src/data.rs b/src/data.rs new file mode 100644 index 0000000..d95d251 --- /dev/null +++ b/src/data.rs @@ -0,0 +1,34 @@ +use std::error::Error; +use std::fs; +use std::path::Path; +use dirs::home_dir; +use serde_json; + +use crate::tasks::Tasks; + + +const TASKS_FILE_PATH: &str = "/.local/share/tasks"; + +pub fn save_tasks>(path: P, tasks: &Tasks) -> Result<(), Box> { + // Convert the tasks to JSON form + let data = serde_json::to_string_pretty(&tasks)?; + + // Write the JSON to the file + fs::write(path, data)?; + + Ok(()) +} + +pub fn load_tasks>(path: P) -> Result> { + // Read JSON from the file + let data = fs::read_to_string(path)?; + + // Load the tasks from JSON form + let tasks: Tasks = serde_json::from_str(&data)?; + + Ok(tasks) +} + +pub fn tasks_file_path() -> String { + format!("{}{}", home_dir().unwrap().to_str().unwrap(), TASKS_FILE_PATH) +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..7a3d287 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,34 @@ +mod tasks; +mod args; +mod data; +mod cli; + +use crate::tasks::Tasks; +use crate::args::TasksArgs; +use std::path::Path; +use clap::Parser; + +fn main() { + // Generate the file path for tasks + let tasks_file_path = data::tasks_file_path(); + + // If the tasks file doesn't exist, create it first + if !Path::new(&tasks_file_path).exists() { + println!("warning: file '~/.local/share/tasks' does not exist. creating.."); + let tasks = Tasks::new(&tasks_file_path); + data::save_tasks(&tasks_file_path, &tasks).unwrap(); + }; + + // Load tasks and check for any errors when loading the tasks + let mut tasks = match data::load_tasks(&tasks_file_path) { + Ok(tasks) => tasks, + Err(_error) => panic!("error: couldn't open file {} - likely corrupted", &tasks_file_path), + }; + + // Parse command line arguments + let arguments = TasksArgs::parse(); + let tasks = cli::execute(&mut tasks, arguments); + + // Save any changes + data::save_tasks(tasks_file_path, &tasks).unwrap() +} diff --git a/src/tasks.rs b/src/tasks.rs new file mode 100644 index 0000000..0fe0944 --- /dev/null +++ b/src/tasks.rs @@ -0,0 +1,110 @@ +use serde::{Deserialize, Serialize}; +use chrono::{DateTime, Utc}; +use colored::*; + + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Tag { + title: String, // The required title of the tag +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] +pub enum Status { + Inbox, + Pending, + Active, + Complete, +} + +impl Status { + pub fn as_string(&self) -> ColoredString { + match self { + Status::Inbox => "📮 Inbox".blue(), + Status::Pending => "🗓️ Pending".yellow(), + Status::Active => "✍️ Active".red(), + Status::Complete => "📗 Complete".green(), + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Task { + pub title: String, // The required title of the task + pub status: Status, // Current status of the task + pub notes: Option, // Any notes to explain the task + pub tags: Option>, // Tasks can be tagged for organisation + pub subtasks: Option>, // Tasks can be hierarchically split into subtasks + pub when: Option>, // The date you want to do the task + pub deadline: Option>, // The latest date the task should be done + pub reminder: Option>, // The datetime a reminder will alert you +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Tasks { + pub path: String, // Where the tasks are stored + pub tasks: Option>, // All the tasks in one vector +} + +impl Task { + pub fn new(title: String) -> Self { + Self { + title, + status: Status::Inbox, + notes: None, + tags: None, + subtasks: None, + when: None, + deadline: None, + reminder: None, + } + } +} + +impl Tasks { + pub fn new(tasks_path: &str) -> Self { + Self { + path: String::from(tasks_path), + tasks: None + } + } + + pub fn get_task(&mut self, id: usize) -> Result<&mut Task, &str> { + if self.tasks.is_none() { + Err("there are no tasks") + } else { + if id >= self.tasks.as_ref().unwrap().len() { + Err("couldn't find task") + } else { + let task = &mut self.tasks.as_mut().unwrap()[id]; + Ok(task) + } + } + } + + #[allow(dead_code)] + pub fn set_status(&mut self, id: usize, status: Status) { + let mut task: &mut Task = self.get_task(id).unwrap(); + task.status = status; + } + + pub fn add(&mut self, task: Task) { + if self.tasks.is_none() { + self.tasks = Some(vec![task]); + } else { + self.tasks.as_mut().unwrap().push(task); + }; + } + + pub fn del(&mut self, id: usize) { + self.tasks.as_mut().unwrap().remove(id); + } + + pub fn len(&self) -> usize { + self.tasks.as_ref().unwrap().len() + } + + pub fn clear(&mut self) { + self.tasks = None; + } +} +