diff --git a/.github/requirements.txt b/.github/requirements.txt deleted file mode 100644 index 295ed680..00000000 --- a/.github/requirements.txt +++ /dev/null @@ -1,51 +0,0 @@ -Babel==2.15.0 -bracex==2.5 -cairocffi==1.7.1 -CairoSVG==2.7.1 -certifi==2024.7.4 -cffi==1.17.0 -charset-normalizer==3.3.2 -click==8.1.7 -colorama==0.4.6 -csscompressor==0.9.5 -cssselect2==0.7.0 -defusedxml==0.7.1 -ghp-import==2.1.0 -gitdb==4.0.11 -GitPython==3.1.43 -htmlmin2==0.1.13 -idna==3.7 -Jinja2==3.1.4 -jsmin==3.0.1 -Markdown==3.6 -MarkupSafe==2.1.5 -mergedeep==1.3.4 -mkdocs==1.6.0 -mkdocs-awesome-pages-plugin==2.9.3 -mkdocs-get-deps==0.2.0 -mkdocs-git-revision-date-localized-plugin==1.2.6 -mkdocs-material==9.5.31 -mkdocs-material-extensions==1.3.1 -mkdocs-minify-plugin==0.8.0 -natsort==8.4.0 -packaging==24.1 -paginate==0.5.6 -pathspec==0.12.1 -pillow==10.4.0 -platformdirs==4.2.2 -pycparser==2.22 -Pygments==2.18.0 -pymdown-extensions==10.9 -python-dateutil==2.9.0.post0 -pytz==2024.1 -PyYAML==6.0.2 -pyyaml_env_tag==0.1 -regex==2024.7.24 -requests==2.32.3 -six==1.16.0 -smmap==5.0.1 -tinycss2==1.3.0 -urllib3==2.2.2 -watchdog==4.0.1 -wcmatch==9.0 -webencodings==0.5.1 diff --git a/.github/workflows/linutil.yml b/.github/workflows/linutil.yml index 9f1e5ee1..187f1e54 100644 --- a/.github/workflows/linutil.yml +++ b/.github/workflows/linutil.yml @@ -39,18 +39,6 @@ jobs: with: targets: x86_64-unknown-linux-musl - - name: Update package version - run: | - prev_version=$(grep 'version' Cargo.toml | head -n +1 | cut -d'"' -f2) - if ! echo " ${prev_version} " | grep -q -E ' [0-9]{2}\.[0-9]{2}\.[0-9]{2} '; then - echo "Could not accurately determine the previous version" - exit 1 - fi - new_version=$(date +"%y.%m.%d") - # The TUI depends upon linutil_core, which has its version updated - sed -i "s/version = \"${prev_version}\"/version = \"${new_version}\"/g" Cargo.toml tui/Cargo.toml - shell: bash - - name: Install cross-rs for cross-compilation run: cargo install cross diff --git a/.github/workflows/shellcheck.yml b/.github/workflows/shellcheck.yml index e3be746d..85feed74 100644 --- a/.github/workflows/shellcheck.yml +++ b/.github/workflows/shellcheck.yml @@ -31,9 +31,3 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 - - - name: Run shfmt - uses: reviewdog/action-shfmt@v1 - with: - shfmt_flags: '-i 4 -ci' - reviewdog_flags: '-fail-level=any' diff --git a/Cargo.lock b/Cargo.lock index 8fd9ac21..148fb3c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,18 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] +version = 4 [[package]] name = "aho-corasick" @@ -25,21 +13,21 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anyhow" -version = "1.0.88" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arrayvec" @@ -49,9 +37,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "bitflags" @@ -61,9 +49,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be" [[package]] name = "byteorder" @@ -88,9 +76,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.28" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7" dependencies = [ "shlex", ] @@ -109,9 +97,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -119,9 +107,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstyle", "clap_lex", @@ -129,9 +117,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -141,15 +129,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "compact_str" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" +checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" dependencies = [ "castaway", "cfg-if", @@ -165,7 +153,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "crossterm_winapi", "mio", "parking_lot", @@ -184,6 +172,41 @@ dependencies = [ "winapi", ] +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.3.11" @@ -211,6 +234,12 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "env_home" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" + [[package]] name = "equivalent" version = "1.0.1" @@ -219,12 +248,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -238,6 +267,18 @@ dependencies = [ "winapi", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + [[package]] name = "getrandom" version = "0.2.15" @@ -251,20 +292,15 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ - "ahash", "allocator-api2", + "equivalent", + "foldhash", ] -[[package]] -name = "hashbrown" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" - [[package]] name = "heck" version = "0.5.0" @@ -272,19 +308,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hermit-abi" -version = "0.3.9" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - -[[package]] -name = "home" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "include_dir" @@ -307,12 +334,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.1", + "hashbrown", ] [[package]] @@ -323,10 +350,13 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" [[package]] name = "instability" -version = "0.3.2" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +checksum = "894813a444908c0c8c0e221b041771d107c4a21de1d317dc49bcc66e3c9e5b3f" dependencies = [ + "darling", + "indoc", + "proc-macro2", "quote", "syn", ] @@ -351,9 +381,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "lazy_static" @@ -363,13 +393,13 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linutil_core" -version = "24.10.31" +version = "25.2.13" dependencies = [ "ego-tree", "include_dir", @@ -381,7 +411,7 @@ dependencies = [ [[package]] name = "linutil_tui" -version = "24.10.31" +version = "25.2.13" dependencies = [ "clap", "linutil_core", @@ -400,9 +430,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "lock_api" @@ -422,11 +452,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", ] [[package]] @@ -446,15 +476,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -477,7 +506,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cfg-if", "cfg_aliases", "libc", @@ -498,12 +527,6 @@ dependencies = [ "libc", ] -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - [[package]] name = "oneshot" version = "0.1.8" @@ -583,18 +606,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -635,7 +658,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "cassowary", "compact_str", "crossterm", @@ -652,18 +675,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", ] [[package]] name = "regex" -version = "1.10.6" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -673,9 +696,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -684,28 +707,28 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ - "bitflags 2.6.0", + "bitflags 2.7.0", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -721,18 +744,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -741,9 +764,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -860,6 +883,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "strum" version = "0.26.3" @@ -884,9 +913,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -910,18 +939,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -930,9 +959,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -953,9 +982,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -997,9 +1026,9 @@ dependencies = [ [[package]] name = "tree-sitter" -version = "0.24.4" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67baf55e7e1b6806063b1e51041069c90afff16afcbbccd278d899f9d84bca4" +checksum = "5f2434c86ba59ed15af56039cc5bf1acf8ba76ce301e32ef08827388ef285ec5" dependencies = [ "cc", "regex", @@ -1020,9 +1049,9 @@ dependencies = [ [[package]] name = "tree-sitter-highlight" -version = "0.24.4" +version = "0.24.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f0f856de10d70a6d14d66db3648f7410c131cd49e989a863f15dda9acae6044" +checksum = "a1df627d3607f08557788a3c85b85042d8ccd5155eb119afff5f0c7b67a40924" dependencies = [ "lazy_static", "regex", @@ -1033,9 +1062,9 @@ dependencies = [ [[package]] name = "tree-sitter-language" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2545046bd1473dac6c626659cc2567c6c0ff302fc8b84a56c4243378276f7f57" +checksum = "c199356c799a8945965bb5f2c55b2ad9d9aa7c4b4f6e587fe9dea0bc715e5f9c" [[package]] name = "tui-term" @@ -1048,15 +1077,15 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-truncate" @@ -1087,12 +1116,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "vt100-ctt" version = "0.16.0" @@ -1109,9 +1132,9 @@ dependencies = [ [[package]] name = "vte" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" +checksum = "9a0b683b20ef64071ff03745b14391751f6beab06a54347885459b77a3f2caa5" dependencies = [ "arrayvec", "utf8parse", @@ -1136,12 +1159,12 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "which" -version = "7.0.0" +version = "7.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" +checksum = "fb4a9e33648339dc1642b0e36e21b3385e6148e289226f657c809dee59df5028" dependencies = [ "either", - "home", + "env_home", "rustix", "winsafe", ] @@ -1177,6 +1200,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -1243,9 +1275,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980" dependencies = [ "memchr", ] @@ -1267,7 +1299,7 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" [[package]] name = "xtask" -version = "24.10.31" +version = "25.2.13" dependencies = [ "linutil_core", ] diff --git a/Cargo.toml b/Cargo.toml index 27b31878..3e732bf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace.package] license = "MIT" -version = "24.10.31" +version = "25.2.13" edition = "2021" [workspace] diff --git a/LICENSE b/LICENSE index 129a6232..03a5d53f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 Chris Titus +Copyright (c) 2025 Chris Titus Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 59a0f8b8..a9db23da 100644 --- a/README.md +++ b/README.md @@ -83,25 +83,18 @@ curl -fsSL https://christitus.com/linuxdev | sh ### CLI arguments -Linutil supports various command-line arguments to customize its behavior. Here are some common arguments you can use: - -- `-c, --config ` : Path to the configuration file. -- `--override-validation` : Show all available options, disregarding compatibility checks (UNSAFE). -- `--size-bypass` : Bypass the terminal size limit. -- `-y, --skip-confirmation` : Skip confirmation prompt before executing commands. -- `-t, --theme ` : Set the theme to use in the application [default: `default`] [possible values: `default`, `compatible`]. -- `-h, --help` : Print help. - -For more detailed usage, run: - -```bash -curl -fsSL https://christitus.com/linux | sh -s -- --help -``` +View available options by running: ```bash linutil --help ``` +For installer options: + +```bash +curl -fsSL https://christitus.com/linux | sh -s -- --help +``` + ## Configuration Linutil supports configuration through a TOML config file. Path to the file can be specified with `--config` (or `-c`). @@ -142,7 +135,7 @@ Docs are now [here](https://github.com/Chris-Titus-Docs/linutil-docs) ## 🏅 Thanks to All Contributors -Thank you to everyone who has contributed to the development of Linutil. Your efforts are greatly appreciated, and you’re helping make this tool better for everyone! +Thank you to everyone who has contributed to the development of Linutil. Your efforts are greatly appreciated, and you're helping make this tool better for everyone! [![Contributors](https://contrib.rocks/image?repo=ChrisTitusTech/linutil)](https://github.com/ChrisTitusTech/linutil/graphs/contributors) diff --git a/core/src/inner.rs b/core/src/inner.rs index 0fadae80..8621ea2b 100644 --- a/core/src/inner.rs +++ b/core/src/inner.rs @@ -111,18 +111,16 @@ fn default_true() -> bool { } #[derive(Deserialize)] +#[serde(rename_all = "snake_case")] enum EntryType { - #[serde(rename = "entries")] Entries(Vec), - #[serde(rename = "command")] Command(String), - #[serde(rename = "script")] Script(PathBuf), } impl Entry { fn is_supported(&self) -> bool { - self.preconditions.as_deref().map_or(true, |preconditions| { + self.preconditions.as_deref().is_none_or(|preconditions| { preconditions.iter().all( |Precondition { matches, @@ -131,18 +129,17 @@ impl Entry { }| { match data { SystemDataType::Environment(var_name) => std::env::var(var_name) - .map_or(false, |var| values.contains(&var) == *matches), - SystemDataType::File(path) => { - std::fs::read_to_string(path).map_or(false, |data| { + .is_ok_and(|var| values.contains(&var) == *matches), + SystemDataType::ContainingFile(file) => std::fs::read_to_string(file) + .is_ok_and(|data| { values .iter() - .any(|matching_value| data.contains(matching_value)) - == *matches - }) - } + .all(|matching| data.contains(matching) == *matches) + }), SystemDataType::CommandExists => values .iter() .all(|command| which::which(command).is_ok() == *matches), + SystemDataType::FileExists => values.iter().all(|p| Path::new(p).is_file()), } }, ) @@ -160,12 +157,11 @@ struct Precondition { } #[derive(Deserialize)] +#[serde(rename_all = "snake_case")] enum SystemDataType { - #[serde(rename = "environment")] Environment(String), - #[serde(rename = "file")] - File(PathBuf), - #[serde(rename = "command_exists")] + ContainingFile(PathBuf), + FileExists, CommandExists, } diff --git a/core/tabs/applications-setup/android-debloat.sh b/core/tabs/applications-setup/android-debloat.sh index 63258023..1db9328b 100644 --- a/core/tabs/applications-setup/android-debloat.sh +++ b/core/tabs/applications-setup/android-debloat.sh @@ -19,7 +19,7 @@ install_adb() { "$ESCALATION_TOOL" "$PACKAGER" add android-tools ;; *) - printf "%b\n" "${RED}Unsupported package manager: "$PACKAGER"${RC}" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac diff --git a/core/tabs/applications-setup/browsers/librewolf.sh b/core/tabs/applications-setup/browsers/librewolf.sh index d8ed06b4..f6974502 100644 --- a/core/tabs/applications-setup/browsers/librewolf.sh +++ b/core/tabs/applications-setup/browsers/librewolf.sh @@ -8,7 +8,7 @@ installLibreWolf() { case "$PACKAGER" in apt-get|nala) "$ESCALATION_TOOL" "$PACKAGER" install -y gnupg lsb-release apt-transport-https ca-certificates - distro=`if echo " una bookworm vanessa focal jammy bullseye vera uma " | grep -q " $(lsb_release -sc) "; then lsb_release -sc; else echo focal; fi` + distro=$(if echo " una bookworm vanessa focal jammy bullseye vera uma " | grep -q "$(lsb_release -sc)"; then "$(lsb_release -sc)"; else echo 'focal'; fi) curl -fsSL https://deb.librewolf.net/keyring.gpg | "$ESCALATION_TOOL" gpg --dearmor -o /usr/share/keyrings/librewolf.gpg echo "Types: deb URIs: https://deb.librewolf.net @@ -49,4 +49,4 @@ Signed-By: /usr/share/keyrings/librewolf.gpg" | "$ESCALATION_TOOL" tee /etc/apt/ checkEnv checkEscalationTool checkAURHelper -installLibreWolf \ No newline at end of file +installLibreWolf diff --git a/core/tabs/applications-setup/browsers/zen-browser.sh b/core/tabs/applications-setup/browsers/zen-browser.sh new file mode 100755 index 00000000..4cd7d932 --- /dev/null +++ b/core/tabs/applications-setup/browsers/zen-browser.sh @@ -0,0 +1,29 @@ +#!/bin/sh -e + +. ../../common-script.sh + +installZenBrowser() { + if ! command_exists io.github.zen_browser.zen && ! command_exists zen-browser; then + printf "%b\n" "${YELLOW}Installing Zen Browser...${RC}" + case "$PACKAGER" in + pacman) + if grep -q avx2 /proc/cpuinfo; then + "$AUR_HELPER" -S --needed --noconfirm zen-browser-avx2-bin + else + "$AUR_HELPER" -S --needed --noconfirm zen-browser-bin + fi + ;; + *) + checkFlatpak + flatpak install -y flathub io.github.zen_browser.zen + ;; + esac + else + printf "%b\n" "${GREEN}Zen Browser is already installed.${RC}" + fi +} + +checkEnv +checkEscalationTool +checkAURHelper +installZenBrowser diff --git a/core/tabs/applications-setup/communication-apps/discord-setup.sh b/core/tabs/applications-setup/communication-apps/discord-setup.sh index f96bd9f2..0843a373 100644 --- a/core/tabs/applications-setup/communication-apps/discord-setup.sh +++ b/core/tabs/applications-setup/communication-apps/discord-setup.sh @@ -17,7 +17,7 @@ installDiscord() { "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm discord ;; dnf) - "$ESCALATION_TOOL" "$PACKAGER" install -y https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm + "$ESCALATION_TOOL" "$PACKAGER" install -y "https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm" "$ESCALATION_TOOL" "$PACKAGER" install -y discord ;; apk) @@ -36,4 +36,4 @@ installDiscord() { checkEnv checkEscalationTool -installDiscord \ No newline at end of file +installDiscord diff --git a/core/tabs/applications-setup/communication-apps/signal-setup.sh b/core/tabs/applications-setup/communication-apps/signal-setup.sh index 18c462b1..48f72ddb 100644 --- a/core/tabs/applications-setup/communication-apps/signal-setup.sh +++ b/core/tabs/applications-setup/communication-apps/signal-setup.sh @@ -8,7 +8,7 @@ installSignal() { case "$PACKAGER" in apt-get|nala) curl -fsSL https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor > signal-desktop-keyring.gpg - cat signal-desktop-keyring.gpg | "$ESCALATION_TOOL" tee /usr/share/keyrings/signal-desktop-keyring.gpg > /dev/null + "$ESCALATION_TOOL" tee /usr/share/keyrings/signal-desktop-keyring.gpg < signal-desktop-keyring.gpg > /dev/null printf "%b\n" 'deb [arch=amd64 signed-by=/usr/share/keyrings/signal-desktop-keyring.gpg] https://updates.signal.org/desktop/apt xenial main' | "$ESCALATION_TOOL" tee /etc/apt/sources.list.d/signal-xenial.list "$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" "$PACKAGER" -y install signal-desktop @@ -39,4 +39,4 @@ installSignal() { checkEnv checkEscalationTool -installSignal \ No newline at end of file +installSignal diff --git a/core/tabs/applications-setup/Developer-tools/githubdesktop-setup.sh b/core/tabs/applications-setup/developer-tools/githubdesktop.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/githubdesktop-setup.sh rename to core/tabs/applications-setup/developer-tools/githubdesktop.sh diff --git a/core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh b/core/tabs/applications-setup/developer-tools/jetbrains-toolbox.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/jetbrains-toolbox.sh rename to core/tabs/applications-setup/developer-tools/jetbrains-toolbox.sh diff --git a/core/tabs/applications-setup/Developer-tools/meld-setup.sh b/core/tabs/applications-setup/developer-tools/meld.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/meld-setup.sh rename to core/tabs/applications-setup/developer-tools/meld.sh diff --git a/core/tabs/applications-setup/Developer-tools/neovim-setup.sh b/core/tabs/applications-setup/developer-tools/neovim.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/neovim-setup.sh rename to core/tabs/applications-setup/developer-tools/neovim.sh diff --git a/core/tabs/applications-setup/Developer-tools/ngrok-setup.sh b/core/tabs/applications-setup/developer-tools/ngrok.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/ngrok-setup.sh rename to core/tabs/applications-setup/developer-tools/ngrok.sh diff --git a/core/tabs/applications-setup/Developer-tools/sublime-setup.sh b/core/tabs/applications-setup/developer-tools/sublime.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/sublime-setup.sh rename to core/tabs/applications-setup/developer-tools/sublime.sh diff --git a/core/tabs/applications-setup/Developer-tools/vscode-setup.sh b/core/tabs/applications-setup/developer-tools/vscode.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/vscode-setup.sh rename to core/tabs/applications-setup/developer-tools/vscode.sh diff --git a/core/tabs/applications-setup/Developer-tools/vscodium-setup.sh b/core/tabs/applications-setup/developer-tools/vscodium.sh similarity index 100% rename from core/tabs/applications-setup/Developer-tools/vscodium-setup.sh rename to core/tabs/applications-setup/developer-tools/vscodium.sh diff --git a/core/tabs/applications-setup/developer-tools/zed.sh b/core/tabs/applications-setup/developer-tools/zed.sh new file mode 100644 index 00000000..150d6214 --- /dev/null +++ b/core/tabs/applications-setup/developer-tools/zed.sh @@ -0,0 +1,52 @@ +#!/bin/sh -e + +. ../../common-script.sh + +installZed() { + if ! command_exists dev.zed.Zed && ! command_exists zed && ! command_exists zeditor; then + printf "%b\n" "${CYAN}Installing Zed.${RC}" + case "$PACKAGER" in + apk) + "$ESCALATION_TOOL" "$PACKAGER" add zed + ;; + pacman) + "$ESCALATION_TOOL" "$PACKAGER" -S zed + ;; + zypper) + "$ESCALATION_TOOL" "$PACKAGER" addrepo -f https://download.opensuse.org/repositories/editors/openSUSE_Tumbleweed/editors.repo + "$ESCALATION_TOOL" "$PACKAGER" install -y zed + ;; + *) + printf "%b\n" "${YELLOW}No official package found for package manager $PACKAGER. Do you want to install flathub package or from source?${RC}" + printf "%b\n" "1) Flathub package" + printf "%b\n" "2) Source" + printf "%b\n" "3) Exit" + printf "%b" "Choose an option: " + read -r choice + case "$choice" in + 1) + checkFlatpak + flatpak install -y flathub dev.zed.Zed + ;; + 2) + curl -f https://zed.dev/install.sh | sh + ;; + 3) + printf "%b\n" "${GREEN}Exiting.${RC}" + exit 0 + ;; + *) + printf "%b\n" "${RED}Invalid option.${RC}" + exit 1 + ;; + esac + ;; + esac + else + printf "%b\n" "${GREEN}Zed is already installed.${RC}" + fi +} + +checkEnv +clear +installZed diff --git a/core/tabs/applications-setup/dwmtitus-setup.sh b/core/tabs/applications-setup/dwmtitus-setup.sh index be23b9ad..5df2a5d1 100755 --- a/core/tabs/applications-setup/dwmtitus-setup.sh +++ b/core/tabs/applications-setup/dwmtitus-setup.sh @@ -35,8 +35,8 @@ install_nerd_font() { FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip" FONT_INSTALLED=$(fc-list | grep -i "Meslo") - # Check if Meslo Nerd-font is already installed - if [ -n "$FONT_INSTALLED" ]; then + # Replace -n test with standard test + if [ ! -z "$FONT_INSTALLED" ]; then printf "%b\n" "${GREEN}Meslo Nerd-fonts are already installed.${RC}" return 0 fi @@ -192,7 +192,7 @@ setupDisplayManager() { "$ESCALATION_TOOL" "$PACKAGER" install -y xorg-x11-xinit xorg-x11-server-Xorg ;; *) - printf "%b\n" "${RED}Unsupported package manager: "$PACKAGER"${RC}" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac @@ -207,29 +207,37 @@ setupDisplayManager() { done printf "%b\n" "${GREEN}Current display manager: $currentdm${RC}" if [ "$currentdm" = "none" ]; then - printf "%b\n" "${YELLOW}--------------------------${RC}" - printf "%b\n" "${YELLOW}Pick your Display Manager ${RC}" - printf "%b\n" "${YELLOW}1. SDDM ${RC}" - printf "%b\n" "${YELLOW}2. LightDM ${RC}" - printf "%b\n" "${YELLOW}3. GDM ${RC}" - printf "%b\n" "${YELLOW} ${RC}" - printf "%b" "${YELLOW}Please select one: ${RC}" - read -r choice - case "$choice" in - 1) - DM="sddm" - ;; - 2) - DM="lightdm" - ;; - 3) - DM="gdm" - ;; - *) - printf "%b\n" "${RED}Invalid selection! Please choose 1, 2, or 3.${RC}" - exit 1 - ;; - esac + while : ; do + printf "%b\n" "${YELLOW}--------------------------${RC}" + printf "%b\n" "${YELLOW}Pick your Display Manager ${RC}" + printf "%b\n" "${YELLOW}1. SDDM ${RC}" + printf "%b\n" "${YELLOW}2. LightDM ${RC}" + printf "%b\n" "${YELLOW}3. GDM ${RC}" + printf "%b\n" "${YELLOW}4. None ${RC}" + printf "%b" "${YELLOW}Please select one: ${RC}" + read -r choice + case "$choice" in + 1) + DM="sddm" + break + ;; + 2) + DM="lightdm" + break + ;; + 3) + DM="gdm" + break + ;; + 4) + printf "%b\n" "${GREEN}No display manager will be installed${RC}" + return 0 + ;; + *) + printf "%b\n" "${RED}Invalid selection! Please choose 1, 2, 3, or 4.${RC}" + ;; + esac + done case "$PACKAGER" in pacman) "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm "$DM" @@ -244,7 +252,7 @@ setupDisplayManager() { "$ESCALATION_TOOL" "$PACKAGER" install -y "$DM" ;; *) - printf "%b\n" "${RED}Unsupported package manager: "$PACKAGER"${RC}" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac diff --git a/core/tabs/applications-setup/linutil-installer.sh b/core/tabs/applications-setup/linutil-installer.sh index 13776fc3..c5af5045 100755 --- a/core/tabs/applications-setup/linutil-installer.sh +++ b/core/tabs/applications-setup/linutil-installer.sh @@ -53,7 +53,7 @@ installLinutil() { ;; *) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - . $HOME/.cargo/env + . "$HOME/.cargo/env" ;; esac fi diff --git a/core/tabs/applications-setup/linutil-updater.sh b/core/tabs/applications-setup/linutil-updater.sh index 4e399a02..1ccf9090 100755 --- a/core/tabs/applications-setup/linutil-updater.sh +++ b/core/tabs/applications-setup/linutil-updater.sh @@ -17,7 +17,7 @@ updateLinutil() { zypper) "$ESCALATION_TOOL" "$PACKAGER" install -n curl gcc make curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - . $HOME/.cargo/env + . "$HOME/.cargo/env" ;; apk) "$ESCALATION_TOOL" "$PACKAGER" add build-base diff --git a/core/tabs/applications-setup/tab_data.toml b/core/tabs/applications-setup/tab_data.toml index a1a3ea45..62eb71a1 100644 --- a/core/tabs/applications-setup/tab_data.toml +++ b/core/tabs/applications-setup/tab_data.toml @@ -39,6 +39,12 @@ description = "Thunderbird is a free, open-source email client that offers power script = "communication-apps/thunderbird-setup.sh" task_list = "I" +[[data.entries]] +name = "ZapZap" +description = "ZapZap is an open source whatsapp desktop client for Linux users developed by rafatosta." +script = "communication-apps/zapzap-setup.sh" +task_list = "I" + [[data.entries]] name = "Zoom" description = "Zoom is a widely-used video conferencing platform that allows users to host virtual meetings, webinars, and online collaboration with features like screen sharing and recording." @@ -51,60 +57,55 @@ name = "Developer Tools" [[data.entries]] name = "Github Desktop" description = "GitHub Desktop is a user-friendly application that simplifies the process of managing Git repositories and interacting with GitHub, providing a graphical interface for tasks like committing, branching, and syncing changes." -script = "Developer-tools/githubdesktop-setup.sh" +script = "developer-tools/githubdesktop.sh" task_list = "I" [[data.entries]] name = "JetBrains Toolbox" description = "JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products." -script = "Developer-tools/jetbrains-toolbox.sh" +script = "developer-tools/jetbrains-toolbox.sh" task_list = "I" [[data.entries]] name = "Meld" description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects." -script = "Developer-tools/meld-setup.sh" +script = "developer-tools/meld.sh" task_list = "I FI" [[data.entries]] name = "Neovim" description = "Neovim is a refactor, and sometimes redactor, in the tradition of Vim.\nIt is not a rewrite but a continuation and extension of Vim.\nThis command configures neovim from CTT's neovim configuration.\nhttps://github.com/ChrisTitusTech/neovim" -script = "Developer-tools/neovim-setup.sh" +script = "developer-tools/neovim.sh" task_list = "I FM" [[data.entries]] name = "Ngrok" description = "Ngrok is a tool that creates secure, temporary tunnels to expose local servers to the internet for testing and development." -script = "Developer-tools/ngrok-setup.sh" +script = "developer-tools/ngrok.sh" task_list = "I" [[data.entries]] name = "Sublime Text" description = "Sublime Text is a fast, lightweight, and customizable text editor known for its simplicity, powerful features, and wide range of plugins for various programming languages." -script = "Developer-tools/sublime-setup.sh" +script = "developer-tools/sublime.sh" task_list = "I" -[[data.entries]] -name = "ZapZap" -description = "ZapZap is an open source whatsapp desktop client for Linux users developed by rafatosta." -script = "communication-apps/zapzap-setup.sh" -task_list = "I" - -[[data.entries]] -name = "Zoom" -description = "Zoom is a widely-used video conferencing platform that allows users to host virtual meetings, webinars, and online collaboration with features like screen sharing and recording." -script = "communication-apps/zoom-setup.sh" - [[data.entries]] name = "VS Code" description = "Visual Studio Code (VS Code) is a lightweight, open-source code editor with built-in support for debugging, version control, and extensions for various programming languages and frameworks." -script = "Developer-tools/vscode-setup.sh" +script = "developer-tools/vscode.sh" task_list = "I" [[data.entries]] name = "VS Codium" description = "VSCodium is a free, open-source version of Visual Studio Code (VS Code) that removes Microsoft-specific telemetry and branding." -script = "Developer-tools/vscodium-setup.sh" +script = "developer-tools/vscodium.sh" +task_list = "I" + +[[data.entries]] +name = "Zed" +description = "Zed is a next-generation code editor written in rust, designed for high-performance collaboration with humans and AI." +script = "developer-tools/zed.sh" task_list = "I" [[data]] @@ -191,6 +192,12 @@ description = "Mozilla Firefox is a free and open-source web browser developed b script = "browsers/firefox.sh" task_list = "I" +[[data.entries]] +name = "Zen Browser" +description = "Zen Browser is a privacy-focused web browser designed for enhanced security and a seamless browsing experience." +script = "browsers/zen-browser.sh" +task_list = "I" + [[data.entries]] name = "Thorium" description = "Thorium is a Chromium-based browser focused on privacy and performance." @@ -335,4 +342,4 @@ values = ["wayland", "Wayland"] name = "ZSH Prompt" description = "The Z shell is a Unix shell that can be used as an interactive login shell and as a command interpreter for shell scripting. Zsh is an extended Bourne shell with many improvements, including some features of Bash, ksh, and tcsh. This command installs ZSH prompt and provides basic configuration." script = "zsh-setup.sh" -task_list = "I FM" \ No newline at end of file +task_list = "I FM" diff --git a/core/tabs/system-setup/arch/hyprland-kool.sh b/core/tabs/system-setup/arch/hyprland-kool.sh new file mode 100644 index 00000000..7c85f857 --- /dev/null +++ b/core/tabs/system-setup/arch/hyprland-kool.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +. ../../common-script.sh + +printf "%b\n" "${YELLOW}Starting Hyprland JaKooLit installation${RC}" + +if ! pacman -Q base-devel >/dev/null 2>&1; then + printf "%b\n" "${YELLOW}Installing base-devel...${RC}" + "$ESCALATION_TOOL" pacman -S --noconfirm base-devel +fi + +git clone --depth=1 https://github.com/JaKooLit/Arch-Hyprland.git "$HOME/Arch-Hyprland" || { printf "%b\n" "${RED}Failed to clone Jakoolits Arch-Hyprland repo${RC}"; exit 1; } +cd "$HOME/Arch-Hyprland" || { printf "%b\n" "${RED}Failed to navigate to Arch-Hyprland directory${RC}"; exit 1; } +chmod +x install.sh +./install.sh diff --git a/core/tabs/system-setup/compile-setup.sh b/core/tabs/system-setup/compile-setup.sh index bb6bb44a..746d1d5f 100755 --- a/core/tabs/system-setup/compile-setup.sh +++ b/core/tabs/system-setup/compile-setup.sh @@ -15,33 +15,33 @@ installDepend() { else printf "%b\n" "${GREEN}Multilib is already enabled.${RC}" fi - "$AUR_HELPER" -S --needed --noconfirm $DEPENDENCIES + "$AUR_HELPER" -S --needed --noconfirm "$DEPENDENCIES" ;; apt-get|nala) COMPILEDEPS='build-essential' "$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" dpkg --add-architecture i386 "$ESCALATION_TOOL" "$PACKAGER" update - "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" "$COMPILEDEPS" ;; dnf) COMPILEDEPS='@development-tools' "$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" "$PACKAGER" config-manager --set-enabled powertools - "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" "$COMPILEDEPS" "$ESCALATION_TOOL" "$PACKAGER" install -y glibc-devel.i686 libgcc.i686 ;; zypper) COMPILEDEPS='patterns-devel-base-devel_basis' "$ESCALATION_TOOL" "$PACKAGER" refresh - "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install $DEPENDENCIES $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install "$DEPENDENCIES" "$COMPILEDEPS" "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install libgcc_s1-gcc7-32bit glibc-devel-32bit ;; apk) "$ESCALATION_TOOL" "$PACKAGER" add build-base multitail tar tree trash-cli unzip cmake jq ;; *) - "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" ;; esac } @@ -49,4 +49,4 @@ installDepend() { checkEnv checkAURHelper checkEscalationTool -installDepend \ No newline at end of file +installDepend diff --git a/core/tabs/system-setup/debian/hyprland-kool-deb.sh b/core/tabs/system-setup/debian/hyprland-kool-deb.sh new file mode 100644 index 00000000..58229792 --- /dev/null +++ b/core/tabs/system-setup/debian/hyprland-kool-deb.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +. ../../common-script.sh + +printf "%b\n" "${YELLOW}Starting Hyprland JaKooLit installation${RC}" +git clone --depth=1 https://github.com/JaKooLit/Debian-Hyprland.git "$HOME/Debian-Hyprland" || { printf "%b\n" "${RED}Failed to clone Jakoolits Debian-Hyprland repo${RC}"; exit 1; } +cd "$HOME/Debian-Hyprland" || { printf "%b\n" "${RED}Failed to navigate to Debian-Hyprland directory${RC}"; exit 1; } +chmod +x install.sh +./install.sh \ No newline at end of file diff --git a/core/tabs/system-setup/fedora/hyprland-kool-fed.sh b/core/tabs/system-setup/fedora/hyprland-kool-fed.sh new file mode 100644 index 00000000..3a7ebd92 --- /dev/null +++ b/core/tabs/system-setup/fedora/hyprland-kool-fed.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +. ../../common-script.sh + +printf "%b\n" "${YELLOW}Starting Hyprland JaKooLit installation${RC}" + +git clone --depth=1 https://github.com/JaKooLit/Fedora-Hyprland.git "$HOME/Fedora-Hyprland" || { printf "%b\n" "${RED}Failed to clone Jakoolits Fedora-Hyprland repo${RC}"; exit 1; } +cd "$HOME/Fedora-Hyprland" || { printf "%b\n" "${RED}Failed to navigate to Fedora-Hyprland directory${RC}"; exit 1; } +chmod +x install.sh +./install.sh \ No newline at end of file diff --git a/core/tabs/system-setup/system-cleanup.sh b/core/tabs/system-setup/system-cleanup.sh index dccbcf3a..70cfd5b6 100755 --- a/core/tabs/system-setup/system-cleanup.sh +++ b/core/tabs/system-setup/system-cleanup.sh @@ -22,7 +22,7 @@ cleanup_system() { ;; pacman) "$ESCALATION_TOOL" "$PACKAGER" -Sc --noconfirm - "$ESCALATION_TOOL" "$PACKAGER" -Rns $(pacman -Qtdq) --noconfirm > /dev/null || true + "$ESCALATION_TOOL" "$PACKAGER" -Rns "$(pacman -Qtdq)" --noconfirm > /dev/null || true ;; apk) "$ESCALATION_TOOL" "$PACKAGER" cache clean diff --git a/core/tabs/system-setup/tab_data.toml b/core/tabs/system-setup/tab_data.toml index 9f80eec0..51aa4745 100644 --- a/core/tabs/system-setup/tab_data.toml +++ b/core/tabs/system-setup/tab_data.toml @@ -16,15 +16,22 @@ task_list = "SI D" multi_select = false [[data.entries]] -name ="Linux Neptune for SteamDeck" +name = "Hyprland JaKooLit" +description = "Install JaKooLit's Hyprland configuration" +script = "arch/hyprland-kool.sh" +task_list = "I MP" +multi_select = false + +[[data.entries]] +name = "Linux Neptune for SteamDeck" description = "Valve's fork of Linux Kernel for the SteamDeck" script = "arch/linux-neptune.sh" task_list = "I PFM K" [[data.entries.preconditions]] matches = true -data = { file = "/sys/devices/virtual/dmi/id/board_vendor" } -values = [ "Valve" ] +data = { containing_file = "/sys/devices/virtual/dmi/id/board_vendor" } +values = ["Valve"] [[data.entries]] name = "Nvidia Drivers && Hardware Acceleration" @@ -50,6 +57,20 @@ description = "Yet Another Yogurt - An AUR Helper Written in Go. To know more ab script = "arch/yay-setup.sh" task_list = "I" +[[data]] +name = "Debian" + +[[data.preconditions]] +matches = true +data = { containing_file = "/etc/os-release" } +values = ["ID=debian"] + +[[data.entries]] +name = "Hyprland JaKooLit" +description = "Install JaKooLit's Hyprland configuration" +script = "debian/hyprland-kool-deb.sh" +task_list = "I MP" + [[data]] name = "Fedora" @@ -64,6 +85,12 @@ description = "Optimizes DNF for parallel downloads" script = "fedora/configure-dnf.sh" task_list = "PFM" +[[data.entries]] +name = "Hyprland JaKooLit" +description = "Install JaKooLit's Hyprland configuration" +script = "fedora/hyprland-kool-fed.sh" +task_list = "I MP" + [[data.entries]] name = "Multimedia Codecs" description = "This script is designed to install multimedia codecs, and to ensure RPM Fusion repositories are installed." @@ -103,7 +130,26 @@ task_list = "I PFM SS" [[data.preconditions]] matches = true data = "command_exists" -values = [ "btrfs" ] +values = ["btrfs"] + +[[data]] +name = "Ubuntu" + +[[data.preconditions]] +matches = true +data = { containing_file = "/etc/os-release" } +values = ["ID=ubuntu"] + +[[data.entries]] +name = "Hyprland JaKooLit" +description = "Install JaKooLit's Hyprland configuration" +script = "ubuntu/hyprland-kool-ubuntu24.sh" +task_list = "I MP" + +[[data.preconditions]] +matches = true +data = { containing_file = "/etc/os-release" } +values = ['VERSION_ID="24.04"'] [[data]] name = "Build Prerequisites" diff --git a/core/tabs/system-setup/ubuntu/hyprland-kool-ubuntu24.sh b/core/tabs/system-setup/ubuntu/hyprland-kool-ubuntu24.sh new file mode 100644 index 00000000..bd12ef76 --- /dev/null +++ b/core/tabs/system-setup/ubuntu/hyprland-kool-ubuntu24.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +. ../../common-script.sh + +printf "%b\n" "${YELLOW}Starting Hyprland JaKooLit installation${RC}" + +git clone -b 24.04 --depth=1 https://github.com/JaKooLit/Ubuntu-Hyprland.git "$HOME/Ubuntu-Hyprland-24.04" || { printf "%b\n" "${RED}Failed to clone Jakoolits Ubuntu-Hyprland repo${RC}"; exit 1; } +cd "$HOME/Ubuntu-Hyprland-24.04" || { printf "%b\n" "${RED}Failed to navigate to Ubuntu-Hyprland-24.04 directory${RC}"; exit 1; } +chmod +x install.sh +./install.sh \ No newline at end of file diff --git a/core/tabs/utils/bluetooth-control.sh b/core/tabs/utils/bluetooth-control.sh index 6bfe266b..f18a32a1 100644 --- a/core/tabs/utils/bluetooth-control.sh +++ b/core/tabs/utils/bluetooth-control.sh @@ -65,12 +65,11 @@ scan_devices() { printf "%b\n" "$devices" fi printf "%b" "Press any key to return to the main menu..." - read -r dummy + read -r _ } # Function to prompt for MAC address using numbers prompt_for_mac() { - action=$1 command=$2 prompt_msg=$3 success_msg=$4 @@ -82,14 +81,14 @@ prompt_for_mac() { if [ -z "$devices" ]; then printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}" printf "%b" "Press any key to return to the main menu..." - read -r dummy + read -r _ return fi # Display devices with numbers device_list=$(echo "$devices" | tr '\n' '\n') i=1 - echo "$device_list" | while IFS= read -r device; do + for device in $device_list; do printf "%d. %s\n" "$i" "$device" i=$((i + 1)) done @@ -102,12 +101,12 @@ prompt_for_mac() { device=$(echo "$device_list" | sed -n "${choice}p") mac=$(echo "$device" | awk '{print $2}') if bluetoothctl info "$mac" > /dev/null 2>&1; then - bluetoothctl "$command" "$mac" && { + if bluetoothctl "$command" "$mac"; then printf "%b\n" "${GREEN}$success_msg${RC}" break - } || { + else printf "%b\n" "${RED}$failure_msg${RC}" - } + fi else printf "%b\n" "${RED}Invalid MAC address. Please try again.${RC}" fi @@ -118,7 +117,7 @@ prompt_for_mac() { fi done printf "%b" "Press any key to return to the main menu..." - read -r dummy + read -r _ } # Function to pair with a device diff --git a/core/tabs/utils/encrypt_decrypt_tool.sh b/core/tabs/utils/encrypt_decrypt_tool.sh index 40e006a2..80e8bbc8 100644 --- a/core/tabs/utils/encrypt_decrypt_tool.sh +++ b/core/tabs/utils/encrypt_decrypt_tool.sh @@ -62,11 +62,11 @@ encrypt_file() { if [ -d "$INPUT_PATH" ]; then # Encrypt each file in the directory find "$INPUT_PATH" -type f | while read -r FILE; do - REL_PATH="${FILE#$INPUT_PATH/}" + REL_PATH="${FILE#"$INPUT_PATH"/}" OUTPUT_FILE="$OUTPUT_PATH/$REL_PATH.enc" mkdir -p "$(dirname "$OUTPUT_FILE")" - openssl enc -aes-256-cbc -salt -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD" - if [ $? -eq 0 ]; then + + if [ "$(openssl enc -aes-256-cbc -salt -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD")" -eq 0 ]; then printf "%b\n" "Encrypted: $OUTPUT_FILE" else printf "%b\n" "Failed to encrypt: $FILE" @@ -79,8 +79,8 @@ encrypt_file() { return fi mkdir -p "$(dirname "$OUTPUT_PATH")" - openssl enc -aes-256-cbc -salt -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD" - if [ $? -eq 0 ]; then + + if [ "$(openssl enc -aes-256-cbc -salt -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD")" -eq 0 ]; then printf "%b\n" "Encrypted: $OUTPUT_PATH" else printf "%b\n" "Failed to encrypt: $INPUT_PATH" @@ -107,11 +107,11 @@ decrypt_file() { if [ -d "$INPUT_PATH" ]; then # Decrypt each file in the directory find "$INPUT_PATH" -type f -name '*.enc' | while read -r FILE; do - REL_PATH="${FILE#$INPUT_PATH/}" + REL_PATH="${FILE#"$INPUT_PATH"/}" OUTPUT_FILE="$OUTPUT_PATH/${REL_PATH%.enc}" mkdir -p "$(dirname "$OUTPUT_FILE")" - openssl enc -aes-256-cbc -d -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD" - if [ $? -eq 0 ]; then + + if [ "$(openssl enc -aes-256-cbc -d -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD")" -eq 0 ]; then printf "%b\n" "Decrypted: $OUTPUT_FILE" else printf "%b\n" "Failed to decrypt: $FILE" @@ -124,8 +124,8 @@ decrypt_file() { return fi mkdir -p "$(dirname "$OUTPUT_PATH")" - openssl enc -aes-256-cbc -d -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD" - if [ $? -eq 0 ]; then + + if [ "$(openssl enc -aes-256-cbc -d -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD")" -eq 0 ]; then printf "%b\n" "Decrypted: $OUTPUT_PATH" else printf "%b\n" "Failed to decrypt: $INPUT_PATH" @@ -148,10 +148,10 @@ main(){ esac printf "%b\n" "Press [Enter] to continue..." - read -r dummy + read -r _ done } checkEnv checkEscalationTool -main \ No newline at end of file +main diff --git a/core/tabs/utils/monitor-control/set_brightness.sh b/core/tabs/utils/monitor-control/set_brightness.sh index 0b7a2a83..ce77e35b 100755 --- a/core/tabs/utils/monitor-control/set_brightness.sh +++ b/core/tabs/utils/monitor-control/set_brightness.sh @@ -29,7 +29,7 @@ adjust_monitor_brightness() { if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" printf "Press [Enter] to continue..." - read -r dummy + read -r _ continue fi @@ -37,7 +37,7 @@ adjust_monitor_brightness() { if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$monitor_count" ]; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" printf "Press [Enter] to continue..." - read -r dummy + read -r _ continue fi diff --git a/core/tabs/utils/monitor-control/set_resolutions.sh b/core/tabs/utils/monitor-control/set_resolutions.sh index 84aea4d5..9dbb7eaf 100755 --- a/core/tabs/utils/monitor-control/set_resolutions.sh +++ b/core/tabs/utils/monitor-control/set_resolutions.sh @@ -33,7 +33,7 @@ set_resolutions() { if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" printf "%b\n" "Press [Enter] to continue..." - read -r dummy + read -r _ continue fi diff --git a/core/tabs/utils/ollama.sh b/core/tabs/utils/ollama.sh index 5552c4f9..47f99539 100644 --- a/core/tabs/utils/ollama.sh +++ b/core/tabs/utils/ollama.sh @@ -85,7 +85,8 @@ run_model() { printf "%b\n" "${installed_models}" printf "%b\n" "${YELLOW}Custom Models${RC}" - custom_models=$(ollama list | grep 'custom-model-prefix') + custom_models=$(ollama list | grep 'custom-model-prefix') + printf "%b\n" "${custom_models}" printf "%b" "Select a model to run: " printf "%b" "Enter the number corresponding to the model or enter the name of a custom model: " @@ -195,7 +196,7 @@ menu() { esac printf "%b\n" "${YELLOW}Press Enter to continue...${RC}" - read -r dummy + read -r _ done } diff --git a/core/tabs/utils/samba-ssh-setup.sh b/core/tabs/utils/samba-ssh-setup.sh index aa0dc30e..2de1bf7d 100755 --- a/core/tabs/utils/samba-ssh-setup.sh +++ b/core/tabs/utils/samba-ssh-setup.sh @@ -173,7 +173,7 @@ setup_ssh_samba(){ printf "%b\n" "5. Exit" printf "%b" "Enter your choice (1-5): " - read CHOICE + read -r CHOICE case "$CHOICE" in 1) @@ -205,4 +205,4 @@ setup_ssh_samba(){ checkEnv checkEscalationTool -setup_ssh_samba \ No newline at end of file +setup_ssh_samba diff --git a/core/tabs/utils/service-control.sh b/core/tabs/utils/service-control.sh index 903fa826..ea51089f 100644 --- a/core/tabs/utils/service-control.sh +++ b/core/tabs/utils/service-control.sh @@ -267,10 +267,10 @@ main() { esac printf "%b\n" "Press [Enter] to continue..." - read -r dummy + read -r _ done } checkEnv checkEscalationTool -main \ No newline at end of file +main diff --git a/core/tabs/utils/timeshift.sh b/core/tabs/utils/timeshift.sh index b38483e5..3b932c25 100644 --- a/core/tabs/utils/timeshift.sh +++ b/core/tabs/utils/timeshift.sh @@ -67,6 +67,7 @@ create_snapshot() { "$ESCALATION_TOOL" timeshift --create --comments "$COMMENT" --tags "$TAG" fi + # shellcheck disable=SC2181 if [ $? -eq 0 ]; then printf "%b\n" "${GREEN}Snapshot created successfully.${RC}" else @@ -93,6 +94,7 @@ restore_snapshot() { "$ESCALATION_TOOL" timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes fi + # shellcheck disable=SC2181 if [ $? -eq 0 ]; then printf "%b\n" "${GREEN}Snapshot restored successfully.${RC}" else @@ -110,6 +112,7 @@ delete_snapshot() { printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}" "$ESCALATION_TOOL" timeshift --delete --snapshot "$SNAPSHOT" --yes + # shellcheck disable=SC2181 if [ $? -eq 0 ]; then printf "%b\n" "${GREEN}Snapshot deleted successfully.${RC}" else @@ -126,6 +129,7 @@ delete_all_snapshots() { if [ "$CONFIRMATION" = "y" ] || [ "$CONFIRMATION" = "Y" ]; then printf "%b\n" "${CYAN}Deleting all snapshots...${RC}" "$ESCALATION_TOOL" timeshift --delete-all --yes + # shellcheck disable=SC2181 if [ $? -eq 0 ]; then printf "%b\n" "${GREEN}All snapshots deleted successfully.${RC}" else @@ -153,7 +157,7 @@ main_menu() { *) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;; esac printf "%b\n" "${CYAN}Press Enter to continue...${RC}" - read -r dummy + read -r _ done } diff --git a/core/tabs/utils/user-account-manager/add_to_group.sh b/core/tabs/utils/user-account-manager/add_to_group.sh index 665cf72a..07720505 100755 --- a/core/tabs/utils/user-account-manager/add_to_group.sh +++ b/core/tabs/utils/user-account-manager/add_to_group.sh @@ -33,7 +33,7 @@ addToGroup() { groups_to_add=$(echo "$groups" | tr ' ' ',') printf "%b" "${YELLOW}Are you sure you want to add user $username to $groups_to_add? [Y/n]: ${RC}" - read -r confirm + read -r _ confirmAction || exit 1 "$ESCALATION_TOOL" usermod -aG "$groups_to_add" "$username" @@ -44,4 +44,4 @@ addToGroup() { checkEnv checkEscalationTool checkGroups -addToGroup \ No newline at end of file +addToGroup diff --git a/core/tabs/utils/user-account-manager/change_password.sh b/core/tabs/utils/user-account-manager/change_password.sh index a909a5b2..20706bd3 100755 --- a/core/tabs/utils/user-account-manager/change_password.sh +++ b/core/tabs/utils/user-account-manager/change_password.sh @@ -17,7 +17,7 @@ changePassword() { read -r password printf "%b" "${YELLOW}Are you sure you want to change password for ""$username""? [Y/n]: ${RC}" - read -r confirm + read -r _ confirmAction || exit 1 echo "$username:$password" | "$ESCALATION_TOOL" chpasswd @@ -30,4 +30,4 @@ changePassword() { checkEnv checkEscalationTool -changePassword \ No newline at end of file +changePassword diff --git a/core/tabs/utils/user-account-manager/delete_user.sh b/core/tabs/utils/user-account-manager/delete_user.sh index aee9482e..f4795872 100755 --- a/core/tabs/utils/user-account-manager/delete_user.sh +++ b/core/tabs/utils/user-account-manager/delete_user.sh @@ -14,7 +14,7 @@ deleteUser() { if id "$username" > /dev/null 2>&1; then printf "%b" "${YELLOW}Are you sure you want to delete user ""$username""? [Y/n]: ${RC}" - read -r confirm + read -r _ confirmAction || exit 1 $ESCALATION_TOOL userdel --remove "$username" 2>/dev/null @@ -27,4 +27,4 @@ deleteUser() { checkEnv checkEscalationTool -deleteUser \ No newline at end of file +deleteUser diff --git a/core/tabs/utils/user-account-manager/remove_from_group.sh b/core/tabs/utils/user-account-manager/remove_from_group.sh index 23935b5e..1c07b006 100755 --- a/core/tabs/utils/user-account-manager/remove_from_group.sh +++ b/core/tabs/utils/user-account-manager/remove_from_group.sh @@ -34,14 +34,14 @@ removeFromGroup() { groups_to_remove=$(echo "$groups" | tr ' ' ',') printf "%b" "${YELLOW}Are you sure you want to remove user $username from $groups_to_remove? [Y/n]: ${RC}" - read -r confirm + read -r _ confirmAction || exit 1 - $ESCALATION_TOOL usermod -rG $groups_to_remove "$username" + $ESCALATION_TOOL usermod -rG "$groups_to_remove" "$username" printf "%b\n" "${GREEN}User successfully removed from $groups_to_remove${RC}" } checkEnv checkEscalationTool -removeFromGroup \ No newline at end of file +removeFromGroup diff --git a/core/tabs/utils/utility_functions.sh b/core/tabs/utils/utility_functions.sh index 09f33c60..acadee68 100755 --- a/core/tabs/utils/utility_functions.sh +++ b/core/tabs/utils/utility_functions.sh @@ -30,6 +30,7 @@ execute_command() { command="$1" printf "Executing: %s\n" "$command" eval "$command" 2>&1 | tee /tmp/xrandr.log | tail -n 20 + # shellcheck disable=SC2181 if [ $? -ne 0 ]; then printf "%b\n" "${RED}An error occurred while executing the command. Check /tmp/xrandr.log for details.${RC}" fi diff --git a/core/tabs/utils/wifi-control.sh b/core/tabs/utils/wifi-control.sh index d4ed2d10..0a8f0515 100755 --- a/core/tabs/utils/wifi-control.sh +++ b/core/tabs/utils/wifi-control.sh @@ -75,33 +75,33 @@ scan_networks() { echo "$networks" | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}' fi printf "%b\n" "Press any key to return to the main menu..." - read -r dummy + read -r _ } # Function to turn WiFi on wifi_on() { clear printf "%b\n" "${YELLOW}Turning WiFi on...${RC}" - nmcli radio wifi on && { + if "$(nmcli radio wifi on)"; then printf "%b\n" "${GREEN}WiFi is now turned on.${RC}" - } || { + else printf "%b\n" "${RED}Failed to turn on WiFi.${RC}" - } + fi printf "%b\n" "Press any key to return to the main menu..." - read -r dummy + read -r _ } # Function to turn WiFi off wifi_off() { clear printf "%b\n" "${YELLOW}Turning WiFi off...${RC}" - nmcli radio wifi off && { + if "$(nmcli radio wifi off)"; then printf "%b\n" "${GREEN}WiFi is now turned off.${RC}" - } || { + else printf "%b\n" "${RED}Failed to turn off WiFi.${RC}" - } + fi printf "%b\n" "Press any key to return to the main menu..." - read -r dummy + read -r _ } # Function to prompt for WiFi network selection @@ -118,7 +118,7 @@ prompt_for_network() { if [ -z "$networks" ]; then printf "%b\n" "${RED}No networks available. Please scan for networks first.${RC}" printf "%b\n" "Press any key to return to the main menu..." - read -r dummy + read -r _ rm -f "$temp_file" return fi @@ -142,18 +142,18 @@ prompt_for_network() { printf "%b" "Enter password for SSID: " "$ssid" read -r password printf "\n" - nmcli dev wifi connect "$ssid" password "$password" && { + if "$(nmcli dev wifi connect "$ssid" password "$password")"; then printf "%b\n" "${GREEN}$success_msg${RC}" - } || { + else printf "%b\n" "${RED}$failure_msg${RC}" - } + fi fi else printf "%b\n" "${RED}Invalid choice. Please try again.${RC}" fi printf "%b\n" "Press any key to return to the selection menu..." - read -r dummy + read -r _ done rm -f "$temp_file" @@ -178,4 +178,4 @@ remove_network() { checkEnv checkEscalationTool setupNetworkManager -main_menu \ No newline at end of file +main_menu diff --git a/man/linutil.1 b/man/linutil.1 index c66c0019..af2163d5 100644 --- a/man/linutil.1 +++ b/man/linutil.1 @@ -71,7 +71,7 @@ Please consider submitting feedback if you do. https://github.com/ChrisTitusTech/linutil/issues .SH COPYRIGHT -Copyright (c) 2024 Chris Titus. +Copyright (c) 2025 Chris Titus. .br MIT License. https://opensource.org/license/MIT diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 00000000..d9ba5fdb --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +imports_granularity = "Crate" \ No newline at end of file diff --git a/startdev.sh b/startdev.sh index 8e27bbf0..7e6b0bb2 100755 --- a/startdev.sh +++ b/startdev.sh @@ -8,8 +8,9 @@ RED='\033[0;31m' # Function to fetch the latest release tag from the GitHub API get_latest_release() { latest_release=$(curl -s https://api.github.com/repos/ChrisTitusTech/linutil/releases | - grep -oP '"tag_name": "\K[^"]*' | - head -n 1) + grep "tag_name" | + head -n 1 | + sed -E 's/.*"tag_name": "([^"]+)".*/\1/') if [ -z "$latest_release" ]; then printf "%b\n" "Error fetching release data" >&2 return 1 diff --git a/tui/Cargo.toml b/tui/Cargo.toml index afcf9ed1..aaa3ed54 100644 --- a/tui/Cargo.toml +++ b/tui/Cargo.toml @@ -14,7 +14,7 @@ default = ["tips"] tips = ["rand"] [dependencies] -clap = { version = "4.5.20", features = ["derive", "std"], default-features = false } +clap = { version = "4.5.20", features = ["derive", "std", "help", "usage"], default-features = false } oneshot = { version = "0.1.8", features = ["std"], default-features = false } portable-pty = "0.8.1" ratatui = { version = "0.29.0", features = ["crossterm"], default-features = false } @@ -22,7 +22,7 @@ tui-term = { version = "0.2.0", default-features = false } time = { version = "0.3.36", features = ["formatting", "local-offset", "macros"], default-features = false } unicode-width = { version = "0.2.0", default-features = false } rand = { version = "0.8.5", optional = true } -linutil_core = { version = "24.10.31", path = "../core" } +linutil_core = { version = "25.2.13", path = "../core" } tree-sitter-highlight = "0.24.4" tree-sitter-bash = "0.23.3" nix = { version = "0.29.0", features = [ "user" ] } diff --git a/tui/src/cli.rs b/tui/src/cli.rs new file mode 100644 index 00000000..564b2d68 --- /dev/null +++ b/tui/src/cli.rs @@ -0,0 +1,35 @@ +use crate::theme::Theme; +use clap::Parser; +use std::path::PathBuf; + +#[derive(Debug, Parser, Clone)] +pub struct Args { + /// Path to the configuration file + #[arg(short, long)] + pub config: Option, + + /// Set the theme to use in the application + #[arg(short, long, value_enum)] + #[arg(default_value_t = Theme::Default)] + pub theme: Theme, + + /// Skip confirmation prompt before executing commands + #[arg(short = 'y', long)] + pub skip_confirmation: bool, + + /// Show all available options, disregarding compatibility checks (UNSAFE) + #[arg(short = 'u', long)] + pub override_validation: bool, + + /// Bypass the terminal size limit + #[arg(short = 's', long)] + pub size_bypass: bool, + + /// Enable mouse interaction + #[arg(short = 'm', long)] + pub mouse: bool, + + /// Bypass root user check + #[arg(short = 'r', long)] + pub bypass_root: bool, +} diff --git a/tui/src/confirmation.rs b/tui/src/confirmation.rs index 3a4e9578..ea465fcc 100644 --- a/tui/src/confirmation.rs +++ b/tui/src/confirmation.rs @@ -1,4 +1,4 @@ -use crate::{float::FloatContent, hint::Shortcut, theme}; +use crate::{float::FloatContent, hint::Shortcut, shortcuts, theme}; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, layout::Alignment, @@ -135,13 +135,13 @@ impl FloatContent for ConfirmPrompt { fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) { ( "Confirmation prompt", - Box::new([ - Shortcut::new("Continue", ["Y", "y"]), - Shortcut::new("Abort", ["N", "n", "q", "Esc"]), - Shortcut::new("Scroll up", ["k", "Up"]), - Shortcut::new("Scroll down", ["j", "Down"]), - Shortcut::new("Close linutil", ["CTRL-c"]), - ]), + shortcuts!( + ("Continue", ["Y", "y"]), + ("Abort", ["N", "n", "q", "Esc"]), + ("Scroll up", ["k", "Up"]), + ("Scroll down", ["j", "Down"]), + ("Close linutil", ["CTRL-c"]), + ), ) } } diff --git a/tui/src/floating_text.rs b/tui/src/floating_text.rs index c2077de5..ee5321ea 100644 --- a/tui/src/floating_text.rs +++ b/tui/src/floating_text.rs @@ -1,4 +1,4 @@ -use crate::{float::FloatContent, hint::Shortcut, theme::Theme}; +use crate::{float::FloatContent, hint::Shortcut, shortcuts, theme::Theme}; use linutil_core::Command; use ratatui::{ crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, @@ -171,7 +171,7 @@ impl<'a> FloatingText<'a> { } } -impl<'a> FloatContent for FloatingText<'a> { +impl FloatContent for FloatingText<'_> { fn draw(&mut self, frame: &mut Frame, area: Rect, _theme: &Theme) { let block = Block::default() .borders(Borders::ALL) @@ -228,13 +228,13 @@ impl<'a> FloatContent for FloatingText<'a> { fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) { ( &self.mode_title, - Box::new([ - Shortcut::new("Scroll down", ["j", "Down"]), - Shortcut::new("Scroll up", ["k", "Up"]), - Shortcut::new("Scroll left", ["h", "Left"]), - Shortcut::new("Scroll right", ["l", "Right"]), - Shortcut::new("Close window", ["Enter", "p", "q", "d", "g"]), - ]), + shortcuts!( + ("Scroll down", ["j", "Down"]), + ("Scroll up", ["k", "Up"]), + ("Scroll left", ["h", "Left"]), + ("Scroll right", ["l", "Right"]), + ("Close window", ["Enter", "p", "q", "d", "g"]) + ), ) } } diff --git a/tui/src/hint.rs b/tui/src/hint.rs index 0f77f7a5..eda009a6 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -36,7 +36,7 @@ pub fn create_shortcut_list( .unwrap_or(0); let columns = (render_width as usize / (max_shortcut_width + 4)).max(1); - let rows = (shortcut_spans.len() + columns - 1) / columns; + let rows = shortcut_spans.len().div_ceil(columns); let mut lines: Vec> = Vec::with_capacity(rows); @@ -78,3 +78,14 @@ impl Shortcut { .collect() } } + +#[macro_export] +macro_rules! shortcuts { + ($(($name:literal,[$($key:literal),+ $(,)?])),* $(,)?) => { + vec![ + $( + Shortcut::new($name, [$($key),*]) + ),* + ].into_boxed_slice() + }; +} diff --git a/tui/src/main.rs b/tui/src/main.rs index ee0c3235..11ace649 100644 --- a/tui/src/main.rs +++ b/tui/src/main.rs @@ -1,3 +1,4 @@ +mod cli; mod confirmation; mod filter; mod float; @@ -5,13 +6,13 @@ mod floating_text; mod hint; mod root; mod running_command; -pub mod state; +mod state; mod theme; #[cfg(feature = "tips")] mod tips; -use crate::theme::Theme; +use crate::cli::Args; use clap::Parser; use ratatui::{ backend::CrosstermBackend, @@ -26,40 +27,17 @@ use ratatui::{ use state::AppState; use std::{ io::{stdout, Result, Stdout}, - path::PathBuf, time::Duration, }; -// Linux utility toolbox -#[derive(Debug, Parser)] -pub struct Args { - #[arg(short, long, help = "Path to the configuration file")] - config: Option, - #[arg(short, long, value_enum)] - #[arg(default_value_t = Theme::Default)] - #[arg(help = "Set the theme to use in the application")] - theme: Theme, - #[arg( - short = 'y', - long, - help = "Skip confirmation prompt before executing commands" - )] - skip_confirmation: bool, - #[arg(long, default_value_t = false)] - #[clap(help = "Show all available options, disregarding compatibility checks (UNSAFE)")] - override_validation: bool, - #[arg(long, default_value_t = false)] - #[clap(help = "Bypass the terminal size limit")] - size_bypass: bool, -} - fn main() -> Result<()> { let args = Args::parse(); - - let mut state = AppState::new(args); + let mut state = AppState::new(args.clone()); stdout().execute(EnterAlternateScreen)?; - stdout().execute(EnableMouseCapture)?; + if args.mouse { + stdout().execute(EnableMouseCapture)?; + } enable_raw_mode()?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; @@ -70,7 +48,9 @@ fn main() -> Result<()> { // restore terminal disable_raw_mode()?; terminal.backend_mut().execute(LeaveAlternateScreen)?; - terminal.backend_mut().execute(DisableMouseCapture)?; + if args.mouse { + terminal.backend_mut().execute(DisableMouseCapture)?; + } terminal.backend_mut().execute(ResetColor)?; terminal.show_cursor()?; diff --git a/tui/src/root.rs b/tui/src/root.rs index 46432d06..23468ef2 100644 --- a/tui/src/root.rs +++ b/tui/src/root.rs @@ -8,8 +8,12 @@ This means you have full system access and commands can potentially damage your Please proceed with caution and make sure you understand what each script does before executing it."; #[cfg(unix)] -pub fn check_root_status<'a>() -> Option> { - (Uid::effective().is_root()).then_some(FloatingText::new( +pub fn check_root_status(bypass_root: bool) -> Option> { + if bypass_root { + return None; + } + + Uid::effective().is_root().then_some(FloatingText::new( ROOT_WARNING.into(), "Root User Warning", true, diff --git a/tui/src/running_command.rs b/tui/src/running_command.rs index d2342826..378eec4d 100644 --- a/tui/src/running_command.rs +++ b/tui/src/running_command.rs @@ -1,4 +1,4 @@ -use crate::{float::FloatContent, hint::Shortcut, theme::Theme}; +use crate::{float::FloatContent, hint::Shortcut, shortcuts, theme::Theme}; use linutil_core::Command; use oneshot::{channel, Receiver}; use portable_pty::{ @@ -139,21 +139,21 @@ impl FloatContent for RunningCommand { if self.is_finished() { ( "Finished command", - Box::new([ - Shortcut::new("Close window", ["Enter", "q"]), - Shortcut::new("Scroll up", ["Page up"]), - Shortcut::new("Scroll down", ["Page down"]), - Shortcut::new("Save log", ["l"]), - ]), + shortcuts!( + ("Close window", ["Enter", "q"]), + ("Scroll up", ["Page up"]), + ("Scroll down", ["Page down"]), + ("Save log", ["l"]), + ), ) } else { ( "Running command", - Box::new([ - Shortcut::new("Kill the command", ["CTRL-c"]), - Shortcut::new("Scroll up", ["Page up"]), - Shortcut::new("Scroll down", ["Page down"]), - ]), + shortcuts!( + ("Kill the command", ["CTRL-c"]), + ("Scroll up", ["Page up"]), + ("Scroll down", ["Page down"]), + ), ) } } diff --git a/tui/src/state.rs b/tui/src/state.rs index cec9cc3c..3baffef3 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -6,6 +6,7 @@ use crate::{ hint::{create_shortcut_list, Shortcut}, root::check_root_status, running_command::RunningCommand, + shortcuts, theme::Theme, Args, }; @@ -65,6 +66,7 @@ pub struct AppState { tip: &'static str, size_bypass: bool, skip_confirmation: bool, + mouse_enabled: bool, } pub enum Focus { @@ -93,8 +95,18 @@ enum SelectedItem { None, } +enum ScrollDir { + Up, + Down, +} + impl AppState { pub fn new(args: Args) -> Self { + #[cfg(unix)] + let root_warning = check_root_status(args.bypass_root); + #[cfg(not(unix))] + let root_warning = None; + let tabs = linutil_core::get_tabs(!args.override_validation); let root_id = tabs[0].tree.root().id(); @@ -121,10 +133,11 @@ impl AppState { tip: crate::tips::get_random_tip(), size_bypass: args.size_bypass, skip_confirmation: args.skip_confirmation, + mouse_enabled: args.mouse, }; #[cfg(unix)] - if let Some(root_warning) = check_root_status() { + if let Some(root_warning) = root_warning { state.spawn_float(root_warning, FLOAT_SIZE, FLOAT_SIZE); } @@ -171,13 +184,13 @@ impl AppState { fn get_list_item_shortcut(&self) -> Box<[Shortcut]> { if self.selected_item_is_dir() { - Box::new([Shortcut::new("Go to selected dir", ["l", "Right", "Enter"])]) + shortcuts!(("Go to selected dir", ["l", "Right", "Enter"])) } else { - Box::new([ - Shortcut::new("Run selected command", ["l", "Right", "Enter"]), - Shortcut::new("Enable preview", ["p"]), - Shortcut::new("Command Description", ["d"]), - ]) + shortcuts!( + ("Run selected command", ["l", "Right", "Enter"]), + ("Enable preview", ["p"]), + ("Command Description", ["d"]) + ) } } @@ -185,10 +198,7 @@ impl AppState { match self.focus { Focus::Search => ( "Search bar", - Box::new([ - Shortcut::new("Abort search", ["Esc", "CTRL-c"]), - Shortcut::new("Search", ["Enter"]), - ]), + shortcuts!(("Abort search", ["Esc", "CTRL-c"]), ("Search", ["Enter"])), ), Focus::List => { @@ -208,35 +218,39 @@ impl AppState { hints.extend(self.get_list_item_shortcut()); } - hints.push(Shortcut::new("Select item above", ["k", "Up"])); - hints.push(Shortcut::new("Select item below", ["j", "Down"])); - hints.push(Shortcut::new("Next theme", ["t"])); - hints.push(Shortcut::new("Previous theme", ["T"])); - hints.push(Shortcut::new("Multi-selection mode", ["v"])); + hints.extend(shortcuts!( + ("Select item above", ["k", "Up"]), + ("Select item below", ["j", "Down"]), + ("Next theme", ["t"]), + ("Previous theme", ["T"]), + ("Multi-selection mode", ["v"]), + )); if self.multi_select { hints.push(Shortcut::new("Select multiple commands", ["Space"])); } - hints.push(Shortcut::new("Next tab", ["Tab"])); - hints.push(Shortcut::new("Previous tab", ["Shift-Tab"])); - hints.push(Shortcut::new("Important actions guide", ["g"])); + hints.extend(shortcuts!( + ("Next tab", ["Tab"]), + ("Previous tab", ["Shift-Tab"]), + ("Important actions guide", ["g"]) + )); ("Command list", hints.into_boxed_slice()) } Focus::TabList => ( "Tab list", - Box::new([ - Shortcut::new("Exit linutil", ["q", "CTRL-c"]), - Shortcut::new("Focus action list", ["l", "Right", "Enter"]), - Shortcut::new("Select item above", ["k", "Up"]), - Shortcut::new("Select item below", ["j", "Down"]), - Shortcut::new("Next theme", ["t"]), - Shortcut::new("Previous theme", ["T"]), - Shortcut::new("Next tab", ["Tab"]), - Shortcut::new("Previous tab", ["Shift-Tab"]), - Shortcut::new("Important actions guide", ["g"]), - Shortcut::new("Multi-selection mode", ["v"]), - ]), + shortcuts!( + ("Exit linutil", ["q", "CTRL-c"]), + ("Focus action list", ["l", "Right", "Enter"]), + ("Select item above", ["k", "Up"]), + ("Select item below", ["j", "Down"]), + ("Next theme", ["t"]), + ("Previous theme", ["T"]), + ("Next tab", ["Tab"]), + ("Previous tab", ["Shift-Tab"]), + ("Important actions guide", ["g"]), + ("Multi-selection mode", ["v"]), + ), ), Focus::FloatingWindow(ref float) => float.get_shortcut_list(), @@ -438,6 +452,10 @@ impl AppState { } pub fn handle_mouse(&mut self, event: &MouseEvent) -> bool { + if !self.mouse_enabled { + return true; + } + if !self.drawable { return true; } @@ -480,7 +498,7 @@ impl AppState { } match &mut self.focus { Focus::FloatingWindow(float) => { - float.content.handle_mouse_event(event); + float.handle_mouse_event(event); } Focus::ConfirmationPrompt(confirm) => { confirm.content.handle_mouse_event(event); @@ -595,24 +613,35 @@ impl AppState { true } - fn scroll_down(&mut self) { - if let Some(selected) = self.selection.selected() { - if selected == self.filter.item_list().len() - 1 { - self.selection.select_first(); - } else { - self.selection.select_next(); - } - } + fn scroll(&mut self, direction: ScrollDir) { + let Some(selected) = self.selection.selected() else { + return; + }; + let list_len = if !self.at_root() { + self.filter.item_list().len() + 1 + } else { + self.filter.item_list().len() + }; + + if list_len == 0 { + return; + }; + + let next_selection = match direction { + ScrollDir::Up if selected == 0 => list_len - 1, + ScrollDir::Down if selected >= list_len - 1 => 0, + ScrollDir::Up => selected - 1, + ScrollDir::Down => selected + 1, + }; + self.selection.select(Some(next_selection)); } fn scroll_up(&mut self) { - if let Some(selected) = self.selection.selected() { - if selected == 0 { - self.selection.select_last(); - } else { - self.selection.select_previous(); - } - } + self.scroll(ScrollDir::Up) + } + + fn scroll_down(&mut self) { + self.scroll(ScrollDir::Down) } fn toggle_multi_select(&mut self) { @@ -733,7 +762,7 @@ impl AppState { self.filter .item_list() .get(selected_index) - .map_or(false, |item| item.has_children) + .is_some_and(|i| i.has_children) } pub fn selected_item_is_cmd(&self) -> bool { diff --git a/xtask/src/docgen.rs b/xtask/src/docgen.rs index 385c1134..15a5e2af 100644 --- a/xtask/src/docgen.rs +++ b/xtask/src/docgen.rs @@ -2,8 +2,7 @@ use std::fs; use linutil_core::Command; -use crate::path; -use crate::DynError; +use crate::{path, DynError}; pub const USER_GUIDE: &str = "userguide.md"; diff --git a/xtask/src/main.rs b/xtask/src/main.rs index fecab8c8..a1be3f7c 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -6,9 +6,10 @@ use std::{env, error::Error}; type DynError = Box; pub mod tasks { - use crate::docgen::USER_GUIDE; - use crate::docgen::{userguide, write}; - use crate::DynError; + use crate::{ + docgen::{userguide, write, USER_GUIDE}, + DynError, + }; pub fn docgen() -> Result<(), DynError> { write(USER_GUIDE, &userguide()?);