Merge branch 'main' into patch-3

This commit is contained in:
Jeevitha Kannan K S 2025-02-22 08:16:58 +05:30 committed by GitHub
commit 3824eb1541
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
61 changed files with 693 additions and 489 deletions

View File

@ -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

View File

@ -39,18 +39,6 @@ jobs:
with: with:
targets: x86_64-unknown-linux-musl 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 - name: Install cross-rs for cross-compilation
run: cargo install cross run: cargo install cross

View File

@ -31,9 +31,3 @@ jobs:
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Run shfmt
uses: reviewdog/action-shfmt@v1
with:
shfmt_flags: '-i 4 -ci'
reviewdog_flags: '-fail-level=any'

326
Cargo.lock generated
View File

@ -1,18 +1,6 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 4
[[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",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
@ -25,21 +13,21 @@ dependencies = [
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.18" version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.8" version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.88" version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
[[package]] [[package]]
name = "arrayvec" name = "arrayvec"
@ -49,9 +37,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.3.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
@ -61,9 +49,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.6.0" version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -88,9 +76,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.28" version = "1.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" checksum = "a012a0df96dd6d06ba9a1b29d6402d1a5d77c6befd2566afdc26e10603dc93d7"
dependencies = [ dependencies = [
"shlex", "shlex",
] ]
@ -109,9 +97,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.20" version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -119,9 +107,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.20" version = "4.5.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"clap_lex", "clap_lex",
@ -129,9 +117,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.18" version = "4.5.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@ -141,15 +129,15 @@ dependencies = [
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.7.2" version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]] [[package]]
name = "compact_str" name = "compact_str"
version = "0.8.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644" checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
dependencies = [ dependencies = [
"castaway", "castaway",
"cfg-if", "cfg-if",
@ -165,7 +153,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.7.0",
"crossterm_winapi", "crossterm_winapi",
"mio", "mio",
"parking_lot", "parking_lot",
@ -184,6 +172,41 @@ dependencies = [
"winapi", "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]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.11" version = "0.3.11"
@ -211,6 +234,12 @@ version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "env_home"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe"
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -219,12 +248,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.9" version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -238,6 +267,18 @@ dependencies = [
"winapi", "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]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.15" version = "0.2.15"
@ -251,20 +292,15 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.5" version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [ dependencies = [
"ahash",
"allocator-api2", "allocator-api2",
"equivalent",
"foldhash",
] ]
[[package]]
name = "hashbrown"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.5.0" version = "0.5.0"
@ -272,19 +308,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]] [[package]]
name = "hermit-abi" name = "ident_case"
version = "0.3.9" version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys",
]
[[package]] [[package]]
name = "include_dir" name = "include_dir"
@ -307,12 +334,12 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.6.0" version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.1", "hashbrown",
] ]
[[package]] [[package]]
@ -323,10 +350,13 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]] [[package]]
name = "instability" name = "instability"
version = "0.3.2" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" checksum = "894813a444908c0c8c0e221b041771d107c4a21de1d317dc49bcc66e3c9e5b3f"
dependencies = [ dependencies = [
"darling",
"indoc",
"proc-macro2",
"quote", "quote",
"syn", "syn",
] ]
@ -351,9 +381,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.11" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
@ -363,13 +393,13 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.161" version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]] [[package]]
name = "linutil_core" name = "linutil_core"
version = "24.10.31" version = "25.2.13"
dependencies = [ dependencies = [
"ego-tree", "ego-tree",
"include_dir", "include_dir",
@ -381,7 +411,7 @@ dependencies = [
[[package]] [[package]]
name = "linutil_tui" name = "linutil_tui"
version = "24.10.31" version = "25.2.13"
dependencies = [ dependencies = [
"clap", "clap",
"linutil_core", "linutil_core",
@ -400,9 +430,9 @@ dependencies = [
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.14" version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]] [[package]]
name = "lock_api" name = "lock_api"
@ -422,11 +452,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "lru" name = "lru"
version = "0.12.4" version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [ dependencies = [
"hashbrown 0.14.5", "hashbrown",
] ]
[[package]] [[package]]
@ -446,15 +476,14 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.0.2" version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
dependencies = [ dependencies = [
"hermit-abi",
"libc", "libc",
"log", "log",
"wasi", "wasi",
"windows-sys", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -477,7 +506,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.7.0",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@ -498,12 +527,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "oneshot" name = "oneshot"
version = "0.1.8" version = "0.1.8"
@ -583,18 +606,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.86" version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.37" version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -635,7 +658,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.7.0",
"cassowary", "cassowary",
"compact_str", "compact_str",
"crossterm", "crossterm",
@ -652,18 +675,18 @@ dependencies = [
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.5.7" version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.7.0",
] ]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.10.6" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -673,9 +696,9 @@ dependencies = [
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.4.7" version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -684,28 +707,28 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.4" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.38" version = "0.38.43"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
dependencies = [ dependencies = [
"bitflags 2.6.0", "bitflags 2.7.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.17" version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]] [[package]]
name = "ryu" name = "ryu"
@ -721,18 +744,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.215" version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.215" version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -741,9 +764,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.7" version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
dependencies = [ dependencies = [
"serde", "serde",
] ]
@ -860,6 +883,12 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.26.3" version = "0.26.3"
@ -884,9 +913,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.87" version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -910,18 +939,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.64" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.64" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -930,9 +959,9 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.36" version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa", "itoa",
@ -953,9 +982,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.18" version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
dependencies = [ dependencies = [
"num-conv", "num-conv",
"time-core", "time-core",
@ -997,9 +1026,9 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter" name = "tree-sitter"
version = "0.24.4" version = "0.24.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67baf55e7e1b6806063b1e51041069c90afff16afcbbccd278d899f9d84bca4" checksum = "5f2434c86ba59ed15af56039cc5bf1acf8ba76ce301e32ef08827388ef285ec5"
dependencies = [ dependencies = [
"cc", "cc",
"regex", "regex",
@ -1020,9 +1049,9 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter-highlight" name = "tree-sitter-highlight"
version = "0.24.4" version = "0.24.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f0f856de10d70a6d14d66db3648f7410c131cd49e989a863f15dda9acae6044" checksum = "a1df627d3607f08557788a3c85b85042d8ccd5155eb119afff5f0c7b67a40924"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"regex", "regex",
@ -1033,9 +1062,9 @@ dependencies = [
[[package]] [[package]]
name = "tree-sitter-language" name = "tree-sitter-language"
version = "0.1.0" version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2545046bd1473dac6c626659cc2567c6c0ff302fc8b84a56c4243378276f7f57" checksum = "c199356c799a8945965bb5f2c55b2ad9d9aa7c4b4f6e587fe9dea0bc715e5f9c"
[[package]] [[package]]
name = "tui-term" name = "tui-term"
@ -1048,15 +1077,15 @@ dependencies = [
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.13" version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.11.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]] [[package]]
name = "unicode-truncate" name = "unicode-truncate"
@ -1087,12 +1116,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "vt100-ctt" name = "vt100-ctt"
version = "0.16.0" version = "0.16.0"
@ -1109,9 +1132,9 @@ dependencies = [
[[package]] [[package]]
name = "vte" name = "vte"
version = "0.13.0" version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" checksum = "9a0b683b20ef64071ff03745b14391751f6beab06a54347885459b77a3f2caa5"
dependencies = [ dependencies = [
"arrayvec", "arrayvec",
"utf8parse", "utf8parse",
@ -1136,12 +1159,12 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "which" name = "which"
version = "7.0.0" version = "7.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9cad3279ade7346b96e38731a641d7343dd6a53d55083dd54eadfa5a1b38c6b" checksum = "fb4a9e33648339dc1642b0e36e21b3385e6148e289226f657c809dee59df5028"
dependencies = [ dependencies = [
"either", "either",
"home", "env_home",
"rustix", "rustix",
"winsafe", "winsafe",
] ]
@ -1177,6 +1200,15 @@ dependencies = [
"windows-targets", "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]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.6" version = "0.52.6"
@ -1243,9 +1275,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.20" version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" checksum = "39281189af81c07ec09db316b302a3e67bf9bd7cbf6c820b50e35fee9c2fa980"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -1267,7 +1299,7 @@ checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904"
[[package]] [[package]]
name = "xtask" name = "xtask"
version = "24.10.31" version = "25.2.13"
dependencies = [ dependencies = [
"linutil_core", "linutil_core",
] ]

View File

@ -1,6 +1,6 @@
[workspace.package] [workspace.package]
license = "MIT" license = "MIT"
version = "24.10.31" version = "25.2.13"
edition = "2021" edition = "2021"
[workspace] [workspace]

View File

@ -1,6 +1,6 @@
MIT License 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -83,25 +83,18 @@ curl -fsSL https://christitus.com/linuxdev | sh
### CLI arguments ### CLI arguments
Linutil supports various command-line arguments to customize its behavior. Here are some common arguments you can use: View available options by running:
- `-c, --config <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 <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
```
```bash ```bash
linutil --help linutil --help
``` ```
For installer options:
```bash
curl -fsSL https://christitus.com/linux | sh -s -- --help
```
## Configuration ## Configuration
Linutil supports configuration through a TOML config file. Path to the file can be specified with `--config` (or `-c`). 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 ## 🏅 Thanks to All Contributors
Thank you to everyone who has contributed to the development of Linutil. Your efforts are greatly appreciated, and youre 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) [![Contributors](https://contrib.rocks/image?repo=ChrisTitusTech/linutil)](https://github.com/ChrisTitusTech/linutil/graphs/contributors)

View File

@ -111,18 +111,16 @@ fn default_true() -> bool {
} }
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "snake_case")]
enum EntryType { enum EntryType {
#[serde(rename = "entries")]
Entries(Vec<Entry>), Entries(Vec<Entry>),
#[serde(rename = "command")]
Command(String), Command(String),
#[serde(rename = "script")]
Script(PathBuf), Script(PathBuf),
} }
impl Entry { impl Entry {
fn is_supported(&self) -> bool { fn is_supported(&self) -> bool {
self.preconditions.as_deref().map_or(true, |preconditions| { self.preconditions.as_deref().is_none_or(|preconditions| {
preconditions.iter().all( preconditions.iter().all(
|Precondition { |Precondition {
matches, matches,
@ -131,18 +129,17 @@ impl Entry {
}| { }| {
match data { match data {
SystemDataType::Environment(var_name) => std::env::var(var_name) SystemDataType::Environment(var_name) => std::env::var(var_name)
.map_or(false, |var| values.contains(&var) == *matches), .is_ok_and(|var| values.contains(&var) == *matches),
SystemDataType::File(path) => { SystemDataType::ContainingFile(file) => std::fs::read_to_string(file)
std::fs::read_to_string(path).map_or(false, |data| { .is_ok_and(|data| {
values values
.iter() .iter()
.any(|matching_value| data.contains(matching_value)) .all(|matching| data.contains(matching) == *matches)
== *matches }),
})
}
SystemDataType::CommandExists => values SystemDataType::CommandExists => values
.iter() .iter()
.all(|command| which::which(command).is_ok() == *matches), .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)] #[derive(Deserialize)]
#[serde(rename_all = "snake_case")]
enum SystemDataType { enum SystemDataType {
#[serde(rename = "environment")]
Environment(String), Environment(String),
#[serde(rename = "file")] ContainingFile(PathBuf),
File(PathBuf), FileExists,
#[serde(rename = "command_exists")]
CommandExists, CommandExists,
} }

View File

@ -19,7 +19,7 @@ install_adb() {
"$ESCALATION_TOOL" "$PACKAGER" add android-tools "$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 exit 1
;; ;;
esac esac

View File

@ -8,7 +8,7 @@ installLibreWolf() {
case "$PACKAGER" in case "$PACKAGER" in
apt-get|nala) apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" install -y gnupg lsb-release apt-transport-https ca-certificates "$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 curl -fsSL https://deb.librewolf.net/keyring.gpg | "$ESCALATION_TOOL" gpg --dearmor -o /usr/share/keyrings/librewolf.gpg
echo "Types: deb echo "Types: deb
URIs: https://deb.librewolf.net URIs: https://deb.librewolf.net
@ -49,4 +49,4 @@ Signed-By: /usr/share/keyrings/librewolf.gpg" | "$ESCALATION_TOOL" tee /etc/apt/
checkEnv checkEnv
checkEscalationTool checkEscalationTool
checkAURHelper checkAURHelper
installLibreWolf installLibreWolf

View File

@ -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

View File

@ -17,7 +17,7 @@ installDiscord() {
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm discord "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm discord
;; ;;
dnf) 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 "$ESCALATION_TOOL" "$PACKAGER" install -y discord
;; ;;
apk) apk)
@ -36,4 +36,4 @@ installDiscord() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
installDiscord installDiscord

View File

@ -8,7 +8,7 @@ installSignal() {
case "$PACKAGER" in case "$PACKAGER" in
apt-get|nala) apt-get|nala)
curl -fsSL https://updates.signal.org/desktop/apt/keys.asc | gpg --dearmor > signal-desktop-keyring.gpg 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 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" update
"$ESCALATION_TOOL" "$PACKAGER" -y install signal-desktop "$ESCALATION_TOOL" "$PACKAGER" -y install signal-desktop
@ -39,4 +39,4 @@ installSignal() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
installSignal installSignal

View File

@ -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

View File

@ -35,8 +35,8 @@ install_nerd_font() {
FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip" FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip"
FONT_INSTALLED=$(fc-list | grep -i "Meslo") FONT_INSTALLED=$(fc-list | grep -i "Meslo")
# Check if Meslo Nerd-font is already installed # Replace -n test with standard test
if [ -n "$FONT_INSTALLED" ]; then if [ ! -z "$FONT_INSTALLED" ]; then
printf "%b\n" "${GREEN}Meslo Nerd-fonts are already installed.${RC}" printf "%b\n" "${GREEN}Meslo Nerd-fonts are already installed.${RC}"
return 0 return 0
fi fi
@ -192,7 +192,7 @@ setupDisplayManager() {
"$ESCALATION_TOOL" "$PACKAGER" install -y xorg-x11-xinit xorg-x11-server-Xorg "$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 exit 1
;; ;;
esac esac
@ -207,29 +207,37 @@ setupDisplayManager() {
done done
printf "%b\n" "${GREEN}Current display manager: $currentdm${RC}" printf "%b\n" "${GREEN}Current display manager: $currentdm${RC}"
if [ "$currentdm" = "none" ]; then if [ "$currentdm" = "none" ]; then
printf "%b\n" "${YELLOW}--------------------------${RC}" while : ; do
printf "%b\n" "${YELLOW}Pick your Display Manager ${RC}" printf "%b\n" "${YELLOW}--------------------------${RC}"
printf "%b\n" "${YELLOW}1. SDDM ${RC}" printf "%b\n" "${YELLOW}Pick your Display Manager ${RC}"
printf "%b\n" "${YELLOW}2. LightDM ${RC}" printf "%b\n" "${YELLOW}1. SDDM ${RC}"
printf "%b\n" "${YELLOW}3. GDM ${RC}" printf "%b\n" "${YELLOW}2. LightDM ${RC}"
printf "%b\n" "${YELLOW} ${RC}" printf "%b\n" "${YELLOW}3. GDM ${RC}"
printf "%b" "${YELLOW}Please select one: ${RC}" printf "%b\n" "${YELLOW}4. None ${RC}"
read -r choice printf "%b" "${YELLOW}Please select one: ${RC}"
case "$choice" in read -r choice
1) case "$choice" in
DM="sddm" 1)
;; DM="sddm"
2) break
DM="lightdm" ;;
;; 2)
3) DM="lightdm"
DM="gdm" break
;; ;;
*) 3)
printf "%b\n" "${RED}Invalid selection! Please choose 1, 2, or 3.${RC}" DM="gdm"
exit 1 break
;; ;;
esac 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 case "$PACKAGER" in
pacman) pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm "$DM" "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm "$DM"
@ -244,7 +252,7 @@ setupDisplayManager() {
"$ESCALATION_TOOL" "$PACKAGER" install -y "$DM" "$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 exit 1
;; ;;
esac esac

View File

@ -53,7 +53,7 @@ installLinutil() {
;; ;;
*) *)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
. $HOME/.cargo/env . "$HOME/.cargo/env"
;; ;;
esac esac
fi fi

View File

@ -17,7 +17,7 @@ updateLinutil() {
zypper) zypper)
"$ESCALATION_TOOL" "$PACKAGER" install -n curl gcc make "$ESCALATION_TOOL" "$PACKAGER" install -n curl gcc make
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
. $HOME/.cargo/env . "$HOME/.cargo/env"
;; ;;
apk) apk)
"$ESCALATION_TOOL" "$PACKAGER" add build-base "$ESCALATION_TOOL" "$PACKAGER" add build-base

View File

@ -39,6 +39,12 @@ description = "Thunderbird is a free, open-source email client that offers power
script = "communication-apps/thunderbird-setup.sh" script = "communication-apps/thunderbird-setup.sh"
task_list = "I" 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]] [[data.entries]]
name = "Zoom" 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." 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]] [[data.entries]]
name = "Github Desktop" 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." 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" task_list = "I"
[[data.entries]] [[data.entries]]
name = "JetBrains Toolbox" name = "JetBrains Toolbox"
description = "JetBrains Toolbox is a collection of tools and an app that help developers work with JetBrains products." 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" task_list = "I"
[[data.entries]] [[data.entries]]
name = "Meld" name = "Meld"
description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects." 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" task_list = "I FI"
[[data.entries]] [[data.entries]]
name = "Neovim" 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" 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" task_list = "I FM"
[[data.entries]] [[data.entries]]
name = "Ngrok" name = "Ngrok"
description = "Ngrok is a tool that creates secure, temporary tunnels to expose local servers to the internet for testing and development." 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" task_list = "I"
[[data.entries]] [[data.entries]]
name = "Sublime Text" 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." 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" 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]] [[data.entries]]
name = "VS Code" 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." 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" task_list = "I"
[[data.entries]] [[data.entries]]
name = "VS Codium" name = "VS Codium"
description = "VSCodium is a free, open-source version of Visual Studio Code (VS Code) that removes Microsoft-specific telemetry and branding." 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" task_list = "I"
[[data]] [[data]]
@ -191,6 +192,12 @@ description = "Mozilla Firefox is a free and open-source web browser developed b
script = "browsers/firefox.sh" script = "browsers/firefox.sh"
task_list = "I" 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]] [[data.entries]]
name = "Thorium" name = "Thorium"
description = "Thorium is a Chromium-based browser focused on privacy and performance." description = "Thorium is a Chromium-based browser focused on privacy and performance."
@ -335,4 +342,4 @@ values = ["wayland", "Wayland"]
name = "ZSH Prompt" 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." 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" script = "zsh-setup.sh"
task_list = "I FM" task_list = "I FM"

View File

@ -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

View File

@ -15,33 +15,33 @@ installDepend() {
else else
printf "%b\n" "${GREEN}Multilib is already enabled.${RC}" printf "%b\n" "${GREEN}Multilib is already enabled.${RC}"
fi fi
"$AUR_HELPER" -S --needed --noconfirm $DEPENDENCIES "$AUR_HELPER" -S --needed --noconfirm "$DEPENDENCIES"
;; ;;
apt-get|nala) apt-get|nala)
COMPILEDEPS='build-essential' COMPILEDEPS='build-essential'
"$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" "$PACKAGER" update
"$ESCALATION_TOOL" dpkg --add-architecture i386 "$ESCALATION_TOOL" dpkg --add-architecture i386
"$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" "$PACKAGER" update
"$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES $COMPILEDEPS "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" "$COMPILEDEPS"
;; ;;
dnf) dnf)
COMPILEDEPS='@development-tools' COMPILEDEPS='@development-tools'
"$ESCALATION_TOOL" "$PACKAGER" update "$ESCALATION_TOOL" "$PACKAGER" update
"$ESCALATION_TOOL" "$PACKAGER" config-manager --set-enabled powertools "$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 "$ESCALATION_TOOL" "$PACKAGER" install -y glibc-devel.i686 libgcc.i686
;; ;;
zypper) zypper)
COMPILEDEPS='patterns-devel-base-devel_basis' COMPILEDEPS='patterns-devel-base-devel_basis'
"$ESCALATION_TOOL" "$PACKAGER" refresh "$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 "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install libgcc_s1-gcc7-32bit glibc-devel-32bit
;; ;;
apk) apk)
"$ESCALATION_TOOL" "$PACKAGER" add build-base multitail tar tree trash-cli unzip cmake jq "$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 esac
} }
@ -49,4 +49,4 @@ installDepend() {
checkEnv checkEnv
checkAURHelper checkAURHelper
checkEscalationTool checkEscalationTool
installDepend installDepend

View File

@ -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

View File

@ -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

View File

@ -22,7 +22,7 @@ cleanup_system() {
;; ;;
pacman) pacman)
"$ESCALATION_TOOL" "$PACKAGER" -Sc --noconfirm "$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) apk)
"$ESCALATION_TOOL" "$PACKAGER" cache clean "$ESCALATION_TOOL" "$PACKAGER" cache clean

View File

@ -16,15 +16,22 @@ task_list = "SI D"
multi_select = false multi_select = false
[[data.entries]] [[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" description = "Valve's fork of Linux Kernel for the SteamDeck"
script = "arch/linux-neptune.sh" script = "arch/linux-neptune.sh"
task_list = "I PFM K" task_list = "I PFM K"
[[data.entries.preconditions]] [[data.entries.preconditions]]
matches = true matches = true
data = { file = "/sys/devices/virtual/dmi/id/board_vendor" } data = { containing_file = "/sys/devices/virtual/dmi/id/board_vendor" }
values = [ "Valve" ] values = ["Valve"]
[[data.entries]] [[data.entries]]
name = "Nvidia Drivers && Hardware Acceleration" 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" script = "arch/yay-setup.sh"
task_list = "I" 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]] [[data]]
name = "Fedora" name = "Fedora"
@ -64,6 +85,12 @@ description = "Optimizes DNF for parallel downloads"
script = "fedora/configure-dnf.sh" script = "fedora/configure-dnf.sh"
task_list = "PFM" 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]] [[data.entries]]
name = "Multimedia Codecs" name = "Multimedia Codecs"
description = "This script is designed to install multimedia codecs, and to ensure RPM Fusion repositories are installed." 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]] [[data.preconditions]]
matches = true matches = true
data = "command_exists" 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]] [[data]]
name = "Build Prerequisites" name = "Build Prerequisites"

View File

@ -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

View File

@ -65,12 +65,11 @@ scan_devices() {
printf "%b\n" "$devices" printf "%b\n" "$devices"
fi fi
printf "%b" "Press any key to return to the main menu..." printf "%b" "Press any key to return to the main menu..."
read -r dummy read -r _
} }
# Function to prompt for MAC address using numbers # Function to prompt for MAC address using numbers
prompt_for_mac() { prompt_for_mac() {
action=$1
command=$2 command=$2
prompt_msg=$3 prompt_msg=$3
success_msg=$4 success_msg=$4
@ -82,14 +81,14 @@ prompt_for_mac() {
if [ -z "$devices" ]; then if [ -z "$devices" ]; then
printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}" printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}"
printf "%b" "Press any key to return to the main menu..." printf "%b" "Press any key to return to the main menu..."
read -r dummy read -r _
return return
fi fi
# Display devices with numbers # Display devices with numbers
device_list=$(echo "$devices" | tr '\n' '\n') device_list=$(echo "$devices" | tr '\n' '\n')
i=1 i=1
echo "$device_list" | while IFS= read -r device; do for device in $device_list; do
printf "%d. %s\n" "$i" "$device" printf "%d. %s\n" "$i" "$device"
i=$((i + 1)) i=$((i + 1))
done done
@ -102,12 +101,12 @@ prompt_for_mac() {
device=$(echo "$device_list" | sed -n "${choice}p") device=$(echo "$device_list" | sed -n "${choice}p")
mac=$(echo "$device" | awk '{print $2}') mac=$(echo "$device" | awk '{print $2}')
if bluetoothctl info "$mac" > /dev/null 2>&1; then if bluetoothctl info "$mac" > /dev/null 2>&1; then
bluetoothctl "$command" "$mac" && { if bluetoothctl "$command" "$mac"; then
printf "%b\n" "${GREEN}$success_msg${RC}" printf "%b\n" "${GREEN}$success_msg${RC}"
break break
} || { else
printf "%b\n" "${RED}$failure_msg${RC}" printf "%b\n" "${RED}$failure_msg${RC}"
} fi
else else
printf "%b\n" "${RED}Invalid MAC address. Please try again.${RC}" printf "%b\n" "${RED}Invalid MAC address. Please try again.${RC}"
fi fi
@ -118,7 +117,7 @@ prompt_for_mac() {
fi fi
done done
printf "%b" "Press any key to return to the main menu..." printf "%b" "Press any key to return to the main menu..."
read -r dummy read -r _
} }
# Function to pair with a device # Function to pair with a device

View File

@ -62,11 +62,11 @@ encrypt_file() {
if [ -d "$INPUT_PATH" ]; then if [ -d "$INPUT_PATH" ]; then
# Encrypt each file in the directory # Encrypt each file in the directory
find "$INPUT_PATH" -type f | while read -r FILE; do 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" OUTPUT_FILE="$OUTPUT_PATH/$REL_PATH.enc"
mkdir -p "$(dirname "$OUTPUT_FILE")" 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" printf "%b\n" "Encrypted: $OUTPUT_FILE"
else else
printf "%b\n" "Failed to encrypt: $FILE" printf "%b\n" "Failed to encrypt: $FILE"
@ -79,8 +79,8 @@ encrypt_file() {
return return
fi fi
mkdir -p "$(dirname "$OUTPUT_PATH")" 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" printf "%b\n" "Encrypted: $OUTPUT_PATH"
else else
printf "%b\n" "Failed to encrypt: $INPUT_PATH" printf "%b\n" "Failed to encrypt: $INPUT_PATH"
@ -107,11 +107,11 @@ decrypt_file() {
if [ -d "$INPUT_PATH" ]; then if [ -d "$INPUT_PATH" ]; then
# Decrypt each file in the directory # Decrypt each file in the directory
find "$INPUT_PATH" -type f -name '*.enc' | while read -r FILE; do 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}" OUTPUT_FILE="$OUTPUT_PATH/${REL_PATH%.enc}"
mkdir -p "$(dirname "$OUTPUT_FILE")" 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" printf "%b\n" "Decrypted: $OUTPUT_FILE"
else else
printf "%b\n" "Failed to decrypt: $FILE" printf "%b\n" "Failed to decrypt: $FILE"
@ -124,8 +124,8 @@ decrypt_file() {
return return
fi fi
mkdir -p "$(dirname "$OUTPUT_PATH")" 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" printf "%b\n" "Decrypted: $OUTPUT_PATH"
else else
printf "%b\n" "Failed to decrypt: $INPUT_PATH" printf "%b\n" "Failed to decrypt: $INPUT_PATH"
@ -148,10 +148,10 @@ main(){
esac esac
printf "%b\n" "Press [Enter] to continue..." printf "%b\n" "Press [Enter] to continue..."
read -r dummy read -r _
done done
} }
checkEnv checkEnv
checkEscalationTool checkEscalationTool
main main

View File

@ -29,7 +29,7 @@ adjust_monitor_brightness() {
if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then
printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" printf "%b\n" "${RED}Invalid selection. Please try again.${RC}"
printf "Press [Enter] to continue..." printf "Press [Enter] to continue..."
read -r dummy read -r _
continue continue
fi fi
@ -37,7 +37,7 @@ adjust_monitor_brightness() {
if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$monitor_count" ]; then if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$monitor_count" ]; then
printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" printf "%b\n" "${RED}Invalid selection. Please try again.${RC}"
printf "Press [Enter] to continue..." printf "Press [Enter] to continue..."
read -r dummy read -r _
continue continue
fi fi

View File

@ -33,7 +33,7 @@ set_resolutions() {
if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then 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" "${RED}Invalid selection. Please try again.${RC}"
printf "%b\n" "Press [Enter] to continue..." printf "%b\n" "Press [Enter] to continue..."
read -r dummy read -r _
continue continue
fi fi

View File

@ -85,7 +85,8 @@ run_model() {
printf "%b\n" "${installed_models}" printf "%b\n" "${installed_models}"
printf "%b\n" "${YELLOW}Custom Models${RC}" 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" "Select a model to run: "
printf "%b" "Enter the number corresponding to the model or enter the name of a custom model: " printf "%b" "Enter the number corresponding to the model or enter the name of a custom model: "
@ -195,7 +196,7 @@ menu() {
esac esac
printf "%b\n" "${YELLOW}Press Enter to continue...${RC}" printf "%b\n" "${YELLOW}Press Enter to continue...${RC}"
read -r dummy read -r _
done done
} }

View File

@ -173,7 +173,7 @@ setup_ssh_samba(){
printf "%b\n" "5. Exit" printf "%b\n" "5. Exit"
printf "%b" "Enter your choice (1-5): " printf "%b" "Enter your choice (1-5): "
read CHOICE read -r CHOICE
case "$CHOICE" in case "$CHOICE" in
1) 1)
@ -205,4 +205,4 @@ setup_ssh_samba(){
checkEnv checkEnv
checkEscalationTool checkEscalationTool
setup_ssh_samba setup_ssh_samba

View File

@ -267,10 +267,10 @@ main() {
esac esac
printf "%b\n" "Press [Enter] to continue..." printf "%b\n" "Press [Enter] to continue..."
read -r dummy read -r _
done done
} }
checkEnv checkEnv
checkEscalationTool checkEscalationTool
main main

View File

@ -67,6 +67,7 @@ create_snapshot() {
"$ESCALATION_TOOL" timeshift --create --comments "$COMMENT" --tags "$TAG" "$ESCALATION_TOOL" timeshift --create --comments "$COMMENT" --tags "$TAG"
fi fi
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "%b\n" "${GREEN}Snapshot created successfully.${RC}" printf "%b\n" "${GREEN}Snapshot created successfully.${RC}"
else else
@ -93,6 +94,7 @@ restore_snapshot() {
"$ESCALATION_TOOL" timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes "$ESCALATION_TOOL" timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes
fi fi
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "%b\n" "${GREEN}Snapshot restored successfully.${RC}" printf "%b\n" "${GREEN}Snapshot restored successfully.${RC}"
else else
@ -110,6 +112,7 @@ delete_snapshot() {
printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}" printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}"
"$ESCALATION_TOOL" timeshift --delete --snapshot "$SNAPSHOT" --yes "$ESCALATION_TOOL" timeshift --delete --snapshot "$SNAPSHOT" --yes
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "%b\n" "${GREEN}Snapshot deleted successfully.${RC}" printf "%b\n" "${GREEN}Snapshot deleted successfully.${RC}"
else else
@ -126,6 +129,7 @@ delete_all_snapshots() {
if [ "$CONFIRMATION" = "y" ] || [ "$CONFIRMATION" = "Y" ]; then if [ "$CONFIRMATION" = "y" ] || [ "$CONFIRMATION" = "Y" ]; then
printf "%b\n" "${CYAN}Deleting all snapshots...${RC}" printf "%b\n" "${CYAN}Deleting all snapshots...${RC}"
"$ESCALATION_TOOL" timeshift --delete-all --yes "$ESCALATION_TOOL" timeshift --delete-all --yes
# shellcheck disable=SC2181
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "%b\n" "${GREEN}All snapshots deleted successfully.${RC}" printf "%b\n" "${GREEN}All snapshots deleted successfully.${RC}"
else else
@ -153,7 +157,7 @@ main_menu() {
*) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;; *) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;;
esac esac
printf "%b\n" "${CYAN}Press Enter to continue...${RC}" printf "%b\n" "${CYAN}Press Enter to continue...${RC}"
read -r dummy read -r _
done done
} }

View File

@ -33,7 +33,7 @@ addToGroup() {
groups_to_add=$(echo "$groups" | tr ' ' ',') 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}" 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 confirmAction || exit 1
"$ESCALATION_TOOL" usermod -aG "$groups_to_add" "$username" "$ESCALATION_TOOL" usermod -aG "$groups_to_add" "$username"
@ -44,4 +44,4 @@ addToGroup() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
checkGroups checkGroups
addToGroup addToGroup

View File

@ -17,7 +17,7 @@ changePassword() {
read -r password read -r password
printf "%b" "${YELLOW}Are you sure you want to change password for ""$username""? [Y/n]: ${RC}" printf "%b" "${YELLOW}Are you sure you want to change password for ""$username""? [Y/n]: ${RC}"
read -r confirm read -r _
confirmAction || exit 1 confirmAction || exit 1
echo "$username:$password" | "$ESCALATION_TOOL" chpasswd echo "$username:$password" | "$ESCALATION_TOOL" chpasswd
@ -30,4 +30,4 @@ changePassword() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
changePassword changePassword

View File

@ -14,7 +14,7 @@ deleteUser() {
if id "$username" > /dev/null 2>&1; then if id "$username" > /dev/null 2>&1; then
printf "%b" "${YELLOW}Are you sure you want to delete user ""$username""? [Y/n]: ${RC}" printf "%b" "${YELLOW}Are you sure you want to delete user ""$username""? [Y/n]: ${RC}"
read -r confirm read -r _
confirmAction || exit 1 confirmAction || exit 1
$ESCALATION_TOOL userdel --remove "$username" 2>/dev/null $ESCALATION_TOOL userdel --remove "$username" 2>/dev/null
@ -27,4 +27,4 @@ deleteUser() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
deleteUser deleteUser

View File

@ -34,14 +34,14 @@ removeFromGroup() {
groups_to_remove=$(echo "$groups" | tr ' ' ',') 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}" 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 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}" printf "%b\n" "${GREEN}User successfully removed from $groups_to_remove${RC}"
} }
checkEnv checkEnv
checkEscalationTool checkEscalationTool
removeFromGroup removeFromGroup

View File

@ -30,6 +30,7 @@ execute_command() {
command="$1" command="$1"
printf "Executing: %s\n" "$command" printf "Executing: %s\n" "$command"
eval "$command" 2>&1 | tee /tmp/xrandr.log | tail -n 20 eval "$command" 2>&1 | tee /tmp/xrandr.log | tail -n 20
# shellcheck disable=SC2181
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
printf "%b\n" "${RED}An error occurred while executing the command. Check /tmp/xrandr.log for details.${RC}" printf "%b\n" "${RED}An error occurred while executing the command. Check /tmp/xrandr.log for details.${RC}"
fi fi

View File

@ -75,33 +75,33 @@ scan_networks() {
echo "$networks" | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}' echo "$networks" | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}'
fi fi
printf "%b\n" "Press any key to return to the main menu..." printf "%b\n" "Press any key to return to the main menu..."
read -r dummy read -r _
} }
# Function to turn WiFi on # Function to turn WiFi on
wifi_on() { wifi_on() {
clear clear
printf "%b\n" "${YELLOW}Turning WiFi on...${RC}" 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}" printf "%b\n" "${GREEN}WiFi is now turned on.${RC}"
} || { else
printf "%b\n" "${RED}Failed to turn on WiFi.${RC}" printf "%b\n" "${RED}Failed to turn on WiFi.${RC}"
} fi
printf "%b\n" "Press any key to return to the main menu..." printf "%b\n" "Press any key to return to the main menu..."
read -r dummy read -r _
} }
# Function to turn WiFi off # Function to turn WiFi off
wifi_off() { wifi_off() {
clear clear
printf "%b\n" "${YELLOW}Turning WiFi off...${RC}" 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}" printf "%b\n" "${GREEN}WiFi is now turned off.${RC}"
} || { else
printf "%b\n" "${RED}Failed to turn off WiFi.${RC}" printf "%b\n" "${RED}Failed to turn off WiFi.${RC}"
} fi
printf "%b\n" "Press any key to return to the main menu..." printf "%b\n" "Press any key to return to the main menu..."
read -r dummy read -r _
} }
# Function to prompt for WiFi network selection # Function to prompt for WiFi network selection
@ -118,7 +118,7 @@ prompt_for_network() {
if [ -z "$networks" ]; then if [ -z "$networks" ]; then
printf "%b\n" "${RED}No networks available. Please scan for networks first.${RC}" 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..." printf "%b\n" "Press any key to return to the main menu..."
read -r dummy read -r _
rm -f "$temp_file" rm -f "$temp_file"
return return
fi fi
@ -142,18 +142,18 @@ prompt_for_network() {
printf "%b" "Enter password for SSID: " "$ssid" printf "%b" "Enter password for SSID: " "$ssid"
read -r password read -r password
printf "\n" 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}" printf "%b\n" "${GREEN}$success_msg${RC}"
} || { else
printf "%b\n" "${RED}$failure_msg${RC}" printf "%b\n" "${RED}$failure_msg${RC}"
} fi
fi fi
else else
printf "%b\n" "${RED}Invalid choice. Please try again.${RC}" printf "%b\n" "${RED}Invalid choice. Please try again.${RC}"
fi fi
printf "%b\n" "Press any key to return to the selection menu..." printf "%b\n" "Press any key to return to the selection menu..."
read -r dummy read -r _
done done
rm -f "$temp_file" rm -f "$temp_file"
@ -178,4 +178,4 @@ remove_network() {
checkEnv checkEnv
checkEscalationTool checkEscalationTool
setupNetworkManager setupNetworkManager
main_menu main_menu

View File

@ -71,7 +71,7 @@ Please consider submitting feedback if you do.
https://github.com/ChrisTitusTech/linutil/issues https://github.com/ChrisTitusTech/linutil/issues
.SH COPYRIGHT .SH COPYRIGHT
Copyright (c) 2024 Chris Titus. Copyright (c) 2025 Chris Titus.
.br .br
MIT License. MIT License.
https://opensource.org/license/MIT https://opensource.org/license/MIT

1
rustfmt.toml Normal file
View File

@ -0,0 +1 @@
imports_granularity = "Crate"

View File

@ -8,8 +8,9 @@ RED='\033[0;31m'
# Function to fetch the latest release tag from the GitHub API # Function to fetch the latest release tag from the GitHub API
get_latest_release() { get_latest_release() {
latest_release=$(curl -s https://api.github.com/repos/ChrisTitusTech/linutil/releases | latest_release=$(curl -s https://api.github.com/repos/ChrisTitusTech/linutil/releases |
grep -oP '"tag_name": "\K[^"]*' | grep "tag_name" |
head -n 1) head -n 1 |
sed -E 's/.*"tag_name": "([^"]+)".*/\1/')
if [ -z "$latest_release" ]; then if [ -z "$latest_release" ]; then
printf "%b\n" "Error fetching release data" >&2 printf "%b\n" "Error fetching release data" >&2
return 1 return 1

View File

@ -14,7 +14,7 @@ default = ["tips"]
tips = ["rand"] tips = ["rand"]
[dependencies] [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 } oneshot = { version = "0.1.8", features = ["std"], default-features = false }
portable-pty = "0.8.1" portable-pty = "0.8.1"
ratatui = { version = "0.29.0", features = ["crossterm"], default-features = false } 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 } time = { version = "0.3.36", features = ["formatting", "local-offset", "macros"], default-features = false }
unicode-width = { version = "0.2.0", default-features = false } unicode-width = { version = "0.2.0", default-features = false }
rand = { version = "0.8.5", optional = true } 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-highlight = "0.24.4"
tree-sitter-bash = "0.23.3" tree-sitter-bash = "0.23.3"
nix = { version = "0.29.0", features = [ "user" ] } nix = { version = "0.29.0", features = [ "user" ] }

35
tui/src/cli.rs Normal file
View File

@ -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<PathBuf>,
/// 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,
}

View File

@ -1,4 +1,4 @@
use crate::{float::FloatContent, hint::Shortcut, theme}; use crate::{float::FloatContent, hint::Shortcut, shortcuts, theme};
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind},
layout::Alignment, layout::Alignment,
@ -135,13 +135,13 @@ impl FloatContent for ConfirmPrompt {
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) { fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) {
( (
"Confirmation prompt", "Confirmation prompt",
Box::new([ shortcuts!(
Shortcut::new("Continue", ["Y", "y"]), ("Continue", ["Y", "y"]),
Shortcut::new("Abort", ["N", "n", "q", "Esc"]), ("Abort", ["N", "n", "q", "Esc"]),
Shortcut::new("Scroll up", ["k", "Up"]), ("Scroll up", ["k", "Up"]),
Shortcut::new("Scroll down", ["j", "Down"]), ("Scroll down", ["j", "Down"]),
Shortcut::new("Close linutil", ["CTRL-c"]), ("Close linutil", ["CTRL-c"]),
]), ),
) )
} }
} }

View File

@ -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 linutil_core::Command;
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, 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) { fn draw(&mut self, frame: &mut Frame, area: Rect, _theme: &Theme) {
let block = Block::default() let block = Block::default()
.borders(Borders::ALL) .borders(Borders::ALL)
@ -228,13 +228,13 @@ impl<'a> FloatContent for FloatingText<'a> {
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) { fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) {
( (
&self.mode_title, &self.mode_title,
Box::new([ shortcuts!(
Shortcut::new("Scroll down", ["j", "Down"]), ("Scroll down", ["j", "Down"]),
Shortcut::new("Scroll up", ["k", "Up"]), ("Scroll up", ["k", "Up"]),
Shortcut::new("Scroll left", ["h", "Left"]), ("Scroll left", ["h", "Left"]),
Shortcut::new("Scroll right", ["l", "Right"]), ("Scroll right", ["l", "Right"]),
Shortcut::new("Close window", ["Enter", "p", "q", "d", "g"]), ("Close window", ["Enter", "p", "q", "d", "g"])
]), ),
) )
} }
} }

View File

@ -36,7 +36,7 @@ pub fn create_shortcut_list(
.unwrap_or(0); .unwrap_or(0);
let columns = (render_width as usize / (max_shortcut_width + 4)).max(1); 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<Line<'static>> = Vec::with_capacity(rows); let mut lines: Vec<Line<'static>> = Vec::with_capacity(rows);
@ -78,3 +78,14 @@ impl Shortcut {
.collect() .collect()
} }
} }
#[macro_export]
macro_rules! shortcuts {
($(($name:literal,[$($key:literal),+ $(,)?])),* $(,)?) => {
vec![
$(
Shortcut::new($name, [$($key),*])
),*
].into_boxed_slice()
};
}

View File

@ -1,3 +1,4 @@
mod cli;
mod confirmation; mod confirmation;
mod filter; mod filter;
mod float; mod float;
@ -5,13 +6,13 @@ mod floating_text;
mod hint; mod hint;
mod root; mod root;
mod running_command; mod running_command;
pub mod state; mod state;
mod theme; mod theme;
#[cfg(feature = "tips")] #[cfg(feature = "tips")]
mod tips; mod tips;
use crate::theme::Theme; use crate::cli::Args;
use clap::Parser; use clap::Parser;
use ratatui::{ use ratatui::{
backend::CrosstermBackend, backend::CrosstermBackend,
@ -26,40 +27,17 @@ use ratatui::{
use state::AppState; use state::AppState;
use std::{ use std::{
io::{stdout, Result, Stdout}, io::{stdout, Result, Stdout},
path::PathBuf,
time::Duration, time::Duration,
}; };
// Linux utility toolbox
#[derive(Debug, Parser)]
pub struct Args {
#[arg(short, long, help = "Path to the configuration file")]
config: Option<PathBuf>,
#[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<()> { fn main() -> Result<()> {
let args = Args::parse(); let args = Args::parse();
let mut state = AppState::new(args.clone());
let mut state = AppState::new(args);
stdout().execute(EnterAlternateScreen)?; stdout().execute(EnterAlternateScreen)?;
stdout().execute(EnableMouseCapture)?; if args.mouse {
stdout().execute(EnableMouseCapture)?;
}
enable_raw_mode()?; enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
@ -70,7 +48,9 @@ fn main() -> Result<()> {
// restore terminal // restore terminal
disable_raw_mode()?; disable_raw_mode()?;
terminal.backend_mut().execute(LeaveAlternateScreen)?; terminal.backend_mut().execute(LeaveAlternateScreen)?;
terminal.backend_mut().execute(DisableMouseCapture)?; if args.mouse {
terminal.backend_mut().execute(DisableMouseCapture)?;
}
terminal.backend_mut().execute(ResetColor)?; terminal.backend_mut().execute(ResetColor)?;
terminal.show_cursor()?; terminal.show_cursor()?;

View File

@ -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."; Please proceed with caution and make sure you understand what each script does before executing it.";
#[cfg(unix)] #[cfg(unix)]
pub fn check_root_status<'a>() -> Option<FloatingText<'a>> { pub fn check_root_status(bypass_root: bool) -> Option<FloatingText<'static>> {
(Uid::effective().is_root()).then_some(FloatingText::new( if bypass_root {
return None;
}
Uid::effective().is_root().then_some(FloatingText::new(
ROOT_WARNING.into(), ROOT_WARNING.into(),
"Root User Warning", "Root User Warning",
true, true,

View File

@ -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 linutil_core::Command;
use oneshot::{channel, Receiver}; use oneshot::{channel, Receiver};
use portable_pty::{ use portable_pty::{
@ -139,21 +139,21 @@ impl FloatContent for RunningCommand {
if self.is_finished() { if self.is_finished() {
( (
"Finished command", "Finished command",
Box::new([ shortcuts!(
Shortcut::new("Close window", ["Enter", "q"]), ("Close window", ["Enter", "q"]),
Shortcut::new("Scroll up", ["Page up"]), ("Scroll up", ["Page up"]),
Shortcut::new("Scroll down", ["Page down"]), ("Scroll down", ["Page down"]),
Shortcut::new("Save log", ["l"]), ("Save log", ["l"]),
]), ),
) )
} else { } else {
( (
"Running command", "Running command",
Box::new([ shortcuts!(
Shortcut::new("Kill the command", ["CTRL-c"]), ("Kill the command", ["CTRL-c"]),
Shortcut::new("Scroll up", ["Page up"]), ("Scroll up", ["Page up"]),
Shortcut::new("Scroll down", ["Page down"]), ("Scroll down", ["Page down"]),
]), ),
) )
} }
} }

View File

@ -6,6 +6,7 @@ use crate::{
hint::{create_shortcut_list, Shortcut}, hint::{create_shortcut_list, Shortcut},
root::check_root_status, root::check_root_status,
running_command::RunningCommand, running_command::RunningCommand,
shortcuts,
theme::Theme, theme::Theme,
Args, Args,
}; };
@ -65,6 +66,7 @@ pub struct AppState {
tip: &'static str, tip: &'static str,
size_bypass: bool, size_bypass: bool,
skip_confirmation: bool, skip_confirmation: bool,
mouse_enabled: bool,
} }
pub enum Focus { pub enum Focus {
@ -93,8 +95,18 @@ enum SelectedItem {
None, None,
} }
enum ScrollDir {
Up,
Down,
}
impl AppState { impl AppState {
pub fn new(args: Args) -> Self { 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 tabs = linutil_core::get_tabs(!args.override_validation);
let root_id = tabs[0].tree.root().id(); let root_id = tabs[0].tree.root().id();
@ -121,10 +133,11 @@ impl AppState {
tip: crate::tips::get_random_tip(), tip: crate::tips::get_random_tip(),
size_bypass: args.size_bypass, size_bypass: args.size_bypass,
skip_confirmation: args.skip_confirmation, skip_confirmation: args.skip_confirmation,
mouse_enabled: args.mouse,
}; };
#[cfg(unix)] #[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); state.spawn_float(root_warning, FLOAT_SIZE, FLOAT_SIZE);
} }
@ -171,13 +184,13 @@ impl AppState {
fn get_list_item_shortcut(&self) -> Box<[Shortcut]> { fn get_list_item_shortcut(&self) -> Box<[Shortcut]> {
if self.selected_item_is_dir() { 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 { } else {
Box::new([ shortcuts!(
Shortcut::new("Run selected command", ["l", "Right", "Enter"]), ("Run selected command", ["l", "Right", "Enter"]),
Shortcut::new("Enable preview", ["p"]), ("Enable preview", ["p"]),
Shortcut::new("Command Description", ["d"]), ("Command Description", ["d"])
]) )
} }
} }
@ -185,10 +198,7 @@ impl AppState {
match self.focus { match self.focus {
Focus::Search => ( Focus::Search => (
"Search bar", "Search bar",
Box::new([ shortcuts!(("Abort search", ["Esc", "CTRL-c"]), ("Search", ["Enter"])),
Shortcut::new("Abort search", ["Esc", "CTRL-c"]),
Shortcut::new("Search", ["Enter"]),
]),
), ),
Focus::List => { Focus::List => {
@ -208,35 +218,39 @@ impl AppState {
hints.extend(self.get_list_item_shortcut()); hints.extend(self.get_list_item_shortcut());
} }
hints.push(Shortcut::new("Select item above", ["k", "Up"])); hints.extend(shortcuts!(
hints.push(Shortcut::new("Select item below", ["j", "Down"])); ("Select item above", ["k", "Up"]),
hints.push(Shortcut::new("Next theme", ["t"])); ("Select item below", ["j", "Down"]),
hints.push(Shortcut::new("Previous theme", ["T"])); ("Next theme", ["t"]),
hints.push(Shortcut::new("Multi-selection mode", ["v"])); ("Previous theme", ["T"]),
("Multi-selection mode", ["v"]),
));
if self.multi_select { if self.multi_select {
hints.push(Shortcut::new("Select multiple commands", ["Space"])); hints.push(Shortcut::new("Select multiple commands", ["Space"]));
} }
hints.push(Shortcut::new("Next tab", ["Tab"])); hints.extend(shortcuts!(
hints.push(Shortcut::new("Previous tab", ["Shift-Tab"])); ("Next tab", ["Tab"]),
hints.push(Shortcut::new("Important actions guide", ["g"])); ("Previous tab", ["Shift-Tab"]),
("Important actions guide", ["g"])
));
("Command list", hints.into_boxed_slice()) ("Command list", hints.into_boxed_slice())
} }
Focus::TabList => ( Focus::TabList => (
"Tab list", "Tab list",
Box::new([ shortcuts!(
Shortcut::new("Exit linutil", ["q", "CTRL-c"]), ("Exit linutil", ["q", "CTRL-c"]),
Shortcut::new("Focus action list", ["l", "Right", "Enter"]), ("Focus action list", ["l", "Right", "Enter"]),
Shortcut::new("Select item above", ["k", "Up"]), ("Select item above", ["k", "Up"]),
Shortcut::new("Select item below", ["j", "Down"]), ("Select item below", ["j", "Down"]),
Shortcut::new("Next theme", ["t"]), ("Next theme", ["t"]),
Shortcut::new("Previous theme", ["T"]), ("Previous theme", ["T"]),
Shortcut::new("Next tab", ["Tab"]), ("Next tab", ["Tab"]),
Shortcut::new("Previous tab", ["Shift-Tab"]), ("Previous tab", ["Shift-Tab"]),
Shortcut::new("Important actions guide", ["g"]), ("Important actions guide", ["g"]),
Shortcut::new("Multi-selection mode", ["v"]), ("Multi-selection mode", ["v"]),
]), ),
), ),
Focus::FloatingWindow(ref float) => float.get_shortcut_list(), Focus::FloatingWindow(ref float) => float.get_shortcut_list(),
@ -438,6 +452,10 @@ impl AppState {
} }
pub fn handle_mouse(&mut self, event: &MouseEvent) -> bool { pub fn handle_mouse(&mut self, event: &MouseEvent) -> bool {
if !self.mouse_enabled {
return true;
}
if !self.drawable { if !self.drawable {
return true; return true;
} }
@ -480,7 +498,7 @@ impl AppState {
} }
match &mut self.focus { match &mut self.focus {
Focus::FloatingWindow(float) => { Focus::FloatingWindow(float) => {
float.content.handle_mouse_event(event); float.handle_mouse_event(event);
} }
Focus::ConfirmationPrompt(confirm) => { Focus::ConfirmationPrompt(confirm) => {
confirm.content.handle_mouse_event(event); confirm.content.handle_mouse_event(event);
@ -595,24 +613,35 @@ impl AppState {
true true
} }
fn scroll_down(&mut self) { fn scroll(&mut self, direction: ScrollDir) {
if let Some(selected) = self.selection.selected() { let Some(selected) = self.selection.selected() else {
if selected == self.filter.item_list().len() - 1 { return;
self.selection.select_first(); };
} else { let list_len = if !self.at_root() {
self.selection.select_next(); 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) { fn scroll_up(&mut self) {
if let Some(selected) = self.selection.selected() { self.scroll(ScrollDir::Up)
if selected == 0 { }
self.selection.select_last();
} else { fn scroll_down(&mut self) {
self.selection.select_previous(); self.scroll(ScrollDir::Down)
}
}
} }
fn toggle_multi_select(&mut self) { fn toggle_multi_select(&mut self) {
@ -733,7 +762,7 @@ impl AppState {
self.filter self.filter
.item_list() .item_list()
.get(selected_index) .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 { pub fn selected_item_is_cmd(&self) -> bool {

View File

@ -2,8 +2,7 @@ use std::fs;
use linutil_core::Command; use linutil_core::Command;
use crate::path; use crate::{path, DynError};
use crate::DynError;
pub const USER_GUIDE: &str = "userguide.md"; pub const USER_GUIDE: &str = "userguide.md";

View File

@ -6,9 +6,10 @@ use std::{env, error::Error};
type DynError = Box<dyn Error>; type DynError = Box<dyn Error>;
pub mod tasks { pub mod tasks {
use crate::docgen::USER_GUIDE; use crate::{
use crate::docgen::{userguide, write}; docgen::{userguide, write, USER_GUIDE},
use crate::DynError; DynError,
};
pub fn docgen() -> Result<(), DynError> { pub fn docgen() -> Result<(), DynError> {
write(USER_GUIDE, &userguide()?); write(USER_GUIDE, &userguide()?);