Add statmon script and update configs

This commit is contained in:
2026-07-27 12:28:01 -07:00
parent 7a9fd83a46
commit 8d587dd4d5
6 changed files with 1213 additions and 3 deletions

View File

@@ -18,6 +18,7 @@ bind = $mainMod, L, exec, hyprlock
bind = $mainMod, M, exit,
bind = $mainMod, N, exec, swaync-client -t -sw
bind = $mainMod, P, pseudo, # dwindle
bind = $mainMod, S, exec, $terminal -e ~/.config/hypr/scripts/statmon/target/release/statmon
bind = $mainMod SHIFT, S, exec, hyprshot -m region --clipboard-only,
bind = $mainMod, Q, exec, ~/.config/hypr/scripts/power-menu.sh
bind = $mainMod, U, exec, ~/.config/hypr/scripts/update-sys.sh up
@@ -96,4 +97,8 @@ bindel = ,XF86MonBrightnessDown, exec, brightnessctl s 10%-
bindl = , XF86AudioNext, exec, playerctl next
bindl = , XF86AudioPause, exec, playerctl play-pause
bindl = , XF86AudioPlay, exec, playerctl play-pause
bindl = , XF86AudioPrev, exec, playerctl previou
bindl = , XF86AudioPrev, exec, playerctl previous
# --- Mouse Side Button Remaps ---
bind = , mouse:276, sendshortcut, , ESCAPE, active
bind = , mouse:275, sendshortcut, , RETURN, active

721
hypr/scripts/statmon/Cargo.lock generated Normal file
View File

@@ -0,0 +1,721 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]]
name = "autocfg"
version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
[[package]]
name = "bitflags"
version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "bumpalo"
version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "cc"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5add81bb678e6cb321aff7fa0dc7689ad82b112dbc032cea19f91d6b8e3582b9"
dependencies = [
"find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
version = "0.4.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "crossbeam-deque"
version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
[[package]]
name = "crossterm"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
dependencies = [
"bitflags",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "either"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d"
[[package]]
name = "errno"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
]
[[package]]
name = "find-msvc-tools"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
[[package]]
name = "futures-core"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7"
[[package]]
name = "futures-task"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109"
[[package]]
name = "futures-util"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa"
dependencies = [
"futures-core",
"futures-task",
"pin-project-lite",
"slab",
]
[[package]]
name = "iana-time-zone"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core 0.62.2",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "js-sys"
version = "0.3.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102"
dependencies = [
"cfg-if",
"futures-util",
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "ntapi"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae"
dependencies = [
"winapi",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "parking_lot"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-link",
]
[[package]]
name = "pin-project-lite"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "proc-macro2"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "redox_syscall"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
dependencies = [
"bitflags",
]
[[package]]
name = "rustversion"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "shlex"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
[[package]]
name = "signal-hook"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno",
"libc",
]
[[package]]
name = "slab"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
name = "smallvec"
version = "1.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
[[package]]
name = "statmon"
version = "0.1.0"
dependencies = [
"chrono",
"crossterm",
"sysinfo",
]
[[package]]
name = "syn"
version = "2.0.119"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sysinfo"
version = "0.30.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"windows",
]
[[package]]
name = "unicode-ident"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasm-bindgen"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
dependencies = [
"unicode-ident",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core 0.52.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"

View File

@@ -0,0 +1,9 @@
[package]
name = "statmon"
version = "0.1.0"
edition = "2024"
[dependencies]
sysinfo = "0.30"
crossterm = "0.27"
chrono = "0.4"

View File

@@ -0,0 +1,475 @@
use chrono::Local;
use crossterm::{
cursor, execute,
style::{Color, ResetColor, SetForegroundColor},
terminal::{Clear, ClearType},
};
use std::{
fs,
io::{stdout, Write},
path::Path,
process::Command,
thread,
time::{Duration, Instant},
};
use sysinfo::{
Components, CpuRefreshKind, MemoryRefreshKind, Networks, ProcessRefreshKind,
RefreshKind, System,
};
// --- BTOP Theme RGB Constants ---
const FG_MAIN: Color = Color::Rgb { r: 157, g: 132, b: 98 }; // #9d8462
const ACCENT: Color = Color::Rgb { r: 255, g: 145, b: 0 }; // #ff9100
const ALERT: Color = Color::Rgb { r: 255, g: 0, b: 0 }; // #ff0000
const METER_BG: Color = Color::Rgb { r: 48, g: 51, b: 64 }; // #303340
fn send_notification(summary: &str, body: &str, urgency: &str) {
let _ = Command::new("notify-send")
.arg("-u")
.arg(urgency)
.arg("-a")
.arg("System Dashboard")
.arg(summary)
.arg(body)
.spawn();
}
fn make_bar(pct: f32, width: usize) -> String {
let clamped = pct.clamp(0.0, 100.0);
let filled = ((clamped / 100.0) * width as f32).round() as usize;
let empty = width.saturating_sub(filled);
format!("[{}{}]", "".repeat(filled), "".repeat(empty))
}
fn get_battery_info() -> (String, u32) {
let bat_paths = ["/sys/class/power_supply/BAT0", "/sys/class/power_supply/BAT1"];
for path in bat_paths {
if Path::new(path).exists() {
let cap_str = fs::read_to_string(format!("{}/capacity", path))
.unwrap_or_default()
.trim()
.to_string();
let status = fs::read_to_string(format!("{}/status", path))
.unwrap_or_default()
.trim()
.to_string();
if let Ok(cap) = cap_str.parse::<u32>() {
return (format!("{}% ({})", cap, status), cap);
}
}
}
("N/A".to_string(), 100)
}
fn get_mouse_battery() -> String {
if let Ok(entries) = fs::read_dir("/sys/class/power_supply") {
for entry in entries.flatten() {
let path = entry.path();
let name = path.file_name().unwrap_or_default().to_string_lossy().to_string();
if name.starts_with("hid") || name.starts_with("mouse") {
let cap = fs::read_to_string(path.join("capacity"))
.unwrap_or_default()
.trim()
.to_string();
let status = fs::read_to_string(path.join("status"))
.unwrap_or_default()
.trim()
.to_string();
if !cap.is_empty() {
let status_str = if status.is_empty() { "Wireless".to_string() } else { status };
return format!("{}% ({})", cap, status_str);
}
}
}
}
"Not Connected / Unknown".to_string()
}
fn get_cpu_temp(components: &Components) -> (String, f32) {
for comp in components {
let label = comp.label().to_lowercase();
if label.contains("core") || label.contains("package") || label.contains("cpu") {
let temp = comp.temperature();
return (format!("{:.0}°C", temp), temp);
}
}
if let Ok(entries) = fs::read_dir("/sys/class/hwmon") {
for entry in entries.flatten() {
let path = entry.path();
if let Ok(name) = fs::read_to_string(path.join("name")) {
if name.contains("coretemp") || name.contains("k10temp") || name.contains("cpu") {
if let Ok(temp_str) = fs::read_to_string(path.join("temp1_input")) {
if let Ok(temp_val) = temp_str.trim().parse::<f32>() {
let temp = temp_val / 1000.0;
return (format!("{:.0}°C", temp), temp);
}
}
}
}
}
}
("N/A".to_string(), 0.0)
}
fn get_gpu_info() -> (String, f32) {
for card_num in 0..4 {
let card_path = format!("/sys/class/drm/card{}/device", card_num);
let path = Path::new(&card_path);
if path.exists() {
let busy_file = if path.join("gpu_busy_percent").exists() {
Some(path.join("gpu_busy_percent"))
} else if path.join("load").exists() {
Some(path.join("load"))
} else {
None
};
if let Some(bf) = busy_file {
let busy_pct = fs::read_to_string(bf)
.unwrap_or_default()
.trim()
.parse::<f32>()
.unwrap_or(0.0);
let vram_used = fs::read_to_string(path.join("mem_info_vram_used"))
.unwrap_or_default()
.trim()
.parse::<u64>()
.unwrap_or(0) / 1024 / 1024;
let vram_total = fs::read_to_string(path.join("mem_info_vram_total"))
.unwrap_or_default()
.trim()
.parse::<u64>()
.unwrap_or(0) / 1024 / 1024;
return if vram_total > 0 {
(format!("{} (VRAM: {}MB / {}MB)", make_bar(busy_pct, 16), vram_used, vram_total), busy_pct)
} else {
(format!("{} ({:.0}%)", make_bar(busy_pct, 16), busy_pct), busy_pct)
};
}
}
}
("N/A".to_string(), 0.0)
}
fn get_nvme_temp() -> String {
if let Ok(entries) = fs::read_dir("/sys/class/hwmon") {
for entry in entries.flatten() {
let path = entry.path();
if let Ok(name) = fs::read_to_string(path.join("name")) {
if name.trim() == "nvme" {
if let Ok(temp_str) = fs::read_to_string(path.join("temp1_input")) {
if let Ok(temp_val) = temp_str.trim().parse::<f32>() {
return format!("{:.0}°C", temp_val / 1000.0);
}
}
}
}
}
}
"N/A".to_string()
}
fn get_disk_io(last_read_sectors: &mut u64, last_write_sectors: &mut u64, elapsed_secs: f32) -> String {
if let Ok(content) = fs::read_to_string("/proc/diskstats") {
let mut total_read = 0u64;
let mut total_write = 0u64;
for line in content.lines() {
let parts: Vec<&str> = line.split_whitespace().collect();
if parts.len() >= 10 {
let dev_name = parts[2];
if dev_name.starts_with("nvme") && dev_name.ends_with("n1") || dev_name.starts_with("sd") && dev_name.len() == 3 {
let r_sectors: u64 = parts[5].parse().unwrap_or(0);
let w_sectors: u64 = parts[9].parse().unwrap_or(0);
total_read += r_sectors;
total_write += w_sectors;
}
}
}
let read_mb = if *last_read_sectors > 0 && total_read >= *last_read_sectors {
((total_read - *last_read_sectors) as f32 * 512.0) / (1024.0 * 1024.0 * elapsed_secs)
} else {
0.0
};
let write_mb = if *last_write_sectors > 0 && total_write >= *last_write_sectors {
((total_write - *last_write_sectors) as f32 * 512.0) / (1024.0 * 1024.0 * elapsed_secs)
} else {
0.0
};
*last_read_sectors = total_read;
*last_write_sectors = total_write;
format!("R: {:.1} MB/s W: {:.1} MB/s", read_mb, write_mb)
} else {
"N/A".to_string()
}
}
fn get_systemd_failed() -> (String, u32) {
if let Ok(output) = Command::new("systemctl").args(["--failed", "--quiet"]).output() {
if output.status.success() {
if let Ok(stdout) = String::from_utf8(output.stdout) {
let lines: Vec<&str> = stdout.lines().filter(|l| !l.trim().is_empty()).collect();
let count = lines.len() as u32;
if count == 0 {
return ("0 units".to_string(), 0);
} else {
return (format!("{} unit(s) failed", count), count);
}
}
}
}
("0 units".to_string(), 0)
}
fn print_line(stdout: &mut std::io::Stdout, label: &str, value: &str, val_color: Color) -> Result<(), Box<dyn std::error::Error>> {
execute!(stdout, SetForegroundColor(FG_MAIN))?;
write!(stdout, " {:<14}: ", label)?;
execute!(stdout, SetForegroundColor(val_color))?;
writeln!(stdout, "{}", value)?;
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut sys = System::new_with_specifics(
RefreshKind::new()
.with_cpu(CpuRefreshKind::everything())
.with_memory(MemoryRefreshKind::everything())
.with_processes(ProcessRefreshKind::everything()),
);
let mut networks = Networks::new_with_refreshed_list();
let mut components = Components::new_with_refreshed_list();
let mut stdout = stdout();
let alert_threshold = Duration::from_secs(10);
let mut core_max_start: Option<Instant> = None;
let mut core_max_alerted = false;
let mut temp_high_start: Option<Instant> = None;
let mut temp_high_alerted = false;
let mut mem_high_start: Option<Instant> = None;
let mut mem_high_alerted = false;
let mut bat_notified_50 = false;
let mut bat_notified_25 = false;
let mut last_read_sectors = 0u64;
let mut last_write_sectors = 0u64;
let mut last_tick = Instant::now();
thread::sleep(Duration::from_millis(1000));
loop {
let elapsed_secs = last_tick.elapsed().as_secs_f32();
last_tick = Instant::now();
sys.refresh_all();
networks.refresh();
components.refresh();
let time_str = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
let (bat_str, bat_pct) = get_battery_info();
let mouse_bat_str = get_mouse_battery();
let (temp_str, temp_val) = get_cpu_temp(&components);
let (gpu_str, _) = get_gpu_info();
let nvme_temp = get_nvme_temp();
let disk_io = get_disk_io(&mut last_read_sectors, &mut last_write_sectors, elapsed_secs);
let (failed_sysd, failed_count) = get_systemd_failed();
// Memory Metrics
let total_mem = sys.total_memory() / 1024 / 1024;
let used_mem = sys.used_memory() / 1024 / 1024;
let mem_pct = if total_mem > 0 { (used_mem as f32 * 100.0) / total_mem as f32 } else { 0.0 };
let total_swap = sys.total_swap() / 1024 / 1024;
let used_swap = sys.used_swap() / 1024 / 1024;
let swap_pct = if total_swap > 0 { (used_swap as f32 * 100.0) / total_swap as f32 } else { 0.0 };
// CPU Metrics
let global_cpu = sys.global_cpu_info().cpu_usage();
let cpus = sys.cpus();
let num_cores = cpus.len() as f32;
let mut has_core_at_100 = false;
let mut core_str = String::new();
for (i, cpu) in cpus.iter().enumerate() {
let usage = cpu.cpu_usage();
if usage >= 99.0 {
has_core_at_100 = true;
}
if usage >= 80.0 {
core_str.push_str(&format!("C{}: {:.0}% | ", i, usage));
}
}
let (final_core_str, core_color) = if core_str.is_empty() {
("All under 80%".to_string(), METER_BG)
} else {
if core_str.ends_with(" | ") {
core_str.truncate(core_str.len() - 3);
}
(core_str, ALERT)
};
// --- NOTIFICATIONS ---
if bat_pct <= 25 && !bat_notified_25 {
send_notification("Low Battery Warning", &format!("Battery is down to {}%!", bat_pct), "critical");
bat_notified_25 = true;
} else if bat_pct <= 50 && bat_pct > 25 && !bat_notified_50 {
send_notification("Battery Notice", &format!("Battery dropped below 50% ({}%).", bat_pct), "normal");
bat_notified_50 = true;
} else if bat_pct > 55 {
bat_notified_50 = false;
bat_notified_25 = false;
}
if has_core_at_100 {
let start = core_max_start.get_or_insert_with(Instant::now);
if start.elapsed() >= alert_threshold && !core_max_alerted {
send_notification("CPU Warning", "A CPU core has been at 100% usage for over 10 seconds!", "critical");
core_max_alerted = true;
}
} else {
core_max_start = None;
core_max_alerted = false;
}
if temp_val >= 85.0 {
let start = temp_high_start.get_or_insert_with(Instant::now);
if start.elapsed() >= alert_threshold && !temp_high_alerted {
send_notification("High Temperature Alert", &format!("CPU Temperature is at {:.0}°C for over 10s!", temp_val), "critical");
temp_high_alerted = true;
}
} else {
temp_high_start = None;
temp_high_alerted = false;
}
if mem_pct >= 80.0 {
let start = mem_high_start.get_or_insert_with(Instant::now);
if start.elapsed() >= alert_threshold && !mem_high_alerted {
send_notification("High Memory Usage", &format!("RAM usage has been above 80% ({:.0}%) for over 10s!", mem_pct), "critical");
mem_high_alerted = true;
}
} else {
mem_high_start = None;
mem_high_alerted = false;
}
// Network Bandwidth Calculations
let mut rx_bytes = 0;
let mut tx_bytes = 0;
for (_iface, data) in &networks {
rx_bytes += data.received();
tx_bytes += data.transmitted();
}
let down_kb = ((rx_bytes / 1024) as f32 / elapsed_secs) as u64;
let up_kb = ((tx_bytes / 1024) as f32 / elapsed_secs) as u64;
// --- Flat Process List Logic ---
let my_pid = std::process::id();
let mut procs: Vec<_> = sys
.processes()
.values()
.filter(|p| p.pid().as_u32() != my_pid)
.collect();
// Sort by individual process CPU usage descending
procs.sort_by(|a, b| b.cpu_usage().partial_cmp(&a.cpu_usage()).unwrap_or(std::cmp::Ordering::Equal));
let top_5 = procs.into_iter().take(5);
// Render Screen
execute!(stdout, cursor::MoveTo(0, 0), Clear(ClearType::FromCursorDown))?;
execute!(stdout, SetForegroundColor(FG_MAIN))?;
println!("================================================================================================");
execute!(stdout, SetForegroundColor(ACCENT))?;
println!(" SYSTEM DASHBOARD ");
execute!(stdout, SetForegroundColor(FG_MAIN))?;
println!("================================================================================================");
print_line(&mut stdout, "Time", &time_str, ACCENT)?;
print_line(&mut stdout, "Laptop Bat", &bat_str, FG_MAIN)?;
print_line(&mut stdout, "Mouse Bat", &mouse_bat_str, FG_MAIN)?;
let temp_color = if temp_val >= 85.0 { ALERT } else if temp_val >= 70.0 { ACCENT } else { FG_MAIN };
print_line(&mut stdout, "CPU Temp", &temp_str, temp_color)?;
let cpu_color = if global_cpu >= 85.0 { ALERT } else if global_cpu >= 60.0 { ACCENT } else { FG_MAIN };
let cpu_bar_val = format!("{} {:.1}%", make_bar(global_cpu, 16), global_cpu);
print_line(&mut stdout, "CPU Usage", &cpu_bar_val, cpu_color)?;
print_line(&mut stdout, "High Cores", &final_core_str, core_color)?;
let mem_color = if mem_pct >= 90.0 { ALERT } else if mem_pct >= 70.0 { ACCENT } else { FG_MAIN };
let mem_bar_val = format!("{} {:.0}% ({}MB / {}MB)", make_bar(mem_pct, 16), mem_pct, used_mem, total_mem);
print_line(&mut stdout, "Memory Usage", &mem_bar_val, mem_color)?;
let swap_color = if swap_pct >= 70.0 { ALERT } else if swap_pct >= 30.0 { ACCENT } else { FG_MAIN };
let swap_bar_val = format!("{} {:.0}% ({}MB / {}MB)", make_bar(swap_pct, 16), swap_pct, used_swap, total_swap);
print_line(&mut stdout, "Swap Usage", &swap_bar_val, swap_color)?;
print_line(&mut stdout, "Radeon GPU", &gpu_str, ACCENT)?;
print_line(&mut stdout, "NVMe Temp", &nvme_temp, FG_MAIN)?;
print_line(&mut stdout, "Disk I/O", &disk_io, ACCENT)?;
print_line(&mut stdout, "Network", &format!("{} KB/s ↑ {} KB/s", down_kb, up_kb), ACCENT)?;
let sysd_color = if failed_count > 0 { ALERT } else { FG_MAIN };
print_line(&mut stdout, "Systemd Units", &failed_sysd, sysd_color)?;
// Render Top 5 Table
execute!(stdout, SetForegroundColor(FG_MAIN))?;
println!("------------------------------------------------------------------------------------------------");
execute!(stdout, SetForegroundColor(ACCENT))?;
println!(" {:<8} {:<30} {:<12} {:<12}", "PID", "NAME", "CPU %", "MEM (MB)");
execute!(stdout, SetForegroundColor(FG_MAIN))?;
println!("------------------------------------------------------------------------------------------------");
for p in top_5 {
let raw_name = p.name();
let display_name = if raw_name.len() > 28 {
format!("{}...", &raw_name[..25])
} else {
raw_name.to_string()
};
// Normalize individual process CPU % across logical cores
let cpu_normalized = p.cpu_usage() / num_cores;
// Direct KiB to MB conversion for single process memory
let mem_mb = p.memory() / 1024;
let row_color = if cpu_normalized >= 25.0 { ALERT } else if cpu_normalized >= 10.0 { ACCENT } else { FG_MAIN };
execute!(stdout, SetForegroundColor(row_color))?;
println!(" {:<8} {:<30} {:<12.1} {:<12}", p.pid().as_u32(), display_name, cpu_normalized, mem_mb);
}
execute!(stdout, SetForegroundColor(FG_MAIN))?;
println!("================================================================================================");
if global_cpu > 85.0 || mem_pct > 90.0 || temp_val > 85.0 {
execute!(stdout, SetForegroundColor(ALERT))?;
println!("\n WARNING: HIGH RESOURCE USAGE DETECTED! ");
}
execute!(stdout, ResetColor)?;
stdout.flush()?;
thread::sleep(Duration::from_secs(2));
}
}