├── .envrc ├── .github └── workflows │ └── build_nix.yml ├── .gitignore ├── .vscode └── settings.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── default.nix ├── example_config.toml ├── flake.lock ├── flake.nix ├── rustfmt.toml ├── shell.nix └── src ├── funcs ├── greet.rs ├── misc.rs ├── mod.rs ├── pkgs.rs └── system_info.rs ├── main.rs └── util ├── conf_structs.rs ├── config.rs ├── formatting.rs ├── mod.rs └── statics.rs /.envrc: -------------------------------------------------------------------------------- 1 | use flake 2 | -------------------------------------------------------------------------------- /.github/workflows/build_nix.yml: -------------------------------------------------------------------------------- 1 | name: "Build legacy Nix package on Ubuntu" 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - uses: cachix/install-nix-action@v12 12 | - name: Building package 13 | run: nix-build . -A defaultPackage.x86_64-linux 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | .idea 3 | .cargo 4 | fleet.toml 5 | .direnv 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "nixEnvSelector.nixFile": "${workspaceRoot}/shell.nix" 3 | } 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.17.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "aho-corasick" 22 | version = "0.7.18" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "ansi_term" 31 | version = "0.12.1" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" 34 | dependencies = [ 35 | "winapi", 36 | ] 37 | 38 | [[package]] 39 | name = "argparse" 40 | version = "0.2.2" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "3f8ebf5827e4ac4fd5946560e6a99776ea73b596d80898f357007317a7141e47" 43 | 44 | [[package]] 45 | name = "autocfg" 46 | version = "1.1.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 49 | 50 | [[package]] 51 | name = "backtrace" 52 | version = "0.3.66" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" 55 | dependencies = [ 56 | "addr2line", 57 | "cc", 58 | "cfg-if", 59 | "libc", 60 | "miniz_oxide", 61 | "object", 62 | "rustc-demangle", 63 | ] 64 | 65 | [[package]] 66 | name = "base64" 67 | version = "0.13.0" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 70 | 71 | [[package]] 72 | name = "bitflags" 73 | version = "1.3.2" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 76 | 77 | [[package]] 78 | name = "bumpalo" 79 | version = "3.10.0" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" 82 | 83 | [[package]] 84 | name = "bytes" 85 | version = "1.1.0" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 88 | 89 | [[package]] 90 | name = "bytesize" 91 | version = "1.1.0" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" 94 | 95 | [[package]] 96 | name = "cc" 97 | version = "1.0.73" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" 100 | 101 | [[package]] 102 | name = "cfg-if" 103 | version = "1.0.0" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 106 | 107 | [[package]] 108 | name = "chrono" 109 | version = "0.4.19" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" 112 | dependencies = [ 113 | "libc", 114 | "num-integer", 115 | "num-traits", 116 | "time", 117 | "winapi", 118 | ] 119 | 120 | [[package]] 121 | name = "darling" 122 | version = "0.5.0" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | checksum = "ebfa6e6eb98ba452aaea6415e529e4890ab09a36aaf03c71146acf9f0eab89f6" 125 | dependencies = [ 126 | "darling_core", 127 | "darling_macro", 128 | ] 129 | 130 | [[package]] 131 | name = "darling_core" 132 | version = "0.5.0" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "c8af196b04f843cd6f1d979c2b3697de0d33050892662efba69112ee7b1fc968" 135 | dependencies = [ 136 | "ident_case", 137 | "proc-macro2 0.3.8", 138 | "quote 0.5.2", 139 | "syn 0.13.11", 140 | ] 141 | 142 | [[package]] 143 | name = "darling_macro" 144 | version = "0.5.0" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "0619148430511a3ecf5e52752a9c948879207ab3096276a5a9ecf8b1e7fbe010" 147 | dependencies = [ 148 | "darling_core", 149 | "quote 0.5.2", 150 | "syn 0.13.11", 151 | ] 152 | 153 | [[package]] 154 | name = "dbus" 155 | version = "0.8.4" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "5cd9e78c210146a1860f897db03412fd5091fd73100778e43ee255cca252cf32" 158 | dependencies = [ 159 | "libc", 160 | "libdbus-sys", 161 | ] 162 | 163 | [[package]] 164 | name = "derive_is_enum_variant" 165 | version = "0.1.1" 166 | source = "registry+https://github.com/rust-lang/crates.io-index" 167 | checksum = "d0ac8859845146979953797f03cc5b282fb4396891807cdb3d04929a88418197" 168 | dependencies = [ 169 | "heck", 170 | "quote 0.3.15", 171 | "syn 0.11.11", 172 | ] 173 | 174 | [[package]] 175 | name = "draconis" 176 | version = "2.4.8" 177 | dependencies = [ 178 | "argparse", 179 | "chrono", 180 | "mpris", 181 | "once_cell", 182 | "openweathermap", 183 | "regex", 184 | "serde", 185 | "substring", 186 | "sys-info", 187 | "systemstat", 188 | "text_io", 189 | "tokio", 190 | "toml", 191 | "tracing", 192 | "tracing-subscriber", 193 | "unicode-segmentation", 194 | "unicode-width", 195 | "whoami", 196 | ] 197 | 198 | [[package]] 199 | name = "encoding_rs" 200 | version = "0.8.31" 201 | source = "registry+https://github.com/rust-lang/crates.io-index" 202 | checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" 203 | dependencies = [ 204 | "cfg-if", 205 | ] 206 | 207 | [[package]] 208 | name = "enum-kinds" 209 | version = "0.4.1" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "d0f21c374dea848c19071b1504ca5ad03c9ad0d03d2e509e68f6623b8fcac4b5" 212 | dependencies = [ 213 | "quote 0.4.2", 214 | "syn 0.12.15", 215 | ] 216 | 217 | [[package]] 218 | name = "error-chain" 219 | version = "0.11.0" 220 | source = "registry+https://github.com/rust-lang/crates.io-index" 221 | checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" 222 | 223 | [[package]] 224 | name = "failure" 225 | version = "0.1.8" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 228 | dependencies = [ 229 | "backtrace", 230 | "failure_derive", 231 | ] 232 | 233 | [[package]] 234 | name = "failure_derive" 235 | version = "0.1.8" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 238 | dependencies = [ 239 | "proc-macro2 1.0.40", 240 | "quote 1.0.20", 241 | "syn 1.0.98", 242 | "synstructure", 243 | ] 244 | 245 | [[package]] 246 | name = "fnv" 247 | version = "1.0.7" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 250 | 251 | [[package]] 252 | name = "form_urlencoded" 253 | version = "1.0.1" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 256 | dependencies = [ 257 | "matches", 258 | "percent-encoding", 259 | ] 260 | 261 | [[package]] 262 | name = "from_variants" 263 | version = "0.4.0" 264 | source = "registry+https://github.com/rust-lang/crates.io-index" 265 | checksum = "2b7b3795d7bd0d40e33224cbb46adb76a88b72c52143e7bcaad33bd8b6e89e32" 266 | dependencies = [ 267 | "from_variants_impl", 268 | ] 269 | 270 | [[package]] 271 | name = "from_variants_impl" 272 | version = "0.4.0" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "d54d084040e9757536fee724381a270bc650a9ca05dcf63a0ad3aaecb1e5b9c0" 275 | dependencies = [ 276 | "darling", 277 | "error-chain", 278 | "quote 0.5.2", 279 | "syn 0.13.11", 280 | ] 281 | 282 | [[package]] 283 | name = "futures" 284 | version = "0.3.21" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" 287 | dependencies = [ 288 | "futures-channel", 289 | "futures-core", 290 | "futures-executor", 291 | "futures-io", 292 | "futures-sink", 293 | "futures-task", 294 | "futures-util", 295 | ] 296 | 297 | [[package]] 298 | name = "futures-channel" 299 | version = "0.3.21" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" 302 | dependencies = [ 303 | "futures-core", 304 | "futures-sink", 305 | ] 306 | 307 | [[package]] 308 | name = "futures-core" 309 | version = "0.3.21" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" 312 | 313 | [[package]] 314 | name = "futures-executor" 315 | version = "0.3.21" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" 318 | dependencies = [ 319 | "futures-core", 320 | "futures-task", 321 | "futures-util", 322 | ] 323 | 324 | [[package]] 325 | name = "futures-io" 326 | version = "0.3.21" 327 | source = "registry+https://github.com/rust-lang/crates.io-index" 328 | checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" 329 | 330 | [[package]] 331 | name = "futures-macro" 332 | version = "0.3.21" 333 | source = "registry+https://github.com/rust-lang/crates.io-index" 334 | checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" 335 | dependencies = [ 336 | "proc-macro2 1.0.40", 337 | "quote 1.0.20", 338 | "syn 1.0.98", 339 | ] 340 | 341 | [[package]] 342 | name = "futures-sink" 343 | version = "0.3.21" 344 | source = "registry+https://github.com/rust-lang/crates.io-index" 345 | checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" 346 | 347 | [[package]] 348 | name = "futures-task" 349 | version = "0.3.21" 350 | source = "registry+https://github.com/rust-lang/crates.io-index" 351 | checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" 352 | 353 | [[package]] 354 | name = "futures-util" 355 | version = "0.3.21" 356 | source = "registry+https://github.com/rust-lang/crates.io-index" 357 | checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" 358 | dependencies = [ 359 | "futures-channel", 360 | "futures-core", 361 | "futures-io", 362 | "futures-macro", 363 | "futures-sink", 364 | "futures-task", 365 | "memchr", 366 | "pin-project-lite", 367 | "pin-utils", 368 | "slab", 369 | ] 370 | 371 | [[package]] 372 | name = "getrandom" 373 | version = "0.2.7" 374 | source = "registry+https://github.com/rust-lang/crates.io-index" 375 | checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" 376 | dependencies = [ 377 | "cfg-if", 378 | "libc", 379 | "wasi 0.11.0+wasi-snapshot-preview1", 380 | ] 381 | 382 | [[package]] 383 | name = "gimli" 384 | version = "0.26.2" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" 387 | 388 | [[package]] 389 | name = "h2" 390 | version = "0.3.13" 391 | source = "registry+https://github.com/rust-lang/crates.io-index" 392 | checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" 393 | dependencies = [ 394 | "bytes", 395 | "fnv", 396 | "futures-core", 397 | "futures-sink", 398 | "futures-util", 399 | "http", 400 | "indexmap", 401 | "slab", 402 | "tokio", 403 | "tokio-util", 404 | "tracing", 405 | ] 406 | 407 | [[package]] 408 | name = "hashbrown" 409 | version = "0.12.3" 410 | source = "registry+https://github.com/rust-lang/crates.io-index" 411 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 412 | 413 | [[package]] 414 | name = "heck" 415 | version = "0.3.3" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" 418 | dependencies = [ 419 | "unicode-segmentation", 420 | ] 421 | 422 | [[package]] 423 | name = "hermit-abi" 424 | version = "0.1.19" 425 | source = "registry+https://github.com/rust-lang/crates.io-index" 426 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 427 | dependencies = [ 428 | "libc", 429 | ] 430 | 431 | [[package]] 432 | name = "http" 433 | version = "0.2.8" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 436 | dependencies = [ 437 | "bytes", 438 | "fnv", 439 | "itoa", 440 | ] 441 | 442 | [[package]] 443 | name = "http-body" 444 | version = "0.4.5" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 447 | dependencies = [ 448 | "bytes", 449 | "http", 450 | "pin-project-lite", 451 | ] 452 | 453 | [[package]] 454 | name = "httparse" 455 | version = "1.7.1" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" 458 | 459 | [[package]] 460 | name = "httpdate" 461 | version = "1.0.2" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 464 | 465 | [[package]] 466 | name = "hyper" 467 | version = "0.14.20" 468 | source = "registry+https://github.com/rust-lang/crates.io-index" 469 | checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" 470 | dependencies = [ 471 | "bytes", 472 | "futures-channel", 473 | "futures-core", 474 | "futures-util", 475 | "h2", 476 | "http", 477 | "http-body", 478 | "httparse", 479 | "httpdate", 480 | "itoa", 481 | "pin-project-lite", 482 | "socket2", 483 | "tokio", 484 | "tower-service", 485 | "tracing", 486 | "want", 487 | ] 488 | 489 | [[package]] 490 | name = "ident_case" 491 | version = "1.0.1" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 494 | 495 | [[package]] 496 | name = "idna" 497 | version = "0.2.3" 498 | source = "registry+https://github.com/rust-lang/crates.io-index" 499 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 500 | dependencies = [ 501 | "matches", 502 | "unicode-bidi", 503 | "unicode-normalization", 504 | ] 505 | 506 | [[package]] 507 | name = "indexmap" 508 | version = "1.9.1" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" 511 | dependencies = [ 512 | "autocfg", 513 | "hashbrown", 514 | ] 515 | 516 | [[package]] 517 | name = "ipnet" 518 | version = "2.5.0" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" 521 | 522 | [[package]] 523 | name = "itoa" 524 | version = "1.0.2" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" 527 | 528 | [[package]] 529 | name = "js-sys" 530 | version = "0.3.58" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" 533 | dependencies = [ 534 | "wasm-bindgen", 535 | ] 536 | 537 | [[package]] 538 | name = "lazy_static" 539 | version = "1.4.0" 540 | source = "registry+https://github.com/rust-lang/crates.io-index" 541 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 542 | 543 | [[package]] 544 | name = "libc" 545 | version = "0.2.126" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" 548 | 549 | [[package]] 550 | name = "libdbus-sys" 551 | version = "0.2.2" 552 | source = "registry+https://github.com/rust-lang/crates.io-index" 553 | checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" 554 | dependencies = [ 555 | "pkg-config", 556 | ] 557 | 558 | [[package]] 559 | name = "lock_api" 560 | version = "0.4.7" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" 563 | dependencies = [ 564 | "autocfg", 565 | "scopeguard", 566 | ] 567 | 568 | [[package]] 569 | name = "log" 570 | version = "0.4.17" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 573 | dependencies = [ 574 | "cfg-if", 575 | ] 576 | 577 | [[package]] 578 | name = "matchers" 579 | version = "0.1.0" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 582 | dependencies = [ 583 | "regex-automata", 584 | ] 585 | 586 | [[package]] 587 | name = "matches" 588 | version = "0.1.9" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 591 | 592 | [[package]] 593 | name = "memchr" 594 | version = "2.5.0" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 597 | 598 | [[package]] 599 | name = "mime" 600 | version = "0.3.16" 601 | source = "registry+https://github.com/rust-lang/crates.io-index" 602 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 603 | 604 | [[package]] 605 | name = "minimal-lexical" 606 | version = "0.2.1" 607 | source = "registry+https://github.com/rust-lang/crates.io-index" 608 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 609 | 610 | [[package]] 611 | name = "miniz_oxide" 612 | version = "0.5.3" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" 615 | dependencies = [ 616 | "adler", 617 | ] 618 | 619 | [[package]] 620 | name = "mio" 621 | version = "0.8.4" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" 624 | dependencies = [ 625 | "libc", 626 | "log", 627 | "wasi 0.11.0+wasi-snapshot-preview1", 628 | "windows-sys", 629 | ] 630 | 631 | [[package]] 632 | name = "mpris" 633 | version = "2.0.0-rc2" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "195e67e2b467af5146f517b0d988b5894e425a77c52a9bb5a065513ef3c2e711" 636 | dependencies = [ 637 | "dbus", 638 | "derive_is_enum_variant", 639 | "enum-kinds", 640 | "failure", 641 | "failure_derive", 642 | "from_variants", 643 | ] 644 | 645 | [[package]] 646 | name = "nom" 647 | version = "7.1.1" 648 | source = "registry+https://github.com/rust-lang/crates.io-index" 649 | checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" 650 | dependencies = [ 651 | "memchr", 652 | "minimal-lexical", 653 | ] 654 | 655 | [[package]] 656 | name = "num-integer" 657 | version = "0.1.45" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 660 | dependencies = [ 661 | "autocfg", 662 | "num-traits", 663 | ] 664 | 665 | [[package]] 666 | name = "num-traits" 667 | version = "0.2.15" 668 | source = "registry+https://github.com/rust-lang/crates.io-index" 669 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 670 | dependencies = [ 671 | "autocfg", 672 | ] 673 | 674 | [[package]] 675 | name = "num_cpus" 676 | version = "1.13.1" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" 679 | dependencies = [ 680 | "hermit-abi", 681 | "libc", 682 | ] 683 | 684 | [[package]] 685 | name = "object" 686 | version = "0.29.0" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" 689 | dependencies = [ 690 | "memchr", 691 | ] 692 | 693 | [[package]] 694 | name = "once_cell" 695 | version = "1.13.0" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" 698 | 699 | [[package]] 700 | name = "openweathermap" 701 | version = "0.2.4" 702 | source = "registry+https://github.com/rust-lang/crates.io-index" 703 | checksum = "5f0d1c2372bc54e111467a33f6614a247b9b430a5ff00e9bcc84bb133bb09403" 704 | dependencies = [ 705 | "futures", 706 | "http", 707 | "rand", 708 | "regex", 709 | "reqwest", 710 | "serde", 711 | "serde_json", 712 | ] 713 | 714 | [[package]] 715 | name = "parking_lot" 716 | version = "0.12.1" 717 | source = "registry+https://github.com/rust-lang/crates.io-index" 718 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 719 | dependencies = [ 720 | "lock_api", 721 | "parking_lot_core", 722 | ] 723 | 724 | [[package]] 725 | name = "parking_lot_core" 726 | version = "0.9.3" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" 729 | dependencies = [ 730 | "cfg-if", 731 | "libc", 732 | "redox_syscall", 733 | "smallvec", 734 | "windows-sys", 735 | ] 736 | 737 | [[package]] 738 | name = "percent-encoding" 739 | version = "2.1.0" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 742 | 743 | [[package]] 744 | name = "pin-project-lite" 745 | version = "0.2.9" 746 | source = "registry+https://github.com/rust-lang/crates.io-index" 747 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 748 | 749 | [[package]] 750 | name = "pin-utils" 751 | version = "0.1.0" 752 | source = "registry+https://github.com/rust-lang/crates.io-index" 753 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 754 | 755 | [[package]] 756 | name = "pkg-config" 757 | version = "0.3.25" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" 760 | 761 | [[package]] 762 | name = "ppv-lite86" 763 | version = "0.2.16" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" 766 | 767 | [[package]] 768 | name = "proc-macro2" 769 | version = "0.2.3" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0" 772 | dependencies = [ 773 | "unicode-xid 0.1.0", 774 | ] 775 | 776 | [[package]] 777 | name = "proc-macro2" 778 | version = "0.3.8" 779 | source = "registry+https://github.com/rust-lang/crates.io-index" 780 | checksum = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" 781 | dependencies = [ 782 | "unicode-xid 0.1.0", 783 | ] 784 | 785 | [[package]] 786 | name = "proc-macro2" 787 | version = "1.0.40" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" 790 | dependencies = [ 791 | "unicode-ident", 792 | ] 793 | 794 | [[package]] 795 | name = "quote" 796 | version = "0.3.15" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 799 | 800 | [[package]] 801 | name = "quote" 802 | version = "0.4.2" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408" 805 | dependencies = [ 806 | "proc-macro2 0.2.3", 807 | ] 808 | 809 | [[package]] 810 | name = "quote" 811 | version = "0.5.2" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" 814 | dependencies = [ 815 | "proc-macro2 0.3.8", 816 | ] 817 | 818 | [[package]] 819 | name = "quote" 820 | version = "1.0.20" 821 | source = "registry+https://github.com/rust-lang/crates.io-index" 822 | checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" 823 | dependencies = [ 824 | "proc-macro2 1.0.40", 825 | ] 826 | 827 | [[package]] 828 | name = "rand" 829 | version = "0.8.5" 830 | source = "registry+https://github.com/rust-lang/crates.io-index" 831 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 832 | dependencies = [ 833 | "libc", 834 | "rand_chacha", 835 | "rand_core", 836 | ] 837 | 838 | [[package]] 839 | name = "rand_chacha" 840 | version = "0.3.1" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 843 | dependencies = [ 844 | "ppv-lite86", 845 | "rand_core", 846 | ] 847 | 848 | [[package]] 849 | name = "rand_core" 850 | version = "0.6.3" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 853 | dependencies = [ 854 | "getrandom", 855 | ] 856 | 857 | [[package]] 858 | name = "redox_syscall" 859 | version = "0.2.13" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" 862 | dependencies = [ 863 | "bitflags", 864 | ] 865 | 866 | [[package]] 867 | name = "regex" 868 | version = "1.7.0" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" 871 | dependencies = [ 872 | "aho-corasick", 873 | "memchr", 874 | "regex-syntax", 875 | ] 876 | 877 | [[package]] 878 | name = "regex-automata" 879 | version = "0.1.10" 880 | source = "registry+https://github.com/rust-lang/crates.io-index" 881 | checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 882 | dependencies = [ 883 | "regex-syntax", 884 | ] 885 | 886 | [[package]] 887 | name = "regex-syntax" 888 | version = "0.6.27" 889 | source = "registry+https://github.com/rust-lang/crates.io-index" 890 | checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" 891 | 892 | [[package]] 893 | name = "reqwest" 894 | version = "0.11.11" 895 | source = "registry+https://github.com/rust-lang/crates.io-index" 896 | checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" 897 | dependencies = [ 898 | "base64", 899 | "bytes", 900 | "encoding_rs", 901 | "futures-core", 902 | "futures-util", 903 | "h2", 904 | "http", 905 | "http-body", 906 | "hyper", 907 | "ipnet", 908 | "js-sys", 909 | "lazy_static", 910 | "log", 911 | "mime", 912 | "percent-encoding", 913 | "pin-project-lite", 914 | "serde", 915 | "serde_json", 916 | "serde_urlencoded", 917 | "tokio", 918 | "tower-service", 919 | "url", 920 | "wasm-bindgen", 921 | "wasm-bindgen-futures", 922 | "web-sys", 923 | "winreg", 924 | ] 925 | 926 | [[package]] 927 | name = "rustc-demangle" 928 | version = "0.1.21" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" 931 | 932 | [[package]] 933 | name = "ryu" 934 | version = "1.0.10" 935 | source = "registry+https://github.com/rust-lang/crates.io-index" 936 | checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" 937 | 938 | [[package]] 939 | name = "scopeguard" 940 | version = "1.1.0" 941 | source = "registry+https://github.com/rust-lang/crates.io-index" 942 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 943 | 944 | [[package]] 945 | name = "serde" 946 | version = "1.0.139" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" 949 | dependencies = [ 950 | "serde_derive", 951 | ] 952 | 953 | [[package]] 954 | name = "serde_derive" 955 | version = "1.0.139" 956 | source = "registry+https://github.com/rust-lang/crates.io-index" 957 | checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" 958 | dependencies = [ 959 | "proc-macro2 1.0.40", 960 | "quote 1.0.20", 961 | "syn 1.0.98", 962 | ] 963 | 964 | [[package]] 965 | name = "serde_json" 966 | version = "1.0.82" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" 969 | dependencies = [ 970 | "itoa", 971 | "ryu", 972 | "serde", 973 | ] 974 | 975 | [[package]] 976 | name = "serde_urlencoded" 977 | version = "0.7.1" 978 | source = "registry+https://github.com/rust-lang/crates.io-index" 979 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 980 | dependencies = [ 981 | "form_urlencoded", 982 | "itoa", 983 | "ryu", 984 | "serde", 985 | ] 986 | 987 | [[package]] 988 | name = "sharded-slab" 989 | version = "0.1.4" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 992 | dependencies = [ 993 | "lazy_static", 994 | ] 995 | 996 | [[package]] 997 | name = "signal-hook-registry" 998 | version = "1.4.0" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 1001 | dependencies = [ 1002 | "libc", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "slab" 1007 | version = "0.4.6" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" 1010 | 1011 | [[package]] 1012 | name = "smallvec" 1013 | version = "1.9.0" 1014 | source = "registry+https://github.com/rust-lang/crates.io-index" 1015 | checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" 1016 | 1017 | [[package]] 1018 | name = "socket2" 1019 | version = "0.4.4" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" 1022 | dependencies = [ 1023 | "libc", 1024 | "winapi", 1025 | ] 1026 | 1027 | [[package]] 1028 | name = "substring" 1029 | version = "1.4.5" 1030 | source = "registry+https://github.com/rust-lang/crates.io-index" 1031 | checksum = "42ee6433ecef213b2e72f587ef64a2f5943e7cd16fbd82dbe8bc07486c534c86" 1032 | dependencies = [ 1033 | "autocfg", 1034 | ] 1035 | 1036 | [[package]] 1037 | name = "syn" 1038 | version = "0.11.11" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 1041 | dependencies = [ 1042 | "quote 0.3.15", 1043 | "synom", 1044 | "unicode-xid 0.0.4", 1045 | ] 1046 | 1047 | [[package]] 1048 | name = "syn" 1049 | version = "0.12.15" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5" 1052 | dependencies = [ 1053 | "proc-macro2 0.2.3", 1054 | "quote 0.4.2", 1055 | "unicode-xid 0.1.0", 1056 | ] 1057 | 1058 | [[package]] 1059 | name = "syn" 1060 | version = "0.13.11" 1061 | source = "registry+https://github.com/rust-lang/crates.io-index" 1062 | checksum = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" 1063 | dependencies = [ 1064 | "proc-macro2 0.3.8", 1065 | "quote 0.5.2", 1066 | "unicode-xid 0.1.0", 1067 | ] 1068 | 1069 | [[package]] 1070 | name = "syn" 1071 | version = "1.0.98" 1072 | source = "registry+https://github.com/rust-lang/crates.io-index" 1073 | checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" 1074 | dependencies = [ 1075 | "proc-macro2 1.0.40", 1076 | "quote 1.0.20", 1077 | "unicode-ident", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "synom" 1082 | version = "0.11.3" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 1085 | dependencies = [ 1086 | "unicode-xid 0.0.4", 1087 | ] 1088 | 1089 | [[package]] 1090 | name = "synstructure" 1091 | version = "0.12.6" 1092 | source = "registry+https://github.com/rust-lang/crates.io-index" 1093 | checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" 1094 | dependencies = [ 1095 | "proc-macro2 1.0.40", 1096 | "quote 1.0.20", 1097 | "syn 1.0.98", 1098 | "unicode-xid 0.2.3", 1099 | ] 1100 | 1101 | [[package]] 1102 | name = "sys-info" 1103 | version = "0.9.1" 1104 | source = "registry+https://github.com/rust-lang/crates.io-index" 1105 | checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" 1106 | dependencies = [ 1107 | "cc", 1108 | "libc", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "systemstat" 1113 | version = "0.1.11" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "5f5dc96f7634f46ac7e485b8c051f5b89ec8ee5cc023236dd12fe4ae2fb52f80" 1116 | dependencies = [ 1117 | "bytesize", 1118 | "chrono", 1119 | "lazy_static", 1120 | "libc", 1121 | "nom", 1122 | "winapi", 1123 | ] 1124 | 1125 | [[package]] 1126 | name = "text_io" 1127 | version = "0.1.10" 1128 | source = "registry+https://github.com/rust-lang/crates.io-index" 1129 | checksum = "442f2674e6bd8489052b958e0eaebd89c26eefa3be9dc359d1e2ecccdc510f45" 1130 | 1131 | [[package]] 1132 | name = "thread_local" 1133 | version = "1.1.4" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" 1136 | dependencies = [ 1137 | "once_cell", 1138 | ] 1139 | 1140 | [[package]] 1141 | name = "time" 1142 | version = "0.1.44" 1143 | source = "registry+https://github.com/rust-lang/crates.io-index" 1144 | checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" 1145 | dependencies = [ 1146 | "libc", 1147 | "wasi 0.10.0+wasi-snapshot-preview1", 1148 | "winapi", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "tinyvec" 1153 | version = "1.6.0" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1156 | dependencies = [ 1157 | "tinyvec_macros", 1158 | ] 1159 | 1160 | [[package]] 1161 | name = "tinyvec_macros" 1162 | version = "0.1.0" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1165 | 1166 | [[package]] 1167 | name = "tokio" 1168 | version = "1.20.0" 1169 | source = "registry+https://github.com/rust-lang/crates.io-index" 1170 | checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e" 1171 | dependencies = [ 1172 | "autocfg", 1173 | "bytes", 1174 | "libc", 1175 | "memchr", 1176 | "mio", 1177 | "num_cpus", 1178 | "once_cell", 1179 | "parking_lot", 1180 | "pin-project-lite", 1181 | "signal-hook-registry", 1182 | "socket2", 1183 | "tokio-macros", 1184 | "winapi", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "tokio-macros" 1189 | version = "1.8.0" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" 1192 | dependencies = [ 1193 | "proc-macro2 1.0.40", 1194 | "quote 1.0.20", 1195 | "syn 1.0.98", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "tokio-util" 1200 | version = "0.7.3" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" 1203 | dependencies = [ 1204 | "bytes", 1205 | "futures-core", 1206 | "futures-sink", 1207 | "pin-project-lite", 1208 | "tokio", 1209 | "tracing", 1210 | ] 1211 | 1212 | [[package]] 1213 | name = "toml" 1214 | version = "0.5.9" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" 1217 | dependencies = [ 1218 | "serde", 1219 | ] 1220 | 1221 | [[package]] 1222 | name = "tower-service" 1223 | version = "0.3.2" 1224 | source = "registry+https://github.com/rust-lang/crates.io-index" 1225 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1226 | 1227 | [[package]] 1228 | name = "tracing" 1229 | version = "0.1.35" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" 1232 | dependencies = [ 1233 | "cfg-if", 1234 | "pin-project-lite", 1235 | "tracing-attributes", 1236 | "tracing-core", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "tracing-attributes" 1241 | version = "0.1.22" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" 1244 | dependencies = [ 1245 | "proc-macro2 1.0.40", 1246 | "quote 1.0.20", 1247 | "syn 1.0.98", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "tracing-core" 1252 | version = "0.1.28" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" 1255 | dependencies = [ 1256 | "once_cell", 1257 | "valuable", 1258 | ] 1259 | 1260 | [[package]] 1261 | name = "tracing-log" 1262 | version = "0.1.3" 1263 | source = "registry+https://github.com/rust-lang/crates.io-index" 1264 | checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 1265 | dependencies = [ 1266 | "lazy_static", 1267 | "log", 1268 | "tracing-core", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "tracing-subscriber" 1273 | version = "0.3.14" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59" 1276 | dependencies = [ 1277 | "ansi_term", 1278 | "matchers", 1279 | "once_cell", 1280 | "regex", 1281 | "sharded-slab", 1282 | "smallvec", 1283 | "thread_local", 1284 | "tracing", 1285 | "tracing-core", 1286 | "tracing-log", 1287 | ] 1288 | 1289 | [[package]] 1290 | name = "try-lock" 1291 | version = "0.2.3" 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" 1293 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1294 | 1295 | [[package]] 1296 | name = "unicode-bidi" 1297 | version = "0.3.8" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" 1300 | 1301 | [[package]] 1302 | name = "unicode-ident" 1303 | version = "1.0.2" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" 1306 | 1307 | [[package]] 1308 | name = "unicode-normalization" 1309 | version = "0.1.21" 1310 | source = "registry+https://github.com/rust-lang/crates.io-index" 1311 | checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" 1312 | dependencies = [ 1313 | "tinyvec", 1314 | ] 1315 | 1316 | [[package]] 1317 | name = "unicode-segmentation" 1318 | version = "1.9.0" 1319 | source = "registry+https://github.com/rust-lang/crates.io-index" 1320 | checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" 1321 | 1322 | [[package]] 1323 | name = "unicode-width" 1324 | version = "0.1.9" 1325 | source = "registry+https://github.com/rust-lang/crates.io-index" 1326 | checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" 1327 | 1328 | [[package]] 1329 | name = "unicode-xid" 1330 | version = "0.0.4" 1331 | source = "registry+https://github.com/rust-lang/crates.io-index" 1332 | checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 1333 | 1334 | [[package]] 1335 | name = "unicode-xid" 1336 | version = "0.1.0" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 1339 | 1340 | [[package]] 1341 | name = "unicode-xid" 1342 | version = "0.2.3" 1343 | source = "registry+https://github.com/rust-lang/crates.io-index" 1344 | checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" 1345 | 1346 | [[package]] 1347 | name = "url" 1348 | version = "2.2.2" 1349 | source = "registry+https://github.com/rust-lang/crates.io-index" 1350 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1351 | dependencies = [ 1352 | "form_urlencoded", 1353 | "idna", 1354 | "matches", 1355 | "percent-encoding", 1356 | ] 1357 | 1358 | [[package]] 1359 | name = "valuable" 1360 | version = "0.1.0" 1361 | source = "registry+https://github.com/rust-lang/crates.io-index" 1362 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 1363 | 1364 | [[package]] 1365 | name = "want" 1366 | version = "0.3.0" 1367 | source = "registry+https://github.com/rust-lang/crates.io-index" 1368 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1369 | dependencies = [ 1370 | "log", 1371 | "try-lock", 1372 | ] 1373 | 1374 | [[package]] 1375 | name = "wasi" 1376 | version = "0.10.0+wasi-snapshot-preview1" 1377 | source = "registry+https://github.com/rust-lang/crates.io-index" 1378 | checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" 1379 | 1380 | [[package]] 1381 | name = "wasi" 1382 | version = "0.11.0+wasi-snapshot-preview1" 1383 | source = "registry+https://github.com/rust-lang/crates.io-index" 1384 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1385 | 1386 | [[package]] 1387 | name = "wasm-bindgen" 1388 | version = "0.2.81" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" 1391 | dependencies = [ 1392 | "cfg-if", 1393 | "wasm-bindgen-macro", 1394 | ] 1395 | 1396 | [[package]] 1397 | name = "wasm-bindgen-backend" 1398 | version = "0.2.81" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" 1401 | dependencies = [ 1402 | "bumpalo", 1403 | "lazy_static", 1404 | "log", 1405 | "proc-macro2 1.0.40", 1406 | "quote 1.0.20", 1407 | "syn 1.0.98", 1408 | "wasm-bindgen-shared", 1409 | ] 1410 | 1411 | [[package]] 1412 | name = "wasm-bindgen-futures" 1413 | version = "0.4.31" 1414 | source = "registry+https://github.com/rust-lang/crates.io-index" 1415 | checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" 1416 | dependencies = [ 1417 | "cfg-if", 1418 | "js-sys", 1419 | "wasm-bindgen", 1420 | "web-sys", 1421 | ] 1422 | 1423 | [[package]] 1424 | name = "wasm-bindgen-macro" 1425 | version = "0.2.81" 1426 | source = "registry+https://github.com/rust-lang/crates.io-index" 1427 | checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" 1428 | dependencies = [ 1429 | "quote 1.0.20", 1430 | "wasm-bindgen-macro-support", 1431 | ] 1432 | 1433 | [[package]] 1434 | name = "wasm-bindgen-macro-support" 1435 | version = "0.2.81" 1436 | source = "registry+https://github.com/rust-lang/crates.io-index" 1437 | checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" 1438 | dependencies = [ 1439 | "proc-macro2 1.0.40", 1440 | "quote 1.0.20", 1441 | "syn 1.0.98", 1442 | "wasm-bindgen-backend", 1443 | "wasm-bindgen-shared", 1444 | ] 1445 | 1446 | [[package]] 1447 | name = "wasm-bindgen-shared" 1448 | version = "0.2.81" 1449 | source = "registry+https://github.com/rust-lang/crates.io-index" 1450 | checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" 1451 | 1452 | [[package]] 1453 | name = "web-sys" 1454 | version = "0.3.58" 1455 | source = "registry+https://github.com/rust-lang/crates.io-index" 1456 | checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" 1457 | dependencies = [ 1458 | "js-sys", 1459 | "wasm-bindgen", 1460 | ] 1461 | 1462 | [[package]] 1463 | name = "whoami" 1464 | version = "1.2.1" 1465 | source = "registry+https://github.com/rust-lang/crates.io-index" 1466 | checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8" 1467 | dependencies = [ 1468 | "wasm-bindgen", 1469 | "web-sys", 1470 | ] 1471 | 1472 | [[package]] 1473 | name = "winapi" 1474 | version = "0.3.9" 1475 | source = "registry+https://github.com/rust-lang/crates.io-index" 1476 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1477 | dependencies = [ 1478 | "winapi-i686-pc-windows-gnu", 1479 | "winapi-x86_64-pc-windows-gnu", 1480 | ] 1481 | 1482 | [[package]] 1483 | name = "winapi-i686-pc-windows-gnu" 1484 | version = "0.4.0" 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" 1486 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1487 | 1488 | [[package]] 1489 | name = "winapi-x86_64-pc-windows-gnu" 1490 | version = "0.4.0" 1491 | source = "registry+https://github.com/rust-lang/crates.io-index" 1492 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1493 | 1494 | [[package]] 1495 | name = "windows-sys" 1496 | version = "0.36.1" 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" 1498 | checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" 1499 | dependencies = [ 1500 | "windows_aarch64_msvc", 1501 | "windows_i686_gnu", 1502 | "windows_i686_msvc", 1503 | "windows_x86_64_gnu", 1504 | "windows_x86_64_msvc", 1505 | ] 1506 | 1507 | [[package]] 1508 | name = "windows_aarch64_msvc" 1509 | version = "0.36.1" 1510 | source = "registry+https://github.com/rust-lang/crates.io-index" 1511 | checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" 1512 | 1513 | [[package]] 1514 | name = "windows_i686_gnu" 1515 | version = "0.36.1" 1516 | source = "registry+https://github.com/rust-lang/crates.io-index" 1517 | checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" 1518 | 1519 | [[package]] 1520 | name = "windows_i686_msvc" 1521 | version = "0.36.1" 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" 1523 | checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" 1524 | 1525 | [[package]] 1526 | name = "windows_x86_64_gnu" 1527 | version = "0.36.1" 1528 | source = "registry+https://github.com/rust-lang/crates.io-index" 1529 | checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" 1530 | 1531 | [[package]] 1532 | name = "windows_x86_64_msvc" 1533 | version = "0.36.1" 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" 1535 | checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" 1536 | 1537 | [[package]] 1538 | name = "winreg" 1539 | version = "0.10.1" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" 1542 | dependencies = [ 1543 | "winapi", 1544 | ] 1545 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = ["marsupialgutz"] 3 | description = "Small terminal welcome program written in rust" 4 | edition = "2021" 5 | license-file = "LICENSE" 6 | name = "draconis" 7 | readme = "README.md" 8 | repository = "https://github.com/marsupialgutz/draconis" 9 | version = "2.4.8" 10 | 11 | [workspace] 12 | 13 | [dependencies] 14 | argparse = "0.2" 15 | chrono = "0.4" 16 | mpris = "2.0.0-rc2" 17 | once_cell = "1.10" 18 | openweathermap = "0.2" 19 | serde = {version = "1.0", features = ["derive"]} 20 | substring = "1.4" 21 | sys-info = "0.9.1" 22 | systemstat = "0.1" 23 | tokio = {version = "1", features = ["full"]} 24 | toml = "0.5.9" 25 | tracing = "0.1" 26 | tracing-subscriber = {version = "0.3", features = ["env-filter"]} 27 | unicode-segmentation = "1.9" 28 | whoami = "1.2.1" 29 | text_io = "0.1" 30 | unicode-width = "0.1.9" 31 | regex = "1.7.0" 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Based License v1.4.1 2 | 3 | Used by MARSUPIALGUTZ on 4 May, 2022. 4 | Written by Kainoa Kanter (ThatOneCalculator) on 1 March, 2022. Last updated on 2 April, 2022. 5 | 6 | --- 7 | 8 | Questions, comments, or concerns? Open an issue here: 9 | https://github.com/ThatOneCalculator/BASED-LICENSE/issues 10 | or send me an email at . 11 | 12 | A non-legally binding summary of the license can be found here: 13 | https://github.com/ThatOneCalculator/BASED-LICENSE/blob/main/SUMMARY.md 14 | 15 | --- 16 | 17 | While the software author(s) can modify the Based License, any and all revisions must be stated below, 18 | including how it was modified. 19 | 20 | Have the license terms been modified? If so, how was it modified? 21 | * No, the terms in this copy of the based license has not been modified. * 22 | 23 | --- 24 | 25 | BEGIN LICENSE TERMS 26 | 27 | All references of "license", "the license", or "Based License" refer to the software license located at 28 | https://github.com/ThatOneCalculator/BASED-LICENSE/blob/main/LICENSE. References to "the software" refer to the 29 | program(s) in which this license is used. "The author(s)" and "the contributor(s)" refer to the author(s) 30 | and contributor(s) of the software using the license, unless otherwise stated. 31 | 32 | All copies of this software that are redistributed (INCLUDING modifications to the software) 33 | must have their source code easily and publicly available, and also be licensed under the Based License, meaning the 34 | Based License is a copyleft license. If the software does not contain a copy of this license, you can obtain a copy 35 | from https://github.com/ThatOneCalculator/BASED-LICENSE/blob/main/LICENSE or open an issue in the 36 | software's issue tracker, if available. 37 | 38 | The author of this software has the right to claim the software as their own, and while anyone can contribute 39 | to, redistribute, and modify this software (under the based license), they cannot claim it as their own software, 40 | and credits must be given to the original author(s) of this software. 41 | 42 | This software is provided with no warranty. If the device you're running this on gets messed up because of 43 | this software, that's on you reading this for not auditing the code before running this software. 44 | 45 | This software cannot be used to mint or produce NFTs (Non Fungible Tokens) or any other similar smart-contract 46 | based proof-of-ownership scheme. This includes the source code, binaries, screenshots, artifacts produced, 47 | websites, the name of the software, or anything else from or of this software. 48 | 49 | If this software depends on other software dependencies under different licenses, the parts that are used under 50 | different licenses must be stated clearly in the software or in documentation. If this software depends on any 51 | non-free network services, that must also be stated clearly in the software or in documentation. 52 | 53 | This software cannot be used as a dependency in other software that is closed source. 54 | 55 | This software may be used for corporate/for-profit purposes as long as it follows every guideline in the Based 56 | License of the version provided by the contributors, including the fact that all components of said software must 57 | be open source. Binaries of this software can be sold, as long as they're bundled with the based license and 58 | a link to the source code. 59 | 60 | By using this software, you agree to the terms above. If you break the terms of this license, the author(s) of the 61 | software this copy of the Based License is being used for have the right to pursue legal action against you if 62 | violations are not resolved within one week (7 days) after being notified by the software author(s). 63 | 64 | END LICENSE TERMS 65 | 66 | ⠘⡀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡜⠀⠀⠀ 67 | ⠑⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡔⠁⠀⠀⠀ 68 | ⠈⠢⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠴⠊⠀⠀⠀⠀⠀ 69 | ⠀⠀⠀⠀⠀ ⠑⠀ ⠀⠀ ⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⣀⣀⡀⢀⣀⣀⣀⡀⠤⠄⠒⠈⠀⠀⠀⠀⠀⠀⠀⠀ 70 | ⠀⠀⠀⠀⠀⠀⠀⠘⣀⠄⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ 71 | ⠀ 72 | ⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠛⠛⠛⠋⠉⠈⠉⠉⠉⠉⠛⠻⢿⣿⣿⣿⣿⣿⣿⣿ 73 | ⣿⣿⣿⣿⣿⡿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣿⣿⣿⣿ 74 | ⣿⣿⣿⣿⡏⣀⠀⠀⠀⠀⠀⠀⠀⣀⣤⣤⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣿ 75 | ⣿⣿⣿⢏⣴⣿⣷⠀⠀⠀⠀⠀⢾⣿⣿⣿⣿⣿⣿⡆⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿ 76 | ⣿⣿⣟⣾⣿⡟⠁⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣷⢢⠀⠀⠀⠀⠀⠀⠀⢸⣿ 77 | ⣿⣿⣿⣿⣟⠀⡴⠄⠀⠀⠀⠀⠀⠀⠙⠻⣿⣿⣿⣿⣷⣄⠀⠀⠀⠀⠀⠀⠀⣿ 78 | ⣿⣿⣿⠟⠻⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠶⢴⣿⣿⣿⣿⣿⣧⠀⠀⠀⠀⠀⠀⣿ 79 | ⣿⣁⡀⠀⠀⢰⢠⣦⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿⣿⣿⣿⣿⡄⠀⣴⣶⣿⡄⣿ 80 | ⣿⡋⠀⠀⠀⠎⢸⣿⡆⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⠗⢘⣿⣟⠛⠿⣼ 81 | ⣿⣿⠋⢀⡌⢰⣿⡿⢿⡀⠀⠀⠀⠀⠀⠙⠿⣿⣿⣿⣿⣿⡇⠀⢸⣿⣿⣧⢀⣼ 82 | ⣿⣿⣷⢻⠄⠘⠛⠋⠛⠃⠀⠀⠀⠀⠀⢿⣧⠈⠉⠙⠛⠋⠀⠀⠀⣿⣿⣿⣿⣿ 83 | ⣿⣿⣧⠀⠈⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠟⠀⠀⠀⠀⢀⢃⠀⠀⢸⣿⣿⣿⣿ 84 | ⣿⣿⡿⠀⠴⢗⣠⣤⣴⡶⠶⠖⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡸⠀⣿⣿⣿⣿ 85 | ⣿⣿⣿⡀⢠⣾⣿⠏⠀⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠛⠉⠀⣿⣿⣿⣿ 86 | ⣿⣿⣿⣧⠈⢹⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿ 87 | ⣿⣿⣿⣿⡄⠈⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣿⣿⣿ 88 | ⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿ 89 | ⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 90 | ⣿⣿⣿⣿⣿⣦⣄⣀⣀⣀⣀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 91 | ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 92 | ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀⠙⣿⣿⡟⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿ 93 | ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⠀⠁⠀⠀⠹⣿⠃⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿ 94 | ⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⢐⣿⣿⣿⣿⣿⣿⣿⣿⣿ 95 | ⣿⣿⣿⣿⠿⠛⠉⠉⠁⠀⢻⣿⡇⠀⠀⠀⠀⠀⠀⢀⠈⣿⣿⡿⠉⠛⠛⠛⠉⠉ 96 | ⣿⡿⠋⠁⠀⠀⢀⣀⣠⡴⣸⣿⣇⡄⠀⠀⠀⠀⢀⡿⠄⠙⠛⠀⣀⣠⣤⣤⠄ 97 | 98 | (The above ASCII art isn't a legally binding part of the license.) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Draconis 2 | 3 | ![image](https://badgen.net/github/release/marsupialgutz/draconis) 4 | ![image](https://badgen.net/crates/v/draconis) 5 | ![image](https://badgen.net/github/stars/marsupialgutz/draconis) 6 | ![image](https://badgen.net/github/commits/marsupialgutz/draconis/main) 7 | ![image](https://badgen.net/github/open-prs/marsupialgutz/draconis) 8 | ![image](https://badgen.net/github/contributors/marsupialgutz/draconis) 9 | 10 | 11 | 🪐 A greeter for your terminal that's out of this world 12 | 13 | ![image](https://user-images.githubusercontent.com/33522919/179458221-d44f7996-d214-46ee-8801-343767ef9295.png) 14 | ![image](https://user-images.githubusercontent.com/33522919/179458079-ca750a6d-b1b4-44e4-a721-63e9250780db.png) 15 | 16 | ## Requirements 17 | 18 | - `pacman-contrib` for pacman 19 | 20 | ## Important 21 | 22 | - This program uses the openweathermap API for fetching the weather. You must have an API key from openweathermap if you want to use the weather function. 23 | - Update checking and package counting will take a long time, and slow down the program by quite a bit. This cannot be avoided because of the fact that these checks require external system commands. Only use these options if you don't mind losing a second or two of time every time you run the program. 24 | - NixOS does not support package update counting. 25 | 26 | ## Installation 27 | - There are two options for installing draconis: 28 | - Run the command `cargo install draconis` 29 | - Get the binary from the releases and move it into a folder in your PATH 30 | 31 | ## How to use 32 | 33 | - Grab the latest release binary and config files from the releases page 34 | - Copy `example_config.toml` to `~/.config/draconis/config.toml` 35 | - Change the config to your liking 36 | - Add the program to your shell's startup 37 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | (import ( 2 | fetchTarball { 3 | url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; 4 | sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; 5 | } 6 | ) { 7 | src = ./.; 8 | }) 9 | .defaultNix 10 | -------------------------------------------------------------------------------- /example_config.toml: -------------------------------------------------------------------------------- 1 | # All values held in this file can be changed to whatever you'd 2 | # like in order to customize Draconis. 3 | 4 | [main] 5 | hostname = "john@homepc" # Defaults to system username@hostname 6 | name = "John" # Defaults to system realname 7 | 8 | [util] 9 | width = 55 10 | 11 | [greeting] 12 | enabled = true 13 | 14 | [icons] 15 | enabled = true 16 | kind = "normal" # normal or emoji 17 | 18 | [time] 19 | enabled = true 20 | kind = "12h" # 12h or 24h 21 | 22 | [weather] 23 | enabled = true 24 | 25 | [weather.values] 26 | api_key = "abc123" # OpenWeatherMap API key 27 | lang = "en" # Language code for weather 28 | location = "New York" # Location to get weather for 29 | units = "imperial" # Units to use for weather 30 | 31 | [system] 32 | 33 | [system.release] 34 | enabled = true 35 | 36 | [system.kernel] 37 | enabled = true 38 | 39 | [system.mem_usage] 40 | enabled = true 41 | free_before_used = false 42 | 43 | [system.disk_usage] 44 | enabled = true 45 | free_before_used = true 46 | 47 | [system.desktop_env] 48 | enabled = true 49 | 50 | [packages] 51 | package_managers = ["pacman", "apt"] # pacman, apt, xbps, portage, apk, and/or dnf 52 | 53 | [packages.package_count] 54 | enabled = true 55 | 56 | [packages.update_count] 57 | enabled = true 58 | 59 | [song] 60 | enabled = true 61 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "fenix": { 4 | "inputs": { 5 | "nixpkgs": "nixpkgs", 6 | "rust-analyzer-src": "rust-analyzer-src" 7 | }, 8 | "locked": { 9 | "lastModified": 1671240515, 10 | "narHash": "sha256-YUkxg/RqDthvfHaLGzgAjDDkA71PZ4FW46T2caUoMVc=", 11 | "owner": "pupbrained", 12 | "repo": "fenix", 13 | "rev": "1a8b5902e7ac4ddc5f98b1a32441bf9dacb55273", 14 | "type": "github" 15 | }, 16 | "original": { 17 | "owner": "pupbrained", 18 | "ref": "patch-1", 19 | "repo": "fenix", 20 | "type": "github" 21 | } 22 | }, 23 | "naersk": { 24 | "inputs": { 25 | "nixpkgs": [ 26 | "nixpkgs" 27 | ] 28 | }, 29 | "locked": { 30 | "lastModified": 1671096816, 31 | "narHash": "sha256-ezQCsNgmpUHdZANDCILm3RvtO1xH8uujk/+EqNvzIOg=", 32 | "owner": "nix-community", 33 | "repo": "naersk", 34 | "rev": "d998160d6a076cfe8f9741e56aeec7e267e3e114", 35 | "type": "github" 36 | }, 37 | "original": { 38 | "owner": "nix-community", 39 | "ref": "master", 40 | "repo": "naersk", 41 | "type": "github" 42 | } 43 | }, 44 | "nixpkgs": { 45 | "locked": { 46 | "lastModified": 1671108576, 47 | "narHash": "sha256-6ggOL6KoaELNA1562tnPjtAnQ9SwsKRTgeuaXvPzCwI=", 48 | "owner": "nixos", 49 | "repo": "nixpkgs", 50 | "rev": "0f5996b524c91677891a432cc99c7567c7c402b1", 51 | "type": "github" 52 | }, 53 | "original": { 54 | "owner": "nixos", 55 | "ref": "nixos-unstable", 56 | "repo": "nixpkgs", 57 | "type": "github" 58 | } 59 | }, 60 | "nixpkgs_2": { 61 | "locked": { 62 | "lastModified": 1671220433, 63 | "narHash": "sha256-j+sC1XLEwEHUgMdu4FuSWedlO/BMC4gWUQ6hvzRCWrs=", 64 | "owner": "NixOS", 65 | "repo": "nixpkgs", 66 | "rev": "093ec6f77bf9a3de6421952d116ea05c9d80f6e5", 67 | "type": "github" 68 | }, 69 | "original": { 70 | "owner": "NixOS", 71 | "ref": "nixpkgs-unstable", 72 | "repo": "nixpkgs", 73 | "type": "github" 74 | } 75 | }, 76 | "root": { 77 | "inputs": { 78 | "fenix": "fenix", 79 | "naersk": "naersk", 80 | "nixpkgs": "nixpkgs_2", 81 | "utils": "utils" 82 | } 83 | }, 84 | "rust-analyzer-src": { 85 | "flake": false, 86 | "locked": { 87 | "lastModified": 1671029659, 88 | "narHash": "sha256-2sqAgHcLWpNGVHG2LQIXgRMuqgCArOD9frQSrrXrwSA=", 89 | "owner": "rust-lang", 90 | "repo": "rust-analyzer", 91 | "rev": "95671d53ea3063da5316784af9ef69c71219f320", 92 | "type": "github" 93 | }, 94 | "original": { 95 | "owner": "rust-lang", 96 | "ref": "nightly", 97 | "repo": "rust-analyzer", 98 | "type": "github" 99 | } 100 | }, 101 | "utils": { 102 | "locked": { 103 | "lastModified": 1667395993, 104 | "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", 105 | "owner": "numtide", 106 | "repo": "flake-utils", 107 | "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", 108 | "type": "github" 109 | }, 110 | "original": { 111 | "owner": "numtide", 112 | "repo": "flake-utils", 113 | "type": "github" 114 | } 115 | } 116 | }, 117 | "root": "root", 118 | "version": 7 119 | } 120 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | naersk = { 4 | url = "github:nix-community/naersk/master"; 5 | inputs.nixpkgs.follows = "nixpkgs"; 6 | }; 7 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 8 | utils.url = "github:numtide/flake-utils"; 9 | fenix.url = "github:pupbrained/fenix/patch-1"; 10 | }; 11 | 12 | outputs = { 13 | self, 14 | nixpkgs, 15 | utils, 16 | naersk, 17 | fenix, 18 | }: 19 | utils.lib.eachDefaultSystem (system: let 20 | pkgs = import nixpkgs {inherit system;}; 21 | naersk-lib = pkgs.callPackage naersk {}; 22 | in { 23 | defaultPackage = let 24 | pkgs = nixpkgs.legacyPackages.${system}; 25 | toolchain = with fenix.packages.${system}; 26 | combine [ 27 | minimal.cargo 28 | minimal.rustc 29 | targets.x86_64-unknown-linux-gnu.latest.rust-std 30 | ]; 31 | in 32 | (naersk.lib.${system}.override { 33 | cargo = toolchain; 34 | rustc = toolchain; 35 | }) 36 | .buildPackage { 37 | src = ./.; 38 | buildInputs = with pkgs; [dbus]; 39 | nativeBuildInputs = with pkgs; [pkg-config]; 40 | }; 41 | 42 | defaultApp = utils.lib.mkApp { 43 | drv = self.defaultPackage."${system}"; 44 | }; 45 | 46 | devShell = with pkgs; 47 | mkShell { 48 | buildInputs = [dbus]; 49 | nativeBuildInputs = [pkg-config]; 50 | RUST_SRC_PATH = rustPlatform.rustLibSrc; 51 | }; 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | tab_spaces = 2 2 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | (import ( 2 | fetchTarball { 3 | url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; 4 | sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; 5 | } 6 | ) { 7 | src = ./.; 8 | }) 9 | .shellNix 10 | -------------------------------------------------------------------------------- /src/funcs/greet.rs: -------------------------------------------------------------------------------- 1 | use { 2 | crate::util::statics::{CONF, GREET_EMOJIS, GREET_ICONS}, 3 | chrono::{Local, Timelike}, 4 | sys_info::hostname, 5 | whoami::{realname, username}, 6 | }; 7 | 8 | #[tracing::instrument] 9 | pub(crate) fn get_hostname() -> Option { 10 | match &CONF.main.hostname { 11 | Some(hostname) => Some(hostname.to_string()), 12 | None => Some(format!("{}@{}", username(), hostname().ok()?)), 13 | } 14 | } 15 | 16 | #[tracing::instrument] 17 | pub(crate) fn greeting() -> Option { 18 | if !CONF.greeting.enabled { 19 | return None; 20 | } 21 | 22 | let name = if CONF.main.name.is_none() { 23 | realname() 24 | } else { 25 | CONF.main.name.as_ref()?.to_string() 26 | }; 27 | 28 | let phrase = if CONF.icons.enabled { 29 | match CONF.icons.kind.as_deref() { 30 | Some("emoji") => match Local::now().hour() { 31 | 6..=11 => format!("{} Good morning", GREET_EMOJIS[0]), 32 | 12..=17 => format!("{} Good afternoon", GREET_EMOJIS[1]), 33 | 18..=22 => format!("{} Good evening", GREET_EMOJIS[2]), 34 | _ => format!("{} Good night", GREET_EMOJIS[3]), 35 | }, 36 | Some("normal") => match Local::now().hour() { 37 | 6..=11 => format!("{} Good morning", GREET_ICONS[0]), 38 | 12..=17 => format!("{} Good afternoon", GREET_ICONS[1]), 39 | 18..=22 => format!("{} Good evening", GREET_ICONS[2]), 40 | _ => format!("{} Good night", GREET_ICONS[3]), 41 | }, 42 | Some(&_) | None => match Local::now().hour() { 43 | 6..=11 => "Good morning".to_string(), 44 | 12..=17 => "Good afternoon".to_string(), 45 | 18..=22 => "Good evening".to_string(), 46 | _ => "Good night".to_string(), 47 | }, 48 | } 49 | } else { 50 | match Local::now().hour() { 51 | 6..=11 => "Good morning".to_string(), 52 | 12..=17 => "Good afternoon".to_string(), 53 | 18..=22 => "Good evening".to_string(), 54 | _ => "Good night".to_string(), 55 | } 56 | }; 57 | 58 | Some(format!("{phrase}, {name}")) 59 | } 60 | -------------------------------------------------------------------------------- /src/funcs/misc.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | use { 4 | crate::util::statics::{CONF, TIME_EMOJIS, TIME_ICONS, WEATHER_EMOJIS, WEATHER_ICONS}, 5 | chrono::{Local, Timelike}, 6 | mpris::PlayerFinder, 7 | openweathermap::weather, 8 | substring::Substring, 9 | }; 10 | 11 | #[tracing::instrument] 12 | pub(crate) fn get_song() -> Option { 13 | if !CONF.song.enabled { 14 | return None; 15 | } 16 | 17 | let songname; 18 | if CONF.song.mode == Some("playerctl".into()) { 19 | let song = Command::new("playerctl") 20 | .args(["metadata", "-f", "{{ artist }} - {{ title }}"]) 21 | .output() 22 | .unwrap(); 23 | songname = String::from_utf8_lossy(song.stdout.as_slice()).to_string(); 24 | if songname.is_empty() { 25 | return None; 26 | } 27 | } else { 28 | let player = PlayerFinder::new().ok()?.find_all().ok()?; 29 | let song = player.first()?.get_metadata().ok()?; // this is blocking 30 | let artists = song.artists()?.join(", "); 31 | songname = format!("{} - {}", artists, song.title()?); 32 | } 33 | 34 | if CONF.icons.enabled { 35 | match CONF.icons.kind.as_deref() { 36 | Some("emoji") => { 37 | if songname.len() > (CONF.util.width as usize) { 38 | Some(format!( 39 | "{}...", 40 | songname.substring(0, (CONF.util.width - 14) as usize) 41 | )) 42 | } else { 43 | Some(songname.trim_end_matches('\n').to_string()) 44 | } 45 | } 46 | Some(&_) | None => { 47 | if songname.len() > (CONF.util.width as usize) { 48 | Some(format!( 49 | "{}...", 50 | songname.substring(0, (CONF.util.width - 14) as usize) 51 | )) 52 | } else { 53 | Some(songname.trim_end_matches('\n').to_string()) 54 | } 55 | } 56 | } 57 | } else if songname.len() > (CONF.util.width as usize) { 58 | Some(format!( 59 | "{}...", 60 | songname.substring(0, (CONF.util.width - 14) as usize) 61 | )) 62 | } else { 63 | Some(songname.trim_end_matches('\n').to_string()) 64 | } 65 | } 66 | 67 | #[tracing::instrument] 68 | pub(crate) async fn get_weather() -> Option { 69 | if CONF.weather.values.api_key.is_none() 70 | || CONF.weather.values.lang.is_none() 71 | || CONF.weather.values.location.is_none() 72 | || CONF.weather.values.units.is_none() 73 | || !CONF.weather.enabled 74 | { 75 | return None; 76 | } 77 | 78 | let api_key = CONF.weather.values.api_key.as_ref().unwrap().as_str(); 79 | let lang = CONF.weather.values.lang.as_ref().unwrap().as_str(); 80 | let location = CONF.weather.values.location.as_ref().unwrap().as_str(); 81 | let units = CONF.weather.values.units.as_ref().unwrap().as_str(); 82 | 83 | match &weather(location, units, lang, api_key).await { 84 | Ok(current) => { 85 | let deg = if units.trim_matches('\"') == "imperial" { 86 | "F" 87 | } else { 88 | "C" 89 | }; 90 | let icon_code = ¤t.weather[0].icon; 91 | let icon = if CONF.icons.enabled { 92 | match CONF.icons.kind.as_deref() { 93 | Some("emoji") => { 94 | match icon_code.as_ref() { 95 | "01d" => WEATHER_EMOJIS[0], // Clear sky 96 | "01n" => WEATHER_EMOJIS[1], 97 | "02d" => WEATHER_EMOJIS[2], // Few clouds 98 | "02n" => WEATHER_EMOJIS[3], 99 | "03d" => WEATHER_EMOJIS[4], // Scattered clouds 100 | "03n" => WEATHER_EMOJIS[5], 101 | "04d" => WEATHER_EMOJIS[6], // Broken clouds 102 | "04n" => WEATHER_EMOJIS[7], 103 | "09d" => WEATHER_EMOJIS[8], // Shower rain 104 | "09n" => WEATHER_EMOJIS[9], 105 | "10d" => WEATHER_EMOJIS[10], // Rain 106 | "10n" => WEATHER_EMOJIS[11], 107 | "11d" => WEATHER_EMOJIS[12], // Thunderstorm 108 | "11n" => WEATHER_EMOJIS[13], 109 | "13d" => WEATHER_EMOJIS[14], // Snow 110 | "13n" => WEATHER_EMOJIS[15], 111 | "40d" => WEATHER_EMOJIS[16], // Mist 112 | "40n" => WEATHER_EMOJIS[17], 113 | "50d" => WEATHER_EMOJIS[18], // Fog 114 | "50n" => WEATHER_EMOJIS[19], 115 | _ => WEATHER_EMOJIS[20], // Unknown 116 | } 117 | } 118 | Some("normal") => match icon_code.as_ref() { 119 | "01d" => WEATHER_ICONS[0], 120 | "01n" => WEATHER_ICONS[1], 121 | "02d" => WEATHER_ICONS[2], 122 | "02n" => WEATHER_ICONS[3], 123 | "03d" => WEATHER_ICONS[4], 124 | "03n" => WEATHER_ICONS[5], 125 | "04d" => WEATHER_ICONS[6], 126 | "04n" => WEATHER_ICONS[7], 127 | "09d" => WEATHER_ICONS[8], 128 | "09n" => WEATHER_ICONS[9], 129 | "10d" => WEATHER_ICONS[10], 130 | "10n" => WEATHER_ICONS[11], 131 | "11d" => WEATHER_ICONS[12], 132 | "11n" => WEATHER_ICONS[13], 133 | "13d" => WEATHER_ICONS[14], 134 | "13n" => WEATHER_ICONS[15], 135 | "40d" => WEATHER_ICONS[16], 136 | "40n" => WEATHER_ICONS[17], 137 | "50d" => WEATHER_ICONS[18], 138 | "50n" => WEATHER_ICONS[19], 139 | _ => WEATHER_ICONS[20], 140 | }, 141 | Some(&_) | None => "", 142 | } 143 | } else { 144 | "" 145 | }; 146 | 147 | let main = current.weather[0].main.to_string(); 148 | let temp = current.main.temp.to_string(); 149 | 150 | if CONF.icons.enabled { 151 | match CONF.icons.kind.as_deref() { 152 | Some("emoji") | Some("normal") => Some(format!( 153 | "│ {} {} {}°{}", 154 | icon, 155 | main, 156 | temp.substring(0, 2), 157 | deg 158 | )), 159 | Some(&_) | None => Some(format!( 160 | "│{} {} {}°{}", 161 | icon, 162 | main, 163 | temp.substring(0, 2), 164 | deg 165 | )), 166 | } 167 | } else { 168 | Some(format!( 169 | "│{} {} {}°{}", 170 | icon, 171 | main, 172 | temp.substring(0, 2), 173 | deg 174 | )) 175 | } 176 | } 177 | Err(e) => { 178 | tracing::warn!( 179 | "Could not fetch weather because: {} - maybe you forgot an API key?", 180 | e 181 | ); 182 | None 183 | } 184 | } 185 | } 186 | 187 | #[tracing::instrument] 188 | pub(crate) fn get_datetime() -> Option { 189 | if !CONF.time.enabled { 190 | return None; 191 | } 192 | 193 | let dt = Local::now(); 194 | let time = match CONF.time.kind.as_deref()? { 195 | "12h" => dt.format("%l:%M %p").to_string(), 196 | "24h" => dt.format("%H:%M").to_string(), 197 | _ => "off".to_string(), 198 | }; 199 | let day = dt.format("%e").to_string(); 200 | let date = match day.trim_start_matches(' ') { 201 | "1" | "21" | "31 " => format!("{} {}st", dt.format("%B"), day.trim_start_matches(' ')), 202 | "2" | "22" => format!("{} {}nd", dt.format("%B"), day.trim_start_matches(' ')), 203 | "3" | "23" => format!("{} {}rd", dt.format("%B"), day.trim_start_matches(' ')), 204 | _ => format!("{} {}th", dt.format("%B"), day.trim_start_matches(' ')), 205 | }; 206 | let time_icon = if CONF.icons.enabled { 207 | match CONF.icons.kind.as_deref() { 208 | Some("emoji") => { 209 | let index: usize = if dt.hour() >= 12 { 210 | (dt.hour() - 12).try_into().unwrap() 211 | } else { 212 | dt.hour().try_into().unwrap() 213 | }; 214 | TIME_EMOJIS[index.min(11)] 215 | } 216 | Some("normal") => { 217 | let index: usize = if dt.hour() >= 12 { 218 | (dt.hour() - 12).try_into().unwrap() 219 | } else { 220 | dt.hour().try_into().unwrap() 221 | }; 222 | TIME_ICONS[index.min(11)] 223 | } 224 | Some(&_) | None => "", 225 | } 226 | } else { 227 | "" 228 | }; 229 | 230 | if CONF.icons.enabled { 231 | match CONF.icons.kind.as_deref() { 232 | Some("emoji") | Some("normal") => Some(format!( 233 | "│ {} {}, {}", 234 | time_icon, 235 | date, 236 | time.trim_start_matches(' ') 237 | )), 238 | Some(&_) | None => Some(format!( 239 | "│{} {}, {}", 240 | time_icon, 241 | date, 242 | time.trim_start_matches(' ') 243 | )), 244 | } 245 | } else { 246 | Some(format!( 247 | "│{} {}, {}", 248 | time_icon, 249 | date, 250 | time.trim_start_matches(' ') 251 | )) 252 | } 253 | } 254 | -------------------------------------------------------------------------------- /src/funcs/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod greet; 2 | pub mod misc; 3 | pub mod pkgs; 4 | pub mod system_info; 5 | -------------------------------------------------------------------------------- /src/funcs/pkgs.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | use { 4 | crate::util::statics::{CONF, PACKAGE_EMOJIS, PACKAGE_ICONS}, 5 | std::process::Stdio, 6 | tokio::{ 7 | io::{AsyncBufReadExt, BufReader}, 8 | process::{ChildStdout, Command}, 9 | }, 10 | }; 11 | 12 | #[derive(Debug)] 13 | enum CommandKind { 14 | Pacman, 15 | Apt, 16 | Xbps, 17 | Portage, 18 | Apk, 19 | Dnf, 20 | NixUser, 21 | NixSystem, 22 | } 23 | 24 | async fn count_lines(skip: i32, mut reader: BufReader) -> Option { 25 | let mut total = 0; 26 | let mut s = String::new(); 27 | 28 | loop { 29 | let n = reader 30 | .read_line(&mut s) 31 | .await 32 | .map_err(|e| tracing::warn!("Failed to read line from command output, {}", e)) 33 | .ok()?; 34 | 35 | if n == 0 { 36 | break; 37 | } 38 | s.clear(); 39 | total += 1; 40 | } 41 | 42 | if total > skip { 43 | Some(total - skip) 44 | } else { 45 | Some(0) 46 | } 47 | } 48 | 49 | fn check_update_commmand(command: String) -> Option<(CommandKind, Command)> { 50 | if !CONF.packages.update_count.enabled { 51 | return None; 52 | } 53 | 54 | let tup = match command.as_str() { 55 | "pacman" => (CommandKind::Pacman, Command::new("checkupdates")), 56 | "apt" => (CommandKind::Apt, { 57 | let mut command = Command::new("apt"); 58 | command.args(["list", "-u"]); 59 | 60 | command 61 | }), 62 | "xbps" => (CommandKind::Xbps, { 63 | let mut command = Command::new("xbps-install"); 64 | command.arg("-Sun"); 65 | command 66 | }), 67 | "portage" => (CommandKind::Portage, { 68 | let mut command = Command::new("eix"); 69 | command.args(["-u", "--format", "''"]); 70 | command 71 | }), 72 | "apk" => (CommandKind::Apk, { 73 | let mut command = Command::new("apk"); 74 | command.args(["-u", "list"]); 75 | command 76 | }), 77 | "dnf" => (CommandKind::Dnf, { 78 | let mut command = Command::new("dnf"); 79 | command.arg("check-update"); 80 | command 81 | }), 82 | other => { 83 | tracing::warn!("Unsupported package manager: {}", other); 84 | return None; 85 | } 86 | }; 87 | 88 | Some(tup) 89 | } 90 | 91 | #[tracing::instrument] 92 | async fn do_update_counting(arg: String) -> Option { 93 | let (kind, mut command) = check_update_commmand(arg)?; 94 | let reader = command 95 | .stderr(Stdio::null()) 96 | .stdout(Stdio::piped()) 97 | .spawn() 98 | .ok()? 99 | .stdout 100 | .take()?; 101 | 102 | let fs = BufReader::new(reader); 103 | match kind { 104 | CommandKind::Apt => count_lines(2, fs).await, 105 | CommandKind::Portage => Some(0), // FIXME: Portage needs a proper update count command 106 | CommandKind::Dnf => count_lines(3, fs).await, 107 | _ => count_lines(0, fs).await, 108 | } 109 | } 110 | 111 | async fn check_updates() -> Option { 112 | match &CONF.packages.package_managers { 113 | Some(toml::Value::Array(pm)) => { 114 | let mut handles = Vec::new(); 115 | 116 | for arg in pm { 117 | if let toml::Value::String(string) = arg { 118 | let handle = tokio::spawn(do_update_counting(string.clone())); 119 | handles.push(handle); 120 | } 121 | } 122 | 123 | let mut total_updates = 0; 124 | 125 | for handle in handles { 126 | total_updates += handle.await.ok()??; 127 | } 128 | 129 | Some(total_updates) 130 | } 131 | Some(toml::Value::String(pm)) => do_update_counting(pm.clone()).await, 132 | _ => None, 133 | } 134 | } 135 | 136 | #[tracing::instrument] 137 | pub(crate) async fn count_updates() -> Option { 138 | let count = check_updates().await?; 139 | let updates = if CONF.icons.enabled { 140 | match CONF.icons.kind.as_deref() { 141 | Some("emoji") => match count { 142 | 0 => format!("{} Up to date", PACKAGE_EMOJIS[0]), 143 | 1 => format!("{} 1 update", PACKAGE_EMOJIS[1]), 144 | 2 => format!("{} 2 updates", PACKAGE_EMOJIS[2]), 145 | 3 => format!("{} 3 updates", PACKAGE_EMOJIS[3]), 146 | 4 => format!("{} 4 updates", PACKAGE_EMOJIS[4]), 147 | 5 => format!("{} 5 updates", PACKAGE_EMOJIS[5]), 148 | 6 => format!("{} 6 updates", PACKAGE_EMOJIS[6]), 149 | 7 => format!("{} 7 updates", PACKAGE_EMOJIS[7]), 150 | 8 => format!("{} 8 updates", PACKAGE_EMOJIS[8]), 151 | 9 => format!("{} 9 updates", PACKAGE_EMOJIS[9]), 152 | 10 => format!("{} 10 updates", PACKAGE_EMOJIS[10]), 153 | _ => format!("{} {} updates", PACKAGE_EMOJIS[11], count), 154 | }, 155 | Some("normal") => match count { 156 | 0 => format!("{} Up to date", PACKAGE_ICONS[0]), 157 | 1 => format!("{} 1 update", PACKAGE_ICONS[1]), 158 | 2 => format!("{} 2 updates", PACKAGE_ICONS[2]), 159 | 3 => format!("{} 3 updates", PACKAGE_ICONS[3]), 160 | 4 => format!("{} 4 updates", PACKAGE_ICONS[4]), 161 | 5 => format!("{} 5 updates", PACKAGE_ICONS[5]), 162 | 6 => format!("{} 6 updates", PACKAGE_ICONS[6]), 163 | 7 => format!("{} 7 updates", PACKAGE_ICONS[7]), 164 | 8 => format!("{} 8 updates", PACKAGE_ICONS[8]), 165 | 9 => format!("{} 9 updates", PACKAGE_ICONS[9]), 166 | _ => format!("{} {} updates", PACKAGE_ICONS[10], count), 167 | }, 168 | Some(&_) | None => format!("{count} updates"), 169 | } 170 | } else { 171 | format!("{count} updates") 172 | }; 173 | Some(format!("│ {updates}")) 174 | } 175 | 176 | fn check_installed_command(command: String) -> Option<(CommandKind, Command)> { 177 | if !CONF.packages.package_count.enabled { 178 | return None; 179 | } 180 | 181 | let tup = match command.as_str() { 182 | "pacman" => (CommandKind::Pacman, { 183 | let mut command = Command::new("pacman"); 184 | command.arg("-Q"); 185 | command 186 | }), 187 | "apt" => (CommandKind::Apt, { 188 | let mut command = Command::new("apt"); 189 | command.args(["list", "-i"]); 190 | command 191 | }), 192 | "xbps" => (CommandKind::Xbps, { 193 | let mut command = Command::new("xbps-query"); 194 | command.arg("-l"); 195 | command 196 | }), 197 | "portage" => (CommandKind::Portage, { 198 | let mut command = Command::new("qlist"); 199 | command.arg("-I"); 200 | command 201 | }), 202 | "apk" => (CommandKind::Apk, { 203 | let mut command = Command::new("apk"); 204 | command.arg("info"); 205 | command 206 | }), 207 | "dnf" => (CommandKind::Dnf, { 208 | let mut command = Command::new("dnf"); 209 | command.args(["list", "installed"]); 210 | command 211 | }), 212 | "nix-user" => (CommandKind::NixUser, { 213 | let mut command = Command::new("nix-store"); 214 | let user = env::var("USER").unwrap_or_else(|_| "UNKNOWN".to_string()); 215 | command.args(["-qR", format!("/home/{user}/.nix-profile").as_str()]); 216 | command 217 | }), 218 | "nix-system" => (CommandKind::NixSystem, { 219 | let mut command = Command::new("nix-store"); 220 | command.args(["-qR", "/run/current-system/sw"]); 221 | command 222 | }), 223 | other => { 224 | tracing::warn!("unknown package manager: {}", other); 225 | return None; 226 | } 227 | }; 228 | 229 | Some(tup) 230 | } 231 | 232 | #[tracing::instrument] 233 | async fn do_installed_counting(arg: String) -> Option { 234 | let (kind, mut command) = check_installed_command(arg)?; 235 | let reader = command 236 | .stderr(Stdio::null()) 237 | .stdout(Stdio::piped()) 238 | .spawn() 239 | .ok()? 240 | .stdout 241 | .take()?; 242 | 243 | let fs = BufReader::new(reader); 244 | match kind { 245 | CommandKind::Apt => count_lines(2, fs).await, 246 | _ => count_lines(0, fs).await, 247 | } 248 | } 249 | 250 | #[tracing::instrument] 251 | pub(crate) async fn get_package_count() -> Option { 252 | match &CONF.packages.package_managers { 253 | Some(toml::Value::Array(pm)) => { 254 | let mut handles = Vec::new(); 255 | 256 | for arg in pm { 257 | if let toml::Value::String(string) = arg { 258 | let handle = tokio::spawn(do_installed_counting(string.to_owned())); 259 | handles.push(handle); 260 | } 261 | } 262 | 263 | let mut total_packages = 0; 264 | 265 | for handle in handles { 266 | total_packages += handle.await.ok()??; 267 | } 268 | 269 | Some(total_packages) 270 | } 271 | Some(toml::Value::String(pm)) => do_installed_counting(pm.clone()).await, 272 | _ => None, 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /src/funcs/system_info.rs: -------------------------------------------------------------------------------- 1 | use { 2 | crate::util::statics::CONF, 3 | std::env, 4 | substring::Substring, 5 | sys_info::{linux_os_release, os_release}, 6 | systemstat::{saturating_sub_bytes, Platform, System}, 7 | }; 8 | 9 | #[tracing::instrument] 10 | pub(crate) fn get_release_blocking() -> Option { 11 | if !CONF.system.release.enabled { 12 | return None; 13 | } 14 | 15 | let rel = linux_os_release().ok()?.pretty_name?; // this performs a blocking read of /etc/os-release 16 | 17 | if CONF.icons.enabled { 18 | match CONF.icons.kind.as_deref() { 19 | Some("emoji") => { 20 | if rel.len() > 41 { 21 | Some(format!("{}...", rel.trim_matches('\"').substring(0, 37))) 22 | } else { 23 | Some( 24 | rel 25 | .trim_matches('\"') 26 | .trim_end_matches('\n') 27 | .trim_end_matches('\"') 28 | .to_string(), 29 | ) 30 | } 31 | } 32 | Some(&_) | None => { 33 | if rel.len() > 42 { 34 | Some(format!("{}...", rel.trim_matches('\"').substring(0, 38))) 35 | } else { 36 | Some( 37 | rel 38 | .trim_matches('\"') 39 | .trim_end_matches('\n') 40 | .trim_end_matches('\"') 41 | .to_string(), 42 | ) 43 | } 44 | } 45 | } 46 | } else if rel.len() > 42 { 47 | Some(format!("{}...", rel.trim_matches('\"').substring(0, 38))) 48 | } else { 49 | Some( 50 | rel 51 | .trim_matches('\"') 52 | .trim_end_matches('\n') 53 | .trim_end_matches('\"') 54 | .to_string(), 55 | ) 56 | } 57 | } 58 | 59 | #[tracing::instrument] 60 | pub(crate) fn get_kernel_blocking() -> Option { 61 | if !CONF.system.kernel.enabled { 62 | return None; 63 | } 64 | 65 | let kernel = os_release().ok()?; // this performs a blocking read of /proc/sys/kernel/osrelease 66 | if CONF.icons.enabled { 67 | match CONF.icons.kind.as_deref() { 68 | Some("emoji") => { 69 | if kernel.len() > 41 { 70 | Some(format!("{}...", kernel.substring(0, 37))) 71 | } else { 72 | Some(kernel.trim_end_matches('\n').to_string()) 73 | } 74 | } 75 | Some(&_) | None => { 76 | if kernel.len() > 42 { 77 | Some(format!("{}...", kernel.substring(0, 38))) 78 | } else { 79 | Some(kernel.trim_end_matches('\n').to_string()) 80 | } 81 | } 82 | } 83 | } else if kernel.len() > 42 { 84 | Some(format!("{}...", kernel.substring(0, 38))) 85 | } else { 86 | Some(kernel.trim_end_matches('\n').to_string()) 87 | } 88 | } 89 | 90 | #[tracing::instrument] 91 | pub(crate) fn get_memory() -> Option { 92 | if !CONF.system.mem_usage.enabled { 93 | return None; 94 | } 95 | 96 | match System::new().memory() { 97 | Ok(mem) => match CONF.system.mem_usage.free_before_used { 98 | Some(false) => Some(format!( 99 | "{} Used / {} ({} Free)", 100 | saturating_sub_bytes(mem.total, mem.free), 101 | mem.total, 102 | mem.free 103 | )), 104 | Some(true) => Some(format!( 105 | "{} Free / {} ({} Used)", 106 | mem.free, 107 | mem.total, 108 | saturating_sub_bytes(mem.total, mem.free) 109 | )), 110 | None => Some(format!( 111 | "{} Used / {} ({} Free)", 112 | saturating_sub_bytes(mem.total, mem.free), 113 | mem.total, 114 | mem.free 115 | )), 116 | }, 117 | Err(x) => panic!("Could not get memory because: {x}"), 118 | } 119 | } 120 | 121 | #[tracing::instrument] 122 | pub(crate) fn get_disk_usage() -> Option { 123 | if !CONF.system.disk_usage.enabled { 124 | return None; 125 | } 126 | 127 | match System::new().mount_at("/") { 128 | Ok(disk) => match CONF.system.disk_usage.free_before_used { 129 | Some(false) => Some(format!( 130 | "{} Used / {} ({} Free)", 131 | saturating_sub_bytes(disk.total, disk.free), 132 | disk.total, 133 | disk.free 134 | )), 135 | Some(true) => Some(format!( 136 | "{} Free / {} ({} Used)", 137 | disk.free, 138 | disk.total, 139 | saturating_sub_bytes(disk.total, disk.free) 140 | )), 141 | None => Some(format!( 142 | "{} Free / {} ({} Used)", 143 | disk.free, 144 | disk.total, 145 | saturating_sub_bytes(disk.total, disk.free) 146 | )), 147 | }, 148 | Err(x) => panic!("Could not get disk usage because: {x}"), 149 | } 150 | } 151 | 152 | #[tracing::instrument] 153 | pub(crate) fn get_environment() -> Option { 154 | if !CONF.system.desktop_env.enabled { 155 | return None; 156 | } 157 | 158 | Some( 159 | env::var::(ToString::to_string(&"XDG_CURRENT_DESKTOP")) 160 | .unwrap_or_else(|_| { 161 | env::var("XDG_SESSION_DESKTOP").unwrap_or_else(|_| { 162 | env::var::(ToString::to_string(&"DESKTOP_SESSION")) 163 | .unwrap_or_else(|_| "Unknown".to_string()) 164 | }) 165 | }) 166 | .replace("none+", ""), 167 | ) 168 | } 169 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(let_chains)] 2 | 3 | use regex::Regex; 4 | 5 | pub mod funcs; 6 | pub mod util; 7 | 8 | use { 9 | crate::{ 10 | funcs::{ 11 | greet::{get_hostname, greeting}, 12 | misc::{get_datetime, get_song, get_weather}, 13 | pkgs::{count_updates, get_package_count}, 14 | system_info::{ 15 | get_disk_usage, get_environment, get_kernel_blocking, get_memory, get_release_blocking, 16 | }, 17 | }, 18 | util::{ 19 | formatting::{ 20 | calc_bottom, calc_whitespace, calc_whitespace_song, calc_with_hostname, upper_first, 21 | }, 22 | statics::{CONF, MISC_EMOJIS, MISC_ICONS, PACKAGE_EMOJIS, PACKAGE_ICONS}, 23 | }, 24 | }, 25 | once_cell::sync::Lazy, 26 | std::{process::exit, time::Instant}, 27 | tracing_subscriber::{ 28 | fmt::{format::FmtSpan, layer}, 29 | prelude::*, 30 | EnvFilter, 31 | }, 32 | }; 33 | 34 | #[tokio::main] 35 | async fn main() { 36 | if CONF.util.width < 50 { 37 | eprintln!("Width attribute must be at least 50, please change it."); 38 | exit(1); 39 | } 40 | 41 | tracing_subscriber::registry() 42 | .with( 43 | layer() 44 | .pretty() 45 | .with_span_events(FmtSpan::NEW | FmtSpan::CLOSE), 46 | ) 47 | .with(EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"))) 48 | .init(); 49 | 50 | tracing::info!("Running"); 51 | 52 | let time = Instant::now(); 53 | 54 | Lazy::force(&CONF); 55 | 56 | // These do not need to be spawned in any way, they are nonblocking 57 | let hostname = get_hostname(); 58 | let greeting = greeting(); 59 | let datetime = get_datetime(); 60 | let memory = get_memory(); 61 | let disk = get_disk_usage(); 62 | let environment = get_environment(); 63 | 64 | // These are proper async functions 65 | let weather = tokio::spawn(get_weather()); 66 | let up_count = tokio::spawn(count_updates()); 67 | let package_count = tokio::spawn(get_package_count()); 68 | 69 | // These are functions that block 70 | let song = tokio::task::spawn_blocking(get_song); 71 | let release = tokio::task::spawn_blocking(get_release_blocking); 72 | let kernel = tokio::task::spawn_blocking(get_kernel_blocking); 73 | 74 | let weather = weather.await.unwrap(); 75 | let up_count = up_count.await.unwrap(); 76 | let package_count = package_count.await.unwrap(); 77 | 78 | let song = song.await.unwrap(); 79 | let release = release.await.unwrap(); 80 | let kernel = kernel.await.unwrap(); 81 | 82 | tracing::info!( 83 | "Finished collecting data in {:.3}", 84 | time.elapsed().as_secs_f32() 85 | ); 86 | 87 | if let Some(hostname) = hostname && let Some(greeting) = greeting && let Some(datetime) = datetime && let Some(weather) = weather { 88 | println!( 89 | "{}", 90 | calc_with_hostname(format!("╭─── \x1b[32m{hostname}\x1b[0m ")) 91 | ); 92 | println!("{}", calc_whitespace(format!("│ {greeting}!"))); 93 | println!("{}", calc_whitespace(datetime)); 94 | println!("{}", calc_whitespace(weather)); 95 | } 96 | 97 | if CONF.icons.enabled { 98 | match CONF.icons.kind.as_deref() { 99 | Some("emoji") => { 100 | if let Some(release) = release && let Some(kernel) = kernel && let Some(memory) = memory && let Some(disk) = disk && let Some(environment) = environment { 101 | println!( 102 | "{}", 103 | calc_whitespace(format!("│ {} {release}", MISC_EMOJIS[0])) 104 | ); 105 | println!( 106 | "{}", 107 | calc_whitespace(format!("│ {} {kernel}", MISC_EMOJIS[1])) 108 | ); 109 | println!( 110 | "{}", 111 | calc_whitespace(format!("│ {} {memory}", MISC_EMOJIS[2])) 112 | ); 113 | println!( 114 | "{}", 115 | calc_whitespace(format!("│ {} {disk}", MISC_EMOJIS[3])) 116 | ); 117 | println!( 118 | "{}", 119 | calc_whitespace(format!( 120 | "│ {} {}", 121 | MISC_EMOJIS[4], 122 | upper_first(environment) 123 | )) 124 | ); 125 | } 126 | } 127 | Some("normal") => { 128 | if let Some(release) = release { 129 | println!( 130 | "{}", 131 | calc_whitespace(format!("│ {} {}", MISC_ICONS[0], release)) 132 | ); 133 | } 134 | if let Some(kernel) = kernel { 135 | println!( 136 | "{}", 137 | calc_whitespace(format!("│ {} {}", MISC_ICONS[1], kernel)) 138 | ); 139 | } 140 | if let Some(memory) = memory { 141 | println!( 142 | "{}", 143 | calc_whitespace(format!("│ {} {}", MISC_ICONS[2], memory)) 144 | ); 145 | } 146 | if let Some(disk) = disk { 147 | println!( 148 | "{}", 149 | calc_whitespace(format!("│ {} {}", MISC_ICONS[3], disk)) 150 | ); 151 | } 152 | 153 | if let Some(environment) = environment { 154 | println!( 155 | "{}", 156 | calc_whitespace(format!( 157 | "│ {} {}", 158 | MISC_ICONS[4], 159 | upper_first(environment) 160 | )) 161 | ); 162 | } 163 | } 164 | Some(&_) | None => { 165 | if let Some(release) = release { 166 | println!("{}", calc_whitespace(format!("│ {release}"))); 167 | } 168 | if let Some(kernel) = kernel { 169 | println!("{}", calc_whitespace(format!("│ {kernel}"))); 170 | } 171 | if let Some(memory) = memory { 172 | println!("{}", calc_whitespace(format!("│ {memory}"))); 173 | } 174 | if let Some(disk) = disk { 175 | println!("{}", calc_whitespace(format!("│ {disk}"))); 176 | } 177 | if let Some(environment) = environment { 178 | println!( 179 | "{}", 180 | calc_whitespace(format!("│ {}", upper_first(environment))) 181 | ); 182 | } 183 | } 184 | } 185 | } else { 186 | if let Some(release) = release { 187 | println!("{}", calc_whitespace(format!("│ {release}"))); 188 | } 189 | if let Some(kernel) = kernel { 190 | println!("{}", calc_whitespace(format!("│ {kernel}"))); 191 | } 192 | if let Some(memory) = memory { 193 | println!("{}", calc_whitespace(format!("│ {memory}"))); 194 | } 195 | if let Some(disk) = disk { 196 | println!("{}", calc_whitespace(format!("│ {disk}"))); 197 | } 198 | 199 | if let Some(environment) = environment { 200 | println!( 201 | "{}", 202 | calc_whitespace(format!("│ {}", upper_first(environment))) 203 | ); 204 | } 205 | } 206 | 207 | if let Some(count) = up_count { 208 | println!("{}", calc_whitespace(count)); 209 | } 210 | 211 | if CONF.icons.enabled { 212 | match CONF.icons.kind.as_deref() { 213 | Some("emoji") => match package_count { 214 | None => (), 215 | Some(0) => println!( 216 | "{}", 217 | calc_whitespace(format!("│ {} No packages", PACKAGE_EMOJIS[12])) 218 | ), 219 | Some(1) => println!( 220 | "{}", 221 | calc_whitespace(format!("│ {} 1 package", PACKAGE_EMOJIS[12])) 222 | ), 223 | Some(n) => println!( 224 | "{}", 225 | calc_whitespace(format!("│ {} {} packages", PACKAGE_EMOJIS[12], n)) 226 | ), 227 | }, 228 | Some("normal") => match package_count { 229 | None => (), 230 | Some(0) => println!( 231 | "{}", 232 | calc_whitespace(format!("│ {} No packages", PACKAGE_ICONS[11])) 233 | ), 234 | Some(1) => println!( 235 | "{}", 236 | calc_whitespace(format!("│ {} 1 package", PACKAGE_ICONS[11])) 237 | ), 238 | Some(n) => println!( 239 | "{}", 240 | calc_whitespace(format!("│ {} {} packages", PACKAGE_ICONS[11], n)) 241 | ), 242 | }, 243 | Some(&_) | None => match package_count { 244 | None => (), 245 | Some(0) => println!("{}", calc_whitespace("│ No packages".to_string())), 246 | Some(1) => println!("{}", calc_whitespace("│ 1 package".to_string())), 247 | Some(n) => println!("{}", calc_whitespace(format!("│ {n} packages"))), 248 | }, 249 | } 250 | } else { 251 | match package_count { 252 | None => (), 253 | Some(0) => println!("{}", calc_whitespace("│ No packages".to_string())), 254 | Some(1) => println!("{}", calc_whitespace("│ 1 package".to_string())), 255 | Some(n) => println!("{}", calc_whitespace(format!("│ {n} packages"))), 256 | } 257 | } 258 | 259 | if CONF.icons.enabled { 260 | match CONF.icons.kind.as_deref() { 261 | Some("emoji") => { 262 | if let Some(song) = song.as_ref() { 263 | let cjk_regex = 264 | Regex::new(r"[\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}\p{Bopomofo}\p{Yi}]+").unwrap(); 265 | if !cjk_regex.is_match(song) { 266 | println!( 267 | "{}", 268 | calc_whitespace_song(format!("│ {} {}", MISC_EMOJIS[5], song.trim_matches('\n'))) 269 | ); 270 | } 271 | } 272 | } 273 | Some("normal") => { 274 | if let Some(song) = song.as_ref() { 275 | let cjk_regex = 276 | Regex::new(r"[\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}\p{Bopomofo}\p{Yi}]+").unwrap(); 277 | if !cjk_regex.is_match(song) { 278 | println!( 279 | "{}", 280 | calc_whitespace_song(format!("│ {} {}", MISC_ICONS[5], song.trim_matches('\n'))) 281 | ); 282 | } 283 | } 284 | } 285 | Some(&_) | None => { 286 | if let Some(song) = song.as_ref() { 287 | println!( 288 | "{}", 289 | calc_whitespace_song(format!("│ {}", song.trim_matches('\n'))) 290 | ); 291 | } 292 | } 293 | } 294 | } else if let Some(song) = song.as_ref() { 295 | println!( 296 | "{}", 297 | calc_whitespace_song(format!("│ {}", song.trim_matches('\n'))) 298 | ); 299 | } 300 | println!("{}", calc_bottom()); 301 | } 302 | -------------------------------------------------------------------------------- /src/util/conf_structs.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Deserialize)] 4 | pub(crate) struct Config { 5 | pub(crate) main: Main, 6 | pub(crate) util: Util, 7 | pub(crate) greeting: Greeting, 8 | pub(crate) icons: Icons, 9 | pub(crate) time: Time, 10 | pub(crate) weather: Weather, 11 | pub(crate) system: System, 12 | pub(crate) packages: Packages, 13 | pub(crate) song: Song, 14 | } 15 | 16 | #[derive(Deserialize)] 17 | pub(crate) struct Main { 18 | pub(crate) hostname: Option, 19 | pub(crate) name: Option, 20 | } 21 | 22 | #[derive(Deserialize)] 23 | pub(crate) struct Util { 24 | pub(crate) width: i32, 25 | } 26 | 27 | #[derive(Deserialize)] 28 | pub(crate) struct Greeting { 29 | pub(crate) enabled: bool, 30 | } 31 | 32 | #[derive(Deserialize)] 33 | pub(crate) struct Icons { 34 | pub(crate) enabled: bool, 35 | pub(crate) kind: Option, 36 | } 37 | 38 | #[derive(Deserialize)] 39 | pub(crate) struct Time { 40 | pub(crate) enabled: bool, 41 | pub(crate) kind: Option, 42 | } 43 | 44 | #[derive(Deserialize)] 45 | pub(crate) struct Weather { 46 | pub(crate) enabled: bool, 47 | pub(crate) values: WeatherValues, 48 | } 49 | 50 | #[derive(Deserialize)] 51 | pub(crate) struct WeatherValues { 52 | pub(crate) api_key: Option, 53 | pub(crate) location: Option, 54 | pub(crate) lang: Option, 55 | pub(crate) units: Option, 56 | } 57 | 58 | #[derive(Deserialize)] 59 | pub(crate) struct System { 60 | pub(crate) release: Release, 61 | pub(crate) kernel: Kernel, 62 | pub(crate) mem_usage: MemUsage, 63 | pub(crate) disk_usage: DiskUsage, 64 | pub(crate) desktop_env: DesktopEnv, 65 | } 66 | 67 | #[derive(Deserialize)] 68 | pub(crate) struct Release { 69 | pub(crate) enabled: bool, 70 | } 71 | 72 | #[derive(Deserialize)] 73 | pub(crate) struct Kernel { 74 | pub(crate) enabled: bool, 75 | } 76 | 77 | #[derive(Deserialize)] 78 | pub(crate) struct MemUsage { 79 | pub(crate) enabled: bool, 80 | pub(crate) free_before_used: Option, 81 | } 82 | 83 | #[derive(Deserialize)] 84 | pub(crate) struct DiskUsage { 85 | pub(crate) enabled: bool, 86 | pub(crate) free_before_used: Option, 87 | } 88 | 89 | #[derive(Deserialize)] 90 | pub(crate) struct DesktopEnv { 91 | pub(crate) enabled: bool, 92 | } 93 | 94 | #[derive(Deserialize)] 95 | pub(crate) struct Packages { 96 | pub(crate) package_managers: Option, 97 | pub(crate) package_count: PackageCount, 98 | pub(crate) update_count: UpdateCount, 99 | } 100 | 101 | #[derive(Deserialize)] 102 | pub(crate) struct PackageCount { 103 | pub(crate) enabled: bool, 104 | } 105 | 106 | #[derive(Deserialize)] 107 | pub(crate) struct UpdateCount { 108 | pub(crate) enabled: bool, 109 | } 110 | 111 | #[derive(Deserialize)] 112 | pub(crate) struct Song { 113 | pub(crate) enabled: bool, 114 | pub(crate) mode: Option, 115 | } 116 | -------------------------------------------------------------------------------- /src/util/config.rs: -------------------------------------------------------------------------------- 1 | use { 2 | crate::util::conf_structs::Config, 3 | argparse::{ArgumentParser, Store, StoreTrue}, 4 | std::{env, io::ErrorKind}, 5 | }; 6 | 7 | pub(crate) fn read_config() -> Config { 8 | let mut path = format!("{}/.config/draconis/config.toml", env::var("HOME").unwrap()); 9 | let mut ver = false; 10 | { 11 | let mut ap = ArgumentParser::new(); 12 | ap.set_description("A simple greeter for your terminal, made in Rust"); 13 | ap.refer(&mut path).add_option( 14 | &["-c", "--config"], 15 | Store, 16 | "Specify a path to a config file", 17 | ); 18 | ap.refer(&mut ver) 19 | .add_option(&["-v", "--version"], StoreTrue, "View program version"); 20 | ap.parse_args_or_exit(); 21 | } 22 | 23 | if ver { 24 | println!("Draconis v{}", env!("CARGO_PKG_VERSION")); 25 | std::process::exit(0); 26 | } 27 | 28 | let content = match std::fs::read_to_string(path) { 29 | Err(e) if e.kind() == ErrorKind::NotFound => { 30 | return toml::from_str( 31 | r#" 32 | [main] 33 | 34 | [util] 35 | 36 | [greeting] 37 | enabled = true 38 | 39 | [icons] 40 | enabled = false 41 | 42 | [time] 43 | enabled = false 44 | 45 | [weather] 46 | enabled = false 47 | 48 | [weather.values] 49 | 50 | [system] 51 | 52 | [system.release] 53 | enabled = false 54 | 55 | [system.kernel] 56 | enabled = false 57 | 58 | [system.mem_usage] 59 | enabled = false 60 | 61 | [system.disk_usage] 62 | enabled = false 63 | 64 | [system.desktop_env] 65 | enabled = false 66 | 67 | [packages] 68 | 69 | [packages.package_count] 70 | enabled = false 71 | 72 | [packages.update_count] 73 | enabled = false 74 | 75 | [song] 76 | enabled = false 77 | "#, 78 | ) 79 | .unwrap(); 80 | } 81 | Err(e) => panic!("{e}"), 82 | Ok(content) => match content.as_ref() { 83 | "" => { 84 | return toml::from_str( 85 | r#" 86 | [main] 87 | 88 | [util] 89 | 90 | [greeting] 91 | enabled = true 92 | 93 | [icons] 94 | enabled = false 95 | 96 | [time] 97 | enabled = false 98 | 99 | [weather] 100 | enabled = false 101 | 102 | [weather.values] 103 | 104 | [system] 105 | 106 | [system.release] 107 | enabled = false 108 | 109 | [system.kernel] 110 | enabled = false 111 | 112 | [system.mem_usage] 113 | enabled = false 114 | 115 | [system.disk_usage] 116 | enabled = false 117 | 118 | [system.desktop_env] 119 | enabled = false 120 | 121 | [packages] 122 | 123 | [packages.package_count] 124 | enabled = false 125 | 126 | [packages.update_count] 127 | enabled = false 128 | 129 | [song] 130 | enabled = false 131 | "#, 132 | ) 133 | .unwrap(); 134 | } 135 | _ => content, 136 | }, 137 | }; 138 | toml::from_str(&content).unwrap() 139 | } 140 | -------------------------------------------------------------------------------- /src/util/formatting.rs: -------------------------------------------------------------------------------- 1 | use substring::Substring; 2 | 3 | use { 4 | crate::util::statics::CONF, unicode_segmentation::UnicodeSegmentation, 5 | unicode_width::UnicodeWidthStr, 6 | }; 7 | 8 | pub(crate) fn upper_first(s: String) -> String { 9 | let mut c = s.chars(); 10 | match c.next() { 11 | None => String::new(), 12 | Some(f) => f.to_uppercase().collect::() + c.as_str(), 13 | } 14 | } 15 | 16 | pub(crate) fn calc_whitespace(text: String) -> String { 17 | let size = ((CONF.util.width - 5) as usize) - text.graphemes(true).count(); 18 | let fs = format!("{}{}", " ".repeat(size), "│"); 19 | format!("{text}{fs}") 20 | } 21 | 22 | pub(crate) fn calc_whitespace_song(text: String) -> String { 23 | if let (_, false) = ((CONF.util.width).overflowing_sub(3).0 as usize) 24 | .overflowing_sub(UnicodeWidthStr::width_cjk(text.as_str())) 25 | { 26 | let size = ((CONF.util.width).overflowing_sub(3).0 as usize) 27 | .overflowing_sub(UnicodeWidthStr::width_cjk(text.as_str())) 28 | .0; 29 | format!("{text}{}│", " ".repeat(size)) 30 | } else { 31 | format!("{}... │", text.substring(0, (CONF.util.width - 9) as usize),) 32 | } 33 | } 34 | 35 | pub(crate) fn calc_with_hostname(text: String) -> String { 36 | let size = if CONF.icons.enabled { 37 | match CONF.icons.kind.as_deref() { 38 | Some("emoji") => ((CONF.util.width + 5) as usize) - text.graphemes(true).count(), 39 | Some(&_) | None => ((CONF.util.width + 4) as usize) - text.graphemes(true).count(), 40 | } 41 | } else { 42 | ((CONF.util.width + 4) as usize) - text.graphemes(true).count() 43 | }; 44 | 45 | let fs = format!("{}{}", "─".repeat(size), "╮"); 46 | format!("{text}{fs}") 47 | } 48 | 49 | pub(crate) fn calc_bottom() -> String { 50 | let size = if CONF.icons.enabled { 51 | match CONF.icons.kind.as_deref() { 52 | Some("emoji") => ((CONF.util.width - 4) as usize) - "╰".graphemes(true).count(), 53 | Some(&_) | None => ((CONF.util.width - 5) as usize) - "╰".graphemes(true).count(), 54 | } 55 | } else { 56 | ((CONF.util.width - 5) as usize) - "╰".graphemes(true).count() 57 | }; 58 | 59 | let fs = format!("{}{}", "─".repeat(size), "╯"); 60 | format!("╰{fs}") 61 | } 62 | -------------------------------------------------------------------------------- /src/util/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod conf_structs; 2 | pub mod config; 3 | pub mod formatting; 4 | pub mod statics; 5 | -------------------------------------------------------------------------------- /src/util/statics.rs: -------------------------------------------------------------------------------- 1 | use { 2 | crate::util::{conf_structs::Config, config::read_config}, 3 | once_cell::sync::Lazy, 4 | }; 5 | 6 | pub(crate) static CONF: Lazy = Lazy::new(read_config); 7 | 8 | pub(crate) static GREET_ICONS: [&str; 4] = ["", "", "", ""]; 9 | pub(crate) static GREET_EMOJIS: [&str; 4] = ["🌇", "🏙️", "🌆", "🌃"]; 10 | pub(crate) static TIME_ICONS: [&str; 12] = 11 | ["", "", "", "", "", "", "", "", "", "", "", ""]; 12 | pub(crate) static TIME_EMOJIS: [&str; 12] = [ 13 | "🕛", "🕐", "🕑", "🕒", "🕓", "🕔", "🕕", "🕖", "🕗", "🕘", "🕙", "🕚", 14 | ]; 15 | pub(crate) static WEATHER_ICONS: [&str; 21] = [ 16 | "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", 17 | "", "", 18 | ]; 19 | pub(crate) static WEATHER_EMOJIS: [&str; 21] = [ 20 | "☀️", "⛅️", "🌙", "☁️", "🌙", "☁️", "☁️", "☁️", "🌧️", "🌧️", "🌧️", "🌧️", "⛈️", "⛈️", "🌨️", "🌨️", "🌫️", "🌫️", "🌫️", 21 | "🌫️", "❓", 22 | ]; 23 | pub(crate) static PACKAGE_ICONS: [&str; 12] = 24 | ["", "", "", "", "", "", "", "", "", "", "", ""]; 25 | pub(crate) static PACKAGE_EMOJIS: [&str; 13] = [ 26 | "☑️", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟", "‼️", "📦", 27 | ]; 28 | pub(crate) static MISC_ICONS: [&str; 6] = ["", "", "", "", "", ""]; 29 | pub(crate) static MISC_EMOJIS: [&str; 6] = ["💻", "🫀", "🧠", "💾", "🖥️", "🎵"]; 30 | --------------------------------------------------------------------------------