├── .clippy.toml ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── CI.yml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets ├── config.template.toml ├── example_scrot.png ├── ocean_man.mp3 └── tasks └── src ├── assignment_utils.rs ├── default_files.rs ├── fileops_utils.rs ├── main.rs ├── posttask_utils.rs ├── rand_utils.rs ├── settings_util.rs └── ui ├── event.rs └── mod.rs /.clippy.toml: -------------------------------------------------------------------------------- 1 | msrv = "1.56.1" 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: ['https://www.redbubble.com/people/kaulmeartman/shop?asc=u'] 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: serde 10 | versions: 11 | - 1.0.123 12 | - 1.0.124 13 | - dependency-name: tinytemplate 14 | versions: 15 | - 1.2.1 16 | - dependency-name: rand 17 | versions: 18 | - 0.8.3 19 | - dependency-name: termion 20 | versions: 21 | - 1.5.6 22 | - dependency-name: serde_derive 23 | versions: 24 | - 1.0.123 25 | - package-ecosystem: github-actions 26 | directory: "/" 27 | schedule: 28 | interval: daily 29 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: [master] 4 | pull_request: 5 | 6 | name: CI 7 | 8 | jobs: 9 | test: 10 | name: test 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | build: [msrv, stable, beta, nightly, macos] 15 | include: 16 | - build: msrv 17 | os: ubuntu-latest 18 | rust: 1.60.0 19 | - build: stable 20 | os: ubuntu-latest 21 | rust: stable 22 | - build: beta 23 | os: ubuntu-latest 24 | rust: beta 25 | - build: nightly 26 | os: ubuntu-latest 27 | rust: nightly 28 | - build: macos 29 | os: macos-latest 30 | rust: stable 31 | steps: 32 | - name: install system dependencies 33 | if: matrix.os == 'ubuntu-latest' 34 | run: sudo apt-get install libasound2-dev 35 | - uses: actions/checkout@v3 36 | - uses: actions-rs/toolchain@v1 37 | with: 38 | profile: minimal 39 | toolchain: ${{ matrix.rust }} 40 | override: true 41 | - uses: actions-rs/cargo@v1 42 | with: 43 | command: test 44 | args: --all-features 45 | 46 | fmt: 47 | name: format 48 | runs-on: ubuntu-latest 49 | steps: 50 | - uses: actions/checkout@v3 51 | - uses: actions-rs/toolchain@v1 52 | with: 53 | toolchain: nightly 54 | override: true 55 | profile: minimal 56 | components: rustfmt 57 | - uses: actions-rs/cargo@v1 58 | with: 59 | command: fmt 60 | args: --all -- --check 61 | 62 | clippy: 63 | name: lint 64 | runs-on: ubuntu-latest 65 | steps: 66 | - name: install system dependencies 67 | run: sudo apt-get install libasound2-dev 68 | - uses: actions/checkout@v3 69 | - uses: actions-rs/toolchain@v1 70 | with: 71 | toolchain: nightly 72 | override: true 73 | profile: minimal 74 | components: clippy 75 | - uses: actions-rs/clippy-check@v1 76 | with: 77 | token: ${{ secrets.GITHUB_TOKEN }} 78 | args: --all-features --tests --examples 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # These are backup files generated by rustfmt 6 | **/*.rs.bk 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.1.2 2 | * bumped dirs to 3.0 3 | * only allow 'c' and 'r' bindings to do things if app is not paused and is currently on a task 4 | * hanging back on rodio 0.11 until [this](https://github.com/RustAudio/rodio/issues/290) is resolved 5 | * add 'h' to toggle a help menu which describes keypresses 6 | * ROUNDED CORNERS!!! 7 | 8 | ## 1.0.0 9 | * increased the space for help page description 10 | * bumped tui-rs to v0.10 + made TagCtr use ITALICS 11 | * added space between 'DO THIS SHIT' and curr. task 12 | * made the tag counter *italics* 13 | * added 'match' logic for **c r i s p** screen switching 14 | * added 'match' logic for **c r i s p** tag weight decision 15 | * fixed bug in recomputing of tag weights (#19) 16 | * moved update_tag_weights to assignment_utils 17 | * added 's' to toggle a stats menu which describes calculated probability of a given task 18 | * unified highlight symbols 19 | 20 | ## 1.1.0 21 | * made all boxes have the same margin 22 | * add default config/task files if they don't exist (thanks to @javabird25!) 23 | * bump tui version to 0.11 24 | 25 | ## 1.1.1 26 | * error in tinytemplate for default files. rolling back till I fix it 27 | 28 | ## 1.1.2 29 | * bump tui-rs to v0.12 30 | * bump rodio to v0.12 + move some functions around to get it working 31 | * fix tinytemplate default file shenanigans 32 | * removed italics within the tag counter 33 | 34 | ## 1.1.3 35 | * changed tagweight table to use percentages instead of floats 36 | 37 | ## 1.1.4 38 | * removed Cargo.lock from .gitignore 39 | * added some comments to tagweighttable function 40 | * bumped tui-rs to v0.13 41 | * bumped rodio to v0.13 42 | 43 | ## 1.2.0 44 | * bumped tui-rs to v0.14 45 | * modified the task table to use a stateful table in the backend 46 | * bumped serde/serde_derive to 1.0.118 47 | * bumped rand to v0.8 48 | * bumpted tinytemplate to v1.2 49 | * added -c/--config option 50 | * create default config directories if they don't exist & no -c option 51 | 52 | ## 1.2.1 53 | * bumped tinytemplate to v1.2.1 54 | * bumped rand to v0.8.3 55 | * bumped termion to v1.5.6 56 | * bumped serde to v1.0.123 57 | * remove serde_derive as dependency 58 | * formatted code and cleaned up some clippy warnings 59 | 60 | ## 1.2.2 61 | * bumped rodio to v0.14 62 | * bumped config to v0.11.0 63 | * bumped dirs to v3.0.2 64 | * bumped tui to v0.15 65 | * fixed a buttload of clippy warnings... but not all :( 66 | 67 | ## 1.2.3 68 | * bumped clap to vbeta.5 69 | * bumped dirs to v4.0.0 70 | * bumped tui to v0.16 71 | * fixed ALL clippy warnings 72 | 73 | ## 1.3.0 74 | * bumped rodio to v0.16 75 | * bumped clap to v3.2.10 76 | * LOTS of refactoring courtesy of @danieleades. thanks! 77 | * added notifications when gauge is complete 78 | * added notification on what current task is 79 | * added version to clap arguments 80 | * bumped tui to v0.17 and switched to crossterm backend 81 | * BREAKING CHANGE: config file format for sound is now different! check the example under assets/ 82 | * add 0 to keyboard shortcuts 83 | * bumped config to v0.13 84 | * bumped tui to 0.18 85 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "ahash" 7 | version = "0.7.4" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98" 10 | dependencies = [ 11 | "getrandom", 12 | "once_cell", 13 | "version_check", 14 | ] 15 | 16 | [[package]] 17 | name = "aho-corasick" 18 | version = "0.7.19" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" 21 | dependencies = [ 22 | "memchr", 23 | ] 24 | 25 | [[package]] 26 | name = "alsa" 27 | version = "0.6.0" 28 | source = "registry+https://github.com/rust-lang/crates.io-index" 29 | checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b" 30 | dependencies = [ 31 | "alsa-sys", 32 | "bitflags", 33 | "libc", 34 | "nix", 35 | ] 36 | 37 | [[package]] 38 | name = "alsa-sys" 39 | version = "0.3.1" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" 42 | dependencies = [ 43 | "libc", 44 | "pkg-config", 45 | ] 46 | 47 | [[package]] 48 | name = "async-broadcast" 49 | version = "0.4.1" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "6d26004fe83b2d1cd3a97609b21e39f9a31535822210fe83205d2ce48866ea61" 52 | dependencies = [ 53 | "event-listener", 54 | "futures-core", 55 | "parking_lot", 56 | ] 57 | 58 | [[package]] 59 | name = "async-channel" 60 | version = "1.7.1" 61 | source = "registry+https://github.com/rust-lang/crates.io-index" 62 | checksum = "e14485364214912d3b19cc3435dde4df66065127f05fa0d75c712f36f12c2f28" 63 | dependencies = [ 64 | "concurrent-queue", 65 | "event-listener", 66 | "futures-core", 67 | ] 68 | 69 | [[package]] 70 | name = "async-executor" 71 | version = "1.4.1" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965" 74 | dependencies = [ 75 | "async-task", 76 | "concurrent-queue", 77 | "fastrand", 78 | "futures-lite", 79 | "once_cell", 80 | "slab", 81 | ] 82 | 83 | [[package]] 84 | name = "async-io" 85 | version = "1.6.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b" 88 | dependencies = [ 89 | "concurrent-queue", 90 | "futures-lite", 91 | "libc", 92 | "log", 93 | "once_cell", 94 | "parking", 95 | "polling", 96 | "slab", 97 | "socket2", 98 | "waker-fn", 99 | "winapi", 100 | ] 101 | 102 | [[package]] 103 | name = "async-lock" 104 | version = "2.5.0" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6" 107 | dependencies = [ 108 | "event-listener", 109 | ] 110 | 111 | [[package]] 112 | name = "async-recursion" 113 | version = "0.3.2" 114 | source = "registry+https://github.com/rust-lang/crates.io-index" 115 | checksum = "d7d78656ba01f1b93024b7c3a0467f1608e4be67d725749fdcd7d2c7678fd7a2" 116 | dependencies = [ 117 | "proc-macro2", 118 | "quote", 119 | "syn", 120 | ] 121 | 122 | [[package]] 123 | name = "async-task" 124 | version = "4.3.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" 127 | 128 | [[package]] 129 | name = "async-trait" 130 | version = "0.1.52" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" 133 | dependencies = [ 134 | "proc-macro2", 135 | "quote", 136 | "syn", 137 | ] 138 | 139 | [[package]] 140 | name = "atty" 141 | version = "0.2.14" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 144 | dependencies = [ 145 | "hermit-abi", 146 | "libc", 147 | "winapi", 148 | ] 149 | 150 | [[package]] 151 | name = "autocfg" 152 | version = "1.1.0" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 155 | 156 | [[package]] 157 | name = "base64" 158 | version = "0.13.0" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 161 | 162 | [[package]] 163 | name = "bindgen" 164 | version = "0.56.0" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | checksum = "2da379dbebc0b76ef63ca68d8fc6e71c0f13e59432e0987e508c1820e6ab5239" 167 | dependencies = [ 168 | "bitflags", 169 | "cexpr", 170 | "clang-sys", 171 | "lazy_static", 172 | "lazycell", 173 | "peeking_take_while", 174 | "proc-macro2", 175 | "quote", 176 | "regex", 177 | "rustc-hash", 178 | "shlex", 179 | ] 180 | 181 | [[package]] 182 | name = "bitflags" 183 | version = "1.3.2" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 186 | 187 | [[package]] 188 | name = "block" 189 | version = "0.1.6" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 192 | 193 | [[package]] 194 | name = "block-buffer" 195 | version = "0.7.3" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" 198 | dependencies = [ 199 | "block-padding", 200 | "byte-tools", 201 | "byteorder", 202 | "generic-array", 203 | ] 204 | 205 | [[package]] 206 | name = "block-padding" 207 | version = "0.1.5" 208 | source = "registry+https://github.com/rust-lang/crates.io-index" 209 | checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" 210 | dependencies = [ 211 | "byte-tools", 212 | ] 213 | 214 | [[package]] 215 | name = "bumpalo" 216 | version = "3.6.1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe" 219 | 220 | [[package]] 221 | name = "byte-tools" 222 | version = "0.3.1" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" 225 | 226 | [[package]] 227 | name = "byteorder" 228 | version = "1.4.2" 229 | source = "registry+https://github.com/rust-lang/crates.io-index" 230 | checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" 231 | 232 | [[package]] 233 | name = "bytes" 234 | version = "1.0.1" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" 237 | 238 | [[package]] 239 | name = "cache-padded" 240 | version = "1.2.0" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c" 243 | 244 | [[package]] 245 | name = "cassowary" 246 | version = "0.3.0" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 249 | 250 | [[package]] 251 | name = "cc" 252 | version = "1.0.67" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" 255 | dependencies = [ 256 | "jobserver", 257 | ] 258 | 259 | [[package]] 260 | name = "cesu8" 261 | version = "1.1.0" 262 | source = "registry+https://github.com/rust-lang/crates.io-index" 263 | checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" 264 | 265 | [[package]] 266 | name = "cexpr" 267 | version = "0.4.0" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" 270 | dependencies = [ 271 | "nom 5.1.2", 272 | ] 273 | 274 | [[package]] 275 | name = "cfg-if" 276 | version = "1.0.0" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 279 | 280 | [[package]] 281 | name = "chrono" 282 | version = "0.4.19" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 285 | dependencies = [ 286 | "libc", 287 | "num-integer", 288 | "num-traits", 289 | "time 0.1.43", 290 | "winapi", 291 | ] 292 | 293 | [[package]] 294 | name = "clang-sys" 295 | version = "1.1.1" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "f54d78e30b388d4815220c8dd03fea5656b6c6d32adb59e89061552a102f8da1" 298 | dependencies = [ 299 | "glob", 300 | "libc", 301 | "libloading", 302 | ] 303 | 304 | [[package]] 305 | name = "clap" 306 | version = "3.2.22" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "86447ad904c7fb335a790c9d7fe3d0d971dc523b8ccd1561a520de9a85302750" 309 | dependencies = [ 310 | "atty", 311 | "bitflags", 312 | "clap_lex", 313 | "indexmap", 314 | "strsim", 315 | "termcolor", 316 | "textwrap", 317 | ] 318 | 319 | [[package]] 320 | name = "clap_lex" 321 | version = "0.2.4" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" 324 | dependencies = [ 325 | "os_str_bytes", 326 | ] 327 | 328 | [[package]] 329 | name = "claxon" 330 | version = "0.4.3" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" 333 | 334 | [[package]] 335 | name = "combine" 336 | version = "4.5.2" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "cc4369b5e4c0cddf64ad8981c0111e7df4f7078f4d6ba98fb31f2e17c4c57b7e" 339 | dependencies = [ 340 | "bytes", 341 | "memchr", 342 | ] 343 | 344 | [[package]] 345 | name = "concurrent-queue" 346 | version = "1.2.2" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" 349 | dependencies = [ 350 | "cache-padded", 351 | ] 352 | 353 | [[package]] 354 | name = "config" 355 | version = "0.13.1" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "3ea917b74b6edfb5024e3b55d3c8f710b5f4ed92646429601a42e96f0812b31b" 358 | dependencies = [ 359 | "async-trait", 360 | "json5", 361 | "lazy_static", 362 | "nom 7.1.0", 363 | "pathdiff", 364 | "ron", 365 | "rust-ini", 366 | "serde", 367 | "serde_json", 368 | "toml", 369 | "yaml-rust", 370 | ] 371 | 372 | [[package]] 373 | name = "core-foundation-sys" 374 | version = "0.8.3" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 377 | 378 | [[package]] 379 | name = "coreaudio-rs" 380 | version = "0.10.0" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "11894b20ebfe1ff903cbdc52259693389eea03b94918a2def2c30c3bf227ad88" 383 | dependencies = [ 384 | "bitflags", 385 | "coreaudio-sys", 386 | ] 387 | 388 | [[package]] 389 | name = "coreaudio-sys" 390 | version = "0.2.8" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "2b7e3347be6a09b46aba228d6608386739fb70beff4f61e07422da87b0bb31fa" 393 | dependencies = [ 394 | "bindgen", 395 | ] 396 | 397 | [[package]] 398 | name = "cpal" 399 | version = "0.14.0" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "7d466b47cf0ea4100186a7c12d7d0166813dda7cf648553554c9c39c6324841b" 402 | dependencies = [ 403 | "alsa", 404 | "core-foundation-sys", 405 | "coreaudio-rs", 406 | "jni", 407 | "js-sys", 408 | "libc", 409 | "mach", 410 | "ndk 0.7.0", 411 | "ndk-context", 412 | "nix", 413 | "oboe", 414 | "once_cell", 415 | "parking_lot", 416 | "stdweb", 417 | "thiserror", 418 | "web-sys", 419 | "windows 0.37.0", 420 | ] 421 | 422 | [[package]] 423 | name = "crossterm" 424 | version = "0.23.2" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17" 427 | dependencies = [ 428 | "bitflags", 429 | "crossterm_winapi", 430 | "libc", 431 | "mio", 432 | "parking_lot", 433 | "signal-hook", 434 | "signal-hook-mio", 435 | "winapi", 436 | ] 437 | 438 | [[package]] 439 | name = "crossterm_winapi" 440 | version = "0.9.0" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 443 | dependencies = [ 444 | "winapi", 445 | ] 446 | 447 | [[package]] 448 | name = "cty" 449 | version = "0.2.2" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" 452 | 453 | [[package]] 454 | name = "derivative" 455 | version = "2.2.0" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 458 | dependencies = [ 459 | "proc-macro2", 460 | "quote", 461 | "syn", 462 | ] 463 | 464 | [[package]] 465 | name = "digest" 466 | version = "0.8.1" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" 469 | dependencies = [ 470 | "generic-array", 471 | ] 472 | 473 | [[package]] 474 | name = "dirs" 475 | version = "4.0.0" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" 478 | dependencies = [ 479 | "dirs-sys", 480 | ] 481 | 482 | [[package]] 483 | name = "dirs-next" 484 | version = "2.0.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 487 | dependencies = [ 488 | "cfg-if", 489 | "dirs-sys-next", 490 | ] 491 | 492 | [[package]] 493 | name = "dirs-sys" 494 | version = "0.3.6" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" 497 | dependencies = [ 498 | "libc", 499 | "redox_users", 500 | "winapi", 501 | ] 502 | 503 | [[package]] 504 | name = "dirs-sys-next" 505 | version = "0.1.2" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 508 | dependencies = [ 509 | "libc", 510 | "redox_users", 511 | "winapi", 512 | ] 513 | 514 | [[package]] 515 | name = "dlv-list" 516 | version = "0.3.0" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" 519 | 520 | [[package]] 521 | name = "enumflags2" 522 | version = "0.7.5" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" 525 | dependencies = [ 526 | "enumflags2_derive", 527 | "serde", 528 | ] 529 | 530 | [[package]] 531 | name = "enumflags2_derive" 532 | version = "0.7.4" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" 535 | dependencies = [ 536 | "proc-macro2", 537 | "quote", 538 | "syn", 539 | ] 540 | 541 | [[package]] 542 | name = "event-listener" 543 | version = "2.5.3" 544 | source = "registry+https://github.com/rust-lang/crates.io-index" 545 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 546 | 547 | [[package]] 548 | name = "fake-simd" 549 | version = "0.1.2" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" 552 | 553 | [[package]] 554 | name = "fastrand" 555 | version = "1.7.0" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" 558 | dependencies = [ 559 | "instant", 560 | ] 561 | 562 | [[package]] 563 | name = "futures-core" 564 | version = "0.3.25" 565 | source = "registry+https://github.com/rust-lang/crates.io-index" 566 | checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" 567 | 568 | [[package]] 569 | name = "futures-io" 570 | version = "0.3.19" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" 573 | 574 | [[package]] 575 | name = "futures-lite" 576 | version = "1.12.0" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 579 | dependencies = [ 580 | "fastrand", 581 | "futures-core", 582 | "futures-io", 583 | "memchr", 584 | "parking", 585 | "pin-project-lite", 586 | "waker-fn", 587 | ] 588 | 589 | [[package]] 590 | name = "futures-sink" 591 | version = "0.3.19" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" 594 | 595 | [[package]] 596 | name = "futures-task" 597 | version = "0.3.19" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" 600 | 601 | [[package]] 602 | name = "futures-util" 603 | version = "0.3.19" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" 606 | dependencies = [ 607 | "futures-core", 608 | "futures-sink", 609 | "futures-task", 610 | "pin-project-lite", 611 | "pin-utils", 612 | "slab", 613 | ] 614 | 615 | [[package]] 616 | name = "generic-array" 617 | version = "0.12.4" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" 620 | dependencies = [ 621 | "typenum", 622 | ] 623 | 624 | [[package]] 625 | name = "getrandom" 626 | version = "0.2.2" 627 | source = "registry+https://github.com/rust-lang/crates.io-index" 628 | checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" 629 | dependencies = [ 630 | "cfg-if", 631 | "libc", 632 | "wasi 0.10.2+wasi-snapshot-preview1", 633 | ] 634 | 635 | [[package]] 636 | name = "glob" 637 | version = "0.3.0" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" 640 | 641 | [[package]] 642 | name = "hashbrown" 643 | version = "0.9.1" 644 | source = "registry+https://github.com/rust-lang/crates.io-index" 645 | checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" 646 | 647 | [[package]] 648 | name = "hashbrown" 649 | version = "0.12.0" 650 | source = "registry+https://github.com/rust-lang/crates.io-index" 651 | checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" 652 | dependencies = [ 653 | "ahash", 654 | ] 655 | 656 | [[package]] 657 | name = "heck" 658 | version = "0.3.3" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 661 | dependencies = [ 662 | "unicode-segmentation", 663 | ] 664 | 665 | [[package]] 666 | name = "hermit-abi" 667 | version = "0.1.18" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" 670 | dependencies = [ 671 | "libc", 672 | ] 673 | 674 | [[package]] 675 | name = "hex" 676 | version = "0.4.3" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 679 | 680 | [[package]] 681 | name = "hound" 682 | version = "3.4.0" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | checksum = "8a164bb2ceaeff4f42542bdb847c41517c78a60f5649671b2a07312b6e117549" 685 | 686 | [[package]] 687 | name = "indexmap" 688 | version = "1.6.1" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" 691 | dependencies = [ 692 | "autocfg", 693 | "hashbrown 0.9.1", 694 | ] 695 | 696 | [[package]] 697 | name = "instant" 698 | version = "0.1.9" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" 701 | dependencies = [ 702 | "cfg-if", 703 | ] 704 | 705 | [[package]] 706 | name = "itoa" 707 | version = "0.4.7" 708 | source = "registry+https://github.com/rust-lang/crates.io-index" 709 | checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" 710 | 711 | [[package]] 712 | name = "jni" 713 | version = "0.19.0" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" 716 | dependencies = [ 717 | "cesu8", 718 | "combine", 719 | "jni-sys", 720 | "log", 721 | "thiserror", 722 | "walkdir", 723 | ] 724 | 725 | [[package]] 726 | name = "jni-sys" 727 | version = "0.3.0" 728 | source = "registry+https://github.com/rust-lang/crates.io-index" 729 | checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" 730 | 731 | [[package]] 732 | name = "jobserver" 733 | version = "0.1.25" 734 | source = "registry+https://github.com/rust-lang/crates.io-index" 735 | checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" 736 | dependencies = [ 737 | "libc", 738 | ] 739 | 740 | [[package]] 741 | name = "js-sys" 742 | version = "0.3.48" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" 745 | dependencies = [ 746 | "wasm-bindgen", 747 | ] 748 | 749 | [[package]] 750 | name = "json5" 751 | version = "0.4.1" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" 754 | dependencies = [ 755 | "pest", 756 | "pest_derive", 757 | "serde", 758 | ] 759 | 760 | [[package]] 761 | name = "lazy_static" 762 | version = "1.4.0" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 765 | 766 | [[package]] 767 | name = "lazycell" 768 | version = "1.3.0" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 771 | 772 | [[package]] 773 | name = "lewton" 774 | version = "0.10.2" 775 | source = "registry+https://github.com/rust-lang/crates.io-index" 776 | checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" 777 | dependencies = [ 778 | "byteorder", 779 | "ogg", 780 | "tinyvec", 781 | ] 782 | 783 | [[package]] 784 | name = "libc" 785 | version = "0.2.134" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" 788 | 789 | [[package]] 790 | name = "libloading" 791 | version = "0.7.0" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" 794 | dependencies = [ 795 | "cfg-if", 796 | "winapi", 797 | ] 798 | 799 | [[package]] 800 | name = "linked-hash-map" 801 | version = "0.5.4" 802 | source = "registry+https://github.com/rust-lang/crates.io-index" 803 | checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" 804 | 805 | [[package]] 806 | name = "lock_api" 807 | version = "0.4.9" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 810 | dependencies = [ 811 | "autocfg", 812 | "scopeguard", 813 | ] 814 | 815 | [[package]] 816 | name = "log" 817 | version = "0.4.14" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 820 | dependencies = [ 821 | "cfg-if", 822 | ] 823 | 824 | [[package]] 825 | name = "mac-notification-sys" 826 | version = "0.5.6" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "3e72d50edb17756489e79d52eb146927bec8eba9dd48faadf9ef08bca3791ad5" 829 | dependencies = [ 830 | "cc", 831 | "dirs-next", 832 | "objc-foundation", 833 | "objc_id", 834 | "time 0.3.15", 835 | ] 836 | 837 | [[package]] 838 | name = "mach" 839 | version = "0.3.2" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" 842 | dependencies = [ 843 | "libc", 844 | ] 845 | 846 | [[package]] 847 | name = "malloc_buf" 848 | version = "0.0.6" 849 | source = "registry+https://github.com/rust-lang/crates.io-index" 850 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 851 | dependencies = [ 852 | "libc", 853 | ] 854 | 855 | [[package]] 856 | name = "maplit" 857 | version = "1.0.2" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" 860 | 861 | [[package]] 862 | name = "memchr" 863 | version = "2.5.0" 864 | source = "registry+https://github.com/rust-lang/crates.io-index" 865 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 866 | 867 | [[package]] 868 | name = "memoffset" 869 | version = "0.6.5" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 872 | dependencies = [ 873 | "autocfg", 874 | ] 875 | 876 | [[package]] 877 | name = "minimal-lexical" 878 | version = "0.2.1" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 881 | 882 | [[package]] 883 | name = "minimp3" 884 | version = "0.5.1" 885 | source = "registry+https://github.com/rust-lang/crates.io-index" 886 | checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" 887 | dependencies = [ 888 | "minimp3-sys", 889 | "slice-deque", 890 | "thiserror", 891 | ] 892 | 893 | [[package]] 894 | name = "minimp3-sys" 895 | version = "0.3.2" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" 898 | dependencies = [ 899 | "cc", 900 | ] 901 | 902 | [[package]] 903 | name = "mio" 904 | version = "0.8.4" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" 907 | dependencies = [ 908 | "libc", 909 | "log", 910 | "wasi 0.11.0+wasi-snapshot-preview1", 911 | "windows-sys", 912 | ] 913 | 914 | [[package]] 915 | name = "ndk" 916 | version = "0.6.0" 917 | source = "registry+https://github.com/rust-lang/crates.io-index" 918 | checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" 919 | dependencies = [ 920 | "bitflags", 921 | "jni-sys", 922 | "ndk-sys 0.3.0", 923 | "num_enum", 924 | "thiserror", 925 | ] 926 | 927 | [[package]] 928 | name = "ndk" 929 | version = "0.7.0" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" 932 | dependencies = [ 933 | "bitflags", 934 | "jni-sys", 935 | "ndk-sys 0.4.0", 936 | "num_enum", 937 | "raw-window-handle", 938 | "thiserror", 939 | ] 940 | 941 | [[package]] 942 | name = "ndk-context" 943 | version = "0.1.1" 944 | source = "registry+https://github.com/rust-lang/crates.io-index" 945 | checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" 946 | 947 | [[package]] 948 | name = "ndk-sys" 949 | version = "0.3.0" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" 952 | dependencies = [ 953 | "jni-sys", 954 | ] 955 | 956 | [[package]] 957 | name = "ndk-sys" 958 | version = "0.4.0" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "21d83ec9c63ec5bf950200a8e508bdad6659972187b625469f58ef8c08e29046" 961 | dependencies = [ 962 | "jni-sys", 963 | ] 964 | 965 | [[package]] 966 | name = "nix" 967 | version = "0.23.1" 968 | source = "registry+https://github.com/rust-lang/crates.io-index" 969 | checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6" 970 | dependencies = [ 971 | "bitflags", 972 | "cc", 973 | "cfg-if", 974 | "libc", 975 | "memoffset", 976 | ] 977 | 978 | [[package]] 979 | name = "nom" 980 | version = "5.1.2" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" 983 | dependencies = [ 984 | "memchr", 985 | "version_check", 986 | ] 987 | 988 | [[package]] 989 | name = "nom" 990 | version = "7.1.0" 991 | source = "registry+https://github.com/rust-lang/crates.io-index" 992 | checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109" 993 | dependencies = [ 994 | "memchr", 995 | "minimal-lexical", 996 | "version_check", 997 | ] 998 | 999 | [[package]] 1000 | name = "notify-rust" 1001 | version = "4.5.10" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "368e89ea58df747ce88be669ae44e79783c1d30bfd540ad0fc520b3f41f0b3b0" 1004 | dependencies = [ 1005 | "mac-notification-sys", 1006 | "serde", 1007 | "tauri-winrt-notification", 1008 | "zbus", 1009 | "zvariant", 1010 | "zvariant_derive", 1011 | ] 1012 | 1013 | [[package]] 1014 | name = "num-derive" 1015 | version = "0.3.3" 1016 | source = "registry+https://github.com/rust-lang/crates.io-index" 1017 | checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" 1018 | dependencies = [ 1019 | "proc-macro2", 1020 | "quote", 1021 | "syn", 1022 | ] 1023 | 1024 | [[package]] 1025 | name = "num-integer" 1026 | version = "0.1.44" 1027 | source = "registry+https://github.com/rust-lang/crates.io-index" 1028 | checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" 1029 | dependencies = [ 1030 | "autocfg", 1031 | "num-traits", 1032 | ] 1033 | 1034 | [[package]] 1035 | name = "num-traits" 1036 | version = "0.2.14" 1037 | source = "registry+https://github.com/rust-lang/crates.io-index" 1038 | checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" 1039 | dependencies = [ 1040 | "autocfg", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "num_enum" 1045 | version = "0.5.7" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" 1048 | dependencies = [ 1049 | "num_enum_derive", 1050 | ] 1051 | 1052 | [[package]] 1053 | name = "num_enum_derive" 1054 | version = "0.5.7" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" 1057 | dependencies = [ 1058 | "proc-macro-crate", 1059 | "proc-macro2", 1060 | "quote", 1061 | "syn", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "num_threads" 1066 | version = "0.1.6" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" 1069 | dependencies = [ 1070 | "libc", 1071 | ] 1072 | 1073 | [[package]] 1074 | name = "numtoa" 1075 | version = "0.1.0" 1076 | source = "registry+https://github.com/rust-lang/crates.io-index" 1077 | checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" 1078 | 1079 | [[package]] 1080 | name = "objc" 1081 | version = "0.2.7" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 1084 | dependencies = [ 1085 | "malloc_buf", 1086 | ] 1087 | 1088 | [[package]] 1089 | name = "objc-foundation" 1090 | version = "0.1.1" 1091 | source = "registry+https://github.com/rust-lang/crates.io-index" 1092 | checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" 1093 | dependencies = [ 1094 | "block", 1095 | "objc", 1096 | "objc_id", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "objc_id" 1101 | version = "0.1.1" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" 1104 | dependencies = [ 1105 | "objc", 1106 | ] 1107 | 1108 | [[package]] 1109 | name = "oboe" 1110 | version = "0.4.6" 1111 | source = "registry+https://github.com/rust-lang/crates.io-index" 1112 | checksum = "27f63c358b4fa0fbcfefd7c8be5cfc39c08ce2389f5325687e7762a48d30a5c1" 1113 | dependencies = [ 1114 | "jni", 1115 | "ndk 0.6.0", 1116 | "ndk-context", 1117 | "num-derive", 1118 | "num-traits", 1119 | "oboe-sys", 1120 | ] 1121 | 1122 | [[package]] 1123 | name = "oboe-sys" 1124 | version = "0.4.5" 1125 | source = "registry+https://github.com/rust-lang/crates.io-index" 1126 | checksum = "3370abb7372ed744232c12954d920d1a40f1c4686de9e79e800021ef492294bd" 1127 | dependencies = [ 1128 | "cc", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "ogg" 1133 | version = "0.8.0" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" 1136 | dependencies = [ 1137 | "byteorder", 1138 | ] 1139 | 1140 | [[package]] 1141 | name = "once_cell" 1142 | version = "1.15.0" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" 1145 | 1146 | [[package]] 1147 | name = "opaque-debug" 1148 | version = "0.2.3" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" 1151 | 1152 | [[package]] 1153 | name = "ordered-multimap" 1154 | version = "0.4.3" 1155 | source = "registry+https://github.com/rust-lang/crates.io-index" 1156 | checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" 1157 | dependencies = [ 1158 | "dlv-list", 1159 | "hashbrown 0.12.0", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "ordered-stream" 1164 | version = "0.0.1" 1165 | source = "registry+https://github.com/rust-lang/crates.io-index" 1166 | checksum = "44630c059eacfd6e08bdaa51b1db2ce33119caa4ddc1235e923109aa5f25ccb1" 1167 | dependencies = [ 1168 | "futures-core", 1169 | "pin-project-lite", 1170 | ] 1171 | 1172 | [[package]] 1173 | name = "os_str_bytes" 1174 | version = "6.0.0" 1175 | source = "registry+https://github.com/rust-lang/crates.io-index" 1176 | checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64" 1177 | 1178 | [[package]] 1179 | name = "parking" 1180 | version = "2.0.0" 1181 | source = "registry+https://github.com/rust-lang/crates.io-index" 1182 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 1183 | 1184 | [[package]] 1185 | name = "parking_lot" 1186 | version = "0.12.1" 1187 | source = "registry+https://github.com/rust-lang/crates.io-index" 1188 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1189 | dependencies = [ 1190 | "lock_api", 1191 | "parking_lot_core", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "parking_lot_core" 1196 | version = "0.9.3" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" 1199 | dependencies = [ 1200 | "cfg-if", 1201 | "libc", 1202 | "redox_syscall", 1203 | "smallvec", 1204 | "windows-sys", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "pathdiff" 1209 | version = "0.2.1" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" 1212 | 1213 | [[package]] 1214 | name = "pathsep" 1215 | version = "0.1.1" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "fa223c370cb326ed75922e69aef96c669a2021545115bfa9778bb640ea575499" 1218 | 1219 | [[package]] 1220 | name = "peeking_take_while" 1221 | version = "0.1.2" 1222 | source = "registry+https://github.com/rust-lang/crates.io-index" 1223 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 1224 | 1225 | [[package]] 1226 | name = "pest" 1227 | version = "2.1.3" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" 1230 | dependencies = [ 1231 | "ucd-trie", 1232 | ] 1233 | 1234 | [[package]] 1235 | name = "pest_derive" 1236 | version = "2.1.0" 1237 | source = "registry+https://github.com/rust-lang/crates.io-index" 1238 | checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" 1239 | dependencies = [ 1240 | "pest", 1241 | "pest_generator", 1242 | ] 1243 | 1244 | [[package]] 1245 | name = "pest_generator" 1246 | version = "2.1.3" 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" 1248 | checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" 1249 | dependencies = [ 1250 | "pest", 1251 | "pest_meta", 1252 | "proc-macro2", 1253 | "quote", 1254 | "syn", 1255 | ] 1256 | 1257 | [[package]] 1258 | name = "pest_meta" 1259 | version = "2.1.3" 1260 | source = "registry+https://github.com/rust-lang/crates.io-index" 1261 | checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" 1262 | dependencies = [ 1263 | "maplit", 1264 | "pest", 1265 | "sha-1", 1266 | ] 1267 | 1268 | [[package]] 1269 | name = "pin-project-lite" 1270 | version = "0.2.9" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1273 | 1274 | [[package]] 1275 | name = "pin-utils" 1276 | version = "0.1.0" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1279 | 1280 | [[package]] 1281 | name = "pkg-config" 1282 | version = "0.3.19" 1283 | source = "registry+https://github.com/rust-lang/crates.io-index" 1284 | checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" 1285 | 1286 | [[package]] 1287 | name = "polling" 1288 | version = "2.2.0" 1289 | source = "registry+https://github.com/rust-lang/crates.io-index" 1290 | checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" 1291 | dependencies = [ 1292 | "cfg-if", 1293 | "libc", 1294 | "log", 1295 | "wepoll-ffi", 1296 | "winapi", 1297 | ] 1298 | 1299 | [[package]] 1300 | name = "ppv-lite86" 1301 | version = "0.2.10" 1302 | source = "registry+https://github.com/rust-lang/crates.io-index" 1303 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 1304 | 1305 | [[package]] 1306 | name = "proc-macro-crate" 1307 | version = "1.1.0" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" 1310 | dependencies = [ 1311 | "thiserror", 1312 | "toml", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "proc-macro2" 1317 | version = "1.0.47" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" 1320 | dependencies = [ 1321 | "unicode-ident", 1322 | ] 1323 | 1324 | [[package]] 1325 | name = "quick-xml" 1326 | version = "0.23.1" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" 1329 | dependencies = [ 1330 | "memchr", 1331 | ] 1332 | 1333 | [[package]] 1334 | name = "quote" 1335 | version = "1.0.9" 1336 | source = "registry+https://github.com/rust-lang/crates.io-index" 1337 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 1338 | dependencies = [ 1339 | "proc-macro2", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "rand" 1344 | version = "0.8.3" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" 1347 | dependencies = [ 1348 | "libc", 1349 | "rand_chacha", 1350 | "rand_core", 1351 | "rand_hc", 1352 | ] 1353 | 1354 | [[package]] 1355 | name = "rand_chacha" 1356 | version = "0.3.0" 1357 | source = "registry+https://github.com/rust-lang/crates.io-index" 1358 | checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" 1359 | dependencies = [ 1360 | "ppv-lite86", 1361 | "rand_core", 1362 | ] 1363 | 1364 | [[package]] 1365 | name = "rand_core" 1366 | version = "0.6.2" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" 1369 | dependencies = [ 1370 | "getrandom", 1371 | ] 1372 | 1373 | [[package]] 1374 | name = "rand_hc" 1375 | version = "0.3.0" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" 1378 | dependencies = [ 1379 | "rand_core", 1380 | ] 1381 | 1382 | [[package]] 1383 | name = "raw-window-handle" 1384 | version = "0.5.0" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a" 1387 | dependencies = [ 1388 | "cty", 1389 | ] 1390 | 1391 | [[package]] 1392 | name = "redox_syscall" 1393 | version = "0.2.16" 1394 | source = "registry+https://github.com/rust-lang/crates.io-index" 1395 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1396 | dependencies = [ 1397 | "bitflags", 1398 | ] 1399 | 1400 | [[package]] 1401 | name = "redox_termios" 1402 | version = "0.1.2" 1403 | source = "registry+https://github.com/rust-lang/crates.io-index" 1404 | checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" 1405 | dependencies = [ 1406 | "redox_syscall", 1407 | ] 1408 | 1409 | [[package]] 1410 | name = "redox_users" 1411 | version = "0.4.0" 1412 | source = "registry+https://github.com/rust-lang/crates.io-index" 1413 | checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" 1414 | dependencies = [ 1415 | "getrandom", 1416 | "redox_syscall", 1417 | ] 1418 | 1419 | [[package]] 1420 | name = "regex" 1421 | version = "1.6.0" 1422 | source = "registry+https://github.com/rust-lang/crates.io-index" 1423 | checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" 1424 | dependencies = [ 1425 | "aho-corasick", 1426 | "memchr", 1427 | "regex-syntax", 1428 | ] 1429 | 1430 | [[package]] 1431 | name = "regex-syntax" 1432 | version = "0.6.27" 1433 | source = "registry+https://github.com/rust-lang/crates.io-index" 1434 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 1435 | 1436 | [[package]] 1437 | name = "remove_dir_all" 1438 | version = "0.5.3" 1439 | source = "registry+https://github.com/rust-lang/crates.io-index" 1440 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 1441 | dependencies = [ 1442 | "winapi", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "rodio" 1447 | version = "0.16.0" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "eb10b653d5ec0e9411a2e7d46e2c7f4046fd87d35b9955bd73ba4108d69072b5" 1450 | dependencies = [ 1451 | "claxon", 1452 | "cpal", 1453 | "hound", 1454 | "lewton", 1455 | "minimp3", 1456 | ] 1457 | 1458 | [[package]] 1459 | name = "ron" 1460 | version = "0.7.0" 1461 | source = "registry+https://github.com/rust-lang/crates.io-index" 1462 | checksum = "1b861ecaade43ac97886a512b360d01d66be9f41f3c61088b42cedf92e03d678" 1463 | dependencies = [ 1464 | "base64", 1465 | "bitflags", 1466 | "serde", 1467 | ] 1468 | 1469 | [[package]] 1470 | name = "rust-ini" 1471 | version = "0.18.0" 1472 | source = "registry+https://github.com/rust-lang/crates.io-index" 1473 | checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" 1474 | dependencies = [ 1475 | "cfg-if", 1476 | "ordered-multimap", 1477 | ] 1478 | 1479 | [[package]] 1480 | name = "rustc-hash" 1481 | version = "1.1.0" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1484 | 1485 | [[package]] 1486 | name = "rusty-krab-manager" 1487 | version = "1.3.0" 1488 | dependencies = [ 1489 | "chrono", 1490 | "clap", 1491 | "config", 1492 | "dirs", 1493 | "notify-rust", 1494 | "pathsep", 1495 | "rand", 1496 | "rodio", 1497 | "serde", 1498 | "termion", 1499 | "tinytemplate", 1500 | "tui", 1501 | ] 1502 | 1503 | [[package]] 1504 | name = "ryu" 1505 | version = "1.0.5" 1506 | source = "registry+https://github.com/rust-lang/crates.io-index" 1507 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1508 | 1509 | [[package]] 1510 | name = "same-file" 1511 | version = "1.0.6" 1512 | source = "registry+https://github.com/rust-lang/crates.io-index" 1513 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 1514 | dependencies = [ 1515 | "winapi-util", 1516 | ] 1517 | 1518 | [[package]] 1519 | name = "scopeguard" 1520 | version = "1.1.0" 1521 | source = "registry+https://github.com/rust-lang/crates.io-index" 1522 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1523 | 1524 | [[package]] 1525 | name = "serde" 1526 | version = "1.0.123" 1527 | source = "registry+https://github.com/rust-lang/crates.io-index" 1528 | checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" 1529 | dependencies = [ 1530 | "serde_derive", 1531 | ] 1532 | 1533 | [[package]] 1534 | name = "serde_derive" 1535 | version = "1.0.123" 1536 | source = "registry+https://github.com/rust-lang/crates.io-index" 1537 | checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" 1538 | dependencies = [ 1539 | "proc-macro2", 1540 | "quote", 1541 | "syn", 1542 | ] 1543 | 1544 | [[package]] 1545 | name = "serde_json" 1546 | version = "1.0.64" 1547 | source = "registry+https://github.com/rust-lang/crates.io-index" 1548 | checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" 1549 | dependencies = [ 1550 | "itoa", 1551 | "ryu", 1552 | "serde", 1553 | ] 1554 | 1555 | [[package]] 1556 | name = "serde_repr" 1557 | version = "0.1.7" 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" 1559 | checksum = "98d0516900518c29efa217c298fa1f4e6c6ffc85ae29fd7f4ee48f176e1a9ed5" 1560 | dependencies = [ 1561 | "proc-macro2", 1562 | "quote", 1563 | "syn", 1564 | ] 1565 | 1566 | [[package]] 1567 | name = "sha-1" 1568 | version = "0.8.2" 1569 | source = "registry+https://github.com/rust-lang/crates.io-index" 1570 | checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" 1571 | dependencies = [ 1572 | "block-buffer", 1573 | "digest", 1574 | "fake-simd", 1575 | "opaque-debug", 1576 | ] 1577 | 1578 | [[package]] 1579 | name = "sha1" 1580 | version = "0.6.1" 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" 1582 | checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" 1583 | dependencies = [ 1584 | "sha1_smol", 1585 | ] 1586 | 1587 | [[package]] 1588 | name = "sha1_smol" 1589 | version = "1.0.0" 1590 | source = "registry+https://github.com/rust-lang/crates.io-index" 1591 | checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" 1592 | 1593 | [[package]] 1594 | name = "shlex" 1595 | version = "0.1.1" 1596 | source = "registry+https://github.com/rust-lang/crates.io-index" 1597 | checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" 1598 | 1599 | [[package]] 1600 | name = "signal-hook" 1601 | version = "0.3.13" 1602 | source = "registry+https://github.com/rust-lang/crates.io-index" 1603 | checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" 1604 | dependencies = [ 1605 | "libc", 1606 | "signal-hook-registry", 1607 | ] 1608 | 1609 | [[package]] 1610 | name = "signal-hook-mio" 1611 | version = "0.2.3" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 1614 | dependencies = [ 1615 | "libc", 1616 | "mio", 1617 | "signal-hook", 1618 | ] 1619 | 1620 | [[package]] 1621 | name = "signal-hook-registry" 1622 | version = "1.4.0" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1625 | dependencies = [ 1626 | "libc", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "slab" 1631 | version = "0.4.5" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" 1634 | 1635 | [[package]] 1636 | name = "slice-deque" 1637 | version = "0.3.0" 1638 | source = "registry+https://github.com/rust-lang/crates.io-index" 1639 | checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" 1640 | dependencies = [ 1641 | "libc", 1642 | "mach", 1643 | "winapi", 1644 | ] 1645 | 1646 | [[package]] 1647 | name = "smallvec" 1648 | version = "1.6.1" 1649 | source = "registry+https://github.com/rust-lang/crates.io-index" 1650 | checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" 1651 | 1652 | [[package]] 1653 | name = "socket2" 1654 | version = "0.4.3" 1655 | source = "registry+https://github.com/rust-lang/crates.io-index" 1656 | checksum = "0f82496b90c36d70af5fcd482edaa2e0bd16fade569de1330405fecbbdac736b" 1657 | dependencies = [ 1658 | "libc", 1659 | "winapi", 1660 | ] 1661 | 1662 | [[package]] 1663 | name = "static_assertions" 1664 | version = "1.1.0" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1667 | 1668 | [[package]] 1669 | name = "stdweb" 1670 | version = "0.1.3" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" 1673 | 1674 | [[package]] 1675 | name = "strsim" 1676 | version = "0.10.0" 1677 | source = "registry+https://github.com/rust-lang/crates.io-index" 1678 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1679 | 1680 | [[package]] 1681 | name = "strum" 1682 | version = "0.22.0" 1683 | source = "registry+https://github.com/rust-lang/crates.io-index" 1684 | checksum = "f7ac893c7d471c8a21f31cfe213ec4f6d9afeed25537c772e08ef3f005f8729e" 1685 | dependencies = [ 1686 | "strum_macros", 1687 | ] 1688 | 1689 | [[package]] 1690 | name = "strum_macros" 1691 | version = "0.22.0" 1692 | source = "registry+https://github.com/rust-lang/crates.io-index" 1693 | checksum = "339f799d8b549e3744c7ac7feb216383e4005d94bdb22561b3ab8f3b808ae9fb" 1694 | dependencies = [ 1695 | "heck", 1696 | "proc-macro2", 1697 | "quote", 1698 | "syn", 1699 | ] 1700 | 1701 | [[package]] 1702 | name = "syn" 1703 | version = "1.0.103" 1704 | source = "registry+https://github.com/rust-lang/crates.io-index" 1705 | checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" 1706 | dependencies = [ 1707 | "proc-macro2", 1708 | "quote", 1709 | "unicode-ident", 1710 | ] 1711 | 1712 | [[package]] 1713 | name = "tauri-winrt-notification" 1714 | version = "0.1.0" 1715 | source = "registry+https://github.com/rust-lang/crates.io-index" 1716 | checksum = "c58de036c4d2e20717024de2a3c4bf56c301f07b21bc8ef9b57189fce06f1f3b" 1717 | dependencies = [ 1718 | "quick-xml", 1719 | "strum", 1720 | "windows 0.39.0", 1721 | ] 1722 | 1723 | [[package]] 1724 | name = "tempfile" 1725 | version = "3.3.0" 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" 1727 | checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" 1728 | dependencies = [ 1729 | "cfg-if", 1730 | "fastrand", 1731 | "libc", 1732 | "redox_syscall", 1733 | "remove_dir_all", 1734 | "winapi", 1735 | ] 1736 | 1737 | [[package]] 1738 | name = "termcolor" 1739 | version = "1.1.2" 1740 | source = "registry+https://github.com/rust-lang/crates.io-index" 1741 | checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" 1742 | dependencies = [ 1743 | "winapi-util", 1744 | ] 1745 | 1746 | [[package]] 1747 | name = "termion" 1748 | version = "1.5.6" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e" 1751 | dependencies = [ 1752 | "libc", 1753 | "numtoa", 1754 | "redox_syscall", 1755 | "redox_termios", 1756 | ] 1757 | 1758 | [[package]] 1759 | name = "textwrap" 1760 | version = "0.15.1" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16" 1763 | 1764 | [[package]] 1765 | name = "thiserror" 1766 | version = "1.0.24" 1767 | source = "registry+https://github.com/rust-lang/crates.io-index" 1768 | checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" 1769 | dependencies = [ 1770 | "thiserror-impl", 1771 | ] 1772 | 1773 | [[package]] 1774 | name = "thiserror-impl" 1775 | version = "1.0.24" 1776 | source = "registry+https://github.com/rust-lang/crates.io-index" 1777 | checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" 1778 | dependencies = [ 1779 | "proc-macro2", 1780 | "quote", 1781 | "syn", 1782 | ] 1783 | 1784 | [[package]] 1785 | name = "time" 1786 | version = "0.1.43" 1787 | source = "registry+https://github.com/rust-lang/crates.io-index" 1788 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 1789 | dependencies = [ 1790 | "libc", 1791 | "winapi", 1792 | ] 1793 | 1794 | [[package]] 1795 | name = "time" 1796 | version = "0.3.15" 1797 | source = "registry+https://github.com/rust-lang/crates.io-index" 1798 | checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" 1799 | dependencies = [ 1800 | "libc", 1801 | "num_threads", 1802 | ] 1803 | 1804 | [[package]] 1805 | name = "tinytemplate" 1806 | version = "1.2.1" 1807 | source = "registry+https://github.com/rust-lang/crates.io-index" 1808 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" 1809 | dependencies = [ 1810 | "serde", 1811 | "serde_json", 1812 | ] 1813 | 1814 | [[package]] 1815 | name = "tinyvec" 1816 | version = "1.1.1" 1817 | source = "registry+https://github.com/rust-lang/crates.io-index" 1818 | checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" 1819 | dependencies = [ 1820 | "tinyvec_macros", 1821 | ] 1822 | 1823 | [[package]] 1824 | name = "tinyvec_macros" 1825 | version = "0.1.0" 1826 | source = "registry+https://github.com/rust-lang/crates.io-index" 1827 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1828 | 1829 | [[package]] 1830 | name = "toml" 1831 | version = "0.5.8" 1832 | source = "registry+https://github.com/rust-lang/crates.io-index" 1833 | checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" 1834 | dependencies = [ 1835 | "serde", 1836 | ] 1837 | 1838 | [[package]] 1839 | name = "tracing" 1840 | version = "0.1.37" 1841 | source = "registry+https://github.com/rust-lang/crates.io-index" 1842 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1843 | dependencies = [ 1844 | "cfg-if", 1845 | "pin-project-lite", 1846 | "tracing-attributes", 1847 | "tracing-core", 1848 | ] 1849 | 1850 | [[package]] 1851 | name = "tracing-attributes" 1852 | version = "0.1.23" 1853 | source = "registry+https://github.com/rust-lang/crates.io-index" 1854 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 1855 | dependencies = [ 1856 | "proc-macro2", 1857 | "quote", 1858 | "syn", 1859 | ] 1860 | 1861 | [[package]] 1862 | name = "tracing-core" 1863 | version = "0.1.30" 1864 | source = "registry+https://github.com/rust-lang/crates.io-index" 1865 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1866 | dependencies = [ 1867 | "once_cell", 1868 | ] 1869 | 1870 | [[package]] 1871 | name = "tui" 1872 | version = "0.18.0" 1873 | source = "registry+https://github.com/rust-lang/crates.io-index" 1874 | checksum = "96fe69244ec2af261bced1d9046a6fee6c8c2a6b0228e59e5ba39bc8ba4ed729" 1875 | dependencies = [ 1876 | "bitflags", 1877 | "cassowary", 1878 | "crossterm", 1879 | "unicode-segmentation", 1880 | "unicode-width", 1881 | ] 1882 | 1883 | [[package]] 1884 | name = "typenum" 1885 | version = "1.15.0" 1886 | source = "registry+https://github.com/rust-lang/crates.io-index" 1887 | checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" 1888 | 1889 | [[package]] 1890 | name = "ucd-trie" 1891 | version = "0.1.3" 1892 | source = "registry+https://github.com/rust-lang/crates.io-index" 1893 | checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" 1894 | 1895 | [[package]] 1896 | name = "uds_windows" 1897 | version = "1.0.2" 1898 | source = "registry+https://github.com/rust-lang/crates.io-index" 1899 | checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" 1900 | dependencies = [ 1901 | "tempfile", 1902 | "winapi", 1903 | ] 1904 | 1905 | [[package]] 1906 | name = "unicode-ident" 1907 | version = "1.0.5" 1908 | source = "registry+https://github.com/rust-lang/crates.io-index" 1909 | checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" 1910 | 1911 | [[package]] 1912 | name = "unicode-segmentation" 1913 | version = "1.7.1" 1914 | source = "registry+https://github.com/rust-lang/crates.io-index" 1915 | checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" 1916 | 1917 | [[package]] 1918 | name = "unicode-width" 1919 | version = "0.1.8" 1920 | source = "registry+https://github.com/rust-lang/crates.io-index" 1921 | checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" 1922 | 1923 | [[package]] 1924 | name = "version_check" 1925 | version = "0.9.2" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" 1928 | 1929 | [[package]] 1930 | name = "waker-fn" 1931 | version = "1.1.0" 1932 | source = "registry+https://github.com/rust-lang/crates.io-index" 1933 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 1934 | 1935 | [[package]] 1936 | name = "walkdir" 1937 | version = "2.3.1" 1938 | source = "registry+https://github.com/rust-lang/crates.io-index" 1939 | checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" 1940 | dependencies = [ 1941 | "same-file", 1942 | "winapi", 1943 | "winapi-util", 1944 | ] 1945 | 1946 | [[package]] 1947 | name = "wasi" 1948 | version = "0.10.2+wasi-snapshot-preview1" 1949 | source = "registry+https://github.com/rust-lang/crates.io-index" 1950 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 1951 | 1952 | [[package]] 1953 | name = "wasi" 1954 | version = "0.11.0+wasi-snapshot-preview1" 1955 | source = "registry+https://github.com/rust-lang/crates.io-index" 1956 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1957 | 1958 | [[package]] 1959 | name = "wasm-bindgen" 1960 | version = "0.2.71" 1961 | source = "registry+https://github.com/rust-lang/crates.io-index" 1962 | checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" 1963 | dependencies = [ 1964 | "cfg-if", 1965 | "wasm-bindgen-macro", 1966 | ] 1967 | 1968 | [[package]] 1969 | name = "wasm-bindgen-backend" 1970 | version = "0.2.71" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" 1973 | dependencies = [ 1974 | "bumpalo", 1975 | "lazy_static", 1976 | "log", 1977 | "proc-macro2", 1978 | "quote", 1979 | "syn", 1980 | "wasm-bindgen-shared", 1981 | ] 1982 | 1983 | [[package]] 1984 | name = "wasm-bindgen-macro" 1985 | version = "0.2.71" 1986 | source = "registry+https://github.com/rust-lang/crates.io-index" 1987 | checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" 1988 | dependencies = [ 1989 | "quote", 1990 | "wasm-bindgen-macro-support", 1991 | ] 1992 | 1993 | [[package]] 1994 | name = "wasm-bindgen-macro-support" 1995 | version = "0.2.71" 1996 | source = "registry+https://github.com/rust-lang/crates.io-index" 1997 | checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" 1998 | dependencies = [ 1999 | "proc-macro2", 2000 | "quote", 2001 | "syn", 2002 | "wasm-bindgen-backend", 2003 | "wasm-bindgen-shared", 2004 | ] 2005 | 2006 | [[package]] 2007 | name = "wasm-bindgen-shared" 2008 | version = "0.2.71" 2009 | source = "registry+https://github.com/rust-lang/crates.io-index" 2010 | checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" 2011 | 2012 | [[package]] 2013 | name = "web-sys" 2014 | version = "0.3.48" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" 2017 | dependencies = [ 2018 | "js-sys", 2019 | "wasm-bindgen", 2020 | ] 2021 | 2022 | [[package]] 2023 | name = "wepoll-ffi" 2024 | version = "0.1.2" 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" 2026 | checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" 2027 | dependencies = [ 2028 | "cc", 2029 | ] 2030 | 2031 | [[package]] 2032 | name = "winapi" 2033 | version = "0.3.9" 2034 | source = "registry+https://github.com/rust-lang/crates.io-index" 2035 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2036 | dependencies = [ 2037 | "winapi-i686-pc-windows-gnu", 2038 | "winapi-x86_64-pc-windows-gnu", 2039 | ] 2040 | 2041 | [[package]] 2042 | name = "winapi-i686-pc-windows-gnu" 2043 | version = "0.4.0" 2044 | source = "registry+https://github.com/rust-lang/crates.io-index" 2045 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2046 | 2047 | [[package]] 2048 | name = "winapi-util" 2049 | version = "0.1.5" 2050 | source = "registry+https://github.com/rust-lang/crates.io-index" 2051 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 2052 | dependencies = [ 2053 | "winapi", 2054 | ] 2055 | 2056 | [[package]] 2057 | name = "winapi-x86_64-pc-windows-gnu" 2058 | version = "0.4.0" 2059 | source = "registry+https://github.com/rust-lang/crates.io-index" 2060 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2061 | 2062 | [[package]] 2063 | name = "windows" 2064 | version = "0.37.0" 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" 2066 | checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647" 2067 | dependencies = [ 2068 | "windows_aarch64_msvc 0.37.0", 2069 | "windows_i686_gnu 0.37.0", 2070 | "windows_i686_msvc 0.37.0", 2071 | "windows_x86_64_gnu 0.37.0", 2072 | "windows_x86_64_msvc 0.37.0", 2073 | ] 2074 | 2075 | [[package]] 2076 | name = "windows" 2077 | version = "0.39.0" 2078 | source = "registry+https://github.com/rust-lang/crates.io-index" 2079 | checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" 2080 | dependencies = [ 2081 | "windows_aarch64_msvc 0.39.0", 2082 | "windows_i686_gnu 0.39.0", 2083 | "windows_i686_msvc 0.39.0", 2084 | "windows_x86_64_gnu 0.39.0", 2085 | "windows_x86_64_msvc 0.39.0", 2086 | ] 2087 | 2088 | [[package]] 2089 | name = "windows-sys" 2090 | version = "0.36.1" 2091 | source = "registry+https://github.com/rust-lang/crates.io-index" 2092 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 2093 | dependencies = [ 2094 | "windows_aarch64_msvc 0.36.1", 2095 | "windows_i686_gnu 0.36.1", 2096 | "windows_i686_msvc 0.36.1", 2097 | "windows_x86_64_gnu 0.36.1", 2098 | "windows_x86_64_msvc 0.36.1", 2099 | ] 2100 | 2101 | [[package]] 2102 | name = "windows_aarch64_msvc" 2103 | version = "0.36.1" 2104 | source = "registry+https://github.com/rust-lang/crates.io-index" 2105 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 2106 | 2107 | [[package]] 2108 | name = "windows_aarch64_msvc" 2109 | version = "0.37.0" 2110 | source = "registry+https://github.com/rust-lang/crates.io-index" 2111 | checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" 2112 | 2113 | [[package]] 2114 | name = "windows_aarch64_msvc" 2115 | version = "0.39.0" 2116 | source = "registry+https://github.com/rust-lang/crates.io-index" 2117 | checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" 2118 | 2119 | [[package]] 2120 | name = "windows_i686_gnu" 2121 | version = "0.36.1" 2122 | source = "registry+https://github.com/rust-lang/crates.io-index" 2123 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 2124 | 2125 | [[package]] 2126 | name = "windows_i686_gnu" 2127 | version = "0.37.0" 2128 | source = "registry+https://github.com/rust-lang/crates.io-index" 2129 | checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" 2130 | 2131 | [[package]] 2132 | name = "windows_i686_gnu" 2133 | version = "0.39.0" 2134 | source = "registry+https://github.com/rust-lang/crates.io-index" 2135 | checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" 2136 | 2137 | [[package]] 2138 | name = "windows_i686_msvc" 2139 | version = "0.36.1" 2140 | source = "registry+https://github.com/rust-lang/crates.io-index" 2141 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 2142 | 2143 | [[package]] 2144 | name = "windows_i686_msvc" 2145 | version = "0.37.0" 2146 | source = "registry+https://github.com/rust-lang/crates.io-index" 2147 | checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" 2148 | 2149 | [[package]] 2150 | name = "windows_i686_msvc" 2151 | version = "0.39.0" 2152 | source = "registry+https://github.com/rust-lang/crates.io-index" 2153 | checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" 2154 | 2155 | [[package]] 2156 | name = "windows_x86_64_gnu" 2157 | version = "0.36.1" 2158 | source = "registry+https://github.com/rust-lang/crates.io-index" 2159 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 2160 | 2161 | [[package]] 2162 | name = "windows_x86_64_gnu" 2163 | version = "0.37.0" 2164 | source = "registry+https://github.com/rust-lang/crates.io-index" 2165 | checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" 2166 | 2167 | [[package]] 2168 | name = "windows_x86_64_gnu" 2169 | version = "0.39.0" 2170 | source = "registry+https://github.com/rust-lang/crates.io-index" 2171 | checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" 2172 | 2173 | [[package]] 2174 | name = "windows_x86_64_msvc" 2175 | version = "0.36.1" 2176 | source = "registry+https://github.com/rust-lang/crates.io-index" 2177 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 2178 | 2179 | [[package]] 2180 | name = "windows_x86_64_msvc" 2181 | version = "0.37.0" 2182 | source = "registry+https://github.com/rust-lang/crates.io-index" 2183 | checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" 2184 | 2185 | [[package]] 2186 | name = "windows_x86_64_msvc" 2187 | version = "0.39.0" 2188 | source = "registry+https://github.com/rust-lang/crates.io-index" 2189 | checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" 2190 | 2191 | [[package]] 2192 | name = "yaml-rust" 2193 | version = "0.4.5" 2194 | source = "registry+https://github.com/rust-lang/crates.io-index" 2195 | checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" 2196 | dependencies = [ 2197 | "linked-hash-map", 2198 | ] 2199 | 2200 | [[package]] 2201 | name = "zbus" 2202 | version = "2.3.2" 2203 | source = "registry+https://github.com/rust-lang/crates.io-index" 2204 | checksum = "2d8f1a037b2c4a67d9654dc7bdfa8ff2e80555bbefdd3c1833c1d1b27c963a6b" 2205 | dependencies = [ 2206 | "async-broadcast", 2207 | "async-channel", 2208 | "async-executor", 2209 | "async-io", 2210 | "async-lock", 2211 | "async-recursion", 2212 | "async-task", 2213 | "async-trait", 2214 | "byteorder", 2215 | "derivative", 2216 | "dirs", 2217 | "enumflags2", 2218 | "event-listener", 2219 | "futures-core", 2220 | "futures-sink", 2221 | "futures-util", 2222 | "hex", 2223 | "lazy_static", 2224 | "nix", 2225 | "once_cell", 2226 | "ordered-stream", 2227 | "rand", 2228 | "serde", 2229 | "serde_repr", 2230 | "sha1", 2231 | "static_assertions", 2232 | "tracing", 2233 | "uds_windows", 2234 | "winapi", 2235 | "zbus_macros", 2236 | "zbus_names", 2237 | "zvariant", 2238 | ] 2239 | 2240 | [[package]] 2241 | name = "zbus_macros" 2242 | version = "2.3.2" 2243 | source = "registry+https://github.com/rust-lang/crates.io-index" 2244 | checksum = "1f8fb5186d1c87ae88cf234974c240671238b4a679158ad3b94ec465237349a6" 2245 | dependencies = [ 2246 | "proc-macro-crate", 2247 | "proc-macro2", 2248 | "quote", 2249 | "regex", 2250 | "syn", 2251 | ] 2252 | 2253 | [[package]] 2254 | name = "zbus_names" 2255 | version = "2.2.0" 2256 | source = "registry+https://github.com/rust-lang/crates.io-index" 2257 | checksum = "41a408fd8a352695690f53906dc7fd036be924ec51ea5e05666ff42685ed0af5" 2258 | dependencies = [ 2259 | "serde", 2260 | "static_assertions", 2261 | "zvariant", 2262 | ] 2263 | 2264 | [[package]] 2265 | name = "zvariant" 2266 | version = "3.7.1" 2267 | source = "registry+https://github.com/rust-lang/crates.io-index" 2268 | checksum = "b794fb7f59af4105697b0449ba31731ee5dbb3e773a17dbdf3d36206ea1b1644" 2269 | dependencies = [ 2270 | "byteorder", 2271 | "enumflags2", 2272 | "libc", 2273 | "serde", 2274 | "static_assertions", 2275 | "zvariant_derive", 2276 | ] 2277 | 2278 | [[package]] 2279 | name = "zvariant_derive" 2280 | version = "3.7.1" 2281 | source = "registry+https://github.com/rust-lang/crates.io-index" 2282 | checksum = "dd58d4b6c8e26d3dd2149c8c40c6613ef6451b9885ff1296d1ac86c388351a54" 2283 | dependencies = [ 2284 | "proc-macro-crate", 2285 | "proc-macro2", 2286 | "quote", 2287 | "syn", 2288 | ] 2289 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rusty-krab-manager" 3 | version = "1.3.0" 4 | authors = ["luak "] 5 | edition = "2018" 6 | readme = "README.md" 7 | license-file = "./LICENSE" 8 | description = """ 9 | Time management TUI inspired by the pomodoro technique as described by Francesco Cirillo 10 | """ 11 | homepage = "https://github.com/aryakaul/rusty-krab-manager" 12 | repository = "https://github.com/aryakaul/rusty-krab-manager" 13 | documentation = "https://github.com/aryakaul/rusty-krab-manager/wiki" 14 | keywords = ["time-management", "tui", "rusty-krab-manager"] 15 | categories = ["command-line-utilities"] 16 | exclude = ["example/*"] 17 | 18 | 19 | [dependencies] 20 | rand = "0.8.3" 21 | chrono = "0.4" 22 | tui = "0.18" 23 | termion = "1.5.6" 24 | config = "0.13" 25 | rodio = "0.16" 26 | dirs = "4.0" 27 | pathsep = "0.1" 28 | tinytemplate = "1.2.1" 29 | serde ={ version = "1.0.123", features = ["derive"] } 30 | clap = "3.2.10" 31 | notify-rust = "4.5.10" 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | ETHICAL LICENSE 2 | Version 2, 01 March 2020 3 | 4 | Copyright (C) 2020 Arya Kaul 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The power of open-source software is considerable and growing 11 | more apparent. As a developer, I cannot help but feel a certain 12 | obligation towards how my work is used and extended by others. 13 | While the vast majority of cases are happily acceptable by myself, 14 | there are significant exceptions. For my own peace of mind, this 15 | license is meant to speak to these exceptions in a way that passes 16 | legal muster. 17 | 18 | The precise terms and conditions for copying, distribution and 19 | modification software licensed under this license follow. 20 | 21 | TERMS AND CONDITIONS 22 | 23 | 0. Definitions. 24 | 25 | "This License" refers to version 1 of the Ethical License. 26 | 27 | "Copyright" also means copyright-like laws that apply to other kinds of 28 | works, such as semiconductor masks. 29 | 30 | "The Program" refers to any copyrightable work licensed under this 31 | License. Each licensee is addressed as "you". "Licensees" and 32 | "recipients" may be individuals or organizations. 33 | 34 | To "modify" a work means to copy from or adapt all or part of the work 35 | in a fashion requiring copyright permission, other than the making of an 36 | exact copy. The resulting work is called a "modified version" of the 37 | earlier work or a work "based on" the earlier work. 38 | 39 | A "covered work" means either the unmodified Program or a work based 40 | on the Program. 41 | 42 | To "propagate" a work means to do anything with it that, without 43 | permission, would make you directly or secondarily liable for 44 | infringement under applicable copyright law, except executing it on a 45 | computer or modifying a private copy. Propagation includes copying, 46 | distribution (with or without modification), making available to the 47 | public, and in some countries other activities as well. 48 | 49 | To "convey" a work means any kind of propagation that enables other 50 | parties to make or receive copies. Mere interaction with a user through 51 | a computer network, with no transfer of a copy, is not conveying. 52 | 53 | An interactive user interface displays "Appropriate Legal Notices" 54 | to the extent that it includes a convenient and prominently visible 55 | feature that (1) displays an appropriate copyright notice, and (2) 56 | tells the user that there is no warranty for the work (except to the 57 | extent that warranties are provided), that licensees may convey the 58 | work under this License, and how to view a copy of this License. If 59 | the interface presents a list of user commands or options, such as a 60 | menu, a prominent item in the list meets this criterion. 61 | 62 | 1. Source Code. 63 | 64 | The "source code" for a work means the preferred form of the work 65 | for making modifications to it. "Object code" means any non-source 66 | form of a work. 67 | 68 | A "Standard Interface" means an interface that either is an official 69 | standard defined by a recognized standards body, or, in the case of 70 | interfaces specified for a particular programming language, one that 71 | is widely used among developers working in that language. 72 | 73 | The "System Libraries" of an executable work include anything, other 74 | than the work as a whole, that (a) is included in the normal form of 75 | packaging a Major Component, but which is not part of that Major 76 | Component, and (b) serves only to enable use of the work with that 77 | Major Component, or to implement a Standard Interface for which an 78 | implementation is available to the public in source code form. A 79 | "Major Component", in this context, means a major essential component 80 | (kernel, window system, and so on) of the specific operating system 81 | (if any) on which the executable work runs, or a compiler used to 82 | produce the work, or an object code interpreter used to run it. 83 | 84 | The "Corresponding Source" for a work in object code form means all 85 | the source code needed to generate, install, and (for an executable 86 | work) run the object code and to modify the work, including scripts to 87 | control those activities. However, it does not include the work's 88 | System Libraries, or general-purpose tools or generally available free 89 | programs which are used unmodified in performing those activities but 90 | which are not part of the work. For example, Corresponding Source 91 | includes interface definition files associated with source files for 92 | the work, and the source code for shared libraries and dynamically 93 | linked subprograms that the work is specifically designed to require, 94 | such as by intimate data communication or control flow between those 95 | subprograms and other parts of the work. 96 | 97 | The Corresponding Source need not include anything that users 98 | can regenerate automatically from other parts of the Corresponding 99 | Source. 100 | 101 | The Corresponding Source for a work in source code form is that 102 | same work. 103 | 104 | 2. Basic Permissions. 105 | 106 | All rights granted under this License are granted for the term of 107 | copyright on the Program, and are irrevocable provided the stated 108 | conditions are met. This License explicitly affirms your unlimited 109 | permission to run the unmodified Program. The output from running a 110 | covered work is covered by this License only if the output, given its 111 | content, constitutes a covered work. This License acknowledges your 112 | rights of fair use or other equivalent, as provided by copyright law. 113 | 114 | You may make, run and propagate covered works that you do not 115 | convey, without conditions so long as your license otherwise remains 116 | in force. You may convey covered works to others for the sole purpose 117 | of having them make modifications exclusively for you, or provide you 118 | with facilities for running those works, provided that you comply with 119 | the terms of this License in conveying all material for which you do 120 | not control copyright. Those thus making or running the covered works 121 | for you must do so exclusively on your behalf, under your direction 122 | and control, on terms that prohibit them from making any copies of 123 | your copyrighted material outside their relationship with you. 124 | 125 | Conveying under any other circumstances is permitted solely under 126 | the conditions stated below. Sublicensing is not allowed; section 10 127 | makes it unnecessary. 128 | 129 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 130 | 131 | No covered work shall be deemed part of an effective technological 132 | measure under any applicable law fulfilling obligations under article 133 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 134 | similar laws prohibiting or restricting circumvention of such 135 | measures. 136 | 137 | When you convey a covered work, you waive any legal power to forbid 138 | circumvention of technological measures to the extent such circumvention 139 | is effected by exercising rights under this License with respect to 140 | the covered work, and you disclaim any intention to limit operation or 141 | modification of the work as a means of enforcing, against the work's 142 | users, your or third parties' legal rights to forbid circumvention of 143 | technological measures. 144 | 145 | 4. Conveying Verbatim Copies. 146 | 147 | You may convey verbatim copies of the Program's source code as you 148 | receive it, in any medium, provided that you conspicuously and 149 | appropriately publish on each copy an appropriate copyright notice; 150 | keep intact all notices stating that this License and any 151 | non-permissive terms added in accord with section 7 apply to the code; 152 | keep intact all notices of the absence of any warranty; and give all 153 | recipients a copy of this License along with the Program. 154 | 155 | You may charge any price or no price for each copy that you convey, 156 | and you may offer support or warranty protection for a fee. 157 | 158 | 5. Conveying Modified Source Versions. 159 | 160 | You may convey a work based on the Program, or the modifications to 161 | produce it from the Program, in the form of source code under the 162 | terms of section 4, provided that you also meet all of these conditions: 163 | 164 | a) The work must carry prominent notices stating that you modified 165 | it, and giving a relevant date. 166 | 167 | b) The work must carry prominent notices stating that it is 168 | released under this License and any conditions added under section 169 | 7. This requirement modifies the requirement in section 4 to 170 | "keep intact all notices". 171 | 172 | c) You must license the entire work, as a whole, under this 173 | License to anyone who comes into possession of a copy. This 174 | License will therefore apply, along with any applicable section 7 175 | additional terms, to the whole of the work, and all its parts, 176 | regardless of how they are packaged. This License gives no 177 | permission to license the work in any other way, but it does not 178 | invalidate such permission if you have separately received it. 179 | 180 | d) If the work has interactive user interfaces, each must display 181 | Appropriate Legal Notices; however, if the Program has interactive 182 | interfaces that do not display Appropriate Legal Notices, your 183 | work need not make them do so. 184 | 185 | A compilation of a covered work with other separate and independent 186 | works, which are not by their nature extensions of the covered work, 187 | and which are not combined with it such as to form a larger program, 188 | in or on a volume of a storage or distribution medium, is called an 189 | "aggregate" if the compilation and its resulting copyright are not 190 | used to limit the access or legal rights of the compilation's users 191 | beyond what the individual works permit. Inclusion of a covered work 192 | in an aggregate does not cause this License to apply to the other 193 | parts of the aggregate. 194 | 195 | 6. Conveying Non-Source Forms. 196 | 197 | You may convey a covered work in object code form under the terms 198 | of sections 4 and 5, provided that you also convey the 199 | machine-readable Corresponding Source under the terms of this License, 200 | in one of these ways: 201 | 202 | a) Convey the object code in, or embodied in, a physical product 203 | (including a physical distribution medium), accompanied by the 204 | Corresponding Source fixed on a durable physical medium 205 | customarily used for software interchange. 206 | 207 | b) Convey the object code in, or embodied in, a physical product 208 | (including a physical distribution medium), accompanied by a 209 | written offer, valid for at least three years and valid for as 210 | long as you offer spare parts or customer support for that product 211 | model, to give anyone who possesses the object code either (1) a 212 | copy of the Corresponding Source for all the software in the 213 | product that is covered by this License, on a durable physical 214 | medium customarily used for software interchange, for a price no 215 | more than your reasonable cost of physically performing this 216 | conveying of source, or (2) access to copy the 217 | Corresponding Source from a network server at no charge. 218 | 219 | c) Convey individual copies of the object code with a copy of the 220 | written offer to provide the Corresponding Source. This 221 | alternative is allowed only occasionally and noncommercially, and 222 | only if you received the object code with such an offer, in accord 223 | with subsection 6b. 224 | 225 | d) Convey the object code by offering access from a designated 226 | place (gratis or for a charge), and offer equivalent access to the 227 | Corresponding Source in the same way through the same place at no 228 | further charge. You need not require recipients to copy the 229 | Corresponding Source along with the object code. If the place to 230 | copy the object code is a network server, the Corresponding Source 231 | may be on a different server (operated by you or a third party) 232 | that supports equivalent copying facilities, provided you maintain 233 | clear directions next to the object code saying where to find the 234 | Corresponding Source. Regardless of what server hosts the 235 | Corresponding Source, you remain obligated to ensure that it is 236 | available for as long as needed to satisfy these requirements. 237 | 238 | e) Convey the object code using peer-to-peer transmission, provided 239 | you inform other peers where the object code and Corresponding 240 | Source of the work are being offered to the general public at no 241 | charge under subsection 6d. 242 | 243 | A separable portion of the object code, whose source code is excluded 244 | from the Corresponding Source as a System Library, need not be 245 | included in conveying the object code work. 246 | 247 | A "User Product" is either (1) a "consumer product", which means any 248 | tangible personal property which is normally used for personal, family, 249 | or household purposes, or (2) anything designed or sold for incorporation 250 | into a dwelling. In determining whether a product is a consumer product, 251 | doubtful cases shall be resolved in favor of coverage. For a particular 252 | product received by a particular user, "normally used" refers to a 253 | typical or common use of that class of product, regardless of the status 254 | of the particular user or of the way in which the particular user 255 | actually uses, or expects or is expected to use, the product. A product 256 | is a consumer product regardless of whether the product has substantial 257 | commercial, industrial or non-consumer uses, unless such uses represent 258 | the only significant mode of use of the product. 259 | 260 | "Installation Information" for a User Product means any methods, 261 | procedures, authorization keys, or other information required to install 262 | and execute modified versions of a covered work in that User Product from 263 | a modified version of its Corresponding Source. The information must 264 | suffice to ensure that the continued functioning of the modified object 265 | code is in no case prevented or interfered with solely because 266 | modification has been made. 267 | 268 | If you convey an object code work under this section in, or with, or 269 | specifically for use in, a User Product, and the conveying occurs as 270 | part of a transaction in which the right of possession and use of the 271 | User Product is transferred to the recipient in perpetuity or for a 272 | fixed term (regardless of how the transaction is characterized), the 273 | Corresponding Source conveyed under this section must be accompanied 274 | by the Installation Information. But this requirement does not apply 275 | if neither you nor any third party retains the ability to install 276 | modified object code on the User Product (for example, the work has 277 | been installed in ROM). 278 | 279 | The requirement to provide Installation Information does not include a 280 | requirement to continue to provide support service, warranty, or updates 281 | for a work that has been modified or installed by the recipient, or for 282 | the User Product in which it has been modified or installed. Access to a 283 | network may be denied when the modification itself materially and 284 | adversely affects the operation of the network or violates the rules and 285 | protocols for communication across the network. 286 | 287 | Corresponding Source conveyed, and Installation Information provided, 288 | in accord with this section must be in a format that is publicly 289 | documented (and with an implementation available to the public in 290 | source code form), and must require no special password or key for 291 | unpacking, reading or copying. 292 | 293 | 7. Additional Terms. 294 | 295 | "Additional permissions" are terms that supplement the terms of this 296 | License by making exceptions from one or more of its conditions. The 297 | following additional permissions apply to the program and derivatives 298 | of it: 299 | 300 | a) The program may not be used in applications and services that 301 | are used for or aid in the exploration, extraction, refinement, 302 | processing, or transportation of fossil fuels. 303 | b) The program may not be used in applications and services that 304 | are used for or aid in the surveillance, subjugation, or interrogation 305 | of a group of individual(s). 306 | c) The program may not be used in applications and services that 307 | are used for or aid in the marketing of goods and/or services to 308 | a group of individual(s). 309 | 310 | 8. Termination. 311 | 312 | You may not propagate or modify a covered work except as expressly 313 | provided under this License. Any attempt otherwise to propagate or 314 | modify it is void, and will automatically terminate your rights under 315 | this License (including any patent licenses granted under the third 316 | paragraph of section 11). 317 | 318 | However, if you cease all violation of this License, then your 319 | license from a particular copyright holder is reinstated (a) 320 | provisionally, unless and until the copyright holder explicitly and 321 | finally terminates your license, and (b) permanently, if the copyright 322 | holder fails to notify you of the violation by some reasonable means 323 | prior to 60 days after the cessation. 324 | 325 | Moreover, your license from a particular copyright holder is 326 | reinstated permanently if the copyright holder notifies you of the 327 | violation by some reasonable means, this is the first time you have 328 | received notice of violation of this License (for any work) from that 329 | copyright holder, and you cure the violation prior to 30 days after 330 | your receipt of the notice. 331 | 332 | Termination of your rights under this section does not terminate the 333 | licenses of parties who have received copies or rights from you under 334 | this License. If your rights have been terminated and not permanently 335 | reinstated, you do not qualify to receive new licenses for the same 336 | material under section 10. 337 | 338 | 9. Acceptance Not Required for Having Copies. 339 | 340 | You are not required to accept this License in order to receive or 341 | run a copy of the Program. Ancillary propagation of a covered work 342 | occurring solely as a consequence of using peer-to-peer transmission 343 | to receive a copy likewise does not require acceptance. However, 344 | nothing other than this License grants you permission to propagate or 345 | modify any covered work. These actions infringe copyright if you do 346 | not accept this License. Therefore, by modifying or propagating a 347 | covered work, you indicate your acceptance of this License to do so. 348 | 349 | 10. Automatic Licensing of Downstream Recipients. 350 | 351 | Each time you convey a covered work, the recipient automatically 352 | receives a license from the original licensors, to run, modify and 353 | propagate that work, subject to this License. You are not responsible 354 | for enforcing compliance by third parties with this License. 355 | 356 | An "entity transaction" is a transaction transferring control of an 357 | organization, or substantially all assets of one, or subdividing an 358 | organization, or merging organizations. If propagation of a covered 359 | work results from an entity transaction, each party to that 360 | transaction who receives a copy of the work also receives whatever 361 | licenses to the work the party's predecessor in interest had or could 362 | give under the previous paragraph, plus a right to possession of the 363 | Corresponding Source of the work from the predecessor in interest, if 364 | the predecessor has it or can get it with reasonable efforts. 365 | 366 | You may not impose any further restrictions on the exercise of the 367 | rights granted or affirmed under this License. For example, you may 368 | not impose a license fee, royalty, or other charge for exercise of 369 | rights granted under this License, and you may not initiate litigation 370 | (including a cross-claim or counterclaim in a lawsuit) alleging that 371 | any patent claim is infringed by making, using, selling, offering for 372 | sale, or importing the Program or any portion of it. 373 | 374 | 11. Patents. 375 | 376 | A "contributor" is a copyright holder who authorizes use under this 377 | License of the Program or a work on which the Program is based. The 378 | work thus licensed is called the contributor's "contributor version". 379 | 380 | A contributor's "essential patent claims" are all patent claims 381 | owned or controlled by the contributor, whether already acquired or 382 | hereafter acquired, that would be infringed by some manner, permitted 383 | by this License, of making, using, or selling its contributor version, 384 | but do not include claims that would be infringed only as a 385 | consequence of further modification of the contributor version. For 386 | purposes of this definition, "control" includes the right to grant 387 | patent sublicenses in a manner consistent with the requirements of 388 | this License. 389 | 390 | Each contributor grants you a non-exclusive, worldwide, royalty-free 391 | patent license under the contributor's essential patent claims, to 392 | make, use, sell, offer for sale, import and otherwise run, modify and 393 | propagate the contents of its contributor version. 394 | 395 | In the following three paragraphs, a "patent license" is any express 396 | agreement or commitment, however denominated, not to enforce a patent 397 | (such as an express permission to practice a patent or covenant not to 398 | sue for patent infringement). To "grant" such a patent license to a 399 | party means to make such an agreement or commitment not to enforce a 400 | patent against the party. 401 | 402 | If you convey a covered work, knowingly relying on a patent license, 403 | and the Corresponding Source of the work is not available for anyone 404 | to copy, free of charge and under the terms of this License, through a 405 | publicly available network server or other readily accessible means, 406 | then you must either (1) cause the Corresponding Source to be so 407 | available, or (2) arrange to deprive yourself of the benefit of the 408 | patent license for this particular work, or (3) arrange, in a manner 409 | consistent with the requirements of this License, to extend the patent 410 | license to downstream recipients. "Knowingly relying" means you have 411 | actual knowledge that, but for the patent license, your conveying the 412 | covered work in a country, or your recipient's use of the covered work 413 | in a country, would infringe one or more identifiable patents in that 414 | country that you have reason to believe are valid. 415 | 416 | If, pursuant to or in connection with a single transaction or 417 | arrangement, you convey, or propagate by procuring conveyance of, a 418 | covered work, and grant a patent license to some of the parties 419 | receiving the covered work authorizing them to use, propagate, modify 420 | or convey a specific copy of the covered work, then the patent license 421 | you grant is automatically extended to all recipients of the covered 422 | work and works based on it. 423 | 424 | A patent license is "discriminatory" if it does not include within 425 | the scope of its coverage, prohibits the exercise of, or is 426 | conditioned on the non-exercise of one or more of the rights that are 427 | specifically granted under this License. You may not convey a covered 428 | work if you are a party to an arrangement with a third party that is 429 | in the business of distributing software, under which you make payment 430 | to the third party based on the extent of your activity of conveying 431 | the work, and under which the third party grants, to any of the 432 | parties who would receive the covered work from you, a discriminatory 433 | patent license (a) in connection with copies of the covered work 434 | conveyed by you (or copies made from those copies), or (b) primarily 435 | for and in connection with specific products or compilations that 436 | contain the covered work, unless you entered into that arrangement, 437 | or that patent license was granted, prior to 28 March 2007. 438 | 439 | Nothing in this License shall be construed as excluding or limiting 440 | any implied license or other defenses to infringement that may 441 | otherwise be available to you under applicable patent law. 442 | 443 | 12. No Surrender of Others' Freedom. 444 | 445 | If conditions are imposed on you (whether by court order, agreement or 446 | otherwise) that contradict the conditions of this License, they do not 447 | excuse you from the conditions of this License. If you cannot convey a 448 | covered work so as to satisfy simultaneously your obligations under this 449 | License and any other pertinent obligations, then as a consequence you may 450 | not convey it at all. For example, if you agree to terms that obligate you 451 | to collect a royalty for further conveying from those to whom you convey 452 | the Program, the only way you could satisfy both those terms and this 453 | License would be to refrain entirely from conveying the Program. 454 | 455 | 13. Penalties 456 | 457 | Violations of any of the terms and conditions included in the License 458 | will lead to the following penalties administered under the supervision 459 | of a adminster of justice: 460 | 461 | a) Robert Downey Jr. dressed in an Iron Man suit will poke the 462 | offender with a long stick 463 | b) The offender will have to bake two large apple pies. The first, 464 | will be thrown in the offender's face by the initial License holder. 465 | The second will be eaten by the initial License holder. 466 | c) The offender will be forced to write 'I will not break License 467 | agreements' on a chalkboard a total of 5,901 times. 468 | d) The offender will have to get a tattoo in a location and design 469 | to the exact specifications of the initial License holder. 470 | e) The offender will donate 1,000,000,000,000 United States dollars 471 | to a charity of the initial License holder's choosing. 472 | 473 | 14. Disclaimer of Warranty. 474 | 475 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 476 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 477 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 478 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 479 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 480 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 481 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 482 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 483 | 484 | 15. Limitation of Liability. 485 | 486 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 487 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 488 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 489 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 490 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 491 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 492 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 493 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 494 | SUCH DAMAGES. 495 | 496 | 16. Interpretation of Sections 14 and 15. 497 | 498 | If the disclaimer of warranty and limitation of liability provided 499 | above cannot be given local legal effect according to their terms, 500 | reviewing courts shall apply local law that most closely approximates 501 | an absolute waiver of all civil liability in connection with the 502 | Program, unless a warranty or assumption of liability accompanies a 503 | copy of the Program in return for a fee. 504 | 505 | END OF TERMS AND CONDITIONS 506 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

rusty-krab-manager

2 |

3 | Crate Status 4 | Crates.io 5 | CI 6 |

7 | 8 |

9 | 10 |

🕰️ - let spongebob manage your time

11 | 12 | 13 | The rusty-krab-manager is a terminal user interface written in Rust designed to facilitate task management with inspiration from the pomodoro technique developed by Francesco Cirillo. [See it in action here!](https://www.reddit.com/r/unixporn/comments/isqa9v/oc_task_management_tui_written_in_rust_using_the/) 14 | 15 | img 16 | 17 | ### More: \[[Installation](https://github.com/aryakaul/rusty-krab-manager/wiki/Installation)\] \[[Configuration](https://github.com/aryakaul/rusty-krab-manager/wiki/Configuration)\] \[[Usage](https://github.com/aryakaul/rusty-krab-manager/wiki/Usage)\] \[[FAQ](https://github.com/aryakaul/rusty-krab-manager/wiki/FAQ)\] 18 | 19 | 20 | Note: This was my first experience coding in Rust so it is extremely likely there are things that could be done better. As a result, any and all pull requests are welcome! 21 | 22 | BIG THANKS to [tui-rs](https://github.com/fdehau/tui-rs) 23 | -------------------------------------------------------------------------------- /assets/config.template.toml: -------------------------------------------------------------------------------- 1 | # this is an example configuration 2 | 3 | # path to the task file 4 | task_filepath = "{task_filepath}" 5 | 6 | # put tags for each assignment. Order dictates the rest 7 | #tags = [ "rando-projects", "schoolwork", "personal" ] 8 | tags = [ "school", "job", "personal" ] 9 | 10 | # boolean to indicate if we should use due dates to weight the assignments 11 | ## when 'true' assignments due earlier will have a higher probability of 12 | ## being pulled. When 'false' equal weight to all assignments 13 | use_due_dates = [ false, true, false ] 14 | 15 | # timings for tasks/breaks/longbreaks in minutes 16 | short_break_time = 1 17 | long_break_time = 5 18 | task_time = 20 19 | 20 | # number of small breaks before big break 21 | maxno_short_breaks = 2 22 | 23 | [sound] 24 | # path to notification sound 25 | file = "{sound_filepath}" 26 | volume = 0.3 27 | 28 | # weights for each tag project are broken down by day of the week. 29 | ## i.e. if you have two tags: ["schoolwork", "personal"] and weights 30 | ## on monday are given as [0.8, 0.2] then a new assignment from the 31 | ## schoolwork tag will be given with 80% probability, and a new one 32 | ## from the homework tag will be given with 20% probability 33 | [weights] 34 | mon = [ 0.2, 0.7, 0.1 ] 35 | tue = [ 0.4, 0.5, 0.1 ] 36 | wed = [ 0.6, 0.3, 0.1 ] 37 | thu = [ 0.7, 0.2, 0.1 ] 38 | fri = [ 0.6, 0.4, 0.0 ] 39 | sat = [ 0.2, 0.3, 0.5 ] 40 | sun = [ 0.3, 0.2, 0.5 ] 41 | -------------------------------------------------------------------------------- /assets/example_scrot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aryakaul/rusty-krab-manager/0c39de264eaf06253c25b4e4150085c879f128b4/assets/example_scrot.png -------------------------------------------------------------------------------- /assets/ocean_man.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aryakaul/rusty-krab-manager/0c39de264eaf06253c25b4e4150085c879f128b4/assets/ocean_man.mp3 -------------------------------------------------------------------------------- /assets/tasks: -------------------------------------------------------------------------------- 1 | # Fill this file with your tasks. 2 | # Each tasks consists of three fields separated by commas: task tag, description and due date. 3 | # 4 | # Task tags are defined in your configuration file by the "tags" setting. 5 | # Descriptions should not contain commas as they will be interpreted as field separators. 6 | # Due dates should be in "year-month-day hour:minure" format. 7 | # Any trailing whitespace symbols will be removed. 8 | # 9 | # Example: 10 | # 11 | # schoolwork, Genetics Problem Set, 2019-12-10 12:20 12 | # schoolwork, Make presentation, 2019-12-20 12:00 13 | # other, work on rust program, 2020-02-29 13:00 14 | # other, wrap present for gf, 2019-02-11 14:00 15 | # other, memes, 2019-10-02 22:00 16 | # 17 | # Lines starting with "#" are considered comments and will be ignored. 18 | # Malformed tasks (tasks with fields more or less than 3 fields) and overdue tasks will be ignored as well. 19 | school, Problem Set 📜, 2050-10-12 10:00 20 | school, Learn how to grow tomatoes 🍅, 2050-09-12 10:00 21 | job, Code the thing 🖥️, 2050-12-12 10:00 22 | personal, Build a defensible homestead 🏡, 2050-01-01 11:11 23 | -------------------------------------------------------------------------------- /src/assignment_utils.rs: -------------------------------------------------------------------------------- 1 | use super::fileops_utils::lines_from_file; 2 | use chrono::prelude::*; 3 | use std::collections::HashMap; 4 | use std::fmt; 5 | use std::path::Path; 6 | use std::process::exit; 7 | use std::str::FromStr; 8 | 9 | // THESE ARE ALL FUNCTIONS RELATED TO THE ASSIGNMENT 10 | // STRUCTURE 11 | // 12 | 13 | // Define 'Assignment' object 14 | #[derive(Clone)] 15 | pub struct Assignment { 16 | pub name: String, 17 | pub tag: String, 18 | pub due_time: String, 19 | } 20 | 21 | // when I print an Assignment object 22 | // what happens? 23 | impl fmt::Display for Assignment { 24 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 25 | write!(f, "({}, {}, {})", self.name, self.tag, self.due_time) 26 | } 27 | } 28 | 29 | // these are functions related to assignments 30 | impl Assignment { 31 | // Turn the string due date associated with a task 32 | // to the DateTime object associated with the chrono function 33 | // note that we always assume Local timezone. 34 | pub fn convert_due_date(&self) -> DateTime { 35 | let convert_due_date = Local.datetime_from_str(&self.due_time, "%Y-%m-%d %H:%M"); 36 | match convert_due_date { 37 | Ok(convert_due_date) => convert_due_date, 38 | _ => panic!("{}", &self.due_time), 39 | } 40 | } 41 | } 42 | 43 | impl FromStr for Assignment { 44 | type Err = &'static str; 45 | 46 | fn from_str(s: &str) -> Result { 47 | let task_vec: Vec<&str> = s.split(',').collect(); 48 | 49 | // ignore all lines in todo list that do not have 3 50 | // fields or that start with '#' 51 | if task_vec.len() != 3 || task_vec[0].starts_with('#') { 52 | return Err("invalid!"); 53 | } 54 | let tag = task_vec[0].trim(); 55 | let name = task_vec[1].trim(); 56 | let due_date = task_vec[2].trim(); 57 | Ok(Self { 58 | name: String::from(name), 59 | tag: String::from(tag), 60 | due_time: String::from(due_date), 61 | }) 62 | } 63 | } 64 | 65 | // Take all minutes until due from all assignments. Find the 66 | // largest value. Divide that value by all values. 67 | // Sum these values. Use that as the denominator for all 68 | // values. Return this probability distribution. 69 | fn turn_timetilldue_into_pdf(due: Vec) -> Vec { 70 | let biggest = due.iter().max().copied().unwrap_or_default(); 71 | 72 | let mut pdf: Vec = Vec::with_capacity(due.len()); 73 | let mut sum = 0_f64; 74 | 75 | for i in due { 76 | let value = biggest as f64 / i as f64; 77 | pdf.push(value); 78 | sum += value; 79 | } 80 | 81 | for prob in &mut pdf { 82 | *prob /= sum; 83 | } 84 | pdf 85 | } 86 | 87 | // Get the amount of time until a given assignment is due in minutes 88 | pub fn find_timeuntildue(due_date: DateTime) -> i64 { 89 | due_date.signed_duration_since(Local::now()).num_minutes() 90 | } 91 | 92 | // Turn a vector containing all assignments, and return a Vec 93 | // that is your probability density function for each assignment 94 | // the index tracks the same assignment 95 | // pub fn turn_assignmentvector_into_pdf(assign: &Vec, use_due: 96 | // bool) -> Vec { 97 | pub fn turn_assignmentvector_into_pdf(assign: &[Assignment], use_due: bool) -> Vec { 98 | if use_due { 99 | let min_till_due = assign 100 | .iter() 101 | .map(|item| find_timeuntildue(item.convert_due_date())) 102 | .collect(); 103 | turn_timetilldue_into_pdf(min_till_due) 104 | } else { 105 | let uniform_prob: f64 = 1.0 / assign.len() as f64; 106 | return vec![uniform_prob; assign.len()]; 107 | } 108 | } 109 | 110 | // Read in the tasks from the task file path and config tag list 111 | // Convert these into a hashmap linking each tag to a vector of 112 | // assignments associated with that tag 113 | pub fn readin_tasks(filepath: &Path, tag_list: &[String]) -> HashMap> { 114 | let lines = lines_from_file(filepath); 115 | let mut tag_to_taskvectors: HashMap<_, _> = tag_list 116 | .iter() 117 | .map(|tags| (tags.to_string(), Vec::default())) 118 | .collect(); 119 | 120 | for new_assign in lines 121 | .iter() 122 | .filter_map(|line| Assignment::from_str(line).ok()) 123 | .filter(|new_assign| find_timeuntildue(new_assign.convert_due_date()) >= 0) 124 | { 125 | assert!( 126 | tag_to_taskvectors.contains_key(&new_assign.tag), 127 | "Tag shown in task list not described in config: {}", 128 | new_assign.tag 129 | ); 130 | 131 | tag_to_taskvectors 132 | .get_mut(&new_assign.tag) 133 | .unwrap() 134 | .push(new_assign); 135 | } 136 | 137 | if tag_to_taskvectors.iter().all(|tag| tag.1.is_empty()) { 138 | eprintln!( 139 | "The task list is empty, or all tasks in your list are overdue.\nFill the file {} \ 140 | with your tasks.", 141 | filepath.display() 142 | ); 143 | exit(1); 144 | } 145 | 146 | tag_to_taskvectors 147 | } 148 | 149 | // convert the hashmap to a vector of strings 150 | pub fn hashmap_to_taskvector( 151 | tagmap: &HashMap>, 152 | tag_vector: &[String], 153 | ) -> Vec> { 154 | tag_vector 155 | .iter() 156 | .flat_map(|tags| tagmap.get(tags).unwrap()) 157 | .cloned() 158 | .map(|item| vec![item.tag, item.name, item.due_time]) 159 | .collect() 160 | } 161 | 162 | pub fn create_weighttable( 163 | tagmap: &HashMap>, 164 | tag_vector: &[String], 165 | tag_weights: &[f64], 166 | use_dues: &[bool], 167 | ) -> Vec> { 168 | let mut toret = vec![]; 169 | for (i_tags, tags) in tag_vector.iter().enumerate() { 170 | let tag_weight = tag_weights[i_tags]; 171 | let assign_vec = tagmap.get(tags).unwrap(); 172 | let assign_pdf = turn_assignmentvector_into_pdf(assign_vec, use_dues[i_tags]); 173 | for (i, curr_assign) in assign_vec.iter().enumerate() { 174 | let mut new = vec![]; 175 | new.push(curr_assign.tag.clone()); 176 | new.push(curr_assign.name.clone()); 177 | new.push(format!("{:.2}%", tag_weight * 100.0)); 178 | new.push(format!("{:.2}%", assign_pdf[i] * 100.0)); 179 | new.push(format!("{:.2}%", (assign_pdf[i] * tag_weight * 100.0))); 180 | toret.push(new); 181 | } 182 | } 183 | // following code to sort by percentage values 184 | toret.sort_by(|a, b| { 185 | b[4][..b[4].find('%').unwrap()] 186 | .parse::() 187 | .unwrap() 188 | .partial_cmp(&a[4][..a[4].find('%').unwrap()].parse::().unwrap()) 189 | .unwrap() 190 | }); 191 | toret 192 | } 193 | 194 | // convert a given assigment to a string vector with newline characters 195 | pub fn taskvector_to_stringvect(curr_assign: &Assignment) -> Vec { 196 | let mut toret: Vec = Vec::with_capacity(3); 197 | let newline = "\n"; 198 | let mut name = curr_assign.name.clone(); 199 | name.push_str(newline); 200 | let mut tag = curr_assign.tag.clone(); 201 | tag.push_str(newline); 202 | let mut due_date = curr_assign.due_time.clone(); 203 | due_date.push_str(newline); 204 | toret.push(tag); 205 | toret.push(name); 206 | toret.push(due_date); 207 | toret 208 | } 209 | 210 | // Convert the vector of tags from the config file to a hashmap 211 | // linking each tag to an integer counter 212 | pub fn get_tag_counter_hashmap(tag_vector: &[String]) -> HashMap<&String, i64> { 213 | tag_vector.iter().map(|tag| (tag, 0)).collect() 214 | } 215 | 216 | // Convert the task hashmap counter to a vector of string tuples 217 | // to be displayed. 218 | pub fn convert_hashmap_to_tuplevector( 219 | x: &HashMap<&String, i64>, 220 | tag: &[String], 221 | ) -> Vec<(String, String)> { 222 | let mut toret: Vec<(String, String)> = Vec::new(); 223 | for tags in tag { 224 | let ctr = x.get(tags).unwrap(); 225 | toret.push((tags.to_string(), ctr.to_string())); 226 | } 227 | toret 228 | } 229 | 230 | pub fn update_tagweights( 231 | tag_to_vector_map: &HashMap>, 232 | initial_tag_weights: &[f64], 233 | vector_of_tags: &[String], 234 | ) -> Vec { 235 | let mut updated_tag_weights = initial_tag_weights.to_owned(); 236 | let mut xi: f64 = 0.0; 237 | let mut ctr = 0; 238 | 239 | for (tag, assign_vec) in tag_to_vector_map { 240 | let tag_idx = vector_of_tags.iter().position(|z| z == tag).unwrap(); 241 | let tag_weight = initial_tag_weights[tag_idx]; 242 | if assign_vec.is_empty() || tag_weight == 0.0 { 243 | xi += tag_weight; 244 | updated_tag_weights[tag_idx] = 0.0; 245 | } else { 246 | ctr += 1; 247 | } 248 | } 249 | let to_add = xi / f64::from(ctr); 250 | for item in updated_tag_weights.iter_mut().take(vector_of_tags.len()) { 251 | if *item != 0.0 { 252 | *item += to_add; 253 | } 254 | } 255 | updated_tag_weights.clone() 256 | } 257 | -------------------------------------------------------------------------------- /src/default_files.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | use std::fs::File; 3 | use std::io::Write; 4 | use std::path::Path; 5 | use tinytemplate::TinyTemplate; 6 | 7 | // Create files required for operation if they don't exist, such as: 8 | // 1. Config ($CONFIG/rusty-krab-manager/config.toml) 9 | // 2. "Ocean man" ($CONFIG/rusty-krab-manager/ocean_man.mp3) 10 | // 3. Tasks ($HOME/rusty-krab-manager-tasks.txt) 11 | pub fn create() { 12 | let mut config_subdir = dirs::config_dir().unwrap(); 13 | config_subdir.push("rusty-krab-manager"); 14 | 15 | let config_filepath = config_subdir.join("config.toml"); 16 | let sound_filepath = config_subdir.join("ocean_man.mp3"); 17 | let task_filepath = config_subdir.join("example_tasks.csv"); 18 | 19 | create_default_file( 20 | &config_filepath, 21 | fill_config(&DefaultConfigData { 22 | sound_filepath: sound_filepath.to_str().unwrap().to_string(), 23 | task_filepath: task_filepath.to_str().unwrap().to_string(), 24 | }) 25 | .as_bytes(), 26 | ); 27 | create_default_file( 28 | &sound_filepath, 29 | include_bytes!(concat!( 30 | "..", 31 | path_separator!(), 32 | "assets", 33 | path_separator!(), 34 | "ocean_man.mp3" 35 | )), 36 | ); 37 | create_default_file( 38 | &task_filepath, 39 | include_bytes!(concat!( 40 | "..", 41 | path_separator!(), 42 | "assets", 43 | path_separator!(), 44 | "tasks" 45 | )), 46 | ); 47 | } 48 | 49 | fn create_default_file(filepath: &Path, contents: &[u8]) { 50 | if filepath.exists() { 51 | return; 52 | } 53 | 54 | let mut file = File::create(filepath).unwrap(); 55 | file.write_all(contents).unwrap(); 56 | } 57 | 58 | #[derive(Serialize)] 59 | struct DefaultConfigData { 60 | task_filepath: String, 61 | sound_filepath: String, 62 | } 63 | 64 | fn fill_config(data: &DefaultConfigData) -> String { 65 | const CONFIG_TEMPLATE: &str = include_str!(concat!( 66 | "..", 67 | path_separator!(), 68 | "assets", 69 | path_separator!(), 70 | "config.template.toml" 71 | )); 72 | let mut template = TinyTemplate::new(); 73 | template.add_template("config", CONFIG_TEMPLATE).unwrap(); 74 | template.render("config", &data).unwrap() 75 | } 76 | -------------------------------------------------------------------------------- /src/fileops_utils.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fs::File, 3 | io::{prelude::*, BufReader}, 4 | path::Path, 5 | }; 6 | 7 | // Read in a file and convert that into a vector of 8 | // strings to be parsed 9 | pub fn lines_from_file(filename: &Path) -> Vec { 10 | let file = File::open(filename).expect("no such file"); 11 | let buf = BufReader::new(file); 12 | buf.lines() 13 | .map(|l| l.expect("Could not parse line")) 14 | .collect() 15 | } 16 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod assignment_utils; 2 | mod default_files; 3 | mod fileops_utils; 4 | mod posttask_utils; 5 | mod rand_utils; 6 | mod settings_util; 7 | mod ui; 8 | 9 | use assignment_utils::{ 10 | convert_hashmap_to_tuplevector, create_weighttable, get_tag_counter_hashmap, 11 | hashmap_to_taskvector, readin_tasks, taskvector_to_stringvect, turn_assignmentvector_into_pdf, 12 | update_tagweights, 13 | }; 14 | use clap::ArgMatches; 15 | use rand_utils::roll_die; 16 | use rodio::Sink; 17 | use settings_util::ConfigOptions; 18 | use std::error::Error; 19 | use std::fs; 20 | use std::io; 21 | use std::path::Path; 22 | use termion::event::Key; 23 | use termion::input::MouseTerminal; 24 | use termion::raw::IntoRawMode; 25 | use termion::screen::AlternateScreen; 26 | //use tui::backend::TermionBackend; 27 | use tui::backend::CrosstermBackend; 28 | use tui::layout::{Constraint, Direction, Layout}; 29 | use tui::Terminal; 30 | use ui::event::{Event, Events}; 31 | use ui::{ 32 | draw_current_task, draw_gauge, draw_help, draw_tag_counter, draw_task_table, draw_weights, App, 33 | HelpTable, WeightTable, 34 | }; 35 | 36 | #[macro_use] 37 | extern crate pathsep; 38 | 39 | // this function reads in the task list provided in 40 | // settings and then randomly selects one task to 41 | // perform. the function returns two string vectors. 42 | // one corresponds to the specific task that was 43 | // chosen, and the other corresponds to the updated 44 | // table of tasks to display. these values are fed 45 | // into the UI. 46 | fn choose_task( 47 | // read in tasks 48 | // from the task file, the vector of tags, 49 | // the vector of tag weights, and the 50 | // vector of booleans denoting whether or not to 51 | // use tag weights 52 | configured_task_path: &Path, 53 | vector_of_tags: &[String], 54 | initial_tag_weights: &[f64], 55 | configured_use_of_due_dates: &[bool], 56 | ) -> (Vec, Vec>, Vec>) { 57 | let tag_to_vector_map = readin_tasks(configured_task_path, vector_of_tags); 58 | 59 | let configured_relative_tag_weights = 60 | update_tagweights(&tag_to_vector_map, initial_tag_weights, vector_of_tags); 61 | 62 | let weighttable_vec = create_weighttable( 63 | &tag_to_vector_map, 64 | vector_of_tags, 65 | &configured_relative_tag_weights, 66 | configured_use_of_due_dates, 67 | ); 68 | 69 | // last Vec will become the stats page 70 | // roll a assignment 71 | // first pick a tag to get an assignment from 72 | let tag_roll = roll_die(&configured_relative_tag_weights); 73 | let chosen_tag = &vector_of_tags[tag_roll]; 74 | 75 | // then get the vector of assignments assigned to that tag 76 | let assignvector = tag_to_vector_map.get(chosen_tag).unwrap(); 77 | // turn this into a pdf and roll an assignment 78 | let assignvector_pdf = 79 | turn_assignmentvector_into_pdf(assignvector, configured_use_of_due_dates[tag_roll]); 80 | let chosen_assign = &assignvector[roll_die(&assignvector_pdf)]; 81 | 82 | // generate table string and current task string. this is for the tui 83 | let assign_string = taskvector_to_stringvect(chosen_assign); 84 | let string_alltask_vec = hashmap_to_taskvector(&tag_to_vector_map, vector_of_tags); 85 | (assign_string, string_alltask_vec, weighttable_vec) 86 | } 87 | 88 | fn load_or_create_configuration_file(args: &ArgMatches) -> io::Result { 89 | if let Some(c) = args.value_of("config") { 90 | println!("Value for config: {}", c); 91 | Ok(c.to_string()) 92 | } else { 93 | if let Some(mut config_dir) = dirs::config_dir() { 94 | config_dir.push("rusty-krab-manager"); 95 | if !config_dir.exists() { 96 | println!("Generating config directories..."); 97 | fs::create_dir_all(config_dir)?; 98 | } 99 | } 100 | default_files::create(); 101 | let mut fullpath = dirs::config_dir().unwrap(); 102 | fullpath.push("rusty-krab-manager"); 103 | fullpath.push("config.toml"); 104 | Ok(fullpath.to_str().unwrap().to_string()) 105 | } 106 | } 107 | 108 | fn main() -> Result<(), Box> { 109 | let matches = clap::Command::new("Rusty-Krab-Manager") 110 | .about("Pomodoro inspired TUI task manager") 111 | .author("Arya K.") 112 | .version("X.X") 113 | .arg( 114 | clap::Arg::new("config") 115 | .short('c') 116 | .long("config") 117 | .value_name("FILE") 118 | .help("Path for a config file") 119 | .takes_value(true), 120 | ) 121 | .arg( 122 | clap::Arg::new("mute") 123 | .short('m') 124 | .long("mute") 125 | .help("Do not play sound after ") 126 | .takes_value(true), 127 | ) 128 | .get_matches(); 129 | 130 | let config = load_or_create_configuration_file(&matches)?; 131 | 132 | // set config variables 133 | let ConfigOptions { 134 | task_path, 135 | sound_path, 136 | sound_volume, 137 | tags, 138 | use_due_dates, 139 | initial_tag_weights, 140 | min_break_time, 141 | max_break_time, 142 | task_time, 143 | maxno_min_breaks, 144 | } = settings_util::readin_settings(&config)?; 145 | 146 | // initialize audio sink 147 | let (_stream, stream_handle) = rodio::OutputStream::try_default().unwrap(); 148 | let sink = Sink::try_new(&stream_handle).unwrap(); 149 | sink.set_volume(sound_volume as f32); 150 | 151 | // initialize tag counter 152 | let mut tag_ctr = get_tag_counter_hashmap(&tags); 153 | 154 | // Choose initial task 155 | let (curr_task, items_to_list, weighttable_vec) = 156 | choose_task(&task_path, &tags, &initial_tag_weights, &use_due_dates); 157 | posttask_utils::nextupnotif(&curr_task[1])?; 158 | 159 | // Terminal initialization for UI 160 | let stdout = io::stdout().into_raw_mode()?; 161 | let stdout = MouseTerminal::from(stdout); 162 | let stdout = AlternateScreen::from(stdout); 163 | let backend = CrosstermBackend::new(stdout); 164 | let mut terminal = Terminal::new(backend)?; 165 | terminal.hide_cursor()?; 166 | 167 | let events = Events::new(); 168 | let mut app = App::new(); 169 | app.completed = convert_hashmap_to_tuplevector(&tag_ctr, &tags); 170 | app.current_task = curr_task; 171 | app.items = items_to_list; 172 | 173 | // Initialize starting parameters 174 | let mut min_break_ctr = 0; 175 | let mut its_task_time = true; 176 | let mut its_min_break_time = false; 177 | let mut its_max_break_time = false; 178 | let mut curr_screen = String::from("tasks"); 179 | 180 | // create help table and flag 181 | let mut help_table = HelpTable::new(); 182 | let mut weight_table = WeightTable::new(weighttable_vec); 183 | 184 | // Enter into UI drawing infinite loop 185 | loop { 186 | terminal.draw(|f| match curr_screen.as_str() { 187 | "help" => { 188 | let rects = Layout::default() 189 | .constraints([Constraint::Percentage(100)].as_ref()) 190 | .split(f.size()); 191 | draw_help(f, &mut help_table, rects[0]); 192 | } 193 | "stats" => { 194 | let rects = Layout::default() 195 | .constraints([Constraint::Percentage(100)].as_ref()) 196 | .split(f.size()); 197 | draw_weights(f, &mut weight_table, rects[0]); 198 | } 199 | _ => { 200 | let chunks = Layout::default() 201 | .direction(Direction::Vertical) 202 | .constraints( 203 | [ 204 | Constraint::Percentage(30), 205 | Constraint::Percentage(50), 206 | Constraint::Percentage(20), 207 | ] 208 | .as_ref(), 209 | ) 210 | .split(f.size()); 211 | let mini_chunks = Layout::default() 212 | .direction(Direction::Horizontal) 213 | .constraints([Constraint::Percentage(75), Constraint::Percentage(25)].as_ref()) 214 | .split(chunks[0]); 215 | // draw_gauge(&mut f, &app, chunks[2]); 216 | draw_gauge(f, &app, chunks[2]); 217 | draw_task_table(f, &mut app, chunks[1]); 218 | draw_current_task(f, &app, mini_chunks[0]); 219 | draw_tag_counter(f, &app, mini_chunks[1]); 220 | } 221 | })?; 222 | 223 | // keybindings 224 | match events.next()? { 225 | Event::Input(input) => match input { 226 | // denote the currently selected task as complete and reroll a new one 227 | Key::Char('c') => { 228 | if its_task_time && !app.paused { 229 | let mut fin_task_tag = app.current_task[0].clone(); 230 | fin_task_tag.pop(); 231 | *tag_ctr.get_mut(&fin_task_tag).unwrap() += 1; 232 | app.completed = convert_hashmap_to_tuplevector(&tag_ctr, &tags); 233 | let (curr_task, items_to_list, weighttable_vec) = 234 | choose_task(&task_path, &tags, &initial_tag_weights, &use_due_dates); 235 | posttask_utils::nextupnotif(&curr_task[1])?; 236 | weight_table = WeightTable::new(weighttable_vec); 237 | app.current_task = curr_task; 238 | app.items = items_to_list; 239 | } else { 240 | } 241 | } 242 | 243 | // reroll the currently selected task without marking current task as complete 244 | Key::Char('r') => { 245 | if its_task_time && !app.paused { 246 | let (curr_task, items_to_list, weighttable_vec) = 247 | choose_task(&task_path, &tags, &initial_tag_weights, &use_due_dates); 248 | posttask_utils::nextupnotif(&curr_task[1])?; 249 | weight_table = WeightTable::new(weighttable_vec); 250 | app.current_task = curr_task; 251 | app.items = items_to_list; 252 | } else { 253 | } 254 | } 255 | 256 | // fast forward timer to the end 257 | Key::Char('f') => { 258 | app.progress = 1.0; 259 | } 260 | 261 | // rewind timer to beginning 262 | Key::Char('0') => { 263 | app.progress = 0.0; 264 | } 265 | 266 | // QUIT 267 | Key::Char('q') => { 268 | break; 269 | } 270 | 271 | // pause rkm 272 | Key::Char('p') => { 273 | if app.paused { 274 | app.paused = false; 275 | app.current_task.pop(); 276 | } else { 277 | app.paused = true; 278 | app.current_task.push("PAUSED".to_string()); 279 | } 280 | } 281 | 282 | // move cursor down or up on task table 283 | Key::Down | Key::Char('j') => match curr_screen.as_str() { 284 | "help" => { 285 | help_table.next(); 286 | } 287 | "stats" => { 288 | weight_table.next(); 289 | } 290 | "tasks" => { 291 | app.next(); 292 | } 293 | _ => {} 294 | }, 295 | 296 | Key::Up | Key::Char('k') => match curr_screen.as_str() { 297 | "help" => { 298 | help_table.previous(); 299 | } 300 | "stats" => { 301 | weight_table.previous(); 302 | } 303 | "tasks" => { 304 | app.previous(); 305 | } 306 | _ => {} 307 | }, 308 | 309 | // toggle help screen 310 | Key::Char('h') => match curr_screen.as_str() { 311 | "help" => { 312 | curr_screen = String::from("tasks"); 313 | } 314 | _ => { 315 | curr_screen = String::from("help"); 316 | } 317 | }, 318 | 319 | // toggle stats rkm 320 | Key::Char('s') => match curr_screen.as_str() { 321 | "stats" => { 322 | curr_screen = String::from("tasks"); 323 | } 324 | _ => { 325 | curr_screen = String::from("stats"); 326 | } 327 | }, 328 | 329 | _ => {} 330 | }, 331 | 332 | // what is done every 250 ms? 333 | Event::Tick => { 334 | // if app is paused do nothing. 335 | if app.paused { 336 | 337 | // is it time for a task? 338 | } else if its_task_time { 339 | // is next break a long break? 340 | if min_break_ctr == maxno_min_breaks { 341 | its_max_break_time = app.update(task_time); 342 | //posttask_utils::nextupnotif("Long Chill!")?; 343 | } else { 344 | // otherwise have a small break 345 | its_min_break_time = app.update(task_time); 346 | //posttask_utils::nextupnotif("Short Chill!")?; 347 | } 348 | 349 | // if task time is up. reset task time. increment tag counter 350 | if its_min_break_time || its_max_break_time { 351 | posttask_utils::playsound(&sound_path, &sink)?; 352 | posttask_utils::finishnotif()?; 353 | let mut fin_task_tag = app.current_task[0].clone(); 354 | fin_task_tag.pop(); 355 | *tag_ctr.get_mut(&fin_task_tag).unwrap() += 1; 356 | app.completed = convert_hashmap_to_tuplevector(&tag_ctr, &tags); 357 | its_task_time = false; 358 | }; 359 | 360 | // time for a small break? 361 | } else if its_min_break_time { 362 | app.current_task = vec![String::from("TAKE A CHILL PILL\n")]; 363 | its_task_time = app.update(min_break_time); 364 | 365 | // if small break over, reroll task 366 | if its_task_time { 367 | posttask_utils::playsound(&sound_path, &sink)?; 368 | posttask_utils::finishnotif()?; 369 | min_break_ctr += 1; 370 | let (curr_task, items_to_list, weighttable_vec) = 371 | choose_task(&task_path, &tags, &initial_tag_weights, &use_due_dates); 372 | posttask_utils::nextupnotif(&curr_task[1])?; 373 | weight_table = WeightTable::new(weighttable_vec); 374 | app.current_task = curr_task; 375 | app.items = items_to_list; 376 | its_min_break_time = false; 377 | } 378 | 379 | // time for big break? 380 | } else if its_max_break_time { 381 | app.current_task = vec![String::from("TAKE A LOONG CHILL PILL\n")]; 382 | its_task_time = app.update(max_break_time); 383 | 384 | // if big break over, reroll task 385 | if its_task_time { 386 | posttask_utils::playsound(&sound_path, &sink)?; 387 | posttask_utils::finishnotif()?; 388 | min_break_ctr = 0; 389 | let (curr_task, items_to_list, weighttable_vec) = 390 | choose_task(&task_path, &tags, &initial_tag_weights, &use_due_dates); 391 | posttask_utils::nextupnotif(&curr_task[1])?; 392 | weight_table = WeightTable::new(weighttable_vec); 393 | app.current_task = curr_task; 394 | app.items = items_to_list; 395 | its_max_break_time = false; 396 | } 397 | } 398 | } 399 | }; 400 | } 401 | Ok(()) 402 | } 403 | -------------------------------------------------------------------------------- /src/posttask_utils.rs: -------------------------------------------------------------------------------- 1 | use notify_rust::Notification; 2 | use rodio::decoder::DecoderError; 3 | use rodio::Sink; 4 | use std::error::Error; 5 | use std::fs::File; 6 | use std::io::BufReader; 7 | use std::path::Path; 8 | 9 | // Play a given sound given a file path to that sound and 10 | // a preexisting rodio sink 11 | pub fn playsound(filepath: &Path, sink: &Sink) -> Result<(), DecoderError> { 12 | let file = File::open(filepath).unwrap(); 13 | let source = rodio::Decoder::new(BufReader::new(file))?; 14 | sink.append(source); 15 | sink.play(); 16 | Ok(()) 17 | } 18 | 19 | pub fn finishnotif() -> Result<(), Box> { 20 | Notification::new() 21 | .summary("Rusty-Krab-Manager") 22 | .body("Time is up!") 23 | .icon("clock") 24 | .show()?; 25 | Ok(()) 26 | } 27 | 28 | pub fn nextupnotif(nexttask: &str) -> Result<(), Box> { 29 | Notification::new() 30 | .summary("Rusty-Krab-Manager") 31 | .body(&format!("Now work on: {}", nexttask)) 32 | .icon("clock") 33 | .show()?; 34 | Ok(()) 35 | } 36 | -------------------------------------------------------------------------------- /src/rand_utils.rs: -------------------------------------------------------------------------------- 1 | // utility functions to implement 2 | // RANDOMNESS 3 | // 4 | 5 | use rand::Rng; 6 | 7 | // Take a probability distribution and 8 | // change it to a cumulative distribution 9 | // where the last element is always 1 10 | pub fn make_cdf(pdf: &[f64]) -> Vec { 11 | let error_margin = f64::EPSILON; 12 | let sum: f64 = pdf.iter().sum(); 13 | assert!( 14 | (sum - 1.0).abs() <= error_margin, 15 | "Probability distribution does not sum to 1! Instead sums to {}", 16 | sum as f32 17 | ); 18 | let mut cdf: Vec = Vec::with_capacity(pdf.len()); 19 | cdf.push(pdf[0]); 20 | for idx in 1..pdf.len() { 21 | cdf.push(cdf[idx - 1] + pdf[idx]); 22 | } 23 | cdf 24 | } 25 | 26 | // Given a probability distribution containing n elements 27 | // randomly roll a n-sided die weighted to the probabilities 28 | // given. Return the index of the side that comes up. 29 | pub fn roll_die(pdf: &[f64]) -> usize { 30 | let mut rng = rand::thread_rng(); 31 | let x = rng.gen::(); 32 | let cdf = make_cdf(pdf); 33 | let index = cdf.iter().position(|&r| x < r).unwrap(); 34 | index 35 | } 36 | -------------------------------------------------------------------------------- /src/settings_util.rs: -------------------------------------------------------------------------------- 1 | use chrono::{Datelike, Local}; 2 | use std::collections::HashMap; 3 | use std::error::Error; 4 | use std::path::{Path, PathBuf}; 5 | 6 | // Take the settings file and convert it 7 | // to a series of raw values to be used 8 | 9 | pub struct ConfigOptions { 10 | pub task_path: PathBuf, 11 | pub sound_path: PathBuf, 12 | pub sound_volume: f64, 13 | pub tags: Vec, 14 | pub use_due_dates: Vec, 15 | pub initial_tag_weights: Vec, 16 | pub min_break_time: i64, 17 | pub max_break_time: i64, 18 | pub task_time: i64, 19 | pub maxno_min_breaks: i64, 20 | } 21 | 22 | pub fn readin_settings(config_path: &str) -> Result> { 23 | // Read in configuration 24 | //let mut settings = config::Config::new(); 25 | //settings.merge(config::File::with_name(config_path))?; 26 | 27 | let settings = config::Config::builder() 28 | // Add in `./Settings.toml` 29 | .add_source(config::File::with_name(config_path)) 30 | // Add in settings from the environment (with a prefix of APP) 31 | // Eg.. `APP_DEBUG=1 ./target/app` would set the `debug` key 32 | .add_source(config::Environment::with_prefix("APP")) 33 | .build() 34 | .unwrap(); 35 | 36 | // get the paths to the task file and sound file 37 | let task_path = settings.get("task_filepath")?; 38 | assert!( 39 | Path::new(&task_path).exists(), 40 | "task filepath does not exist" 41 | ); 42 | 43 | let sound_path = settings.get("sound.file")?; 44 | assert!( 45 | Path::new(&sound_path).exists(), 46 | "Sound filepath does not exist" 47 | ); 48 | let sound_volume = settings.get_float("sound.volume")?; 49 | 50 | // get the vector of tags 51 | let tags = settings.get_array("tags")?; 52 | //let tags: Vec = tags.into_iter().map(|i| i.into_str().unwrap()).collect(); 53 | let tags: Vec = tags.into_iter().map(|i| i.into_string().unwrap()).collect(); 54 | //let tags: Vec = tags.into_iter().map(|i| i.unwrap()).collect(); 55 | let taglen = tags.len(); 56 | 57 | // get boolean vector of whether to use due dates or not 58 | let use_due_dates = settings.get_array("use_due_dates")?; 59 | let use_due_dates: Vec = use_due_dates 60 | .into_iter() 61 | .map(|i| i.into_bool().unwrap()) 62 | .collect(); 63 | 64 | assert!( 65 | taglen == use_due_dates.len(), 66 | "use_due_dates vector length does not match number of tags in config" 67 | ); 68 | 69 | // get weights tags for all days of the week 70 | let mut weights_map = HashMap::new(); 71 | for day in ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] { 72 | let path = format!("weights.{}", day); 73 | let weights: Vec = settings 74 | .get_array(&path)? 75 | .into_iter() 76 | .map(|i| i.into_float().unwrap()) 77 | .collect(); 78 | weights_map.insert(day, weights); 79 | } 80 | 81 | let curr_day: u32 = Local::now().weekday().number_from_monday(); 82 | let tag_weights = match curr_day { 83 | 1 => weights_map.remove("mon"), 84 | 2 => weights_map.remove("tue"), 85 | 3 => weights_map.remove("wed"), 86 | 4 => weights_map.remove("thu"), 87 | 5 => weights_map.remove("fri"), 88 | 6 => weights_map.remove("sat"), 89 | 7 => weights_map.remove("sun"), 90 | _ => unreachable!(), 91 | } 92 | .unwrap(); 93 | assert!( 94 | taglen == tag_weights.len(), 95 | "current day tag weights do not match number of tags in config" 96 | ); 97 | 98 | let error_margin = f64::EPSILON; 99 | let tag_weights_sum: f64 = tag_weights.iter().sum(); 100 | assert!( 101 | (tag_weights_sum - 1.0).abs() <= error_margin, 102 | "current day tag weights do not sum to 1. they sum to {}", 103 | tag_weights_sum 104 | ); 105 | 106 | let min_break_time = settings.get_int("short_break_time")?; 107 | let max_break_time = settings.get_int("long_break_time")?; 108 | let task_time = settings.get_int("task_time")?; 109 | let maxno_min_breaks = settings.get_int("maxno_short_breaks")?; 110 | 111 | Ok(ConfigOptions { 112 | task_path, 113 | sound_path, 114 | sound_volume, 115 | tags, 116 | use_due_dates, 117 | initial_tag_weights: tag_weights, 118 | min_break_time, 119 | max_break_time, 120 | task_time, 121 | maxno_min_breaks, 122 | }) 123 | } 124 | -------------------------------------------------------------------------------- /src/ui/event.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::sync::mpsc; 3 | use std::thread; 4 | use std::time::Duration; 5 | use termion::event::Key; 6 | use termion::input::TermRead; 7 | 8 | pub enum Event { 9 | Input(I), 10 | Tick, 11 | } 12 | 13 | /// A small event handler that wrap termion input and tick events. Each event 14 | /// type is handled in its own thread and returned to a common `Receiver` 15 | #[allow(dead_code)] 16 | pub struct Events { 17 | rx: mpsc::Receiver>, 18 | input_handle: thread::JoinHandle<()>, 19 | tick_handle: thread::JoinHandle<()>, 20 | } 21 | 22 | #[derive(Debug, Clone, Copy)] 23 | pub struct Config { 24 | pub exit_key: Key, 25 | pub tick_rate: Duration, 26 | } 27 | 28 | impl Default for Config { 29 | fn default() -> Self { 30 | Self { 31 | exit_key: Key::Char('q'), 32 | tick_rate: Duration::from_millis(250), 33 | } 34 | } 35 | } 36 | 37 | impl Events { 38 | pub fn new() -> Self { 39 | Self::with_config(Config::default()) 40 | } 41 | 42 | pub fn with_config(config: Config) -> Self { 43 | let (tx, rx) = mpsc::channel(); 44 | let input_handle = { 45 | let tx = tx.clone(); 46 | thread::spawn(move || { 47 | let stdin = io::stdin(); 48 | for evt in stdin.keys().flatten() { 49 | if let Err(evt) = tx.send(Event::Input(evt)) { 50 | eprintln!("{}", evt); 51 | return; 52 | } 53 | if evt == config.exit_key { 54 | return; 55 | } 56 | } 57 | }) 58 | }; 59 | let tick_handle = { 60 | // let tx = tx.clone(); 61 | thread::spawn(move || { 62 | let tx = tx.clone(); 63 | loop { 64 | tx.send(Event::Tick).unwrap(); 65 | thread::sleep(config.tick_rate); 66 | } 67 | }) 68 | }; 69 | Self { 70 | rx, 71 | input_handle, 72 | tick_handle, 73 | } 74 | } 75 | 76 | pub fn next(&self) -> Result, mpsc::RecvError> { 77 | self.rx.recv() 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/ui/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod event; 2 | use tui::backend::Backend; 3 | use tui::layout::{Alignment, Constraint, Rect}; 4 | use tui::style::{Color, Modifier, Style}; 5 | use tui::text::{Span, Spans}; 6 | use tui::widgets::{ 7 | Block, BorderType, Borders, Cell, Gauge, List, ListItem, Paragraph, Row, Table, TableState, 8 | Wrap, 9 | }; 10 | use tui::Frame; 11 | 12 | // Tag Weight Table drawing functions 13 | pub struct WeightTable { 14 | state: TableState, 15 | items: Vec>, 16 | } 17 | 18 | impl WeightTable { 19 | pub fn new(weight_table_vec: Vec>) -> Self { 20 | Self { 21 | state: TableState::default(), 22 | items: weight_table_vec, 23 | } 24 | } 25 | 26 | pub fn next(&mut self) { 27 | let i = match self.state.selected() { 28 | Some(i) => { 29 | if i > self.items.len() - 1 { 30 | 0 31 | } else { 32 | i + 1 33 | } 34 | } 35 | None => 0, 36 | }; 37 | self.state.select(Some(i)); 38 | } 39 | 40 | pub fn previous(&mut self) { 41 | let i = match self.state.selected() { 42 | Some(i) => { 43 | if i == 0 { 44 | self.items.len() - 1 45 | } else { 46 | i - 1 47 | } 48 | } 49 | None => 0, 50 | }; 51 | self.state.select(Some(i)); 52 | } 53 | } 54 | 55 | // draw weight table in the specificed rectangle. 56 | pub fn draw_weights(f: &mut Frame, tagweight_table: &mut WeightTable, area: Rect) 57 | where 58 | B: Backend, 59 | { 60 | let selected_style = Style::default() 61 | .fg(Color::Yellow) 62 | .add_modifier(Modifier::BOLD); 63 | let normal_style = Style::default().fg(Color::White); 64 | let widths = [ 65 | Constraint::Percentage(20), 66 | Constraint::Percentage(40), 67 | Constraint::Percentage(10), 68 | Constraint::Percentage(10), 69 | Constraint::Percentage(20), 70 | ]; 71 | 72 | // fill in the table with the values 73 | let rows = tagweight_table.items.iter().map(|i| { 74 | let cells = i.iter().map(|c| { 75 | let x = c.clone(); 76 | Cell::from(x) 77 | }); 78 | Row::new(cells).style(normal_style) 79 | }); 80 | 81 | // instantiate the table with the tasks provided in the task list 82 | let table = Table::new(rows) 83 | .header( 84 | Row::new(vec!["Tag", "Task", "TagProb", "DueProb", "TotalProb"]) 85 | .style(Style::default().add_modifier(Modifier::BOLD)) 86 | .bottom_margin(1), 87 | ) 88 | .block( 89 | Block::default() 90 | .borders(Borders::ALL) 91 | .title("TAG WEIGHT TABLE") 92 | .border_type(BorderType::Rounded), 93 | ) 94 | .highlight_style(selected_style) 95 | .widths(&widths); 96 | 97 | f.render_stateful_widget(table, area, &mut tagweight_table.state); 98 | } 99 | 100 | // Help Table drawing functions 101 | pub struct HelpTable<'a> { 102 | state: TableState, 103 | items: Vec>, 104 | } 105 | 106 | impl<'a> HelpTable<'a> { 107 | pub fn new() -> HelpTable<'a> { 108 | HelpTable { 109 | state: TableState::default(), 110 | items: vec![ 111 | vec!["k", "scroll up in ALL TASKS table"], 112 | vec!["j", "scroll down in ALL TASKS table"], 113 | vec!["r", "reroll the given task without marking as complete"], 114 | vec!["c", "complete the given task and select a new one"], 115 | vec!["f", "fast forward current task bar to completion"], 116 | vec!["0", "rewid current task bar back to 0"], 117 | vec!["p", "toggle pause"], 118 | vec!["s", "access stats menu"], 119 | vec!["q", "quit rusty-krab-manager"], 120 | vec!["h", "toggle help menu"], 121 | ], 122 | } 123 | } 124 | 125 | pub fn next(&mut self) { 126 | let i = match self.state.selected() { 127 | Some(i) => { 128 | if i > self.items.len() - 1 { 129 | 0 130 | } else { 131 | i + 1 132 | } 133 | } 134 | None => 0, 135 | }; 136 | self.state.select(Some(i)); 137 | } 138 | 139 | pub fn previous(&mut self) { 140 | let i = match self.state.selected() { 141 | Some(i) => { 142 | if i == 0 { 143 | self.items.len() - 1 144 | } else { 145 | i - 1 146 | } 147 | } 148 | None => 0, 149 | }; 150 | self.state.select(Some(i)); 151 | } 152 | } 153 | 154 | pub fn draw_help(f: &mut Frame, helptable: &mut HelpTable, area: Rect) 155 | where 156 | B: Backend, 157 | { 158 | let selected_style = Style::default() 159 | .fg(Color::Yellow) 160 | .add_modifier(Modifier::BOLD); 161 | let normal_style = Style::default().fg(Color::White); 162 | let widths = [Constraint::Percentage(20), Constraint::Percentage(80)]; 163 | let rows = helptable.items.iter().map(|i| { 164 | let cells = i.iter().map(|c| Cell::from(*c)); 165 | // cells.pop; 166 | Row::new(cells).style(normal_style) 167 | }); 168 | 169 | // instantiate the table with the tasks provided in the task list 170 | let table = Table::new(rows) 171 | .header( 172 | Row::new(vec!["Keypress", "Description"]) 173 | .style(Style::default().add_modifier(Modifier::BOLD)) 174 | .bottom_margin(1), 175 | ) 176 | .block( 177 | Block::default() 178 | .borders(Borders::ALL) 179 | .title("HELP TABLE") 180 | .border_type(BorderType::Rounded), 181 | ) 182 | .highlight_style(selected_style) 183 | .highlight_symbol(" ") 184 | .widths(&widths); 185 | 186 | f.render_stateful_widget(table, area, &mut helptable.state); 187 | } 188 | 189 | // Define the current TUI application 190 | // and its variables 191 | pub struct App { 192 | state: TableState, 193 | pub items: Vec>, 194 | // pub selected: usize, 195 | pub progress: f64, 196 | pub current_task: Vec, 197 | pub paused: bool, 198 | pub completed: Vec<(String, String)>, 199 | } 200 | 201 | impl App { 202 | // Instantiate the default application. 203 | // If all goes according to plan none of these 204 | // values are actually used. Used for debugging. 205 | pub fn new() -> Self { 206 | Self { 207 | items: vec![vec![ 208 | String::from("GANG"), 209 | String::from("GANG"), 210 | String::from("GANG"), 211 | ]], 212 | // selected: 0, 213 | state: TableState::default(), 214 | progress: 0.0, 215 | current_task: vec![ 216 | String::from("Hello\n"), 217 | String::from("Heyyo!\n"), 218 | String::from("MEMES\n"), 219 | ], 220 | paused: false, 221 | completed: vec![ 222 | (String::from("GANG"), String::from("0")), 223 | (String::from("GANG"), String::from("1")), 224 | (String::from("GANG"), String::from("2")), 225 | (String::from("GANG"), String::from("3")), 226 | (String::from("GANG"), String::from("4")), 227 | ], 228 | } 229 | } 230 | 231 | // Function to update the app. 232 | // This runs every 250 milliseconds and returns 233 | // true when the app hits 100% 234 | pub fn update(&mut self, minutes: i64) -> bool { 235 | self.progress += (250.0 / 60000.0) / minutes as f64; 236 | if self.progress > 1.0 { 237 | self.progress = 0.0; 238 | return true; 239 | } 240 | false 241 | } 242 | 243 | pub fn next(&mut self) { 244 | let i = match self.state.selected() { 245 | Some(i) => { 246 | if i > self.items.len() - 1 { 247 | 0 248 | } else { 249 | i + 1 250 | } 251 | } 252 | None => 0, 253 | }; 254 | self.state.select(Some(i)); 255 | } 256 | 257 | pub fn previous(&mut self) { 258 | let i = match self.state.selected() { 259 | Some(i) => { 260 | if i == 0 { 261 | self.items.len() - 1 262 | } else { 263 | i - 1 264 | } 265 | } 266 | None => 0, 267 | }; 268 | self.state.select(Some(i)); 269 | } 270 | } 271 | 272 | // Draw the gauge used to showcase the remaining 273 | // amount of time left to do whatever. 274 | pub fn draw_gauge(f: &mut Frame, app: &App, area: Rect) 275 | where 276 | B: Backend, 277 | { 278 | let gauge = Gauge::default() 279 | .block( 280 | Block::default() 281 | .title("TIME LEFT") 282 | .borders(Borders::ALL) 283 | .border_type(BorderType::Rounded), 284 | ) 285 | .gauge_style(Style::default().fg(Color::Yellow)) 286 | .ratio(app.progress); 287 | f.render_widget(gauge, area); 288 | } 289 | 290 | // Draw the task table to showcase what tasks 291 | // the rusty-krab-manager has read from the given 292 | // task list 293 | pub fn draw_task_table(f: &mut Frame, app: &mut App, area: Rect) 294 | where 295 | B: Backend, 296 | { 297 | // set basic values 298 | // let padding = 5; 299 | // let offset = area 300 | // .height 301 | // .checked_sub(padding) 302 | // .and_then(|height| app.selected.checked_sub(height as usize)) 303 | // .unwrap_or(0); 304 | 305 | let selected_style = Style::default() 306 | .fg(Color::Yellow) 307 | .add_modifier(Modifier::BOLD); 308 | let normal_style = Style::default().fg(Color::White); 309 | let widths = [ 310 | Constraint::Percentage(20), 311 | Constraint::Percentage(50), 312 | Constraint::Percentage(30), 313 | ]; 314 | 315 | // code snippet based on spotify-tui. essentially allows 316 | // scrollable tables 317 | // let rows = app.items.iter().skip(offset).enumerate().map(|(i, item)| { 318 | // if Some(i) == app.selected.checked_sub(offset) { 319 | // Row::StyledData(item.into_iter(), selected_style) 320 | // } else { 321 | // Row::StyledData(item.into_iter(), normal_style) 322 | // } 323 | // }); 324 | let rows = app.items.iter().map(|i| { 325 | let cells = i.iter().map(|c| { 326 | let x = c.clone(); 327 | Cell::from(x) 328 | }); 329 | Row::new(cells).style(normal_style) 330 | }); 331 | 332 | // instantiate the table with the tasks provided in the task list 333 | let task_table = Table::new(rows) 334 | .header( 335 | Row::new(vec!["Tag", "Name", "Due Date"]) 336 | .style(Style::default().add_modifier(Modifier::BOLD)) 337 | .bottom_margin(1), 338 | ) 339 | .block( 340 | Block::default() 341 | .borders(Borders::ALL) 342 | .title("ALL TASKS") 343 | .border_type(BorderType::Rounded), 344 | ) 345 | .highlight_symbol(">> ") 346 | .highlight_style(selected_style) 347 | .widths(&widths) 348 | .column_spacing(1); 349 | 350 | f.render_stateful_widget(task_table, area, &mut app.state); 351 | } 352 | 353 | // Draw the current task that has been selected. 354 | pub fn draw_current_task(f: &mut Frame, app: &App, area: Rect) 355 | where 356 | B: Backend, 357 | { 358 | let mut new_shit = vec![]; 359 | let x = Spans::from(Span::styled( 360 | "DO THIS SHIT", 361 | Style::default() 362 | .bg(Color::Green) 363 | .add_modifier(Modifier::BOLD), 364 | )); 365 | new_shit.push(x); 366 | new_shit.push(Spans::from(Span::raw(""))); 367 | 368 | // push whatever the current task is 369 | for i in 0..app.current_task.len() { 370 | new_shit.push(Spans::from(Span::raw(&app.current_task[i]))); 371 | } 372 | let task_paragraph = Paragraph::new(new_shit.clone()) 373 | .block( 374 | Block::default() 375 | .title("CURRENT TASK") 376 | .borders(Borders::ALL) 377 | .border_type(BorderType::Rounded), 378 | ) 379 | .alignment(Alignment::Center) 380 | .wrap(Wrap { trim: true }); 381 | f.render_widget(task_paragraph, area); 382 | } 383 | 384 | // Draw the counter to keep track of the number 385 | // of tags done 386 | pub fn draw_tag_counter(f: &mut Frame, app: &App, area: Rect) 387 | where 388 | B: Backend, 389 | { 390 | let stuff: Vec = app 391 | .completed 392 | .iter() 393 | .map(|(tag, ctr)| { 394 | let tagspan = Spans::from(vec![Span::styled( 395 | tag.clone() + ": " + ctr, 396 | Style::default(), 397 | )]); 398 | ListItem::new(vec![tagspan]) 399 | }) 400 | .collect(); 401 | 402 | let task_ctr = List::new(stuff).block( 403 | Block::default() 404 | .borders(Borders::ALL) 405 | .title("COUNTER") 406 | .border_type(BorderType::Rounded), 407 | ); 408 | f.render_widget(task_ctr, area); 409 | } 410 | --------------------------------------------------------------------------------