├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── alert.rs ├── cli.rs ├── error.rs ├── format.rs ├── input.rs ├── main.rs ├── notify_end.wav ├── pomodoro.rs ├── prelude.rs ├── stopwatch.rs ├── terminal.rs └── timer.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /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 = "aho-corasick" 7 | version = "1.0.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" 10 | dependencies = [ 11 | "memchr", 12 | ] 13 | 14 | [[package]] 15 | name = "alsa" 16 | version = "0.4.3" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934" 19 | dependencies = [ 20 | "alsa-sys", 21 | "bitflags 1.3.2", 22 | "libc", 23 | "nix 0.15.0", 24 | ] 25 | 26 | [[package]] 27 | name = "alsa-sys" 28 | version = "0.3.1" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" 31 | dependencies = [ 32 | "libc", 33 | "pkg-config", 34 | ] 35 | 36 | [[package]] 37 | name = "anstream" 38 | version = "0.3.2" 39 | source = "registry+https://github.com/rust-lang/crates.io-index" 40 | checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" 41 | dependencies = [ 42 | "anstyle", 43 | "anstyle-parse", 44 | "anstyle-query", 45 | "anstyle-wincon", 46 | "colorchoice", 47 | "is-terminal", 48 | "utf8parse", 49 | ] 50 | 51 | [[package]] 52 | name = "anstyle" 53 | version = "1.0.1" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" 56 | 57 | [[package]] 58 | name = "anstyle-parse" 59 | version = "0.2.1" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" 62 | dependencies = [ 63 | "utf8parse", 64 | ] 65 | 66 | [[package]] 67 | name = "anstyle-query" 68 | version = "1.0.0" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" 71 | dependencies = [ 72 | "windows-sys", 73 | ] 74 | 75 | [[package]] 76 | name = "anstyle-wincon" 77 | version = "1.0.1" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" 80 | dependencies = [ 81 | "anstyle", 82 | "windows-sys", 83 | ] 84 | 85 | [[package]] 86 | name = "async-broadcast" 87 | version = "0.5.1" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" 90 | dependencies = [ 91 | "event-listener", 92 | "futures-core", 93 | ] 94 | 95 | [[package]] 96 | name = "async-channel" 97 | version = "1.8.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" 100 | dependencies = [ 101 | "concurrent-queue", 102 | "event-listener", 103 | "futures-core", 104 | ] 105 | 106 | [[package]] 107 | name = "async-executor" 108 | version = "1.5.1" 109 | source = "registry+https://github.com/rust-lang/crates.io-index" 110 | checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" 111 | dependencies = [ 112 | "async-lock", 113 | "async-task", 114 | "concurrent-queue", 115 | "fastrand", 116 | "futures-lite", 117 | "slab", 118 | ] 119 | 120 | [[package]] 121 | name = "async-fs" 122 | version = "1.6.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" 125 | dependencies = [ 126 | "async-lock", 127 | "autocfg", 128 | "blocking", 129 | "futures-lite", 130 | ] 131 | 132 | [[package]] 133 | name = "async-io" 134 | version = "1.13.0" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" 137 | dependencies = [ 138 | "async-lock", 139 | "autocfg", 140 | "cfg-if 1.0.0", 141 | "concurrent-queue", 142 | "futures-lite", 143 | "log", 144 | "parking", 145 | "polling", 146 | "rustix 0.37.22", 147 | "slab", 148 | "socket2", 149 | "waker-fn", 150 | ] 151 | 152 | [[package]] 153 | name = "async-lock" 154 | version = "2.7.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" 157 | dependencies = [ 158 | "event-listener", 159 | ] 160 | 161 | [[package]] 162 | name = "async-process" 163 | version = "1.7.0" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" 166 | dependencies = [ 167 | "async-io", 168 | "async-lock", 169 | "autocfg", 170 | "blocking", 171 | "cfg-if 1.0.0", 172 | "event-listener", 173 | "futures-lite", 174 | "rustix 0.37.22", 175 | "signal-hook", 176 | "windows-sys", 177 | ] 178 | 179 | [[package]] 180 | name = "async-recursion" 181 | version = "1.0.4" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" 184 | dependencies = [ 185 | "proc-macro2", 186 | "quote", 187 | "syn 2.0.23", 188 | ] 189 | 190 | [[package]] 191 | name = "async-task" 192 | version = "4.4.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" 195 | 196 | [[package]] 197 | name = "async-trait" 198 | version = "0.1.70" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "79fa67157abdfd688a259b6648808757db9347af834624f27ec646da976aee5d" 201 | dependencies = [ 202 | "proc-macro2", 203 | "quote", 204 | "syn 2.0.23", 205 | ] 206 | 207 | [[package]] 208 | name = "atomic-waker" 209 | version = "1.1.1" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" 212 | 213 | [[package]] 214 | name = "autocfg" 215 | version = "1.1.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 218 | 219 | [[package]] 220 | name = "bindgen" 221 | version = "0.64.0" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" 224 | dependencies = [ 225 | "bitflags 1.3.2", 226 | "cexpr", 227 | "clang-sys", 228 | "lazy_static", 229 | "lazycell", 230 | "peeking_take_while", 231 | "proc-macro2", 232 | "quote", 233 | "regex", 234 | "rustc-hash", 235 | "shlex", 236 | "syn 1.0.109", 237 | ] 238 | 239 | [[package]] 240 | name = "bitflags" 241 | version = "1.3.2" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 244 | 245 | [[package]] 246 | name = "bitflags" 247 | version = "2.3.3" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" 250 | 251 | [[package]] 252 | name = "block" 253 | version = "0.1.6" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" 256 | 257 | [[package]] 258 | name = "block-buffer" 259 | version = "0.10.4" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 262 | dependencies = [ 263 | "generic-array", 264 | ] 265 | 266 | [[package]] 267 | name = "blocking" 268 | version = "1.3.1" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" 271 | dependencies = [ 272 | "async-channel", 273 | "async-lock", 274 | "async-task", 275 | "atomic-waker", 276 | "fastrand", 277 | "futures-lite", 278 | "log", 279 | ] 280 | 281 | [[package]] 282 | name = "bumpalo" 283 | version = "3.13.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 286 | 287 | [[package]] 288 | name = "byteorder" 289 | version = "1.4.3" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 292 | 293 | [[package]] 294 | name = "cc" 295 | version = "1.0.79" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 298 | 299 | [[package]] 300 | name = "cexpr" 301 | version = "0.6.0" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" 304 | dependencies = [ 305 | "nom", 306 | ] 307 | 308 | [[package]] 309 | name = "cfg-if" 310 | version = "0.1.10" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 313 | 314 | [[package]] 315 | name = "cfg-if" 316 | version = "1.0.0" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 319 | 320 | [[package]] 321 | name = "clang-sys" 322 | version = "1.6.1" 323 | source = "registry+https://github.com/rust-lang/crates.io-index" 324 | checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" 325 | dependencies = [ 326 | "glob", 327 | "libc", 328 | "libloading", 329 | ] 330 | 331 | [[package]] 332 | name = "clap" 333 | version = "4.3.10" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" 336 | dependencies = [ 337 | "clap_builder", 338 | "clap_derive", 339 | "once_cell", 340 | ] 341 | 342 | [[package]] 343 | name = "clap_builder" 344 | version = "4.3.10" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" 347 | dependencies = [ 348 | "anstream", 349 | "anstyle", 350 | "clap_lex", 351 | "strsim", 352 | ] 353 | 354 | [[package]] 355 | name = "clap_derive" 356 | version = "4.3.2" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" 359 | dependencies = [ 360 | "heck", 361 | "proc-macro2", 362 | "quote", 363 | "syn 2.0.23", 364 | ] 365 | 366 | [[package]] 367 | name = "clap_lex" 368 | version = "0.5.0" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" 371 | 372 | [[package]] 373 | name = "claxon" 374 | version = "0.4.3" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" 377 | 378 | [[package]] 379 | name = "cloudabi" 380 | version = "0.0.3" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 383 | dependencies = [ 384 | "bitflags 1.3.2", 385 | ] 386 | 387 | [[package]] 388 | name = "colorchoice" 389 | version = "1.0.0" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" 392 | 393 | [[package]] 394 | name = "concurrent-queue" 395 | version = "2.2.0" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" 398 | dependencies = [ 399 | "crossbeam-utils", 400 | ] 401 | 402 | [[package]] 403 | name = "core-foundation-sys" 404 | version = "0.6.2" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" 407 | 408 | [[package]] 409 | name = "coreaudio-rs" 410 | version = "0.9.1" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "f229761965dad3e9b11081668a6ea00f1def7aa46062321b5ec245b834f6e491" 413 | dependencies = [ 414 | "bitflags 1.3.2", 415 | "coreaudio-sys", 416 | ] 417 | 418 | [[package]] 419 | name = "coreaudio-sys" 420 | version = "0.2.12" 421 | source = "registry+https://github.com/rust-lang/crates.io-index" 422 | checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" 423 | dependencies = [ 424 | "bindgen", 425 | ] 426 | 427 | [[package]] 428 | name = "cpal" 429 | version = "0.12.1" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "be4410231e181e24e3e4612dfca601601e40942003e6a52a12d9d80f19fd9737" 432 | dependencies = [ 433 | "alsa", 434 | "core-foundation-sys", 435 | "coreaudio-rs", 436 | "js-sys", 437 | "lazy_static", 438 | "libc", 439 | "mach", 440 | "nix 0.15.0", 441 | "parking_lot 0.9.0", 442 | "stdweb", 443 | "thiserror", 444 | "web-sys", 445 | "winapi", 446 | ] 447 | 448 | [[package]] 449 | name = "cpufeatures" 450 | version = "0.2.8" 451 | source = "registry+https://github.com/rust-lang/crates.io-index" 452 | checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" 453 | dependencies = [ 454 | "libc", 455 | ] 456 | 457 | [[package]] 458 | name = "crossbeam-utils" 459 | version = "0.8.16" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 462 | dependencies = [ 463 | "cfg-if 1.0.0", 464 | ] 465 | 466 | [[package]] 467 | name = "crossterm" 468 | version = "0.26.1" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 471 | dependencies = [ 472 | "bitflags 1.3.2", 473 | "crossterm_winapi", 474 | "libc", 475 | "mio", 476 | "parking_lot 0.12.1", 477 | "signal-hook", 478 | "signal-hook-mio", 479 | "winapi", 480 | ] 481 | 482 | [[package]] 483 | name = "crossterm_winapi" 484 | version = "0.9.1" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 487 | dependencies = [ 488 | "winapi", 489 | ] 490 | 491 | [[package]] 492 | name = "crypto-common" 493 | version = "0.1.6" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 496 | dependencies = [ 497 | "generic-array", 498 | "typenum", 499 | ] 500 | 501 | [[package]] 502 | name = "derivative" 503 | version = "2.2.0" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 506 | dependencies = [ 507 | "proc-macro2", 508 | "quote", 509 | "syn 1.0.109", 510 | ] 511 | 512 | [[package]] 513 | name = "digest" 514 | version = "0.10.7" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 517 | dependencies = [ 518 | "block-buffer", 519 | "crypto-common", 520 | ] 521 | 522 | [[package]] 523 | name = "dirs-next" 524 | version = "2.0.0" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" 527 | dependencies = [ 528 | "cfg-if 1.0.0", 529 | "dirs-sys-next", 530 | ] 531 | 532 | [[package]] 533 | name = "dirs-sys-next" 534 | version = "0.1.2" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" 537 | dependencies = [ 538 | "libc", 539 | "redox_users", 540 | "winapi", 541 | ] 542 | 543 | [[package]] 544 | name = "enumflags2" 545 | version = "0.7.7" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" 548 | dependencies = [ 549 | "enumflags2_derive", 550 | "serde", 551 | ] 552 | 553 | [[package]] 554 | name = "enumflags2_derive" 555 | version = "0.7.7" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" 558 | dependencies = [ 559 | "proc-macro2", 560 | "quote", 561 | "syn 2.0.23", 562 | ] 563 | 564 | [[package]] 565 | name = "equivalent" 566 | version = "1.0.0" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" 569 | 570 | [[package]] 571 | name = "errno" 572 | version = "0.3.1" 573 | source = "registry+https://github.com/rust-lang/crates.io-index" 574 | checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" 575 | dependencies = [ 576 | "errno-dragonfly", 577 | "libc", 578 | "windows-sys", 579 | ] 580 | 581 | [[package]] 582 | name = "errno-dragonfly" 583 | version = "0.1.2" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 586 | dependencies = [ 587 | "cc", 588 | "libc", 589 | ] 590 | 591 | [[package]] 592 | name = "event-listener" 593 | version = "2.5.3" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 596 | 597 | [[package]] 598 | name = "fastrand" 599 | version = "1.9.0" 600 | source = "registry+https://github.com/rust-lang/crates.io-index" 601 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 602 | dependencies = [ 603 | "instant", 604 | ] 605 | 606 | [[package]] 607 | name = "futures-core" 608 | version = "0.3.28" 609 | source = "registry+https://github.com/rust-lang/crates.io-index" 610 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 611 | 612 | [[package]] 613 | name = "futures-io" 614 | version = "0.3.28" 615 | source = "registry+https://github.com/rust-lang/crates.io-index" 616 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 617 | 618 | [[package]] 619 | name = "futures-lite" 620 | version = "1.13.0" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" 623 | dependencies = [ 624 | "fastrand", 625 | "futures-core", 626 | "futures-io", 627 | "memchr", 628 | "parking", 629 | "pin-project-lite", 630 | "waker-fn", 631 | ] 632 | 633 | [[package]] 634 | name = "futures-sink" 635 | version = "0.3.28" 636 | source = "registry+https://github.com/rust-lang/crates.io-index" 637 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 638 | 639 | [[package]] 640 | name = "futures-task" 641 | version = "0.3.28" 642 | source = "registry+https://github.com/rust-lang/crates.io-index" 643 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 644 | 645 | [[package]] 646 | name = "futures-util" 647 | version = "0.3.28" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 650 | dependencies = [ 651 | "futures-core", 652 | "futures-io", 653 | "futures-sink", 654 | "futures-task", 655 | "memchr", 656 | "pin-project-lite", 657 | "pin-utils", 658 | "slab", 659 | ] 660 | 661 | [[package]] 662 | name = "generic-array" 663 | version = "0.14.7" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 666 | dependencies = [ 667 | "typenum", 668 | "version_check", 669 | ] 670 | 671 | [[package]] 672 | name = "getrandom" 673 | version = "0.2.10" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 676 | dependencies = [ 677 | "cfg-if 1.0.0", 678 | "libc", 679 | "wasi", 680 | ] 681 | 682 | [[package]] 683 | name = "glob" 684 | version = "0.3.1" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" 687 | 688 | [[package]] 689 | name = "hashbrown" 690 | version = "0.14.0" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" 693 | 694 | [[package]] 695 | name = "heck" 696 | version = "0.4.1" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 699 | 700 | [[package]] 701 | name = "hermit-abi" 702 | version = "0.3.2" 703 | source = "registry+https://github.com/rust-lang/crates.io-index" 704 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 705 | 706 | [[package]] 707 | name = "hex" 708 | version = "0.4.3" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 711 | 712 | [[package]] 713 | name = "hound" 714 | version = "3.5.0" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1" 717 | 718 | [[package]] 719 | name = "indexmap" 720 | version = "2.0.0" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" 723 | dependencies = [ 724 | "equivalent", 725 | "hashbrown", 726 | ] 727 | 728 | [[package]] 729 | name = "instant" 730 | version = "0.1.12" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 733 | dependencies = [ 734 | "cfg-if 1.0.0", 735 | ] 736 | 737 | [[package]] 738 | name = "io-lifetimes" 739 | version = "1.0.11" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" 742 | dependencies = [ 743 | "hermit-abi", 744 | "libc", 745 | "windows-sys", 746 | ] 747 | 748 | [[package]] 749 | name = "is-terminal" 750 | version = "0.4.8" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" 753 | dependencies = [ 754 | "hermit-abi", 755 | "rustix 0.38.2", 756 | "windows-sys", 757 | ] 758 | 759 | [[package]] 760 | name = "js-sys" 761 | version = "0.3.64" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 764 | dependencies = [ 765 | "wasm-bindgen", 766 | ] 767 | 768 | [[package]] 769 | name = "lazy_static" 770 | version = "1.4.0" 771 | source = "registry+https://github.com/rust-lang/crates.io-index" 772 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 773 | 774 | [[package]] 775 | name = "lazycell" 776 | version = "1.3.0" 777 | source = "registry+https://github.com/rust-lang/crates.io-index" 778 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 779 | 780 | [[package]] 781 | name = "lewton" 782 | version = "0.10.2" 783 | source = "registry+https://github.com/rust-lang/crates.io-index" 784 | checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" 785 | dependencies = [ 786 | "byteorder", 787 | "ogg", 788 | "tinyvec", 789 | ] 790 | 791 | [[package]] 792 | name = "libc" 793 | version = "0.2.147" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 796 | 797 | [[package]] 798 | name = "libloading" 799 | version = "0.7.4" 800 | source = "registry+https://github.com/rust-lang/crates.io-index" 801 | checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" 802 | dependencies = [ 803 | "cfg-if 1.0.0", 804 | "winapi", 805 | ] 806 | 807 | [[package]] 808 | name = "linux-raw-sys" 809 | version = "0.3.8" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" 812 | 813 | [[package]] 814 | name = "linux-raw-sys" 815 | version = "0.4.3" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" 818 | 819 | [[package]] 820 | name = "lock_api" 821 | version = "0.3.4" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" 824 | dependencies = [ 825 | "scopeguard", 826 | ] 827 | 828 | [[package]] 829 | name = "lock_api" 830 | version = "0.4.10" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 833 | dependencies = [ 834 | "autocfg", 835 | "scopeguard", 836 | ] 837 | 838 | [[package]] 839 | name = "log" 840 | version = "0.4.19" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 843 | 844 | [[package]] 845 | name = "mac-notification-sys" 846 | version = "0.5.6" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "3e72d50edb17756489e79d52eb146927bec8eba9dd48faadf9ef08bca3791ad5" 849 | dependencies = [ 850 | "cc", 851 | "dirs-next", 852 | "objc-foundation", 853 | "objc_id", 854 | "time", 855 | ] 856 | 857 | [[package]] 858 | name = "mach" 859 | version = "0.3.2" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" 862 | dependencies = [ 863 | "libc", 864 | ] 865 | 866 | [[package]] 867 | name = "malloc_buf" 868 | version = "0.0.6" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" 871 | dependencies = [ 872 | "libc", 873 | ] 874 | 875 | [[package]] 876 | name = "maybe-uninit" 877 | version = "2.0.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 880 | 881 | [[package]] 882 | name = "memchr" 883 | version = "2.5.0" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 886 | 887 | [[package]] 888 | name = "memoffset" 889 | version = "0.7.1" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" 892 | dependencies = [ 893 | "autocfg", 894 | ] 895 | 896 | [[package]] 897 | name = "minimal-lexical" 898 | version = "0.2.1" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 901 | 902 | [[package]] 903 | name = "minimp3" 904 | version = "0.5.1" 905 | source = "registry+https://github.com/rust-lang/crates.io-index" 906 | checksum = "985438f75febf74c392071a975a29641b420dd84431135a6e6db721de4b74372" 907 | dependencies = [ 908 | "minimp3-sys", 909 | "slice-deque", 910 | "thiserror", 911 | ] 912 | 913 | [[package]] 914 | name = "minimp3-sys" 915 | version = "0.3.2" 916 | source = "registry+https://github.com/rust-lang/crates.io-index" 917 | checksum = "e21c73734c69dc95696c9ed8926a2b393171d98b3f5f5935686a26a487ab9b90" 918 | dependencies = [ 919 | "cc", 920 | ] 921 | 922 | [[package]] 923 | name = "mio" 924 | version = "0.8.8" 925 | source = "registry+https://github.com/rust-lang/crates.io-index" 926 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 927 | dependencies = [ 928 | "libc", 929 | "log", 930 | "wasi", 931 | "windows-sys", 932 | ] 933 | 934 | [[package]] 935 | name = "nix" 936 | version = "0.15.0" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229" 939 | dependencies = [ 940 | "bitflags 1.3.2", 941 | "cc", 942 | "cfg-if 0.1.10", 943 | "libc", 944 | "void", 945 | ] 946 | 947 | [[package]] 948 | name = "nix" 949 | version = "0.26.2" 950 | source = "registry+https://github.com/rust-lang/crates.io-index" 951 | checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" 952 | dependencies = [ 953 | "bitflags 1.3.2", 954 | "cfg-if 1.0.0", 955 | "libc", 956 | "memoffset", 957 | "static_assertions", 958 | ] 959 | 960 | [[package]] 961 | name = "nom" 962 | version = "7.1.3" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 965 | dependencies = [ 966 | "memchr", 967 | "minimal-lexical", 968 | ] 969 | 970 | [[package]] 971 | name = "notify-rust" 972 | version = "4.8.0" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "2bfa211d18e360f08e36c364308f394b5eb23a6629150690e109a916dc6f610e" 975 | dependencies = [ 976 | "log", 977 | "mac-notification-sys", 978 | "serde", 979 | "tauri-winrt-notification", 980 | "zbus", 981 | ] 982 | 983 | [[package]] 984 | name = "objc" 985 | version = "0.2.7" 986 | source = "registry+https://github.com/rust-lang/crates.io-index" 987 | checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" 988 | dependencies = [ 989 | "malloc_buf", 990 | ] 991 | 992 | [[package]] 993 | name = "objc-foundation" 994 | version = "0.1.1" 995 | source = "registry+https://github.com/rust-lang/crates.io-index" 996 | checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" 997 | dependencies = [ 998 | "block", 999 | "objc", 1000 | "objc_id", 1001 | ] 1002 | 1003 | [[package]] 1004 | name = "objc_id" 1005 | version = "0.1.1" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" 1008 | dependencies = [ 1009 | "objc", 1010 | ] 1011 | 1012 | [[package]] 1013 | name = "ogg" 1014 | version = "0.8.0" 1015 | source = "registry+https://github.com/rust-lang/crates.io-index" 1016 | checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" 1017 | dependencies = [ 1018 | "byteorder", 1019 | ] 1020 | 1021 | [[package]] 1022 | name = "once_cell" 1023 | version = "1.18.0" 1024 | source = "registry+https://github.com/rust-lang/crates.io-index" 1025 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 1026 | 1027 | [[package]] 1028 | name = "ordered-stream" 1029 | version = "0.2.0" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" 1032 | dependencies = [ 1033 | "futures-core", 1034 | "pin-project-lite", 1035 | ] 1036 | 1037 | [[package]] 1038 | name = "parking" 1039 | version = "2.1.0" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" 1042 | 1043 | [[package]] 1044 | name = "parking_lot" 1045 | version = "0.9.0" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" 1048 | dependencies = [ 1049 | "lock_api 0.3.4", 1050 | "parking_lot_core 0.6.3", 1051 | "rustc_version", 1052 | ] 1053 | 1054 | [[package]] 1055 | name = "parking_lot" 1056 | version = "0.12.1" 1057 | source = "registry+https://github.com/rust-lang/crates.io-index" 1058 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1059 | dependencies = [ 1060 | "lock_api 0.4.10", 1061 | "parking_lot_core 0.9.8", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "parking_lot_core" 1066 | version = "0.6.3" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" 1069 | dependencies = [ 1070 | "cfg-if 0.1.10", 1071 | "cloudabi", 1072 | "libc", 1073 | "redox_syscall 0.1.57", 1074 | "rustc_version", 1075 | "smallvec 0.6.14", 1076 | "winapi", 1077 | ] 1078 | 1079 | [[package]] 1080 | name = "parking_lot_core" 1081 | version = "0.9.8" 1082 | source = "registry+https://github.com/rust-lang/crates.io-index" 1083 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 1084 | dependencies = [ 1085 | "cfg-if 1.0.0", 1086 | "libc", 1087 | "redox_syscall 0.3.5", 1088 | "smallvec 1.10.0", 1089 | "windows-targets", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "peeking_take_while" 1094 | version = "0.1.2" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" 1097 | 1098 | [[package]] 1099 | name = "pin-project-lite" 1100 | version = "0.2.10" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" 1103 | 1104 | [[package]] 1105 | name = "pin-utils" 1106 | version = "0.1.0" 1107 | source = "registry+https://github.com/rust-lang/crates.io-index" 1108 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1109 | 1110 | [[package]] 1111 | name = "pkg-config" 1112 | version = "0.3.27" 1113 | source = "registry+https://github.com/rust-lang/crates.io-index" 1114 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 1115 | 1116 | [[package]] 1117 | name = "polling" 1118 | version = "2.8.0" 1119 | source = "registry+https://github.com/rust-lang/crates.io-index" 1120 | checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" 1121 | dependencies = [ 1122 | "autocfg", 1123 | "bitflags 1.3.2", 1124 | "cfg-if 1.0.0", 1125 | "concurrent-queue", 1126 | "libc", 1127 | "log", 1128 | "pin-project-lite", 1129 | "windows-sys", 1130 | ] 1131 | 1132 | [[package]] 1133 | name = "porsmo" 1134 | version = "0.3.3" 1135 | dependencies = [ 1136 | "clap", 1137 | "crossterm", 1138 | "notify-rust", 1139 | "rodio", 1140 | "thiserror", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "ppv-lite86" 1145 | version = "0.2.17" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1148 | 1149 | [[package]] 1150 | name = "proc-macro-crate" 1151 | version = "1.3.1" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" 1154 | dependencies = [ 1155 | "once_cell", 1156 | "toml_edit", 1157 | ] 1158 | 1159 | [[package]] 1160 | name = "proc-macro2" 1161 | version = "1.0.63" 1162 | source = "registry+https://github.com/rust-lang/crates.io-index" 1163 | checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" 1164 | dependencies = [ 1165 | "unicode-ident", 1166 | ] 1167 | 1168 | [[package]] 1169 | name = "quick-xml" 1170 | version = "0.23.1" 1171 | source = "registry+https://github.com/rust-lang/crates.io-index" 1172 | checksum = "11bafc859c6815fbaffbbbf4229ecb767ac913fecb27f9ad4343662e9ef099ea" 1173 | dependencies = [ 1174 | "memchr", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "quote" 1179 | version = "1.0.29" 1180 | source = "registry+https://github.com/rust-lang/crates.io-index" 1181 | checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" 1182 | dependencies = [ 1183 | "proc-macro2", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "rand" 1188 | version = "0.8.5" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1191 | dependencies = [ 1192 | "libc", 1193 | "rand_chacha", 1194 | "rand_core", 1195 | ] 1196 | 1197 | [[package]] 1198 | name = "rand_chacha" 1199 | version = "0.3.1" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1202 | dependencies = [ 1203 | "ppv-lite86", 1204 | "rand_core", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "rand_core" 1209 | version = "0.6.4" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1212 | dependencies = [ 1213 | "getrandom", 1214 | ] 1215 | 1216 | [[package]] 1217 | name = "redox_syscall" 1218 | version = "0.1.57" 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" 1220 | checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" 1221 | 1222 | [[package]] 1223 | name = "redox_syscall" 1224 | version = "0.2.16" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1227 | dependencies = [ 1228 | "bitflags 1.3.2", 1229 | ] 1230 | 1231 | [[package]] 1232 | name = "redox_syscall" 1233 | version = "0.3.5" 1234 | source = "registry+https://github.com/rust-lang/crates.io-index" 1235 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 1236 | dependencies = [ 1237 | "bitflags 1.3.2", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "redox_users" 1242 | version = "0.4.3" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1245 | dependencies = [ 1246 | "getrandom", 1247 | "redox_syscall 0.2.16", 1248 | "thiserror", 1249 | ] 1250 | 1251 | [[package]] 1252 | name = "regex" 1253 | version = "1.8.4" 1254 | source = "registry+https://github.com/rust-lang/crates.io-index" 1255 | checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" 1256 | dependencies = [ 1257 | "aho-corasick", 1258 | "memchr", 1259 | "regex-syntax", 1260 | ] 1261 | 1262 | [[package]] 1263 | name = "regex-syntax" 1264 | version = "0.7.2" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" 1267 | 1268 | [[package]] 1269 | name = "rodio" 1270 | version = "0.12.0" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "94b2b7fa7b318a4b22f0ff62bbe1e53403e1eef28ac304a00dfe4f73ab30204c" 1273 | dependencies = [ 1274 | "claxon", 1275 | "cpal", 1276 | "hound", 1277 | "lewton", 1278 | "minimp3", 1279 | ] 1280 | 1281 | [[package]] 1282 | name = "rustc-hash" 1283 | version = "1.1.0" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 1286 | 1287 | [[package]] 1288 | name = "rustc_version" 1289 | version = "0.2.3" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 1292 | dependencies = [ 1293 | "semver", 1294 | ] 1295 | 1296 | [[package]] 1297 | name = "rustix" 1298 | version = "0.37.22" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "8818fa822adcc98b18fedbb3632a6a33213c070556b5aa7c4c8cc21cff565c4c" 1301 | dependencies = [ 1302 | "bitflags 1.3.2", 1303 | "errno", 1304 | "io-lifetimes", 1305 | "libc", 1306 | "linux-raw-sys 0.3.8", 1307 | "windows-sys", 1308 | ] 1309 | 1310 | [[package]] 1311 | name = "rustix" 1312 | version = "0.38.2" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "aabcb0461ebd01d6b79945797c27f8529082226cb630a9865a71870ff63532a4" 1315 | dependencies = [ 1316 | "bitflags 2.3.3", 1317 | "errno", 1318 | "libc", 1319 | "linux-raw-sys 0.4.3", 1320 | "windows-sys", 1321 | ] 1322 | 1323 | [[package]] 1324 | name = "scopeguard" 1325 | version = "1.1.0" 1326 | source = "registry+https://github.com/rust-lang/crates.io-index" 1327 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1328 | 1329 | [[package]] 1330 | name = "semver" 1331 | version = "0.9.0" 1332 | source = "registry+https://github.com/rust-lang/crates.io-index" 1333 | checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 1334 | dependencies = [ 1335 | "semver-parser", 1336 | ] 1337 | 1338 | [[package]] 1339 | name = "semver-parser" 1340 | version = "0.7.0" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 1343 | 1344 | [[package]] 1345 | name = "serde" 1346 | version = "1.0.166" 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" 1348 | checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" 1349 | dependencies = [ 1350 | "serde_derive", 1351 | ] 1352 | 1353 | [[package]] 1354 | name = "serde_derive" 1355 | version = "1.0.166" 1356 | source = "registry+https://github.com/rust-lang/crates.io-index" 1357 | checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" 1358 | dependencies = [ 1359 | "proc-macro2", 1360 | "quote", 1361 | "syn 2.0.23", 1362 | ] 1363 | 1364 | [[package]] 1365 | name = "serde_repr" 1366 | version = "0.1.13" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "6f0a21fba416426ac927b1691996e82079f8b6156e920c85345f135b2e9ba2de" 1369 | dependencies = [ 1370 | "proc-macro2", 1371 | "quote", 1372 | "syn 2.0.23", 1373 | ] 1374 | 1375 | [[package]] 1376 | name = "sha1" 1377 | version = "0.10.5" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1380 | dependencies = [ 1381 | "cfg-if 1.0.0", 1382 | "cpufeatures", 1383 | "digest", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "shlex" 1388 | version = "1.1.0" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" 1391 | 1392 | [[package]] 1393 | name = "signal-hook" 1394 | version = "0.3.15" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 1397 | dependencies = [ 1398 | "libc", 1399 | "signal-hook-registry", 1400 | ] 1401 | 1402 | [[package]] 1403 | name = "signal-hook-mio" 1404 | version = "0.2.3" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 1407 | dependencies = [ 1408 | "libc", 1409 | "mio", 1410 | "signal-hook", 1411 | ] 1412 | 1413 | [[package]] 1414 | name = "signal-hook-registry" 1415 | version = "1.4.1" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 1418 | dependencies = [ 1419 | "libc", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "slab" 1424 | version = "0.4.8" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 1427 | dependencies = [ 1428 | "autocfg", 1429 | ] 1430 | 1431 | [[package]] 1432 | name = "slice-deque" 1433 | version = "0.3.0" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "31ef6ee280cdefba6d2d0b4b78a84a1c1a3f3a4cec98c2d4231c8bc225de0f25" 1436 | dependencies = [ 1437 | "libc", 1438 | "mach", 1439 | "winapi", 1440 | ] 1441 | 1442 | [[package]] 1443 | name = "smallvec" 1444 | version = "0.6.14" 1445 | source = "registry+https://github.com/rust-lang/crates.io-index" 1446 | checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" 1447 | dependencies = [ 1448 | "maybe-uninit", 1449 | ] 1450 | 1451 | [[package]] 1452 | name = "smallvec" 1453 | version = "1.10.0" 1454 | source = "registry+https://github.com/rust-lang/crates.io-index" 1455 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1456 | 1457 | [[package]] 1458 | name = "socket2" 1459 | version = "0.4.9" 1460 | source = "registry+https://github.com/rust-lang/crates.io-index" 1461 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 1462 | dependencies = [ 1463 | "libc", 1464 | "winapi", 1465 | ] 1466 | 1467 | [[package]] 1468 | name = "static_assertions" 1469 | version = "1.1.0" 1470 | source = "registry+https://github.com/rust-lang/crates.io-index" 1471 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1472 | 1473 | [[package]] 1474 | name = "stdweb" 1475 | version = "0.1.3" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" 1478 | 1479 | [[package]] 1480 | name = "strsim" 1481 | version = "0.10.0" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" 1484 | 1485 | [[package]] 1486 | name = "syn" 1487 | version = "1.0.109" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1490 | dependencies = [ 1491 | "proc-macro2", 1492 | "quote", 1493 | "unicode-ident", 1494 | ] 1495 | 1496 | [[package]] 1497 | name = "syn" 1498 | version = "2.0.23" 1499 | source = "registry+https://github.com/rust-lang/crates.io-index" 1500 | checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" 1501 | dependencies = [ 1502 | "proc-macro2", 1503 | "quote", 1504 | "unicode-ident", 1505 | ] 1506 | 1507 | [[package]] 1508 | name = "tauri-winrt-notification" 1509 | version = "0.1.2" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "4f5bff1d532fead7c43324a0fa33643b8621a47ce2944a633be4cb6c0240898f" 1512 | dependencies = [ 1513 | "quick-xml", 1514 | "windows", 1515 | ] 1516 | 1517 | [[package]] 1518 | name = "tempfile" 1519 | version = "3.6.0" 1520 | source = "registry+https://github.com/rust-lang/crates.io-index" 1521 | checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" 1522 | dependencies = [ 1523 | "autocfg", 1524 | "cfg-if 1.0.0", 1525 | "fastrand", 1526 | "redox_syscall 0.3.5", 1527 | "rustix 0.37.22", 1528 | "windows-sys", 1529 | ] 1530 | 1531 | [[package]] 1532 | name = "thiserror" 1533 | version = "1.0.43" 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" 1535 | checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42" 1536 | dependencies = [ 1537 | "thiserror-impl", 1538 | ] 1539 | 1540 | [[package]] 1541 | name = "thiserror-impl" 1542 | version = "1.0.43" 1543 | source = "registry+https://github.com/rust-lang/crates.io-index" 1544 | checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f" 1545 | dependencies = [ 1546 | "proc-macro2", 1547 | "quote", 1548 | "syn 2.0.23", 1549 | ] 1550 | 1551 | [[package]] 1552 | name = "time" 1553 | version = "0.3.22" 1554 | source = "registry+https://github.com/rust-lang/crates.io-index" 1555 | checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd" 1556 | dependencies = [ 1557 | "serde", 1558 | "time-core", 1559 | ] 1560 | 1561 | [[package]] 1562 | name = "time-core" 1563 | version = "0.1.1" 1564 | source = "registry+https://github.com/rust-lang/crates.io-index" 1565 | checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" 1566 | 1567 | [[package]] 1568 | name = "tinyvec" 1569 | version = "1.6.0" 1570 | source = "registry+https://github.com/rust-lang/crates.io-index" 1571 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1572 | dependencies = [ 1573 | "tinyvec_macros", 1574 | ] 1575 | 1576 | [[package]] 1577 | name = "tinyvec_macros" 1578 | version = "0.1.1" 1579 | source = "registry+https://github.com/rust-lang/crates.io-index" 1580 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1581 | 1582 | [[package]] 1583 | name = "toml_datetime" 1584 | version = "0.6.3" 1585 | source = "registry+https://github.com/rust-lang/crates.io-index" 1586 | checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" 1587 | 1588 | [[package]] 1589 | name = "toml_edit" 1590 | version = "0.19.11" 1591 | source = "registry+https://github.com/rust-lang/crates.io-index" 1592 | checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" 1593 | dependencies = [ 1594 | "indexmap", 1595 | "toml_datetime", 1596 | "winnow", 1597 | ] 1598 | 1599 | [[package]] 1600 | name = "tracing" 1601 | version = "0.1.37" 1602 | source = "registry+https://github.com/rust-lang/crates.io-index" 1603 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1604 | dependencies = [ 1605 | "cfg-if 1.0.0", 1606 | "pin-project-lite", 1607 | "tracing-attributes", 1608 | "tracing-core", 1609 | ] 1610 | 1611 | [[package]] 1612 | name = "tracing-attributes" 1613 | version = "0.1.26" 1614 | source = "registry+https://github.com/rust-lang/crates.io-index" 1615 | checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" 1616 | dependencies = [ 1617 | "proc-macro2", 1618 | "quote", 1619 | "syn 2.0.23", 1620 | ] 1621 | 1622 | [[package]] 1623 | name = "tracing-core" 1624 | version = "0.1.31" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 1627 | dependencies = [ 1628 | "once_cell", 1629 | ] 1630 | 1631 | [[package]] 1632 | name = "typenum" 1633 | version = "1.16.0" 1634 | source = "registry+https://github.com/rust-lang/crates.io-index" 1635 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1636 | 1637 | [[package]] 1638 | name = "uds_windows" 1639 | version = "1.0.2" 1640 | source = "registry+https://github.com/rust-lang/crates.io-index" 1641 | checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" 1642 | dependencies = [ 1643 | "tempfile", 1644 | "winapi", 1645 | ] 1646 | 1647 | [[package]] 1648 | name = "unicode-ident" 1649 | version = "1.0.10" 1650 | source = "registry+https://github.com/rust-lang/crates.io-index" 1651 | checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" 1652 | 1653 | [[package]] 1654 | name = "utf8parse" 1655 | version = "0.2.1" 1656 | source = "registry+https://github.com/rust-lang/crates.io-index" 1657 | checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" 1658 | 1659 | [[package]] 1660 | name = "version_check" 1661 | version = "0.9.4" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1664 | 1665 | [[package]] 1666 | name = "void" 1667 | version = "1.0.2" 1668 | source = "registry+https://github.com/rust-lang/crates.io-index" 1669 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 1670 | 1671 | [[package]] 1672 | name = "waker-fn" 1673 | version = "1.1.0" 1674 | source = "registry+https://github.com/rust-lang/crates.io-index" 1675 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 1676 | 1677 | [[package]] 1678 | name = "wasi" 1679 | version = "0.11.0+wasi-snapshot-preview1" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1682 | 1683 | [[package]] 1684 | name = "wasm-bindgen" 1685 | version = "0.2.87" 1686 | source = "registry+https://github.com/rust-lang/crates.io-index" 1687 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 1688 | dependencies = [ 1689 | "cfg-if 1.0.0", 1690 | "wasm-bindgen-macro", 1691 | ] 1692 | 1693 | [[package]] 1694 | name = "wasm-bindgen-backend" 1695 | version = "0.2.87" 1696 | source = "registry+https://github.com/rust-lang/crates.io-index" 1697 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 1698 | dependencies = [ 1699 | "bumpalo", 1700 | "log", 1701 | "once_cell", 1702 | "proc-macro2", 1703 | "quote", 1704 | "syn 2.0.23", 1705 | "wasm-bindgen-shared", 1706 | ] 1707 | 1708 | [[package]] 1709 | name = "wasm-bindgen-macro" 1710 | version = "0.2.87" 1711 | source = "registry+https://github.com/rust-lang/crates.io-index" 1712 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 1713 | dependencies = [ 1714 | "quote", 1715 | "wasm-bindgen-macro-support", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "wasm-bindgen-macro-support" 1720 | version = "0.2.87" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 1723 | dependencies = [ 1724 | "proc-macro2", 1725 | "quote", 1726 | "syn 2.0.23", 1727 | "wasm-bindgen-backend", 1728 | "wasm-bindgen-shared", 1729 | ] 1730 | 1731 | [[package]] 1732 | name = "wasm-bindgen-shared" 1733 | version = "0.2.87" 1734 | source = "registry+https://github.com/rust-lang/crates.io-index" 1735 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 1736 | 1737 | [[package]] 1738 | name = "web-sys" 1739 | version = "0.3.64" 1740 | source = "registry+https://github.com/rust-lang/crates.io-index" 1741 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 1742 | dependencies = [ 1743 | "js-sys", 1744 | "wasm-bindgen", 1745 | ] 1746 | 1747 | [[package]] 1748 | name = "winapi" 1749 | version = "0.3.9" 1750 | source = "registry+https://github.com/rust-lang/crates.io-index" 1751 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1752 | dependencies = [ 1753 | "winapi-i686-pc-windows-gnu", 1754 | "winapi-x86_64-pc-windows-gnu", 1755 | ] 1756 | 1757 | [[package]] 1758 | name = "winapi-i686-pc-windows-gnu" 1759 | version = "0.4.0" 1760 | source = "registry+https://github.com/rust-lang/crates.io-index" 1761 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1762 | 1763 | [[package]] 1764 | name = "winapi-x86_64-pc-windows-gnu" 1765 | version = "0.4.0" 1766 | source = "registry+https://github.com/rust-lang/crates.io-index" 1767 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1768 | 1769 | [[package]] 1770 | name = "windows" 1771 | version = "0.39.0" 1772 | source = "registry+https://github.com/rust-lang/crates.io-index" 1773 | checksum = "f1c4bd0a50ac6020f65184721f758dba47bb9fbc2133df715ec74a237b26794a" 1774 | dependencies = [ 1775 | "windows_aarch64_msvc 0.39.0", 1776 | "windows_i686_gnu 0.39.0", 1777 | "windows_i686_msvc 0.39.0", 1778 | "windows_x86_64_gnu 0.39.0", 1779 | "windows_x86_64_msvc 0.39.0", 1780 | ] 1781 | 1782 | [[package]] 1783 | name = "windows-sys" 1784 | version = "0.48.0" 1785 | source = "registry+https://github.com/rust-lang/crates.io-index" 1786 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1787 | dependencies = [ 1788 | "windows-targets", 1789 | ] 1790 | 1791 | [[package]] 1792 | name = "windows-targets" 1793 | version = "0.48.1" 1794 | source = "registry+https://github.com/rust-lang/crates.io-index" 1795 | checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 1796 | dependencies = [ 1797 | "windows_aarch64_gnullvm", 1798 | "windows_aarch64_msvc 0.48.0", 1799 | "windows_i686_gnu 0.48.0", 1800 | "windows_i686_msvc 0.48.0", 1801 | "windows_x86_64_gnu 0.48.0", 1802 | "windows_x86_64_gnullvm", 1803 | "windows_x86_64_msvc 0.48.0", 1804 | ] 1805 | 1806 | [[package]] 1807 | name = "windows_aarch64_gnullvm" 1808 | version = "0.48.0" 1809 | source = "registry+https://github.com/rust-lang/crates.io-index" 1810 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 1811 | 1812 | [[package]] 1813 | name = "windows_aarch64_msvc" 1814 | version = "0.39.0" 1815 | source = "registry+https://github.com/rust-lang/crates.io-index" 1816 | checksum = "ec7711666096bd4096ffa835238905bb33fb87267910e154b18b44eaabb340f2" 1817 | 1818 | [[package]] 1819 | name = "windows_aarch64_msvc" 1820 | version = "0.48.0" 1821 | source = "registry+https://github.com/rust-lang/crates.io-index" 1822 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 1823 | 1824 | [[package]] 1825 | name = "windows_i686_gnu" 1826 | version = "0.39.0" 1827 | source = "registry+https://github.com/rust-lang/crates.io-index" 1828 | checksum = "763fc57100a5f7042e3057e7e8d9bdd7860d330070251a73d003563a3bb49e1b" 1829 | 1830 | [[package]] 1831 | name = "windows_i686_gnu" 1832 | version = "0.48.0" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 1835 | 1836 | [[package]] 1837 | name = "windows_i686_msvc" 1838 | version = "0.39.0" 1839 | source = "registry+https://github.com/rust-lang/crates.io-index" 1840 | checksum = "7bc7cbfe58828921e10a9f446fcaaf649204dcfe6c1ddd712c5eebae6bda1106" 1841 | 1842 | [[package]] 1843 | name = "windows_i686_msvc" 1844 | version = "0.48.0" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 1847 | 1848 | [[package]] 1849 | name = "windows_x86_64_gnu" 1850 | version = "0.39.0" 1851 | source = "registry+https://github.com/rust-lang/crates.io-index" 1852 | checksum = "6868c165637d653ae1e8dc4d82c25d4f97dd6605eaa8d784b5c6e0ab2a252b65" 1853 | 1854 | [[package]] 1855 | name = "windows_x86_64_gnu" 1856 | version = "0.48.0" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 1859 | 1860 | [[package]] 1861 | name = "windows_x86_64_gnullvm" 1862 | version = "0.48.0" 1863 | source = "registry+https://github.com/rust-lang/crates.io-index" 1864 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 1865 | 1866 | [[package]] 1867 | name = "windows_x86_64_msvc" 1868 | version = "0.39.0" 1869 | source = "registry+https://github.com/rust-lang/crates.io-index" 1870 | checksum = "5e4d40883ae9cae962787ca76ba76390ffa29214667a111db9e0a1ad8377e809" 1871 | 1872 | [[package]] 1873 | name = "windows_x86_64_msvc" 1874 | version = "0.48.0" 1875 | source = "registry+https://github.com/rust-lang/crates.io-index" 1876 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 1877 | 1878 | [[package]] 1879 | name = "winnow" 1880 | version = "0.4.7" 1881 | source = "registry+https://github.com/rust-lang/crates.io-index" 1882 | checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" 1883 | dependencies = [ 1884 | "memchr", 1885 | ] 1886 | 1887 | [[package]] 1888 | name = "xdg-home" 1889 | version = "1.0.0" 1890 | source = "registry+https://github.com/rust-lang/crates.io-index" 1891 | checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" 1892 | dependencies = [ 1893 | "nix 0.26.2", 1894 | "winapi", 1895 | ] 1896 | 1897 | [[package]] 1898 | name = "zbus" 1899 | version = "3.14.1" 1900 | source = "registry+https://github.com/rust-lang/crates.io-index" 1901 | checksum = "31de390a2d872e4cd04edd71b425e29853f786dc99317ed72d73d6fcf5ebb948" 1902 | dependencies = [ 1903 | "async-broadcast", 1904 | "async-executor", 1905 | "async-fs", 1906 | "async-io", 1907 | "async-lock", 1908 | "async-process", 1909 | "async-recursion", 1910 | "async-task", 1911 | "async-trait", 1912 | "blocking", 1913 | "byteorder", 1914 | "derivative", 1915 | "enumflags2", 1916 | "event-listener", 1917 | "futures-core", 1918 | "futures-sink", 1919 | "futures-util", 1920 | "hex", 1921 | "nix 0.26.2", 1922 | "once_cell", 1923 | "ordered-stream", 1924 | "rand", 1925 | "serde", 1926 | "serde_repr", 1927 | "sha1", 1928 | "static_assertions", 1929 | "tracing", 1930 | "uds_windows", 1931 | "winapi", 1932 | "xdg-home", 1933 | "zbus_macros", 1934 | "zbus_names", 1935 | "zvariant", 1936 | ] 1937 | 1938 | [[package]] 1939 | name = "zbus_macros" 1940 | version = "3.14.1" 1941 | source = "registry+https://github.com/rust-lang/crates.io-index" 1942 | checksum = "41d1794a946878c0e807f55a397187c11fc7a038ba5d868e7db4f3bd7760bc9d" 1943 | dependencies = [ 1944 | "proc-macro-crate", 1945 | "proc-macro2", 1946 | "quote", 1947 | "regex", 1948 | "syn 1.0.109", 1949 | "zvariant_utils", 1950 | ] 1951 | 1952 | [[package]] 1953 | name = "zbus_names" 1954 | version = "2.6.0" 1955 | source = "registry+https://github.com/rust-lang/crates.io-index" 1956 | checksum = "fb80bb776dbda6e23d705cf0123c3b95df99c4ebeaec6c2599d4a5419902b4a9" 1957 | dependencies = [ 1958 | "serde", 1959 | "static_assertions", 1960 | "zvariant", 1961 | ] 1962 | 1963 | [[package]] 1964 | name = "zvariant" 1965 | version = "3.15.0" 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" 1967 | checksum = "44b291bee0d960c53170780af148dca5fa260a63cdd24f1962fa82e03e53338c" 1968 | dependencies = [ 1969 | "byteorder", 1970 | "enumflags2", 1971 | "libc", 1972 | "serde", 1973 | "static_assertions", 1974 | "zvariant_derive", 1975 | ] 1976 | 1977 | [[package]] 1978 | name = "zvariant_derive" 1979 | version = "3.15.0" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "934d7a7dfc310d6ee06c87ffe88ef4eca7d3e37bb251dece2ef93da8f17d8ecd" 1982 | dependencies = [ 1983 | "proc-macro-crate", 1984 | "proc-macro2", 1985 | "quote", 1986 | "syn 1.0.109", 1987 | "zvariant_utils", 1988 | ] 1989 | 1990 | [[package]] 1991 | name = "zvariant_utils" 1992 | version = "1.0.1" 1993 | source = "registry+https://github.com/rust-lang/crates.io-index" 1994 | checksum = "7234f0d811589db492d16893e3f21e8e2fd282e6d01b0cddee310322062cc200" 1995 | dependencies = [ 1996 | "proc-macro2", 1997 | "quote", 1998 | "syn 1.0.109", 1999 | ] 2000 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "porsmo" 3 | version = "0.3.3" 4 | edition = "2021" 5 | readme = "README.md" 6 | license = "MIT" 7 | description = "A pomodoro, timer and stopwatch, all in one app" 8 | homepage = "https://github.com/ColorCookie-dev/porsmo" 9 | repository = "https://github.com/ColorCookie-dev/porsmo" 10 | keywords = ["cli", "pomodoro", "timer", "countdown"] 11 | categories = ["command-line-utilities"] 12 | 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [dependencies] 16 | notify-rust = "4" 17 | rodio = "0.12.0" 18 | crossterm = "0.26.1" 19 | clap = { version = "4.3.0", features = ["derive"] } 20 | thiserror = "1.0.43" 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Color Cookie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Porsmo 2 | A rust program for pomodoro, timer, stopwatch - all in one. 3 | -------------------------------------------------------------------------------- /src/alert.rs: -------------------------------------------------------------------------------- 1 | use notify_rust::Notification; 2 | use rodio::{Decoder, OutputStream, Sink}; 3 | use std::{io::Cursor, thread}; 4 | 5 | #[derive(Debug, thiserror::Error)] 6 | pub enum AlertError { 7 | #[error("Failed to show notification")] 8 | FailedToNotify(#[from] notify_rust::error::Error), 9 | 10 | #[error(transparent)] 11 | SoundError(#[from] SoundError), 12 | } 13 | 14 | pub fn notify_default(title: impl AsRef, message: impl AsRef) -> Result<(), AlertError> { 15 | Notification::new() 16 | .appname("Porsmo") 17 | .summary(title.as_ref()) 18 | .body(message.as_ref()) 19 | .show()?; 20 | Ok(()) 21 | } 22 | pub fn alert(title: impl Into, message: impl Into) { 23 | let title = title.into(); 24 | let message = message.into(); 25 | thread::spawn(move || { 26 | notify_default(title, message).unwrap(); 27 | play_bell().unwrap(); 28 | }); 29 | } 30 | 31 | #[derive(Debug, Clone, Copy)] 32 | pub struct Alerter(bool); 33 | 34 | impl Default for Alerter { 35 | fn default() -> Self { 36 | Self(false) 37 | } 38 | } 39 | 40 | impl Alerter { 41 | pub fn alert_once(&mut self, title: impl Into, message: impl Into) { 42 | if !self.0 { 43 | self.0 = true; 44 | alert(title, message); 45 | } 46 | } 47 | 48 | pub fn reset(&mut self) { 49 | self.0 = false; 50 | } 51 | } 52 | 53 | #[derive(Debug, thiserror::Error)] 54 | pub enum SoundError { 55 | #[error(transparent)] 56 | StreamError(#[from] rodio::StreamError), 57 | 58 | #[error(transparent)] 59 | DevicesError(#[from] rodio::DevicesError), 60 | 61 | #[error(transparent)] 62 | DecoderError(#[from] rodio::decoder::DecoderError), 63 | 64 | #[error("No devices found")] 65 | NoDevice, 66 | } 67 | 68 | impl From for SoundError { 69 | fn from(err: rodio::PlayError) -> Self { 70 | match err { 71 | rodio::PlayError::NoDevice => Self::NoDevice, 72 | rodio::PlayError::DecoderError(e) => Self::DecoderError(e), 73 | } 74 | } 75 | } 76 | 77 | pub fn play_bell() -> Result<(), SoundError> { 78 | let (_stream, stream_handle) = OutputStream::try_default()?; 79 | 80 | // let volume = 0.5; 81 | let audio = Decoder::new(Cursor::new(include_bytes!("notify_end.wav")))?; 82 | Sink::try_new(&stream_handle).map(|sink| { 83 | sink.append(audio); 84 | // sink.set_volume(volume); 85 | sink.sleep_until_end(); 86 | })?; 87 | 88 | Ok(()) 89 | } 90 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use crate::format::parse_duration; 4 | use clap::{Parser, Subcommand}; 5 | 6 | #[derive(Parser)] 7 | #[command(author, version, about)] 8 | pub struct Cli { 9 | #[command(subcommand, name = "mode")] 10 | pub mode: Option, 11 | } 12 | 13 | #[derive(Subcommand)] 14 | pub enum CounterMode { 15 | /// alias: s, stopwatch, counts up until you tell it to stop 16 | #[command(name = "stopwatch", alias = "s")] 17 | Stopwatch /* { 18 | #[arg( 19 | value_parser = parse_duration, 20 | default_value = "0s", 21 | value_name = "time" 22 | )] 23 | /// start from a particular time: example values: 30m 20m 40m 2h25m30s 24 | start_time: Duration, 25 | }*/, 26 | /// alias: t, timer, counts down until you tell it to stop, or it ends 27 | #[command(name = "timer", alias = "t")] 28 | Timer { 29 | /// target time: example values 30m 20m 40m 2h25m30s 30 | #[arg(value_parser = parse_duration, value_name = "time")] 31 | target: Duration, 32 | }, 33 | /// alias: p, pomodoro, for all you productivity needs (default) 34 | #[command(name = "pomodoro", alias = "p")] 35 | Pomodoro { 36 | #[clap(subcommand, name = "mode")] 37 | mode: PomoMode, 38 | ///Display a message after quitting the pomodoro timer 39 | #[arg(short, name = "exitmessage")] 40 | exitmessage: bool, 41 | }, 42 | } 43 | 44 | #[derive(Subcommand, Debug)] 45 | pub enum PomoMode { 46 | /// alias: s, short pomodoro, with 25m, 5m, 10m values (default) 47 | #[command(name = "short", alias = "s")] 48 | Short, 49 | /// alias: l, long pomodoro, with 55m, 10m, 20m values 50 | #[command(name = "long", alias = "l")] 51 | Long, 52 | /// alias: c, custom pomodoro, with any specified values 53 | #[command(name = "custom", alias = "c")] 54 | Custom { 55 | /// target work time: example values 30m 20m 40m 2h25m30s 56 | #[arg(value_parser = parse_duration, value_name = "work-time")] 57 | work_time: Duration, 58 | /// target break time: example values 30m 20m 40m 2h25m30s 59 | #[arg(value_parser = parse_duration, value_name = "break-time")] 60 | break_time: Duration, 61 | /// target long break time: example values 30m 20m 40m 2h25m30s 62 | #[arg(value_parser = parse_duration, value_name = "long-break-time")] 63 | long_break: Duration, 64 | }, 65 | } 66 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use std::num::ParseIntError; 2 | 3 | #[derive(Debug, thiserror::Error)] 4 | pub enum PorsmoError { 5 | #[error("Error entering raw mode in terminal")] 6 | FailedRawModeEnter(#[source] crossterm::ErrorKind), 7 | 8 | #[error("Error initializing terminal with alternate screen and mouse capture")] 9 | FailedInitialization(#[source] crossterm::ErrorKind), 10 | 11 | #[error("Wrong format for time")] 12 | WrongFormatError, 13 | 14 | #[error(transparent)] 15 | ParseIntError(#[from] ParseIntError), 16 | 17 | #[error(transparent)] 18 | CrosstermError(#[from] crossterm::ErrorKind), 19 | } 20 | -------------------------------------------------------------------------------- /src/format.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | use std::borrow::Borrow; 3 | 4 | use crate::prelude::*; 5 | 6 | pub fn format_duration(dur: impl Borrow) -> String { 7 | let dur = dur.borrow(); 8 | let total_secs = dur.as_secs(); 9 | let secs = total_secs % 60; 10 | let mins = ((total_secs - secs) % (60 * 60)) / 60; 11 | let hours = (total_secs - mins * 60 - secs) / (60 * 60); 12 | format!("{hours}h {mins}m {secs}s") 13 | } 14 | 15 | pub fn parse_duration(text: &str) -> Result { 16 | let (hours, text) = match text.split_once('h') { 17 | Some((hours, rest)) => { 18 | let hours = hours.parse::()?; 19 | (Duration::from_secs(hours * 3600), rest) 20 | }, 21 | None => (Duration::ZERO, text), 22 | }; 23 | 24 | let (mins, text) = match text.split_once('m') { 25 | Some((mins, text)) => { 26 | let mins = mins.parse::()?; 27 | (Duration::from_secs(mins * 60), text) 28 | }, 29 | None => (Duration::ZERO, text), 30 | }; 31 | 32 | let (secs, _) = match text.split_once('s') { 33 | Some((secs, "")) => { 34 | let secs = secs.parse::()?; 35 | (Duration::from_secs(secs), text) 36 | }, 37 | None if text == "" => (Duration::ZERO, ""), 38 | _ => return Err(PorsmoError::WrongFormatError), 39 | }; 40 | 41 | Ok(hours + mins + secs) 42 | } 43 | -------------------------------------------------------------------------------- /src/input.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use std::time::Duration; 3 | 4 | use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; 5 | 6 | pub enum Command { 7 | Quit, 8 | Pause, 9 | Resume, 10 | Toggle, 11 | Enter, 12 | Skip, 13 | Yes, 14 | No, 15 | Invalid, 16 | } 17 | 18 | impl From for Command { 19 | fn from(event: Event) -> Self { 20 | match event { 21 | Event::Key(key) => Command::from(key), 22 | _ => Command::Invalid, 23 | } 24 | } 25 | } 26 | 27 | impl From for Command { 28 | fn from(key: KeyEvent) -> Self { 29 | match key { 30 | KeyEvent { 31 | code: KeyCode::Char('q'), 32 | kind: KeyEventKind::Press, 33 | modifiers: KeyModifiers::NONE, 34 | .. 35 | } => Self::Quit, 36 | KeyEvent { 37 | code: KeyCode::Char('c'), 38 | kind: KeyEventKind::Press, 39 | modifiers: KeyModifiers::CONTROL, 40 | .. 41 | } => Self::Quit, 42 | KeyEvent { 43 | code: KeyCode::Char('z'), 44 | kind: KeyEventKind::Press, 45 | modifiers: KeyModifiers::CONTROL, 46 | .. 47 | } => Self::Quit, 48 | KeyEvent { 49 | code: KeyCode::Char(' '), 50 | kind: KeyEventKind::Press, 51 | modifiers: KeyModifiers::NONE, 52 | .. 53 | } => Self::Toggle, 54 | KeyEvent { 55 | code: KeyCode::Enter, 56 | kind: KeyEventKind::Press, 57 | modifiers: KeyModifiers::NONE, 58 | .. 59 | } => Self::Enter, 60 | KeyEvent { 61 | code: KeyCode::Char('S'), 62 | kind: KeyEventKind::Press, 63 | modifiers: KeyModifiers::SHIFT, 64 | .. 65 | } => Self::Skip, 66 | KeyEvent { 67 | code: KeyCode::Char('y'), 68 | kind: KeyEventKind::Press, 69 | modifiers: KeyModifiers::NONE, 70 | .. 71 | } => Self::Yes, 72 | KeyEvent { 73 | code: KeyCode::Char('n'), 74 | kind: KeyEventKind::Press, 75 | modifiers: KeyModifiers::NONE, 76 | .. 77 | } => Self::No, 78 | KeyEvent { 79 | code: KeyCode::Char('t'), 80 | kind: KeyEventKind::Press, 81 | modifiers: KeyModifiers::NONE, 82 | .. 83 | } => Self::Toggle, 84 | KeyEvent { 85 | code: KeyCode::Char('p'), 86 | kind: KeyEventKind::Press, 87 | modifiers: KeyModifiers::NONE, 88 | .. 89 | } => Self::Pause, 90 | KeyEvent { 91 | code: KeyCode::Char('c'), 92 | kind: KeyEventKind::Press, 93 | modifiers: KeyModifiers::NONE, 94 | .. 95 | } => Self::Resume, 96 | _ => Self::Invalid, 97 | } 98 | } 99 | } 100 | 101 | pub struct CommandIter; 102 | 103 | impl Iterator for CommandIter { 104 | type Item = Result; 105 | 106 | fn next(&mut self) -> Option { 107 | Some(get_event(TIMEOUT).transpose()?.map(Command::from)) 108 | } 109 | } 110 | 111 | pub const TIMEOUT: Duration = Duration::from_millis(250); 112 | 113 | pub fn get_event(timeout: Duration) -> Result> { 114 | if event::poll(timeout)? { 115 | Ok(Some(event::read()?)) 116 | } else { 117 | Ok(None) 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | mod alert; 2 | mod cli; 3 | mod error; 4 | mod format; 5 | mod input; 6 | mod pomodoro; 7 | mod prelude; 8 | mod stopwatch; 9 | mod terminal; 10 | mod timer; 11 | 12 | use crate::input::{get_event, Command, TIMEOUT}; 13 | use crate::pomodoro::PomodoroConfig; 14 | use clap::Parser; 15 | use cli::{Cli, CounterMode, PomoMode}; 16 | use pomodoro::PomodoroUI; 17 | use prelude::*; 18 | use std::io::Write; 19 | use stopwatch::StopwatchUI; 20 | use terminal::TerminalHandler; 21 | use timer::TimerUI; 22 | 23 | fn main() -> Result<()> { 24 | let args = Cli::parse(); 25 | let mut terminal = TerminalHandler::new()?; 26 | let stdout = terminal.stdout(); 27 | let exitmessagestring = match args.mode { 28 | Some(CounterMode::Stopwatch) => StopwatchUI::default().run_ui(stdout)?, 29 | Some(CounterMode::Timer { target }) => TimerUI::new(target).run_ui(stdout)?, 30 | Some(CounterMode::Pomodoro { 31 | mode: PomoMode::Short, 32 | exitmessage: _, 33 | }) => PomodoroUI::new(PomodoroConfig::short()).run_ui(stdout)?, 34 | Some(CounterMode::Pomodoro { 35 | mode: PomoMode::Long, 36 | exitmessage: _, 37 | }) => PomodoroUI::new(PomodoroConfig::long()).run_ui(stdout)?, 38 | Some(CounterMode::Pomodoro { 39 | mode: 40 | PomoMode::Custom { 41 | work_time, 42 | break_time, 43 | long_break, 44 | }, 45 | exitmessage: _, 46 | }) => PomodoroUI::new(PomodoroConfig::new(work_time, break_time, long_break)) 47 | .run_ui(stdout)?, 48 | None => PomodoroUI::new(PomodoroConfig::short()).run_ui(stdout)?, 49 | }; 50 | drop(terminal); 51 | if matches!( 52 | args.mode, 53 | Some(CounterMode::Pomodoro { 54 | mode: _, 55 | exitmessage: true 56 | }) 57 | ) { 58 | println!("{}", exitmessagestring); 59 | } 60 | Ok(()) 61 | } 62 | 63 | pub trait CounterUI: Sized { 64 | fn show(&mut self, out: &mut impl Write) -> Result<()>; 65 | fn update(&mut self, command: Command); 66 | fn run_ui(mut self, out: &mut impl Write) -> Result { 67 | loop { 68 | self.show(out)?; 69 | if let Some(cmd) = get_event(TIMEOUT)?.map(Command::from) { 70 | match cmd { 71 | Command::Quit => break, 72 | cmd => self.update(cmd), 73 | } 74 | } 75 | } 76 | Ok(String::new()) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/notify_end.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ColorCookie-dev/porsmo/a041a9617a54a1753392f051662801c4314ca5e1/src/notify_end.wav -------------------------------------------------------------------------------- /src/pomodoro.rs: -------------------------------------------------------------------------------- 1 | use crate::alert::Alerter; 2 | use crate::input::{get_event, TIMEOUT}; 3 | use crate::stopwatch::Stopwatch; 4 | use crate::terminal::running_color; 5 | use crate::{format::format_duration, input::Command}; 6 | use crate::{prelude::*, CounterUI}; 7 | use crossterm::cursor::{MoveTo, MoveToNextLine}; 8 | use crossterm::style::Print; 9 | use crossterm::terminal::{Clear, ClearType}; 10 | use crossterm::{queue, style::Color, style::Stylize}; 11 | 12 | use std::io::Write; 13 | use std::time::{Duration, Instant}; 14 | 15 | #[derive(Clone, Copy, Debug, Default)] 16 | pub enum Mode { 17 | #[default] 18 | Work, 19 | Break, 20 | LongBreak, 21 | } 22 | 23 | #[derive(Copy, Clone, Debug)] 24 | pub struct PomodoroConfig { 25 | pub work_time: Duration, 26 | pub break_time: Duration, 27 | pub long_break: Duration, 28 | } 29 | 30 | impl Default for PomodoroConfig { 31 | fn default() -> Self { 32 | Self::short() 33 | } 34 | } 35 | 36 | impl PomodoroConfig { 37 | pub fn new(work_time: Duration, break_time: Duration, long_break: Duration) -> Self { 38 | Self { 39 | work_time, 40 | break_time, 41 | long_break, 42 | } 43 | } 44 | 45 | pub fn short() -> Self { 46 | Self { 47 | work_time: Duration::from_secs(25 * 60), 48 | break_time: Duration::from_secs(5 * 60), 49 | long_break: Duration::from_secs(10 * 60), 50 | } 51 | } 52 | 53 | pub fn long() -> Self { 54 | Self { 55 | work_time: Duration::from_secs(55 * 60), 56 | break_time: Duration::from_secs(10 * 60), 57 | long_break: Duration::from_secs(20 * 60), 58 | } 59 | } 60 | 61 | pub fn current_target(&self, mode: Mode) -> Duration { 62 | match mode { 63 | Mode::Work => self.work_time, 64 | Mode::Break => self.break_time, 65 | Mode::LongBreak => self.long_break, 66 | } 67 | } 68 | } 69 | 70 | #[derive(Debug, Clone, Copy)] 71 | pub struct Session { 72 | pub mode: Mode, 73 | pub round: u32, 74 | pub elapsed_time: [Duration; 2], 75 | } 76 | 77 | impl Default for Session { 78 | fn default() -> Self { 79 | Self { 80 | mode: Mode::default(), 81 | round: 1, 82 | elapsed_time: [Duration::ZERO; 2], 83 | } 84 | } 85 | } 86 | 87 | impl Session { 88 | pub fn advance(self, duration: Duration) -> Self { 89 | match self.mode { 90 | Mode::Work if self.round % 4 == 0 => Self { 91 | mode: Mode::LongBreak, 92 | elapsed_time: [self.elapsed_time[0] + duration, self.elapsed_time[1]], 93 | ..self 94 | }, 95 | Mode::Work => Self { 96 | mode: Mode::Break, 97 | elapsed_time: [self.elapsed_time[0] + duration, self.elapsed_time[1]], 98 | ..self 99 | }, 100 | Mode::Break | Mode::LongBreak => Self { 101 | mode: Mode::Work, 102 | round: self.round + 1, 103 | elapsed_time: [self.elapsed_time[0], self.elapsed_time[1] + duration], 104 | }, 105 | } 106 | } 107 | 108 | pub fn next(&self) -> Self { 109 | self.advance(Duration::ZERO) 110 | } 111 | } 112 | 113 | const CONTROLS: &str = "[Q]: quit, [Shift S]: Skip, [Space]: pause/resume"; 114 | const ENDING_CONTROLS: &str = "[Q]: quit, [Shift S]: Skip, [Space]: pause/resume, [Enter]: Next"; 115 | const SKIP_CONTROLS: &str = "[Enter]: Yes, [Q/N]: No"; 116 | 117 | fn default_title(mode: Mode) -> &'static str { 118 | match mode { 119 | Mode::Work => "Pomodoro (Work)", 120 | Mode::Break => "Pomodoro (Break)", 121 | Mode::LongBreak => "Pomodoro (Long Break)", 122 | } 123 | } 124 | 125 | fn end_title(next_mode: Mode) -> &'static str { 126 | match next_mode { 127 | Mode::Work => "Break has ended! Start work?", 128 | Mode::Break => "Work has ended! Start break?", 129 | Mode::LongBreak => "Work has ended! Start a long break", 130 | } 131 | } 132 | 133 | fn alert_message(next_mode: Mode) -> (&'static str, &'static str) { 134 | match next_mode { 135 | Mode::Work => ("Your break ended!", "Time for some work"), 136 | Mode::Break => ("Pomodoro ended!", "Time for a short break"), 137 | Mode::LongBreak => ("Pomodoro 4 sessions complete!", "Time for a long break"), 138 | } 139 | } 140 | 141 | #[derive(Debug, Clone, Copy)] 142 | enum UIMode { 143 | Skip(Duration), 144 | Running(Stopwatch), 145 | } 146 | 147 | impl Default for UIMode { 148 | fn default() -> Self { 149 | Self::Running(Stopwatch::default()) 150 | } 151 | } 152 | 153 | #[derive(Debug, Default, Clone, Copy)] 154 | pub struct PomodoroUI { 155 | config: PomodoroConfig, 156 | session: Session, 157 | ui_mode: UIMode, 158 | alerter: Alerter, 159 | } 160 | 161 | impl PomodoroUI { 162 | pub fn new(config: PomodoroConfig) -> Self { 163 | Self { 164 | config, 165 | ..Default::default() 166 | } 167 | } 168 | } 169 | 170 | impl CounterUI for PomodoroUI { 171 | fn show(&mut self, out: &mut impl Write) -> Result<()> { 172 | pomodoro_show( 173 | out, 174 | &self.config, 175 | &self.ui_mode, 176 | &self.session, 177 | &mut self.alerter, 178 | ) 179 | } 180 | 181 | fn update(&mut self, command: Command) { 182 | pomodoro_update( 183 | command, 184 | &self.config, 185 | &mut self.alerter, 186 | &mut self.ui_mode, 187 | &mut self.session, 188 | ); 189 | } 190 | 191 | fn run_ui(mut self, out: &mut impl Write) -> Result { 192 | loop { 193 | self.show(out)?; 194 | if let Some(cmd) = get_event(TIMEOUT)?.map(Command::from) { 195 | match cmd { 196 | Command::Quit => { 197 | self.session = match self.ui_mode { 198 | UIMode::Skip(elapsed) => self.session.advance(elapsed), 199 | UIMode::Running(stopwatch) => self.session.advance(stopwatch.elapsed()), 200 | }; 201 | break; 202 | } 203 | cmd => self.update(cmd), 204 | } 205 | } 206 | } 207 | Ok(format!( 208 | "You have spent {} working and {} on break. Well done!", 209 | format_duration(self.session.elapsed_time[0]), 210 | format_duration(self.session.elapsed_time[1]), 211 | )) 212 | } 213 | } 214 | 215 | fn pomodoro_update( 216 | command: Command, 217 | config: &PomodoroConfig, 218 | alerter: &mut Alerter, 219 | ui_mode: &mut UIMode, 220 | session: &mut Session, 221 | ) { 222 | match ui_mode { 223 | UIMode::Skip(elapsed) => match command { 224 | Command::Quit | Command::No => { 225 | *ui_mode = UIMode::Running(Stopwatch::new(Some(Instant::now()), *elapsed)) 226 | } 227 | Command::Enter | Command::Yes => { 228 | alerter.reset(); 229 | *session = session.advance(*elapsed); 230 | *ui_mode = UIMode::Running(Stopwatch::default()); 231 | } 232 | _ => (), 233 | }, 234 | UIMode::Running(ref mut stopwatch) => { 235 | let elapsed = stopwatch.elapsed(); 236 | let target = config.current_target(session.mode); 237 | 238 | match command { 239 | Command::Enter if elapsed >= target => { 240 | alerter.reset(); 241 | *session = session.advance(elapsed); 242 | *ui_mode = UIMode::Running(Stopwatch::default()); 243 | } 244 | Command::Pause => stopwatch.stop(), 245 | Command::Resume => stopwatch.start(), 246 | Command::Toggle => stopwatch.toggle(), 247 | Command::Skip => *ui_mode = UIMode::Skip(elapsed), 248 | _ => (), 249 | } 250 | } 251 | } 252 | } 253 | 254 | fn pomodoro_show( 255 | out: &mut impl Write, 256 | config: &PomodoroConfig, 257 | ui_mode: &UIMode, 258 | session: &Session, 259 | alerter: &mut Alerter, 260 | ) -> Result<()> { 261 | let target = config.current_target(session.mode); 262 | let round_number = format!("Session: {}", session.round); 263 | match ui_mode { 264 | UIMode::Skip(..) => { 265 | let (color, skip_to) = match session.next().mode { 266 | Mode::Work => (Color::Red, "skip to work?"), 267 | Mode::Break => (Color::Green, "skip to break?"), 268 | Mode::LongBreak => (Color::Green, "skip to long break?"), 269 | }; 270 | queue!( 271 | out, 272 | MoveTo(0, 0), 273 | Print(skip_to.with(color)), 274 | Clear(ClearType::UntilNewLine), 275 | MoveToNextLine(1), 276 | Print(round_number), 277 | Clear(ClearType::UntilNewLine), 278 | MoveToNextLine(1), 279 | Print(SKIP_CONTROLS), 280 | Clear(ClearType::FromCursorDown), 281 | )?; 282 | } 283 | UIMode::Running(stopwatch) if stopwatch.elapsed() < target => { 284 | let time_left = target.saturating_sub(stopwatch.elapsed()); 285 | 286 | queue!( 287 | out, 288 | MoveTo(0, 0), 289 | Print(default_title(session.mode)), 290 | Clear(ClearType::UntilNewLine), 291 | MoveToNextLine(1), 292 | Print(format_duration(&time_left).with(running_color(stopwatch.started())),), 293 | Clear(ClearType::UntilNewLine), 294 | MoveToNextLine(1), 295 | Print(CONTROLS), 296 | Clear(ClearType::UntilNewLine), 297 | MoveToNextLine(1), 298 | Print(round_number), 299 | Clear(ClearType::FromCursorDown), 300 | )?; 301 | } 302 | UIMode::Running(stopwatch) => { 303 | let excess_time = stopwatch.elapsed().saturating_sub(target); 304 | let (title, message) = alert_message(session.next().mode); 305 | alerter.alert_once(title, message); 306 | 307 | queue!( 308 | out, 309 | MoveTo(0, 0), 310 | Print(end_title(session.next().mode)), 311 | Clear(ClearType::UntilNewLine), 312 | MoveToNextLine(1), 313 | Print( 314 | format!("+{}", format_duration(&excess_time),) 315 | .with(running_color(stopwatch.started())) 316 | ), 317 | Clear(ClearType::UntilNewLine), 318 | MoveToNextLine(1), 319 | Print(ENDING_CONTROLS), 320 | Clear(ClearType::UntilNewLine), 321 | MoveToNextLine(1), 322 | Print(round_number), 323 | Clear(ClearType::UntilNewLine), 324 | MoveToNextLine(1), 325 | Print(message), 326 | Clear(ClearType::FromCursorDown), 327 | )?; 328 | } 329 | } 330 | out.flush()?; 331 | Ok(()) 332 | } 333 | -------------------------------------------------------------------------------- /src/prelude.rs: -------------------------------------------------------------------------------- 1 | pub use crate::error::PorsmoError; 2 | 3 | pub type Result = core::result::Result; 4 | -------------------------------------------------------------------------------- /src/stopwatch.rs: -------------------------------------------------------------------------------- 1 | use std::time::Instant; 2 | use std::{io::Write, time::Duration}; 3 | 4 | use crate::{prelude::*, CounterUI}; 5 | use crate::terminal::running_color; 6 | use crate::{format::format_duration, input::Command}; 7 | use crossterm::{ 8 | cursor::{MoveTo, MoveToNextLine}, 9 | queue, 10 | style::{Print, Stylize}, 11 | terminal::{Clear, ClearType}, 12 | }; 13 | 14 | #[derive(Debug, Clone, Copy)] 15 | pub struct Stopwatch { 16 | start_time: Option, 17 | elapsed_before: Duration, 18 | } 19 | 20 | impl Default for Stopwatch { 21 | fn default() -> Self { 22 | Self { 23 | start_time: Some(Instant::now()), 24 | elapsed_before: Duration::ZERO, 25 | } 26 | } 27 | } 28 | 29 | impl Stopwatch { 30 | pub fn new(start_time: Option, elapsed_before: Duration) -> Self { 31 | Self { 32 | start_time, 33 | elapsed_before, 34 | } 35 | } 36 | 37 | pub fn elapsed(&self) -> Duration { 38 | match self.start_time { 39 | Some(start_time) => self.elapsed_before + start_time.elapsed(), 40 | None => self.elapsed_before, 41 | } 42 | } 43 | 44 | pub fn started(&self) -> bool { 45 | if matches!(self.start_time, None) { 46 | false 47 | } else { 48 | true 49 | } 50 | } 51 | 52 | pub fn start(&mut self) { 53 | if matches!(self.start_time, None) { 54 | self.start_time = Some(Instant::now()); 55 | } 56 | } 57 | 58 | pub fn stop(&mut self) { 59 | if let Some(start_time) = self.start_time { 60 | self.elapsed_before += start_time.elapsed(); 61 | self.start_time = None; 62 | } 63 | } 64 | 65 | pub fn toggle(&mut self) { 66 | match self.start_time { 67 | Some(start_time) => { 68 | self.elapsed_before += start_time.elapsed(); 69 | self.start_time = None; 70 | } 71 | None => { 72 | self.start_time = Some(Instant::now()); 73 | } 74 | } 75 | } 76 | } 77 | 78 | #[derive(Debug, Clone, Copy, Default)] 79 | pub struct StopwatchUI { 80 | stopwatch: Stopwatch, 81 | } 82 | 83 | impl CounterUI for StopwatchUI { 84 | fn show(&mut self, out: &mut impl Write) -> Result<()> { 85 | let elapsed = self.stopwatch.elapsed(); 86 | let is_running = self.stopwatch.started(); 87 | queue!( 88 | out, 89 | MoveTo(0, 0), 90 | Print("Stopwatch"), 91 | Clear(ClearType::UntilNewLine), 92 | MoveToNextLine(1), 93 | Print(format_duration(elapsed).with(running_color(is_running))), 94 | Clear(ClearType::UntilNewLine), 95 | MoveToNextLine(1), 96 | Print("[Q]: quit, [Space]: pause/resume"), 97 | Clear(ClearType::FromCursorDown), 98 | )?; 99 | out.flush()?; 100 | Ok(()) 101 | } 102 | 103 | fn update(&mut self, command: Command) { 104 | match command { 105 | Command::Pause => self.stopwatch.stop(), 106 | Command::Resume => self.stopwatch.start(), 107 | Command::Toggle | Command::Enter => self.stopwatch.toggle(), 108 | _ => (), 109 | } 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/terminal.rs: -------------------------------------------------------------------------------- 1 | use crate::{error::PorsmoError, prelude::*}; 2 | use crossterm::{ 3 | cursor::{Hide, MoveTo, Show}, 4 | execute, 5 | style::Color, 6 | terminal::{ 7 | disable_raw_mode, enable_raw_mode, Clear, ClearType, EnterAlternateScreen, 8 | LeaveAlternateScreen, 9 | }, 10 | }; 11 | use std::io::{stdout, Stdout}; 12 | 13 | pub struct TerminalHandler(Stdout); 14 | 15 | impl TerminalHandler { 16 | pub fn new() -> Result { 17 | enable_raw_mode().map_err(PorsmoError::FailedRawModeEnter)?; 18 | 19 | let mut stdout = std::io::stdout(); 20 | execute!( 21 | &mut stdout, 22 | EnterAlternateScreen, 23 | Hide, 24 | Clear(ClearType::All), 25 | MoveTo(0, 0), 26 | ) 27 | .map_err(PorsmoError::FailedInitialization)?; 28 | 29 | Ok(Self(stdout)) 30 | } 31 | 32 | pub fn stdout(&mut self) -> &mut Stdout { 33 | &mut self.0 34 | } 35 | } 36 | 37 | impl Drop for TerminalHandler { 38 | fn drop(&mut self) { 39 | disable_raw_mode().expect("Failed to disable raw mode"); 40 | execute!(stdout(), Clear(ClearType::All), Show, LeaveAlternateScreen,) 41 | .expect("Failed to reset screen"); 42 | } 43 | } 44 | 45 | pub fn running_color(running: bool) -> Color { 46 | match running { 47 | true => Color::Green, 48 | false => Color::Red, 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/timer.rs: -------------------------------------------------------------------------------- 1 | use crate::alert::Alerter; 2 | use crate::stopwatch::Stopwatch; 3 | use crate::terminal::running_color; 4 | use crate::{format::format_duration, input::Command}; 5 | use crate::{prelude::*, CounterUI}; 6 | use crossterm::terminal::{Clear, ClearType}; 7 | use crossterm::{ 8 | cursor::{MoveTo, MoveToNextLine}, 9 | queue, 10 | style::{Print, Stylize}, 11 | }; 12 | use std::io::Write; 13 | use std::time::Duration; 14 | 15 | fn timer_show( 16 | out: &mut impl Write, 17 | elapsed: Duration, 18 | target: Duration, 19 | is_running: bool, 20 | alerter: &mut Alerter, 21 | ) -> Result<()> { 22 | let (title, timer, controls) = if elapsed < target { 23 | let time_left = target.saturating_sub(elapsed); 24 | ( 25 | "Timer", 26 | format_duration(time_left).with(running_color(is_running)), 27 | "[Q]: quit, [Space]: pause/resume", 28 | ) 29 | } else { 30 | alerter.alert_once( 31 | "The timer has ended!", 32 | format!( 33 | "Your Timer of {initial} has ended", 34 | initial = format_duration(target) 35 | ), 36 | ); 37 | let excess_time = format_duration(elapsed.saturating_sub(target)); 38 | ( 39 | "Timer has ended", 40 | format!("+{excess_time}").with(running_color(is_running)), 41 | "[Q]: quit, [Space]: pause/resume", 42 | ) 43 | }; 44 | queue!( 45 | out, 46 | MoveTo(0, 0), 47 | Print(title), 48 | Clear(ClearType::UntilNewLine), 49 | MoveToNextLine(1), 50 | Print(timer), 51 | Clear(ClearType::UntilNewLine), 52 | MoveToNextLine(1), 53 | Print(controls), 54 | Clear(ClearType::UntilNewLine), 55 | MoveToNextLine(1), 56 | Clear(ClearType::FromCursorDown), 57 | )?; 58 | out.flush()?; 59 | Ok(()) 60 | } 61 | 62 | fn timer_update(command: Command, stopwatch: &mut Stopwatch) { 63 | match command { 64 | Command::Pause => stopwatch.stop(), 65 | Command::Resume => stopwatch.start(), 66 | Command::Toggle | Command::Enter => stopwatch.toggle(), 67 | _ => (), 68 | } 69 | } 70 | 71 | #[derive(Debug, Default, Clone, Copy)] 72 | pub struct TimerUI { 73 | stopwatch: Stopwatch, 74 | target: Duration, 75 | alerter: Alerter, 76 | } 77 | 78 | impl TimerUI { 79 | pub fn new(target: Duration) -> Self { 80 | Self { target, ..Default::default() } 81 | } 82 | } 83 | 84 | impl CounterUI for TimerUI { 85 | fn show(&mut self, out: &mut impl Write) -> Result<()> { 86 | let elapsed = self.stopwatch.elapsed(); 87 | let is_running = self.stopwatch.started(); 88 | timer_show(out, elapsed, self.target, is_running, &mut self.alerter) 89 | } 90 | 91 | fn update(&mut self, command: Command) { 92 | timer_update(command, &mut self.stopwatch) 93 | } 94 | } 95 | 96 | --------------------------------------------------------------------------------