mirror of
https://github.com/orhun/systeroid
synced 2024-09-30 04:33:31 +00:00
feat(tui): improve logging (#83)
* chore(deps): add logging dependencies * refactor(cli): use log functions for logging * refactor(core): use log functions for logging * feat(tui): add logging for tui * feat(args): add an option for setting the log file for TUI logs * chore(core): add trace logging * fix(cli): make log level configurable via RUST_LOG * chore(log): improve logging * chore(tui): add logs to specific events * style(tui): update the colors for the logger widget * feat(log): allow setting the log level for tui * chore(config)!: remove the verbose option * fix(test): update render tui test * chore(tui): update MSRV for tui * chore(audit): add configuration file for cargo-audit * chore: Bump the Rust version in Dockerfile * feat(log): add target to logs * docs(readme): update documentation about logging
This commit is contained in:
parent
80be6c5053
commit
3ace96419c
8
.cargo/audit.toml
Normal file
8
.cargo/audit.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[advisories]
|
||||||
|
ignore = [
|
||||||
|
"RUSTSEC-2020-0071", # `chrono` - Potential segfault in the time crate
|
||||||
|
]
|
||||||
|
|
||||||
|
[output]
|
||||||
|
quiet = false
|
||||||
|
deny = ["warnings"]
|
536
Cargo.lock
generated
536
Cargo.lock
generated
|
@ -28,6 +28,15 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -67,6 +76,12 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
|
@ -79,12 +94,33 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||||
|
dependencies = [
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
"time",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
|
@ -95,6 +131,16 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "codespan-reporting"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
|
||||||
|
dependencies = [
|
||||||
|
"termcolor",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colored"
|
name = "colored"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -138,6 +184,12 @@ dependencies = [
|
||||||
"x11-clipboard",
|
"x11-clipboard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -190,6 +242,50 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxx"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"cxxbridge-flags",
|
||||||
|
"cxxbridge-macro",
|
||||||
|
"link-cplusplus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxx-build"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"codespan-reporting",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"scratch",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxxbridge-flags"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cxxbridge-macro"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.15",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -250,6 +346,40 @@ dependencies = [
|
||||||
"syn 1.0.109",
|
"syn 1.0.109",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
|
||||||
|
dependencies = [
|
||||||
|
"humantime",
|
||||||
|
"is-terminal",
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||||
|
dependencies = [
|
||||||
|
"errno-dragonfly",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno-dragonfly"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.25"
|
version = "1.0.25"
|
||||||
|
@ -266,6 +396,15 @@ version = "1.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fxhash"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
@ -293,7 +432,7 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -353,6 +492,42 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
|
||||||
|
dependencies = [
|
||||||
|
"cxx",
|
||||||
|
"cxx-build",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ignore"
|
name = "ignore"
|
||||||
version = "0.4.20"
|
version = "0.4.20"
|
||||||
|
@ -370,12 +545,44 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "io-lifetimes"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.1",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is-terminal"
|
||||||
|
version = "0.4.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi 0.3.1",
|
||||||
|
"io-lifetimes",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy-bytes-cast"
|
name = "lazy-bytes-cast"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
|
@ -404,6 +611,31 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "link-cplusplus"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b085a4f2cde5781fc4b1717f2e86c62f5cda49de7ba99a7c2eae02b61c9064c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
|
@ -492,6 +724,25 @@ dependencies = [
|
||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num_cpus"
|
name = "num_cpus"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
|
@ -553,6 +804,29 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-sys 0.45.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parseit"
|
name = "parseit"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -680,6 +954,20 @@ dependencies = [
|
||||||
"ordered-multimap",
|
"ordered-multimap",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.37.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f79bef90eb6d984c72722595b5b1348ab39275a5e5123faca6863bf07d75a4e0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"errno",
|
||||||
|
"io-lifetimes",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
|
@ -707,6 +995,12 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scratch"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.160"
|
version = "1.0.160"
|
||||||
|
@ -812,7 +1106,9 @@ dependencies = [
|
||||||
name = "systeroid"
|
name = "systeroid"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"env_logger",
|
||||||
"getopts",
|
"getopts",
|
||||||
|
"log",
|
||||||
"parseit",
|
"parseit",
|
||||||
"systeroid-core",
|
"systeroid-core",
|
||||||
]
|
]
|
||||||
|
@ -824,6 +1120,7 @@ dependencies = [
|
||||||
"colored",
|
"colored",
|
||||||
"dirs-next",
|
"dirs-next",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"log",
|
||||||
"parseit",
|
"parseit",
|
||||||
"rayon",
|
"rayon",
|
||||||
"rust-ini",
|
"rust-ini",
|
||||||
|
@ -840,13 +1137,24 @@ dependencies = [
|
||||||
"colorsys",
|
"colorsys",
|
||||||
"copypasta-ext",
|
"copypasta-ext",
|
||||||
"getopts",
|
"getopts",
|
||||||
|
"log",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"systeroid-core",
|
"systeroid-core",
|
||||||
"termion",
|
"termion",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
"tui-logger",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termion"
|
name = "termion"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
@ -889,6 +1197,31 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tui-logger"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b9e708d73f97e548b2d6e75f9931aff915a5b8bbad8fc7c7a63273994af6b5b"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"fxhash",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"parking_lot",
|
||||||
|
"ratatui",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
|
@ -923,12 +1256,72 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.10.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 1.0.109",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.84"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-client"
|
name = "wayland-client"
|
||||||
version = "0.29.5"
|
version = "0.29.5"
|
||||||
|
@ -1053,6 +1446,147 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.45.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.42.2",
|
||||||
|
"windows_aarch64_msvc 0.42.2",
|
||||||
|
"windows_i686_gnu 0.42.2",
|
||||||
|
"windows_i686_msvc 0.42.2",
|
||||||
|
"windows_x86_64_gnu 0.42.2",
|
||||||
|
"windows_x86_64_gnullvm 0.42.2",
|
||||||
|
"windows_x86_64_msvc 0.42.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.0",
|
||||||
|
"windows_aarch64_msvc 0.48.0",
|
||||||
|
"windows_i686_gnu 0.48.0",
|
||||||
|
"windows_i686_msvc 0.48.0",
|
||||||
|
"windows_x86_64_gnu 0.48.0",
|
||||||
|
"windows_x86_64_gnullvm 0.48.0",
|
||||||
|
"windows_x86_64_msvc 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.42.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x11-clipboard"
|
name = "x11-clipboard"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
|
|
|
@ -3,6 +3,7 @@ members = ["systeroid-core", "systeroid-tui", "systeroid"]
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
parseit = { version = "0.1.2", features = ["gzip"] }
|
parseit = { version = "0.1.2", features = ["gzip"] }
|
||||||
|
log = { version = "0.4.17", features = ["std"] }
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 0
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM rust:1.66.1-alpine3.17 as builder
|
FROM rust:1.69.0-alpine3.17 as builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN apk update
|
RUN apk update
|
||||||
RUN apk add --no-cache musl-dev bash git
|
RUN apk add --no-cache musl-dev bash git
|
||||||
|
|
85
README.md
85
README.md
|
@ -77,6 +77,7 @@ Although **systeroid** does not need the parameter section to be specified expli
|
||||||
- [Loading values from the system directories](#loading-values-from-the-system-directories)
|
- [Loading values from the system directories](#loading-values-from-the-system-directories)
|
||||||
- [Searching parameters](#searching-parameters)
|
- [Searching parameters](#searching-parameters)
|
||||||
- [Showing information about parameters](#showing-information-about-parameters)
|
- [Showing information about parameters](#showing-information-about-parameters)
|
||||||
|
- [Verbose logging](#verbose-logging)
|
||||||
- [TUI](#tui)
|
- [TUI](#tui)
|
||||||
- [Usage](#usage-2)
|
- [Usage](#usage-2)
|
||||||
- [Key Bindings](#key-bindings)
|
- [Key Bindings](#key-bindings)
|
||||||
|
@ -93,6 +94,7 @@ Although **systeroid** does not need the parameter section to be specified expli
|
||||||
- [Changing the colors](#changing-the-colors)
|
- [Changing the colors](#changing-the-colors)
|
||||||
- [Viewing the parameter documentation](#viewing-the-parameter-documentation)
|
- [Viewing the parameter documentation](#viewing-the-parameter-documentation)
|
||||||
- [Setting the refresh rate](#setting-the-refresh-rate)
|
- [Setting the refresh rate](#setting-the-refresh-rate)
|
||||||
|
- [Logging](#logging)
|
||||||
- [Configuration](#configuration)
|
- [Configuration](#configuration)
|
||||||
- [Resources](#resources)
|
- [Resources](#resources)
|
||||||
- [References](#references)
|
- [References](#references)
|
||||||
|
@ -398,6 +400,20 @@ It is also possible to retrieve information about multiple parameters:
|
||||||
systeroid -E --pattern '.*ipv4.*' --no-pager
|
systeroid -E --pattern '.*ipv4.*' --no-pager
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Verbose logging
|
||||||
|
|
||||||
|
`--verbose` flag can be used to enable verbose logging:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
systeroid --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, `RUST_LOG` environment variable can be set accordingly to filter based on different log levels.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
RUST_LOG=trace systeroid
|
||||||
|
```
|
||||||
|
|
||||||
## TUI
|
## TUI
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
@ -440,6 +456,7 @@ systeroid-tui [options]
|
||||||
| <kbd>enter</kbd> | select / set parameter value |
|
| <kbd>enter</kbd> | select / set parameter value |
|
||||||
| <kbd>s</kbd> | save parameter value |
|
| <kbd>s</kbd> | save parameter value |
|
||||||
| <kbd>c</kbd> | copy to clipboard |
|
| <kbd>c</kbd> | copy to clipboard |
|
||||||
|
| <kbd>ctrl-l</kbd>, <kbd>f2</kbd> | show logs |
|
||||||
| <kbd>r</kbd>, <kbd>f5</kbd> | refresh |
|
| <kbd>r</kbd>, <kbd>f5</kbd> | refresh |
|
||||||
| <kbd>esc</kbd> | cancel / exit |
|
| <kbd>esc</kbd> | cancel / exit |
|
||||||
| <kbd>q</kbd>, <kbd>ctrl-c/ctrl-d</kbd> | exit |
|
| <kbd>q</kbd>, <kbd>ctrl-c/ctrl-d</kbd> | exit |
|
||||||
|
@ -524,15 +541,16 @@ Press <kbd>:</kbd> to open the command prompt for running a command. Available c
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `:help` | Show help |
|
| `:help` | show help |
|
||||||
| `:search` | Enable search |
|
| `:search` | enable search |
|
||||||
| `:select` | Select the current parameter in the list |
|
| `:select` | select the current parameter in the list |
|
||||||
| `:set <name> <value>` | Set parameter value |
|
| `:set <name> <value>` | set parameter value |
|
||||||
| `:save <name> <value>` | Save parameter value to file |
|
| `:save <name> <value>` | save parameter value to file |
|
||||||
| `:scroll [area] [direction] <amount>` | Scroll the list or text<br>- areas: `list`, `docs`, `section`<br>- directions: `up`, `down`, `top`, `bottom`, `right`, `left` |
|
| `:scroll [area] [direction] <amount>` | scroll the list or text<br>- areas: `list`, `docs`, `section`<br>- directions: `up`, `down`, `top`, `bottom`, `right`, `left` |
|
||||||
| `:copy` | Copy to clipboard |
|
| `:copy` | copy to clipboard |
|
||||||
| `:refresh` | Refresh values |
|
| `:logs` | show logs |
|
||||||
| `:quit`, `:q` | Quit |
|
| `:refresh` | refresh values |
|
||||||
|
| `:quit`, `:q` | quit |
|
||||||
|
|
||||||
#### Copying to clipboard
|
#### Copying to clipboard
|
||||||
|
|
||||||
|
@ -570,6 +588,55 @@ It is possible to specify a value in milliseconds via `--tick-rate` argument for
|
||||||
systeroid-tui --tick-rate 500
|
systeroid-tui --tick-rate 500
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Logging
|
||||||
|
|
||||||
|
To view the log messages, press <kbd>ctrl-l</kbd>. It will bring up a pane in the TUI for analyzing the logs:
|
||||||
|
|
||||||
|
![Logs](assets/systeroid-tui-logs.gif)
|
||||||
|
|
||||||
|
This pane consists of two parts. Left is the target selector and on the right side the logging messages view scrolling up.
|
||||||
|
|
||||||
|
The target selector controls:
|
||||||
|
|
||||||
|
- Capturing of log messages by the logger.
|
||||||
|
- Selection of levels for display in the logging message view.
|
||||||
|
|
||||||
|
The two columns have the following meaning:
|
||||||
|
|
||||||
|
- Code `EWIDT`: `E` stands for Error, `W` for Warn, and similarly Info, Debug and Trace.
|
||||||
|
- Inverted characters (EWIDT) are enabled log levels in the view.
|
||||||
|
- Normal characters show enabled capturing of a log level per target.
|
||||||
|
- If any of EWIDT are not shown, then the respective log level is not captured.
|
||||||
|
|
||||||
|
This logger pane has the following key bindings and they are only activated while the logs are being shown:
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
| ------------------- | -------------------------------------------------------------- |
|
||||||
|
| <kbd>h</kbd> | toggles target selector widget hidden/visible |
|
||||||
|
| <kbd>f</kbd> | toggle focus on the selected target only |
|
||||||
|
| <kbd>up</kbd> | select previous target in target selector widget |
|
||||||
|
| <kbd>down</kbd> | select next target in target selector widget |
|
||||||
|
| <kbd>left</kbd> | reduce SHOWN (!) log messages by one level |
|
||||||
|
| <kbd>right</kbd> | increase SHOWN (!) log messages by one level |
|
||||||
|
| <kbd>-</kbd> | reduce CAPTURED (!) log messages by one level |
|
||||||
|
| <kbd>+</kbd> | increase CAPTURED (!) log messages by one level |
|
||||||
|
| <kbd>pageup</kbd> | enter Page Mode and scroll approx. half page up in log history |
|
||||||
|
| <kbd>pagedown</kbd> | only in page mode: scroll 10 events down in log history |
|
||||||
|
| <kbd>escape</kbd> | exit page mode and go back to scrolling mode |
|
||||||
|
| <kbd>space</kbd> | toggles hiding of targets, which have logfilter set to off |
|
||||||
|
|
||||||
|
For saving the logs to a file, you can use the `--log-file` argument:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
systeroid-tui --log-file systeroid.log
|
||||||
|
```
|
||||||
|
|
||||||
|
`RUST_LOG` environment variable can be used to set the log level accordingly.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
RUST_LOG=debug systeroid-tui
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
**systeroid** can be configured with a configuration file that uses the [INI format](https://en.wikipedia.org/wiki/INI_file). It can be specified via `--config` or `SYSTEROID_CONFIG` environment variable. It can also be placed in one of the following global locations:
|
**systeroid** can be configured with a configuration file that uses the [INI format](https://en.wikipedia.org/wiki/INI_file). It can be specified via `--config` or `SYSTEROID_CONFIG` environment variable. It can also be placed in one of the following global locations:
|
||||||
|
|
BIN
assets/systeroid-tui-logs.gif
Normal file
BIN
assets/systeroid-tui-logs.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
|
@ -17,8 +17,6 @@ display_deprecated = false
|
||||||
kernel_docs = "/usr/share/doc/linux"
|
kernel_docs = "/usr/share/doc/linux"
|
||||||
|
|
||||||
[cli]
|
[cli]
|
||||||
; enable verbose logging
|
|
||||||
verbose = false
|
|
||||||
; ignore unknown variable errors
|
; ignore unknown variable errors
|
||||||
ignore_errors = true
|
ignore_errors = true
|
||||||
; do not print variable after the value is set
|
; do not print variable after the value is set
|
||||||
|
@ -59,6 +57,8 @@ tick_rate = 250
|
||||||
no_docs = true
|
no_docs = true
|
||||||
; path for saving the changed kernel parameters
|
; path for saving the changed kernel parameters
|
||||||
save_path = "/etc/sysctl.conf"
|
save_path = "/etc/sysctl.conf"
|
||||||
|
; file to save the logs
|
||||||
|
;log_file = "systeroid.log"
|
||||||
|
|
||||||
[tui.colors]
|
[tui.colors]
|
||||||
; available colors are defined in https://docs.rs/tui/latest/tui/style/enum.Color.html
|
; available colors are defined in https://docs.rs/tui/latest/tui/style/enum.Color.html
|
||||||
|
|
|
@ -23,6 +23,9 @@ Use this option to set a custom path for the kernel documentation.
|
||||||
\fB\-\-save\-path\fR <path>
|
\fB\-\-save\-path\fR <path>
|
||||||
Use this option to set the path for saving the changed parameters.
|
Use this option to set the path for saving the changed parameters.
|
||||||
.TP
|
.TP
|
||||||
|
\fB\-l\fR, \fB\-\-log\-file\fR <path>
|
||||||
|
Use this option to set the file to save the logs.
|
||||||
|
.TP
|
||||||
\fB\-s\fR, \fB\-\-section\fR <section>
|
\fB\-s\fR, \fB\-\-section\fR <section>
|
||||||
Use this option to set the section to filter.
|
Use this option to set the section to filter.
|
||||||
.HP
|
.HP
|
||||||
|
@ -61,6 +64,8 @@ systeroid-tui \-D /usr/share/doc/linux
|
||||||
.br
|
.br
|
||||||
systeroid-tui \-\-save-path 99-local.conf
|
systeroid-tui \-\-save-path 99-local.conf
|
||||||
.br
|
.br
|
||||||
|
systeroid-tui \-\-log-file systeroid.log
|
||||||
|
.br
|
||||||
systeroid-tui -n
|
systeroid-tui -n
|
||||||
|
|
||||||
.SH KEY BINDINGS
|
.SH KEY BINDINGS
|
||||||
|
|
|
@ -12,6 +12,8 @@ edition = "2021"
|
||||||
rust-version = "1.64.0"
|
rust-version = "1.64.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
parseit.workspace = true
|
||||||
|
log.workspace = true
|
||||||
sysctl = "0.5.4"
|
sysctl = "0.5.4"
|
||||||
thiserror = "1.0.40"
|
thiserror = "1.0.40"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
|
@ -20,5 +22,4 @@ colored = "2.0.0"
|
||||||
serde = { version = "1.0.160", features = ["derive"] }
|
serde = { version = "1.0.160", features = ["derive"] }
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
dirs-next = "2.0.0"
|
dirs-next = "2.0.0"
|
||||||
parseit.workspace = true
|
|
||||||
rust-ini = "0.18.0"
|
rust-ini = "0.18.0"
|
||||||
|
|
|
@ -54,8 +54,6 @@ pub struct Config {
|
||||||
/// CLI configuration.
|
/// CLI configuration.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct CliConfig {
|
pub struct CliConfig {
|
||||||
/// Whether if the verbose logging is enabled.
|
|
||||||
pub verbose: bool,
|
|
||||||
/// Whether if the errors should be ignored.
|
/// Whether if the errors should be ignored.
|
||||||
pub ignore_errors: bool,
|
pub ignore_errors: bool,
|
||||||
/// Whether if the quiet mode is enabled.
|
/// Whether if the quiet mode is enabled.
|
||||||
|
@ -88,6 +86,8 @@ pub struct TuiConfig {
|
||||||
pub no_docs: bool,
|
pub no_docs: bool,
|
||||||
/// Path for saving the changed kernel parameters.
|
/// Path for saving the changed kernel parameters.
|
||||||
pub save_path: Option<PathBuf>,
|
pub save_path: Option<PathBuf>,
|
||||||
|
/// File to save the logs.
|
||||||
|
pub log_file: Option<String>,
|
||||||
/// Color configuration.
|
/// Color configuration.
|
||||||
pub color: TuiColorConfig,
|
pub color: TuiColorConfig,
|
||||||
}
|
}
|
||||||
|
@ -116,6 +116,7 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(path) = config_path {
|
if let Some(path) = config_path {
|
||||||
|
log::trace!(target: "config", "Parsing configuration from {:?}", path);
|
||||||
let ini = Ini::load_from_file(path)?;
|
let ini = Ini::load_from_file(path)?;
|
||||||
if let Some(general_section) = ini.section(Some("general")) {
|
if let Some(general_section) = ini.section(Some("general")) {
|
||||||
if let Some(display_deprecated) = general_section.get("display_deprecated") {
|
if let Some(display_deprecated) = general_section.get("display_deprecated") {
|
||||||
|
@ -126,7 +127,6 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(section) = ini.section(Some("cli")) {
|
if let Some(section) = ini.section(Some("cli")) {
|
||||||
parse_ini_flag!(self, cli, section, verbose);
|
|
||||||
parse_ini_flag!(self, cli, section, ignore_errors);
|
parse_ini_flag!(self, cli, section, ignore_errors);
|
||||||
parse_ini_flag!(self, cli, section, quiet);
|
parse_ini_flag!(self, cli, section, quiet);
|
||||||
parse_ini_flag!(self, cli, section, no_pager);
|
parse_ini_flag!(self, cli, section, no_pager);
|
||||||
|
@ -162,6 +162,9 @@ impl Config {
|
||||||
if let Some(save_path) = section.get("save_path") {
|
if let Some(save_path) = section.get("save_path") {
|
||||||
self.tui.save_path = Some(PathBuf::from(save_path));
|
self.tui.save_path = Some(PathBuf::from(save_path));
|
||||||
}
|
}
|
||||||
|
if let Some(log_file) = section.get("log_file") {
|
||||||
|
self.tui.log_file = Some(log_file.to_string());
|
||||||
|
}
|
||||||
parse_ini_flag!(self, tui, section, no_docs);
|
parse_ini_flag!(self, tui, section, no_docs);
|
||||||
}
|
}
|
||||||
if let Some(section) = ini.section(Some("tui.colors")) {
|
if let Some(section) = ini.section(Some("tui.colors")) {
|
||||||
|
@ -183,7 +186,6 @@ impl Default for Config {
|
||||||
display_deprecated: false,
|
display_deprecated: false,
|
||||||
kernel_docs: None,
|
kernel_docs: None,
|
||||||
cli: CliConfig {
|
cli: CliConfig {
|
||||||
verbose: false,
|
|
||||||
ignore_errors: false,
|
ignore_errors: false,
|
||||||
quiet: false,
|
quiet: false,
|
||||||
no_pager: false,
|
no_pager: false,
|
||||||
|
@ -207,6 +209,7 @@ impl Default for Config {
|
||||||
tick_rate: 250,
|
tick_rate: 250,
|
||||||
no_docs: false,
|
no_docs: false,
|
||||||
save_path: None,
|
save_path: None,
|
||||||
|
log_file: None,
|
||||||
color: TuiColorConfig {
|
color: TuiColorConfig {
|
||||||
fg_color: String::from("white"),
|
fg_color: String::from("white"),
|
||||||
bg_color: String::from("black"),
|
bg_color: String::from("black"),
|
||||||
|
|
|
@ -51,9 +51,7 @@ impl Sysctl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if config.cli.verbose {
|
log::trace!(target: "sysctl", "{} ({})", e, ctl.name()?);
|
||||||
eprintln!("{} ({})", e, ctl.name()?);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,6 +66,7 @@ impl Sysctl {
|
||||||
|
|
||||||
/// Returns the parameters that matches the given query.
|
/// Returns the parameters that matches the given query.
|
||||||
pub fn get_parameters(&self, query: &str) -> Vec<&Parameter> {
|
pub fn get_parameters(&self, query: &str) -> Vec<&Parameter> {
|
||||||
|
log::trace!(target: "sysctl", "Querying parameters: {:?}", query);
|
||||||
let query = query.replace('/', ".");
|
let query = query.replace('/', ".");
|
||||||
let parameters = self
|
let parameters = self
|
||||||
.parameters
|
.parameters
|
||||||
|
@ -79,7 +78,8 @@ impl Sysctl {
|
||||||
})
|
})
|
||||||
.collect::<Vec<&Parameter>>();
|
.collect::<Vec<&Parameter>>();
|
||||||
if parameters.is_empty() && !self.config.cli.ignore_errors {
|
if parameters.is_empty() && !self.config.cli.ignore_errors {
|
||||||
eprintln!(
|
log::error!(
|
||||||
|
target: "sysctl",
|
||||||
"{}: cannot stat {}{}: No such file or directory",
|
"{}: cannot stat {}{}: No such file or directory",
|
||||||
env!("CARGO_PKG_NAME").split('-').collect::<Vec<_>>()[0],
|
env!("CARGO_PKG_NAME").split('-').collect::<Vec<_>>()[0],
|
||||||
PROC_PATH,
|
PROC_PATH,
|
||||||
|
@ -91,6 +91,7 @@ impl Sysctl {
|
||||||
|
|
||||||
/// Updates the descriptions of the kernel parameters using the given cached data.
|
/// Updates the descriptions of the kernel parameters using the given cached data.
|
||||||
pub fn update_docs_from_cache(&mut self, cache: &Cache) -> Result<()> {
|
pub fn update_docs_from_cache(&mut self, cache: &Cache) -> Result<()> {
|
||||||
|
log::trace!(target: "cache", "{:?}", cache);
|
||||||
let mut kernel_docs_path = if let Some(path) = &self.config.kernel_docs {
|
let mut kernel_docs_path = if let Some(path) = &self.config.kernel_docs {
|
||||||
vec![path.to_path_buf()]
|
vec![path.to_path_buf()]
|
||||||
} else {
|
} else {
|
||||||
|
@ -109,6 +110,7 @@ impl Sysctl {
|
||||||
}
|
}
|
||||||
if let Some(path) = kernel_docs_path.iter().find(|path| path.exists()) {
|
if let Some(path) = kernel_docs_path.iter().find(|path| path.exists()) {
|
||||||
if cache.exists(PARAMETERS_CACHE_LABEL) {
|
if cache.exists(PARAMETERS_CACHE_LABEL) {
|
||||||
|
log::trace!(target: "cache", "Cache hit for {:?}", path);
|
||||||
let cache_data = cache.read(PARAMETERS_CACHE_LABEL)?;
|
let cache_data = cache.read(PARAMETERS_CACHE_LABEL)?;
|
||||||
if cache_data.timestamp == CacheData::<()>::get_timestamp(path)? {
|
if cache_data.timestamp == CacheData::<()>::get_timestamp(path)? {
|
||||||
self.update_params(cache_data.data);
|
self.update_params(cache_data.data);
|
||||||
|
@ -117,13 +119,14 @@ impl Sysctl {
|
||||||
}
|
}
|
||||||
self.update_docs(path)?;
|
self.update_docs(path)?;
|
||||||
if env::var(DISABLE_CACHE_ENV).is_err() {
|
if env::var(DISABLE_CACHE_ENV).is_err() {
|
||||||
|
log::trace!(target: "cache", "Writing cache to {:?}", cache);
|
||||||
cache.write(
|
cache.write(
|
||||||
CacheData::new(&self.parameters, path)?,
|
CacheData::new(&self.parameters, path)?,
|
||||||
PARAMETERS_CACHE_LABEL,
|
PARAMETERS_CACHE_LABEL,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!("warning: `Linux kernel documentation cannot be found. Please specify a path via '-D' argument`");
|
log::error!(target: "sysctl", "warning: `Linux kernel documentation cannot be found. Please specify a path via '-D' argument`");
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -146,6 +149,7 @@ impl Sysctl {
|
||||||
|
|
||||||
/// Updates the descriptions of the kernel parameters.
|
/// Updates the descriptions of the kernel parameters.
|
||||||
fn update_docs(&mut self, kernel_docs: &Path) -> Result<()> {
|
fn update_docs(&mut self, kernel_docs: &Path) -> Result<()> {
|
||||||
|
log::trace!(target: "sysctl", "Parsing the kernel documentation from {:?}", kernel_docs);
|
||||||
let documents = parse_kernel_docs(kernel_docs)?;
|
let documents = parse_kernel_docs(kernel_docs)?;
|
||||||
self.parameters
|
self.parameters
|
||||||
.par_iter_mut()
|
.par_iter_mut()
|
||||||
|
@ -187,6 +191,13 @@ impl Sysctl {
|
||||||
let save_path = save_path
|
let save_path = save_path
|
||||||
.clone()
|
.clone()
|
||||||
.unwrap_or_else(|| PathBuf::from(DEFAULT_PRELOAD));
|
.unwrap_or_else(|| PathBuf::from(DEFAULT_PRELOAD));
|
||||||
|
log::trace!(
|
||||||
|
target: "param",
|
||||||
|
"Writing the new value ({:?}) of {:?} to {:?}",
|
||||||
|
new_value,
|
||||||
|
param_name,
|
||||||
|
save_path
|
||||||
|
);
|
||||||
let data = format!("{param_name} = {new_value}");
|
let data = format!("{param_name} = {new_value}");
|
||||||
if save_path.exists() {
|
if save_path.exists() {
|
||||||
let contents = reader::read_to_string(&save_path)?;
|
let contents = reader::read_to_string(&save_path)?;
|
||||||
|
|
|
@ -188,6 +188,7 @@ impl Parameter {
|
||||||
config: &Config,
|
config: &Config,
|
||||||
output: &mut Output,
|
output: &mut Output,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
log::trace!(target: "param", "Setting the value of {:?} to {:?}", self.name, new_value);
|
||||||
let ctl = Ctl::new(&self.name)?;
|
let ctl = Ctl::new(&self.name)?;
|
||||||
let new_value = ctl.set_value_string(new_value)?;
|
let new_value = ctl.set_value_string(new_value)?;
|
||||||
self.value = new_value;
|
self.value = new_value;
|
||||||
|
|
|
@ -10,7 +10,7 @@ repository = "https://github.com/orhun/systeroid"
|
||||||
keywords = ["linux", "kernel", "parameter", "sysctl", "tui"]
|
keywords = ["linux", "kernel", "parameter", "sysctl", "tui"]
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.64.0"
|
rust-version = "1.68.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# clipboard support is enabled as default
|
# clipboard support is enabled as default
|
||||||
|
@ -24,6 +24,7 @@ thiserror = "1.0.40"
|
||||||
getopts = "0.2.21"
|
getopts = "0.2.21"
|
||||||
copypasta-ext = { version = "0.4.4", optional = true }
|
copypasta-ext = { version = "0.4.4", optional = true }
|
||||||
colorsys = "0.6.7"
|
colorsys = "0.6.7"
|
||||||
|
log.workspace = true
|
||||||
|
|
||||||
[dependencies.systeroid-core]
|
[dependencies.systeroid-core]
|
||||||
version = "0.3.2" # managed by release.sh
|
version = "0.3.2" # managed by release.sh
|
||||||
|
@ -35,6 +36,11 @@ version = "0.20.1"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["termion"]
|
features = ["termion"]
|
||||||
|
|
||||||
|
[dependencies.tui-logger]
|
||||||
|
version = "0.9.0"
|
||||||
|
default-features = false
|
||||||
|
features = ["ratatui-support"]
|
||||||
|
|
||||||
# metadata for cargo-binstall to get the right artifacts
|
# metadata for cargo-binstall to get the right artifacts
|
||||||
[package.metadata.binstall]
|
[package.metadata.binstall]
|
||||||
pkg-url = "{ repo }/releases/download/v{ version }/systeroid-{ version }-{ target }.{ archive-format }"
|
pkg-url = "{ repo }/releases/download/v{ version }/systeroid-{ version }-{ target }.{ archive-format }"
|
||||||
|
|
|
@ -4,11 +4,13 @@ use crate::options::{CopyOption, Direction, ScrollArea};
|
||||||
use crate::widgets::SelectableList;
|
use crate::widgets::SelectableList;
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
use copypasta_ext::{display::DisplayServer, ClipboardProviderExt};
|
use copypasta_ext::{display::DisplayServer, ClipboardProviderExt};
|
||||||
|
use log::{Level, LevelFilter};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use systeroid_core::sysctl::controller::Sysctl;
|
use systeroid_core::sysctl::controller::Sysctl;
|
||||||
use systeroid_core::sysctl::parameter::Parameter;
|
use systeroid_core::sysctl::parameter::Parameter;
|
||||||
use systeroid_core::sysctl::section::Section;
|
use systeroid_core::sysctl::section::Section;
|
||||||
|
use tui_logger::TuiWidgetState;
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
/// Representation of a key binding.
|
/// Representation of a key binding.
|
||||||
|
@ -87,6 +89,11 @@ pub const KEY_BINDINGS: &[&KeyBinding] = &[
|
||||||
action: "copy to clipboard",
|
action: "copy to clipboard",
|
||||||
command: None,
|
command: None,
|
||||||
},
|
},
|
||||||
|
&KeyBinding {
|
||||||
|
key: "ctrl-l, f2",
|
||||||
|
action: "show logs",
|
||||||
|
command: Some("logs"),
|
||||||
|
},
|
||||||
&KeyBinding {
|
&KeyBinding {
|
||||||
key: "r, f5",
|
key: "r, f5",
|
||||||
action: "refresh",
|
action: "refresh",
|
||||||
|
@ -113,6 +120,10 @@ pub struct App<'a> {
|
||||||
pub running: bool,
|
pub running: bool,
|
||||||
/// Whether if the help message is shown.
|
/// Whether if the help message is shown.
|
||||||
pub show_help: bool,
|
pub show_help: bool,
|
||||||
|
/// Whether if the logs are shown.
|
||||||
|
pub show_logs: bool,
|
||||||
|
/// Logger state.
|
||||||
|
pub logger_state: TuiWidgetState,
|
||||||
/// Input buffer.
|
/// Input buffer.
|
||||||
pub input: Option<String>,
|
pub input: Option<String>,
|
||||||
/// Time tracker for measuring the time for clearing the input.
|
/// Time tracker for measuring the time for clearing the input.
|
||||||
|
@ -144,6 +155,8 @@ impl<'a> App<'a> {
|
||||||
let mut app = Self {
|
let mut app = Self {
|
||||||
running: true,
|
running: true,
|
||||||
show_help: false,
|
show_help: false,
|
||||||
|
show_logs: false,
|
||||||
|
logger_state: TuiWidgetState::new().set_default_display_level(LevelFilter::Trace),
|
||||||
input: None,
|
input: None,
|
||||||
input_time: None,
|
input_time: None,
|
||||||
input_cursor: 0,
|
input_cursor: 0,
|
||||||
|
@ -167,16 +180,16 @@ impl<'a> App<'a> {
|
||||||
app.parameter_list.items = app.sysctl.parameters.clone();
|
app.parameter_list.items = app.sysctl.parameters.clone();
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
{
|
{
|
||||||
app.clipboard = match DisplayServer::select().try_context() {
|
app.clipboard =
|
||||||
None => {
|
match DisplayServer::select().try_context() {
|
||||||
app.input = Some(String::from(
|
None => {
|
||||||
|
app.log(Level::Error, String::from(
|
||||||
"Failed to initialize clipboard, no suitable clipboard provider found",
|
"Failed to initialize clipboard, no suitable clipboard provider found",
|
||||||
));
|
));
|
||||||
app.input_time = Some(Instant::now());
|
None
|
||||||
None
|
}
|
||||||
|
clipboard => clipboard,
|
||||||
}
|
}
|
||||||
clipboard => clipboard,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
app
|
app
|
||||||
}
|
}
|
||||||
|
@ -186,6 +199,13 @@ impl<'a> App<'a> {
|
||||||
self.input.is_some() && self.input_time.is_none()
|
self.input.is_some() && self.input_time.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the log message for the application.
|
||||||
|
pub fn log(&mut self, level: Level, message: String) {
|
||||||
|
log::log!(target: "tui", level, "{message}");
|
||||||
|
self.input = Some(message);
|
||||||
|
self.input_time = Some(Instant::now());
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs a search operation in the kernel parameter list.
|
/// Performs a search operation in the kernel parameter list.
|
||||||
pub fn search(&mut self) {
|
pub fn search(&mut self) {
|
||||||
let section = self
|
let section = self
|
||||||
|
@ -228,7 +248,8 @@ impl<'a> App<'a> {
|
||||||
/// Copies the selected entry to the clipboard.
|
/// Copies the selected entry to the clipboard.
|
||||||
#[cfg(feature = "clipboard")]
|
#[cfg(feature = "clipboard")]
|
||||||
fn copy_to_clipboard(&mut self, copy_option: CopyOption) -> Result<()> {
|
fn copy_to_clipboard(&mut self, copy_option: CopyOption) -> Result<()> {
|
||||||
self.input = Some(if let Some(clipboard) = self.clipboard.as_mut() {
|
log::debug!(target: "tui", "Copying to clipboard: {:?}", copy_option);
|
||||||
|
if let Some(clipboard) = self.clipboard.as_mut() {
|
||||||
if let Some(parameter) = self.parameter_list.selected() {
|
if let Some(parameter) = self.parameter_list.selected() {
|
||||||
match copy_option {
|
match copy_option {
|
||||||
CopyOption::Name => clipboard.set_contents(parameter.name.clone()),
|
CopyOption::Name => clipboard.set_contents(parameter.name.clone()),
|
||||||
|
@ -238,22 +259,23 @@ impl<'a> App<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map_err(|e| crate::error::Error::ClipboardError(e.to_string()))?;
|
.map_err(|e| crate::error::Error::ClipboardError(e.to_string()))?;
|
||||||
String::from("Copied to clipboard!")
|
self.log(Level::Info, String::from("Copied to clipboard!"));
|
||||||
} else {
|
} else {
|
||||||
String::from("No parameter is selected")
|
self.log(Level::Warn, String::from("No parameter is selected"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String::from("Clipboard is not initialized")
|
self.log(Level::Error, String::from("Clipboard is not initialized"));
|
||||||
});
|
}
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shows a message about clipboard being not enabled.
|
/// Shows a message about clipboard being not enabled.
|
||||||
#[cfg(not(feature = "clipboard"))]
|
#[cfg(not(feature = "clipboard"))]
|
||||||
fn copy_to_clipboard(&mut self, _: CopyOption) -> Result<()> {
|
fn copy_to_clipboard(&mut self, _: CopyOption) -> Result<()> {
|
||||||
self.input = Some(String::from("Clipboard support is not enabled"));
|
self.log(
|
||||||
self.input_time = Some(Instant::now());
|
Level::Warn,
|
||||||
|
String::from("Clipboard support is not enabled"),
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,6 +290,12 @@ impl<'a> App<'a> {
|
||||||
self.show_help = true;
|
self.show_help = true;
|
||||||
hide_popup = false;
|
hide_popup = false;
|
||||||
}
|
}
|
||||||
|
Command::Logs => {
|
||||||
|
self.show_logs = !self.show_logs;
|
||||||
|
}
|
||||||
|
Command::LoggerEvent(event) => {
|
||||||
|
self.logger_state.transition(&event.0);
|
||||||
|
}
|
||||||
Command::Select => {
|
Command::Select => {
|
||||||
if let Some(copy_option) = self
|
if let Some(copy_option) = self
|
||||||
.options
|
.options
|
||||||
|
@ -312,8 +340,7 @@ impl<'a> App<'a> {
|
||||||
self.run_command(Command::Refresh)?;
|
self.run_command(Command::Refresh)?;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.input = Some(e.to_string());
|
self.log(Level::Error, e.to_string());
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if save_to_file {
|
if save_to_file {
|
||||||
|
@ -323,17 +350,15 @@ impl<'a> App<'a> {
|
||||||
&self.sysctl.config.tui.save_path,
|
&self.sysctl.config.tui.save_path,
|
||||||
) {
|
) {
|
||||||
Ok(path) => {
|
Ok(path) => {
|
||||||
self.input = Some(format!("Saved to file: {path:?}"));
|
self.log(Level::Info, format!("Saved to file: {path:?}"));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.input = Some(format!("Failed to save: {e}"));
|
self.log(Level::Error, format!("Failed to save: {e}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.input = Some(String::from("Unknown parameter"));
|
self.log(Level::Warn, String::from("Unknown parameter"));
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Scroll(ScrollArea::List, Direction::Up, amount) => {
|
Command::Scroll(ScrollArea::List, Direction::Up, amount) => {
|
||||||
|
@ -442,8 +467,7 @@ impl<'a> App<'a> {
|
||||||
self.run_command(command)?;
|
self.run_command(command)?;
|
||||||
hide_popup = false;
|
hide_popup = false;
|
||||||
} else {
|
} else {
|
||||||
self.input = Some(String::from("Unknown command"));
|
self.log(Level::Warn, String::from("Unknown command"));
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,8 +540,7 @@ impl<'a> App<'a> {
|
||||||
hide_popup = false;
|
hide_popup = false;
|
||||||
self.show_help = false;
|
self.show_help = false;
|
||||||
} else {
|
} else {
|
||||||
self.input = Some(String::from("No parameter is selected"));
|
self.log(Level::Warn, String::from("No parameter is selected"));
|
||||||
self.input_time = Some(Instant::now());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Refresh => {
|
Command::Refresh => {
|
||||||
|
@ -531,6 +554,7 @@ impl<'a> App<'a> {
|
||||||
parameter.value = param.value.to_string();
|
parameter.value = param.value.to_string();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
self.log(Level::Info, String::from("Refreshed!"));
|
||||||
}
|
}
|
||||||
Command::Cancel => {
|
Command::Cancel => {
|
||||||
if self.input.is_some() {
|
if self.input.is_some() {
|
||||||
|
|
|
@ -26,6 +26,8 @@ pub struct Args {
|
||||||
pub kernel_docs: Option<PathBuf>,
|
pub kernel_docs: Option<PathBuf>,
|
||||||
/// Path for the changed parameters.
|
/// Path for the changed parameters.
|
||||||
pub save_path: Option<PathBuf>,
|
pub save_path: Option<PathBuf>,
|
||||||
|
/// File to save the logs.
|
||||||
|
pub log_file: Option<String>,
|
||||||
/// Sysctl section to filter.
|
/// Sysctl section to filter.
|
||||||
pub section: Option<Section>,
|
pub section: Option<Section>,
|
||||||
/// Query to search on startup.
|
/// Query to search on startup.
|
||||||
|
@ -62,6 +64,7 @@ impl Args {
|
||||||
"set the path for saving the changed parameters",
|
"set the path for saving the changed parameters",
|
||||||
"<path>",
|
"<path>",
|
||||||
);
|
);
|
||||||
|
opts.optopt("l", "log-file", "set the file to save the logs", "<path>");
|
||||||
opts.optopt("s", "section", "set the section to filter", "<section>");
|
opts.optopt("s", "section", "set the section to filter", "<section>");
|
||||||
opts.optopt("q", "query", "set the query to search", "<query>");
|
opts.optopt("q", "query", "set the query to search", "<query>");
|
||||||
opts.optopt(
|
opts.optopt(
|
||||||
|
@ -123,6 +126,7 @@ impl Args {
|
||||||
.or_else(|| env::var(KERNEL_DOCS_ENV).ok())
|
.or_else(|| env::var(KERNEL_DOCS_ENV).ok())
|
||||||
.map(PathBuf::from),
|
.map(PathBuf::from),
|
||||||
save_path: matches.opt_str("save-path").map(PathBuf::from),
|
save_path: matches.opt_str("save-path").map(PathBuf::from),
|
||||||
|
log_file: matches.opt_str("l"),
|
||||||
section: matches.opt_str("s").map(Section::from),
|
section: matches.opt_str("s").map(Section::from),
|
||||||
search_query: matches.opt_str("q"),
|
search_query: matches.opt_str("q"),
|
||||||
fg_color: matches
|
fg_color: matches
|
||||||
|
|
|
@ -1,12 +1,44 @@
|
||||||
use crate::options::{Direction, ScrollArea};
|
use crate::options::{Direction, ScrollArea};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use termion::event::Key;
|
use termion::event::Key;
|
||||||
|
use tui_logger::TuiWidgetEvent;
|
||||||
|
|
||||||
|
/// Possible logger widget commands.
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct LoggerCommand(pub TuiWidgetEvent);
|
||||||
|
|
||||||
|
impl Eq for LoggerCommand {}
|
||||||
|
|
||||||
|
impl LoggerCommand {
|
||||||
|
/// Parses a logger command from the given key.
|
||||||
|
pub fn parse(key: Key) -> Option<Self> {
|
||||||
|
match key {
|
||||||
|
Key::Char(' ') => Some(Self(TuiWidgetEvent::SpaceKey)),
|
||||||
|
Key::Esc => Some(Self(TuiWidgetEvent::EscapeKey)),
|
||||||
|
Key::PageUp => Some(Self(TuiWidgetEvent::PrevPageKey)),
|
||||||
|
Key::PageDown => Some(Self(TuiWidgetEvent::NextPageKey)),
|
||||||
|
Key::Up => Some(Self(TuiWidgetEvent::UpKey)),
|
||||||
|
Key::Down => Some(Self(TuiWidgetEvent::DownKey)),
|
||||||
|
Key::Left => Some(Self(TuiWidgetEvent::LeftKey)),
|
||||||
|
Key::Right => Some(Self(TuiWidgetEvent::RightKey)),
|
||||||
|
Key::Char('+') => Some(Self(TuiWidgetEvent::PlusKey)),
|
||||||
|
Key::Char('-') => Some(Self(TuiWidgetEvent::MinusKey)),
|
||||||
|
Key::Char('h') => Some(Self(TuiWidgetEvent::HideKey)),
|
||||||
|
Key::Char('f') => Some(Self(TuiWidgetEvent::FocusKey)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Possible application commands.
|
/// Possible application commands.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
/// Show help.
|
/// Show help.
|
||||||
Help,
|
Help,
|
||||||
|
/// Show logs.
|
||||||
|
Logs,
|
||||||
|
/// Logger event.
|
||||||
|
LoggerEvent(LoggerCommand),
|
||||||
/// Perform an action based on the selected entry.
|
/// Perform an action based on the selected entry.
|
||||||
Select,
|
Select,
|
||||||
/// Save the value of a parameter to a file.
|
/// Save the value of a parameter to a file.
|
||||||
|
@ -42,6 +74,7 @@ impl FromStr for Command {
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
match s {
|
match s {
|
||||||
"help" => Ok(Command::Help),
|
"help" => Ok(Command::Help),
|
||||||
|
"logs" => Ok(Command::Logs),
|
||||||
"search" => Ok(Command::Search),
|
"search" => Ok(Command::Search),
|
||||||
"select" => Ok(Command::Select),
|
"select" => Ok(Command::Select),
|
||||||
"copy" => Ok(Command::Copy),
|
"copy" => Ok(Command::Copy),
|
||||||
|
@ -91,6 +124,7 @@ impl Command {
|
||||||
} else {
|
} else {
|
||||||
match key {
|
match key {
|
||||||
Key::Char('?') | Key::F(1) => Command::Help,
|
Key::Char('?') | Key::F(1) => Command::Help,
|
||||||
|
Key::Ctrl('l') | Key::F(2) => Command::Logs,
|
||||||
Key::Up | Key::Char('k') => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
Key::Up | Key::Char('k') => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
||||||
Key::Down | Key::Char('j') => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
Key::Down | Key::Char('j') => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
||||||
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
||||||
|
@ -135,6 +169,7 @@ mod tests {
|
||||||
fn test_command() {
|
fn test_command() {
|
||||||
for (command, value) in vec![
|
for (command, value) in vec![
|
||||||
(Command::Help, "help"),
|
(Command::Help, "help"),
|
||||||
|
(Command::Logs, "logs"),
|
||||||
(Command::Search, "search"),
|
(Command::Search, "search"),
|
||||||
(Command::Select, "select"),
|
(Command::Select, "select"),
|
||||||
(Command::Copy, "copy"),
|
(Command::Copy, "copy"),
|
||||||
|
@ -181,6 +216,7 @@ mod tests {
|
||||||
assert_command_parser! {
|
assert_command_parser! {
|
||||||
input_mode: false,
|
input_mode: false,
|
||||||
Key::Char('?') => Command::Help,
|
Key::Char('?') => Command::Help,
|
||||||
|
Key::Ctrl('l') => Command::Logs,
|
||||||
Key::Up => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
Key::Up => Command::Scroll(ScrollArea::List, Direction::Up, 1),
|
||||||
Key::Down => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
Key::Down => Command::Scroll(ScrollArea::List, Direction::Down, 1),
|
||||||
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
Key::PageUp => Command::Scroll(ScrollArea::List, Direction::Up, 4),
|
||||||
|
|
|
@ -15,6 +15,12 @@ pub enum Error {
|
||||||
/// Error that may occur while parsing a color.
|
/// Error that may occur while parsing a color.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
ColorParseError(#[from] colorsys::ParseError),
|
ColorParseError(#[from] colorsys::ParseError),
|
||||||
|
/// Error that may occur if the logger is already set.
|
||||||
|
#[error(transparent)]
|
||||||
|
LoggerSetError(#[from] log::SetLoggerError),
|
||||||
|
/// Error that may occur when the string doesn’t match any of the log levels.
|
||||||
|
#[error(transparent)]
|
||||||
|
LoggerParseError(#[from] log::ParseLevelError),
|
||||||
/// Error that may occur in the core library.
|
/// Error that may occur in the core library.
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
SysctlError(#[from] systeroid_core::error::Error),
|
SysctlError(#[from] systeroid_core::error::Error),
|
||||||
|
|
|
@ -27,6 +27,10 @@ use crate::command::Command;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
use crate::event::{Event, EventHandler};
|
use crate::event::{Event, EventHandler};
|
||||||
use crate::style::Colors;
|
use crate::style::Colors;
|
||||||
|
use command::LoggerCommand;
|
||||||
|
use log::LevelFilter;
|
||||||
|
use std::env;
|
||||||
|
use std::str::FromStr;
|
||||||
use systeroid_core::cache::Cache;
|
use systeroid_core::cache::Cache;
|
||||||
use systeroid_core::config::Config;
|
use systeroid_core::config::Config;
|
||||||
use systeroid_core::sysctl::controller::Sysctl;
|
use systeroid_core::sysctl::controller::Sysctl;
|
||||||
|
@ -42,11 +46,22 @@ pub fn run<B: Backend>(args: Args, backend: B) -> Result<()> {
|
||||||
};
|
};
|
||||||
config.tui.tick_rate = args.tick_rate;
|
config.tui.tick_rate = args.tick_rate;
|
||||||
config.tui.save_path = args.save_path;
|
config.tui.save_path = args.save_path;
|
||||||
|
config.tui.log_file = args.log_file;
|
||||||
config.tui.no_docs = args.no_docs;
|
config.tui.no_docs = args.no_docs;
|
||||||
config.tui.color.fg_color = args.fg_color;
|
config.tui.color.fg_color = args.fg_color;
|
||||||
config.tui.color.bg_color = args.bg_color;
|
config.tui.color.bg_color = args.bg_color;
|
||||||
config.parse(args.config)?;
|
config.parse(args.config)?;
|
||||||
let colors = Colors::new(&config.tui.color.bg_color, &config.tui.color.fg_color)?;
|
let colors = Colors::new(&config.tui.color.bg_color, &config.tui.color.fg_color)?;
|
||||||
|
tui_logger::init_logger(if let Ok(log_level) = env::var("RUST_LOG") {
|
||||||
|
LevelFilter::from_str(&log_level)?
|
||||||
|
} else {
|
||||||
|
LevelFilter::Trace
|
||||||
|
})?;
|
||||||
|
tui_logger::set_default_level(LevelFilter::Trace);
|
||||||
|
if let Some(ref log_file) = config.tui.log_file {
|
||||||
|
tui_logger::set_log_file(log_file)?;
|
||||||
|
}
|
||||||
|
log::trace!(target: "config", "{:?}", config);
|
||||||
let mut sysctl = Sysctl::init(config)?;
|
let mut sysctl = Sysctl::init(config)?;
|
||||||
if !sysctl.config.tui.no_docs {
|
if !sysctl.config.tui.no_docs {
|
||||||
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
||||||
|
@ -75,7 +90,12 @@ pub fn run<B: Backend>(args: Args, backend: B) -> Result<()> {
|
||||||
terminal.draw(|frame| ui::render(frame, &mut app, &colors))?;
|
terminal.draw(|frame| ui::render(frame, &mut app, &colors))?;
|
||||||
match event_handler.next()? {
|
match event_handler.next()? {
|
||||||
Event::KeyPress(key) => {
|
Event::KeyPress(key) => {
|
||||||
let command = Command::parse(key, app.is_input_mode());
|
let mut command = Command::parse(key, app.is_input_mode());
|
||||||
|
if app.show_logs {
|
||||||
|
command = LoggerCommand::parse(key)
|
||||||
|
.map(Command::LoggerEvent)
|
||||||
|
.unwrap_or(command);
|
||||||
|
}
|
||||||
app.run_command(command)?;
|
app.run_command(command)?;
|
||||||
}
|
}
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
|
|
|
@ -3,9 +3,11 @@ use crate::style::Colors;
|
||||||
use crate::widgets::SelectableList;
|
use crate::widgets::SelectableList;
|
||||||
use tui::backend::Backend;
|
use tui::backend::Backend;
|
||||||
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
use tui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
||||||
|
use tui::style::{Color as TuiColor, Style};
|
||||||
use tui::text::{Span, Text};
|
use tui::text::{Span, Text};
|
||||||
use tui::widgets::{Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table, Wrap};
|
use tui::widgets::{Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table, Wrap};
|
||||||
use tui::Frame;
|
use tui::Frame;
|
||||||
|
use tui_logger::{TuiLoggerLevelOutput, TuiLoggerSmartWidget};
|
||||||
use unicode_width::UnicodeWidthStr;
|
use unicode_width::UnicodeWidthStr;
|
||||||
|
|
||||||
/// Renders the user interface.
|
/// Renders the user interface.
|
||||||
|
@ -16,35 +18,48 @@ pub fn render<B: Backend>(frame: &mut Frame<'_, B>, app: &mut App, colors: &Colo
|
||||||
.and_then(|parameter| parameter.get_documentation());
|
.and_then(|parameter| parameter.get_documentation());
|
||||||
let rect = frame.size();
|
let rect = frame.size();
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Vertical)
|
||||||
.constraints(if documentation.is_some() {
|
.constraints(if app.show_logs {
|
||||||
[Constraint::Percentage(50), Constraint::Percentage(50)]
|
[Constraint::Percentage(60), Constraint::Percentage(40)]
|
||||||
} else {
|
} else {
|
||||||
[Constraint::Percentage(100), Constraint::Min(0)]
|
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||||
})
|
})
|
||||||
.split(rect);
|
.split(rect);
|
||||||
{
|
{
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Horizontal)
|
||||||
.constraints(if app.input.is_some() {
|
.constraints(if documentation.is_some() {
|
||||||
[Constraint::Min(rect.height - 3), Constraint::Min(3)]
|
[Constraint::Percentage(50), Constraint::Percentage(50)]
|
||||||
} else {
|
} else {
|
||||||
[Constraint::Percentage(100), Constraint::Min(0)]
|
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||||
})
|
})
|
||||||
.split(chunks[0]);
|
.split(chunks[0]);
|
||||||
render_parameter_list(frame, chunks[0], app, colors);
|
{
|
||||||
if app.input.is_some() {
|
let chunks = Layout::default()
|
||||||
render_input_prompt(frame, chunks[1], rect.height - 2, app, colors);
|
.direction(Direction::Vertical)
|
||||||
|
.constraints(if app.input.is_some() {
|
||||||
|
[Constraint::Min(chunks[0].height - 3), Constraint::Min(3)]
|
||||||
|
} else {
|
||||||
|
[Constraint::Percentage(100), Constraint::Min(0)]
|
||||||
|
})
|
||||||
|
.split(chunks[0]);
|
||||||
|
render_parameter_list(frame, chunks[0], app, colors);
|
||||||
|
if app.input.is_some() {
|
||||||
|
render_input_prompt(frame, chunks[1], chunks[0].height + 1, app, colors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(documentation) = documentation {
|
||||||
|
render_parameter_documentation(
|
||||||
|
frame,
|
||||||
|
chunks[1],
|
||||||
|
documentation,
|
||||||
|
&mut app.docs_scroll_amount,
|
||||||
|
colors,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(documentation) = documentation {
|
if app.show_logs {
|
||||||
render_parameter_documentation(
|
render_log_view(frame, chunks[1], app, colors);
|
||||||
frame,
|
|
||||||
chunks[1],
|
|
||||||
documentation,
|
|
||||||
&mut app.docs_scroll_amount,
|
|
||||||
colors,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if app.show_help {
|
if app.show_help {
|
||||||
render_help_text(frame, rect, &mut app.key_bindings, colors);
|
render_help_text(frame, rect, &mut app.key_bindings, colors);
|
||||||
|
@ -463,3 +478,24 @@ fn render_input_prompt<B: Backend>(
|
||||||
rect,
|
rect,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Renders the log view.
|
||||||
|
fn render_log_view<B: Backend>(frame: &mut Frame<'_, B>, rect: Rect, app: &App, colors: &Colors) {
|
||||||
|
let logger_widget = TuiLoggerSmartWidget::default()
|
||||||
|
.style_trace(Style::default().fg(TuiColor::DarkGray))
|
||||||
|
.style_debug(Style::default().fg(TuiColor::Blue))
|
||||||
|
.style_warn(Style::default().fg(TuiColor::Yellow))
|
||||||
|
.style_error(Style::default().fg(TuiColor::Red))
|
||||||
|
.style_info(Style::default().fg(TuiColor::Green))
|
||||||
|
.highlight_style(colors.get_fg_style())
|
||||||
|
.border_style(colors.get_fg_style())
|
||||||
|
.style(colors.get_bg_style())
|
||||||
|
.output_separator(':')
|
||||||
|
.output_timestamp(Some("%H:%M:%S".to_string()))
|
||||||
|
.output_level(Some(TuiLoggerLevelOutput::Long))
|
||||||
|
.output_target(true)
|
||||||
|
.output_file(true)
|
||||||
|
.output_line(true)
|
||||||
|
.state(&app.logger_state);
|
||||||
|
frame.render_widget(logger_widget, rect);
|
||||||
|
}
|
||||||
|
|
|
@ -307,10 +307,10 @@ fn test_render_tui() -> Result<()> {
|
||||||
"│vm.stat_interval =││============= │",
|
"│vm.stat_interval =││============= │",
|
||||||
"│ ││The time interval │",
|
"│ ││The time interval │",
|
||||||
"│ ││between which vm │",
|
"│ ││between which vm │",
|
||||||
"│ ││statistics are │",
|
"│ 2/2 ││statistics are │",
|
||||||
"│ ││updated │",
|
"╰──────────────────╯│updated │",
|
||||||
"│ ││- │",
|
"╭──────────────────╮│- │",
|
||||||
"│ 2/2 ││Parameter: │",
|
"│MSG: Refreshed! ││Parameter: │",
|
||||||
"╰──────────────────╯╰──────────────────╯",
|
"╰──────────────────╯╰──────────────────╯",
|
||||||
]),
|
]),
|
||||||
terminal.backend(),
|
terminal.backend(),
|
||||||
|
|
|
@ -10,7 +10,7 @@ repository = "https://github.com/orhun/systeroid"
|
||||||
keywords = ["linux", "kernel", "parameter", "sysctl"]
|
keywords = ["linux", "kernel", "parameter", "sysctl"]
|
||||||
categories = ["command-line-utilities"]
|
categories = ["command-line-utilities"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
default-run="systeroid"
|
default-run = "systeroid"
|
||||||
rust-version = "1.64.0"
|
rust-version = "1.64.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -18,8 +18,10 @@ rust-version = "1.64.0"
|
||||||
live-tests = []
|
live-tests = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
getopts = "0.2.21"
|
|
||||||
parseit.workspace = true
|
parseit.workspace = true
|
||||||
|
log.workspace = true
|
||||||
|
env_logger = "0.10.0"
|
||||||
|
getopts = "0.2.21"
|
||||||
|
|
||||||
[dependencies.systeroid-core]
|
[dependencies.systeroid-core]
|
||||||
version = "0.3.2" # managed by release.sh
|
version = "0.3.2" # managed by release.sh
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
if !pager.is_empty() {
|
if !pager.is_empty() {
|
||||||
eprintln!("pager error: `{e}`");
|
log::error!("pager error: `{e}`");
|
||||||
}
|
}
|
||||||
fallback_to_default = true;
|
fallback_to_default = true;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
if parameters.len() == 1 {
|
if parameters.len() == 1 {
|
||||||
let param = parameters[0];
|
let param = parameters[0];
|
||||||
if DEPRECATED_PARAMS.contains(¶m.get_absolute_name().unwrap_or_default()) {
|
if DEPRECATED_PARAMS.contains(¶m.get_absolute_name().unwrap_or_default()) {
|
||||||
eprintln!(
|
log::error!(
|
||||||
"{}: {} is deprecated, value not set",
|
"{}: {} is deprecated, value not set",
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
parameter
|
parameter
|
||||||
|
@ -145,14 +145,14 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
param.update_value(&new_value, &config, self.output)?;
|
param.update_value(&new_value, &config, self.output)?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
eprintln!(
|
log::error!(
|
||||||
"{}: ambiguous parameter name: {}",
|
"{}: ambiguous parameter name: {}",
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
parameter
|
parameter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if write_mode {
|
} else if write_mode {
|
||||||
eprintln!(
|
log::error!(
|
||||||
"{}: {:?} must be in the format: name=value",
|
"{}: {:?} must be in the format: name=value",
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
parameter
|
parameter
|
||||||
|
@ -171,13 +171,13 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
let lines = stdin.lock().lines();
|
let lines = stdin.lock().lines();
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if let Err(e) = self.process_parameter(line?, true, false) {
|
if let Err(e) = self.process_parameter(line?, true, false) {
|
||||||
println!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
log::info!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
eprintln!(
|
log::error!(
|
||||||
"{}: cannot open {:?}: No such file or directory",
|
"{}: cannot open {:?}: No such file or directory",
|
||||||
env!("CARGO_PKG_NAME"),
|
env!("CARGO_PKG_NAME"),
|
||||||
path
|
path
|
||||||
|
@ -194,7 +194,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
if !parameter.starts_with('-') {
|
if !parameter.starts_with('-') {
|
||||||
process_result?;
|
process_result?;
|
||||||
} else if let Err(e) = process_result {
|
} else if let Err(e) = process_result {
|
||||||
eprintln!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
log::error!("{}: {}", env!("CARGO_PKG_NAME"), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -208,7 +208,7 @@ impl<'a, Output: Write> App<'a, Output> {
|
||||||
{
|
{
|
||||||
if let Ok(glob_walker) = globwalk::glob(preload_path.to_string_lossy()) {
|
if let Ok(glob_walker) = globwalk::glob(preload_path.to_string_lossy()) {
|
||||||
for file in glob_walker.filter_map(|v| v.ok()) {
|
for file in glob_walker.filter_map(|v| v.ok()) {
|
||||||
println!("* Applying {} ...", file.path().display());
|
log::info!("* Applying {} ...", file.path().display());
|
||||||
self.preload_from_file(file.path().to_path_buf())?;
|
self.preload_from_file(file.path().to_path_buf())?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,13 @@ pub fn run<Output: Write>(args: Args, output: &mut Output) -> Result<()> {
|
||||||
kernel_docs: args.kernel_docs,
|
kernel_docs: args.kernel_docs,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
config.cli.verbose = args.verbose;
|
|
||||||
config.cli.ignore_errors = args.ignore_errors;
|
config.cli.ignore_errors = args.ignore_errors;
|
||||||
config.cli.quiet = args.quiet;
|
config.cli.quiet = args.quiet;
|
||||||
config.cli.no_pager = args.no_pager;
|
config.cli.no_pager = args.no_pager;
|
||||||
config.cli.display_type = args.display_type;
|
config.cli.display_type = args.display_type;
|
||||||
config.cli.output_type = args.output_type;
|
config.cli.output_type = args.output_type;
|
||||||
config.parse(args.config)?;
|
config.parse(args.config)?;
|
||||||
|
log::trace!("{:?}", config);
|
||||||
let mut sysctl = Sysctl::init(config)?;
|
let mut sysctl = Sysctl::init(config)?;
|
||||||
if args.explain {
|
if args.explain {
|
||||||
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
sysctl.update_docs_from_cache(&Cache::init()?)?;
|
||||||
|
|
|
@ -1,10 +1,19 @@
|
||||||
|
use env_logger::Builder as LoggerBuilder;
|
||||||
|
use log::LevelFilter;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io;
|
use std::io::{self, Write};
|
||||||
use std::process::{self, Command};
|
use std::process::{self, Command};
|
||||||
use systeroid::args::Args;
|
use systeroid::args::Args;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if let Some(args) = Args::parse(env::args().collect()) {
|
if let Some(args) = Args::parse(env::args().collect()) {
|
||||||
|
let mut builder = LoggerBuilder::from_default_env();
|
||||||
|
if args.verbose {
|
||||||
|
builder.filter(None, LevelFilter::Trace);
|
||||||
|
}
|
||||||
|
builder
|
||||||
|
.format(|buf, record| writeln!(buf, "{}", record.args()))
|
||||||
|
.init();
|
||||||
if args.show_tui {
|
if args.show_tui {
|
||||||
let bin = format!("{}-tui", env!("CARGO_PKG_NAME"));
|
let bin = format!("{}-tui", env!("CARGO_PKG_NAME"));
|
||||||
let mut command = Command::new(&bin);
|
let mut command = Command::new(&bin);
|
||||||
|
@ -17,7 +26,7 @@ fn main() {
|
||||||
match command.spawn().map(|mut child| child.wait()) {
|
match command.spawn().map(|mut child| child.wait()) {
|
||||||
Ok(_) => process::exit(0),
|
Ok(_) => process::exit(0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Cannot run `{bin}` ({e})");
|
log::error!("Cannot run `{bin}` ({e})");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +35,7 @@ fn main() {
|
||||||
match systeroid::run(args, &mut stdout) {
|
match systeroid::run(args, &mut stdout) {
|
||||||
Ok(_) => process::exit(0),
|
Ok(_) => process::exit(0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("{e}");
|
log::error!("{e}");
|
||||||
process::exit(1)
|
process::exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue