Merge remote-tracking branch 'upstream/main' into flatpak

This commit is contained in:
JEEVITHA KANNAN K S 2024-10-01 11:19:03 +05:30
commit 6e7fe51f91
No known key found for this signature in database
GPG Key ID: 5904C34A2F7CE333
29 changed files with 641 additions and 93 deletions

34
Cargo.lock generated
View File

@ -194,9 +194,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.17"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac"
checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
dependencies = [
"clap_builder",
"clap_derive",
@ -204,9 +204,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.17"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73"
checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
dependencies = [
"anstream",
"anstyle",
@ -216,9 +216,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.13"
version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0"
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [
"heck",
"proc-macro2",
@ -491,7 +491,7 @@ checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "linutil_core"
version = "24.9.23"
version = "24.9.28"
dependencies = [
"ego-tree",
"include_dir",
@ -503,7 +503,7 @@ dependencies = [
[[package]]
name = "linutil_tui"
version = "24.9.23"
version = "24.9.28"
dependencies = [
"ansi-to-tui",
"anstyle",
@ -519,7 +519,7 @@ dependencies = [
"tree-sitter-bash",
"tree-sitter-highlight",
"tui-term",
"unicode-width",
"unicode-width 0.2.0",
"zips",
]
@ -792,7 +792,7 @@ dependencies = [
"strum_macros",
"unicode-segmentation",
"unicode-truncate",
"unicode-width",
"unicode-width 0.1.14",
]
[[package]]
@ -1205,14 +1205,20 @@ checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
dependencies = [
"itertools",
"unicode-segmentation",
"unicode-width",
"unicode-width 0.1.14",
]
[[package]]
name = "unicode-width"
version = "0.1.13"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "utf8parse"
@ -1234,7 +1240,7 @@ checksum = "84cd863bf0db7e392ba3bd04994be3473491b31e66340672af5d11943c6274de"
dependencies = [
"itoa",
"log",
"unicode-width",
"unicode-width 0.1.14",
"vte",
]

View File

@ -1,6 +1,6 @@
[workspace.package]
license = "MIT"
version = "24.9.23"
version = "24.9.28"
[workspace.dependencies]
ego-tree = "0.6.2"

View File

@ -1,13 +1,15 @@
use crate::{Command, ListNode, Tab};
use ego_tree::{NodeMut, Tree};
use include_dir::{include_dir, Dir};
use serde::Deserialize;
use std::{
fs::File,
io::{BufRead, BufReader, Read},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
rc::Rc,
};
use crate::{Command, ListNode, Tab};
use ego_tree::{NodeMut, Tree};
use include_dir::{include_dir, Dir};
use serde::Deserialize;
use tempdir::TempDir;
const TAB_DATA: Dir = include_dir!("$CARGO_MANIFEST_DIR/tabs");
@ -35,12 +37,12 @@ pub fn get_tabs(validate: bool) -> Vec<Tab> {
},
directory,
)| {
let mut tree = Tree::new(ListNode {
let mut tree = Tree::new(Rc::new(ListNode {
name: "root".to_string(),
description: String::new(),
command: Command::None,
task_list: String::new(),
});
}));
let mut root = tree.root_mut();
create_directory(data, &mut root, &directory, validate);
Tab {
@ -164,28 +166,28 @@ fn filter_entries(entries: &mut Vec<Entry>) {
fn create_directory(
data: Vec<Entry>,
node: &mut NodeMut<ListNode>,
node: &mut NodeMut<Rc<ListNode>>,
command_dir: &Path,
validate: bool,
) {
for entry in data {
match entry.entry_type {
EntryType::Entries(entries) => {
let mut node = node.append(ListNode {
let mut node = node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::None,
task_list: String::new(),
});
}));
create_directory(entries, &mut node, command_dir, validate);
}
EntryType::Command(command) => {
node.append(ListNode {
node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::Raw(command),
task_list: String::new(),
});
}));
}
EntryType::Script(script) => {
let script = command_dir.join(script);
@ -194,7 +196,7 @@ fn create_directory(
}
if let Some((executable, args)) = get_shebang(&script, validate) {
node.append(ListNode {
node.append(Rc::new(ListNode {
name: entry.name,
description: entry.description,
command: Command::LocalFile {
@ -203,7 +205,7 @@ fn create_directory(
file: script,
},
task_list: entry.task_list,
});
}));
}
}
}

View File

@ -1,5 +1,7 @@
mod inner;
use std::rc::Rc;
use ego_tree::Tree;
use std::path::PathBuf;
@ -20,7 +22,7 @@ pub enum Command {
#[derive(Clone, Hash, Eq, PartialEq)]
pub struct Tab {
pub name: String,
pub tree: Tree<ListNode>,
pub tree: Tree<Rc<ListNode>>,
pub multi_selectable: bool,
}

View File

@ -3,10 +3,25 @@
. ../../common-script.sh
installMeld() {
cd "$HOME" && git clone https://gitlab.gnome.org/GNOME/meld.git
echo "PATH=\$PATH:$HOME/meld/bin" | "$ESCALATION_TOOL" tee -a /etc/environment
if ! command_exists meld; then
printf "%b\n" "${YELLOW}Installing Meld...${RC}"
case "$PACKAGER" in
pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm meld
;;
apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" -y install meld
;;
*)
. ../setup-flatpak.sh
flatpak install -y flathub org.gnome.meld
;;
esac
else
printf "%b\n" "${GREEN}Meld is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installMeld
installMeld

View File

@ -4,15 +4,6 @@
gitpath="$HOME/.local/share/neovim"
checkNeovimVer() {
# lazy.nvim requires nvim >= 0.8.0
nvim_version=$(nvim --version | head -n 1 | awk '{print $2}')
if [ "$(printf "%s\n" "$nvim_version" "0.8.0" | sort -V | head -n 1)" != "0.8.0" ]; then
printf "%b\n" "${RED}Neovim version $nvim_version not supported.${RC}"
exit 1
fi
}
cloneNeovim() {
# Check if the dir exists before attempting to clone into it.
if [ -d "$gitpath" ]; then
@ -30,7 +21,10 @@ installNeovim() {
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck git
;;
apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" install -y neovim ripgrep fd-find python3-venv luarocks golang-go shellcheck git
"$ESCALATION_TOOL" "$PACKAGER" install -y ripgrep fd-find python3-venv luarocks golang-go shellcheck git
curl -sSLo /tmp/nvim.appimage https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
chmod u+x /tmp/nvim.appimage
"$ESCALATION_TOOL" mv /tmp/nvim.appimage /usr/local/bin/nvim
;;
dnf|zypper)
"$ESCALATION_TOOL" "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git
@ -60,7 +54,6 @@ linkNeovimConfig() {
checkEnv
checkEscalationTool
installNeovim
checkNeovimVer
cloneNeovim
backupNeovimConfig
linkNeovimConfig

View File

@ -17,7 +17,6 @@ installVsCodium() {
printf "%b\n" "[gitlab.com_paulcarroty_vscodium_repo]\nname=gitlab.com_paulcarroty_vscodium_repo\nbaseurl=https://download.vscodium.com/rpms/\nenabled=1\ngpgcheck=1\nrepo_gpgcheck=1\ngpgkey=https://gitlab.com/paulcarroty/vscodium-deb-rpm-repo/-/raw/master/pub.gpg\nmetadata_expire=1h" | "$ESCALATION_TOOL" tee -a /etc/zypp/repos.d/vscodium.repo
"$ESCALATION_TOOL" "$PACKAGER" refresh
"$ESCALATION_TOOL" "$PACKAGER" --non-interactive install codium
;;
pacman)
"$AUR_HELPER" -S --noconfirm vscodium-bin

View File

@ -15,9 +15,9 @@ installLinutil() {
printf "%b" "Enter your choice: "
read -r choice
case $choice in
1) "$AUR_HELPER" -S --noconfirm linutil ;;
2) "$AUR_HELPER" -S --noconfirm linutil-bin ;;
3) "$AUR_HELPER" -S --noconfirm linutil-git ;;
1) "$AUR_HELPER" -S --needed --noconfirm linutil ;;
2) "$AUR_HELPER" -S --needed --noconfirm linutil-bin ;;
3) "$AUR_HELPER" -S --needed --noconfirm linutil-git ;;
*)
printf "%b\n" "${RED}Invalid choice:${RC} $choice"
exit 1

View File

@ -0,0 +1,38 @@
#!/bin/sh -e
. ../common-script.sh
installFreeOffice() {
if ! command_exists softmaker-freeoffice-2024 freeoffice softmaker; then
printf "%b\n" "${YELLOW}Installing Free Office...${RC}"
case "$PACKAGER" in
apt-get|nala)
curl -O https://www.softmaker.net/down/softmaker-freeoffice-2024_1218-01_amd64.deb
"$ESCALATION_TOOL" "$PACKAGER" install -y ./softmaker-freeoffice-2024_1218-01_amd64.deb
;;
zypper)
"$ESCALATION_TOOL" "$PACKAGER" addrepo -f https://shop.softmaker.com/repo/rpm SoftMaker
"$ESCALATION_TOOL" "$PACKAGER" --gpg-auto-import-keys refresh
"$ESCALATION_TOOL" "$PACKAGER" --non-interactive install softmaker-freeoffice-2024
;;
pacman)
"$AUR_HELPER" -S --needed --noconfirm freeoffice
;;
dnf)
"$ESCALATION_TOOL" curl -O -qO /etc/yum.repos.d/softmaker.repo https://shop.softmaker.com/repo/softmaker.repo
"$ESCALATION_TOOL" "$PACKAGER" install -y softmaker-freeoffice-2024
;;
*)
printf "%b\n" "${RED}Unsupported package manager: ""$PACKAGER""${RC}"
exit 1
;;
esac
else
printf "%b\n" "${GREEN}Free Office is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
checkAurHelper
installFreeOffice

View File

@ -0,0 +1,31 @@
#!/bin/sh -e
. ../common-script.sh
installLibreOffice() {
if ! command_exists libreoffice; then
printf "%b\n" "${YELLOW}Installing Libre Office...${RC}"
case "$PACKAGER" in
apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" install -y libreoffice-core
;;
zypper|dnf)
. ./setup-flatpak.sh
flatpak install -y flathub org.libreoffice.LibreOffice
;;
pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm libreoffice-fresh
;;
*)
printf "%b\n" "${RED}Unsupported package manager: ""$PACKAGER""${RC}"
exit 1
;;
esac
else
printf "%b\n" "${GREEN}Libre Office is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installLibreOffice

View File

@ -0,0 +1,33 @@
#!/bin/sh -e
. ../common-script.sh
installOnlyOffice() {
if ! command_exists onlyoffice-desktopeditors; then
printf "%b\n" "${YELLOW}Installing Only Office..${RC}."
case "$PACKAGER" in
apt-get|nala)
curl -O https://download.onlyoffice.com/install/desktop/editors/linux/onlyoffice-desktopeditors_amd64.deb
"$ESCALATION_TOOL" "$PACKAGER" install -y ./onlyoffice-desktopeditors_amd64.deb
;;
zypper|dnf)
. ./setup-flatpak.sh
flatpak install -y flathub org.onlyoffice.desktopeditors
;;
pacman)
"$AUR_HELPER" -S --needed --noconfirm onlyoffice
;;
*)
printf "%b\n" "${RED}Unsupported package manager: ""$PACKAGER""${RC}"
exit 1
;;
esac
else
printf "%b\n" "${GREEN}Only Office is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
checkAurHelper
installOnlyOffice

View File

@ -0,0 +1,25 @@
#!/bin/sh -e
. ../common-script.sh
installWpsOffice() {
if ! command_exists com.wps.Office; then
printf "%b\n" "${YELLOW}Installing WPS Office...${RC}"
case "$PACKAGER" in
pacman)
"$AUR_HELPER" -S --needed --noconfirm wps-office
;;
*)
. ./setup-flatpak.sh
flatpak install flathub com.wps.Office
;;
esac
else
printf "%b\n" "${GREEN}WPS Office is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
checkAurHelper
installWpsOffice

View File

@ -0,0 +1,23 @@
#!/bin/sh -e
. ../common-script.sh
installEvince() {
if ! command_exists evince; then
printf "%b\n" "${YELLOW}Installing Evince...${RC}"
case "$PACKAGER" in
pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm evince
;;
*)
"$ESCALATION_TOOL" "$PACKAGER" install -y evince
;;
esac
else
printf "%b\n" "${GREEN}Evince is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installEvince

View File

@ -0,0 +1,23 @@
#!/bin/sh -e
. ../common-script.sh
installOkular() {
if ! command_exists okular; then
printf "%b\n" "${YELLOW}Installing Okular...${RC}"
case "$PACKAGER" in
pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm okular
;;
*)
"$ESCALATION_TOOL" "$PACKAGER" install -y okular
;;
esac
else
printf "%b\n" "${GREEN}Okular is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installOkular

View File

@ -0,0 +1,23 @@
#!/bin/sh -e
. ../common-script.sh
installPdfstudio() {
if ! command_exists pdfstudio2024; then
printf "%b\n" "${YELLOW}Installing PDF Studio...${RC}"
curl -O https://download.qoppa.com/pdfstudio/PDFStudio_linux64.sh
"$ESCALATION_TOOL" chmod +x PDFStudio_linux64.sh
if sh PDFStudio_linux64.sh; then
printf "%b\n" "${GREEN}PDF Studio installed successfully!${RC}"
else
printf "%b\n" "${RED}PDF Studio installation failed!${RC}"
fi
rm PDFStudio_linux64.sh
else
printf "%b\n" "${GREEN}PDF Studio is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installPdfstudio

View File

@ -0,0 +1,23 @@
#!/bin/sh -e
. ../common-script.sh
installPdfstudioviewer() {
if ! command_exists pdfstudioviewer2024; then
printf "%b\n" "${YELLOW}Installing PDF Studio Viewer...${RC}"
curl -O https://download.qoppa.com/pdfstudioviewer/PDFStudioViewer_linux64.sh
"$ESCALATION_TOOL" chmod +x PDFStudioViewer_linux64.sh
if sh PDFStudioViewer_linux64.sh; then
printf "%b\n" "${GREEN}PDF Studio Viewer installed successfully!${RC}"
else
printf "%b\n" "${RED}Installation failed!${RC}"
fi
rm PDFStudioViewer_linux64.sh
else
printf "%b\n" "${GREEN}PDF Studio Viewer is already installed.${RC}"
fi
}
checkEnv
checkEscalationTool
installPdfstudioviewer

View File

@ -37,7 +37,7 @@ task_list = "I"
name = "Meld"
description = "Meld is a visual diff and merge tool that helps compare files, directories, and version-controlled projects."
script = "Developer-tools/meld-setup.sh"
task_list = "I"
task_list = "I FI"
[[data.entries]]
name = "Ngrok"
@ -90,6 +90,51 @@ description = "Thunderbird is a free, open-source email client that offers power
script = "communication-apps/thunderbird-setup.sh"
task_list = "I"
[[data]]
name = "Office Suites"
[[data.entries]]
name = "LibreOffice"
script = "office-suites/libreoffice.sh"
task_list = "I"
[[data.entries]]
name = "OnlyOffice"
script = "office-suites/onlyoffice.sh"
task_list = "I"
[[data.entries]]
name = "FreeOffice"
script = "office-suites/freeoffice.sh"
task_list = "I"
[[data.entries]]
name = "WPS Office"
script = "office-suites/wpsoffice.sh"
task_list = "I"
[[data]]
name = "PDF Suites"
[[data.entries]]
name = "Evince"
script = "pdf-suites/evince.sh"
task_list = "I"
[[data.entries]]
name = "Okular"
script = "pdf-suites/okular.sh"
task_list = "I"
[[data.entries]]
name = "PDF Studio"
script = "pdf-suites/pdfstudio.sh"
task_list = "I"
[[data.entries]]
name = "PDF Studio Viewer"
script = "pdf-suites/pdfstudioviewer.sh"
[[data]]
name = "Web Browsers"
@ -223,12 +268,6 @@ matches = true
data = "command_exists"
values = [ "linutil" ]
[[data]]
name = "Office Suite"
description = "An office suite installer is a software package that installs productivity tools such as word processing, spreadsheets, presentations, and pdf viewers for business and personal use."
script = "office-suite-setup.sh"
task_list = "I"
[[data]]
name = "Rofi"
description = "Rofi is a window switcher, run dialog, ssh-launcher and dmenu replacement that started as a clone of simpleswitcher, written by Sean Pringle and later expanded by Dave Davenport.\nThis command installs and configures rofi with configuration from CTT's DWM repo.\nhttps://github.com/ChrisTitusTech/dwm-titus"

View File

@ -59,7 +59,7 @@ updateSystem() {
printf "%b\n" "${GREEN}Updating system${RC}"
case "$PACKAGER" in
apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" update -y
"$ESCALATION_TOOL" "$PACKAGER" update
"$ESCALATION_TOOL" "$PACKAGER" upgrade -y
;;
dnf)

View File

@ -43,11 +43,13 @@ task_list = "PFM"
[[data.entries]]
name = "Multimedia Codecs"
description = "This script is designed to install multimedia codecs, and to ensure RPM Fusion repositories are installed."
script = "fedora/multimedia-codecs.sh"
task_list = "I"
[[data.entries]]
name = "Nvidia Proprietary Drivers"
description = "This script is designed to download the proprietary NVIDIA drivers in Fedora."
script = "fedora/nvidia-proprietary-driver-setup.sh"
task_list = "I"
@ -71,6 +73,7 @@ task_list = "I"
[[data]]
name = "Full System Cleanup"
description = "This script is designed to remove unnecessary packages, clean old cache files, remove temporary files, and to empty the trash."
script = "system-cleanup.sh"
task_list = "RP PFM"
@ -97,3 +100,9 @@ name = "Remove Snaps"
description = "This script is designed to remove snap"
script = "remove-snaps.sh"
task_list = "RP"
[[data]]
name = "TTY Fonts"
description = "This Script will set the default TTY font to Terminus size 32 Bold"
script = "terminus-tty.sh"
task_list = "I PFM"

View File

@ -0,0 +1,66 @@
#!/bin/sh -e
. ../common-script.sh
InstallTermiusFonts() {
if [ ! -f "/usr/share/kbd/consolefonts/ter-c18b.psf.gz" ] &&
[ ! -f "/usr/share/consolefonts/Uni3-TerminusBold18x10.psf.gz" ] &&
[ ! -f "/usr/lib/kbd/consolefonts/ter-p32n.psf.gz" ]; then
printf "%b\n" "${YELLOW}Installing Terminus Fonts...${RC}"
case "$PACKAGER" in
pacman)
"$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm terminus-font
;;
apt-get|nala)
"$ESCALATION_TOOL" "$PACKAGER" install -y fonts-terminus
;;
dnf)
"$ESCALATION_TOOL" "$PACKAGER" install -y terminus-fonts-console
;;
*)
printf "%b\n" "${RED}Unsupported package manager: ""$PACKAGER""${RC}"
exit 1
;;
esac
else
printf "%b\n" "${GREEN}Terminus Fonts is already installed.${RC}"
fi
}
SetTermiusFonts() {
case "$DTYPE" in
arch)
printf "%b\n" "${YELLOW}Updating FONT= line in /etc/vconsole.conf...${RC}"
"$ESCALATION_TOOL" sed -i 's/^FONT=.*/FONT=ter-v32b/' /etc/vconsole.conf
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
"$ESCALATION_TOOL" setfont -C /dev/tty1 ter-v32b
fi
printf "%b\n" "${GREEN}Terminus font set for TTY.${RC}"
;;
debian)
printf "%b\n" "${YELLOW}Updating console-setup configuration...${RC}"
"$ESCALATION_TOOL" sed -i 's/^CODESET=.*/CODESET="guess"/' /etc/default/console-setup
"$ESCALATION_TOOL" sed -i 's/^FONTFACE=.*/FONTFACE="TerminusBold"/' /etc/default/console-setup
"$ESCALATION_TOOL" sed -i 's/^FONTSIZE=.*/FONTSIZE="16x32"/' /etc/default/console-setup
printf "%b\n" "${GREEN}Console-setup configuration updated for Terminus font.${RC}"
# Editing console-setup requires initramfs to be regenerated
"$ESCALATION_TOOL" update-initramfs -u
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
"$ESCALATION_TOOL" setfont -C /dev/tty1 /usr/share/consolefonts/Uni3-TerminusBold32x16.psf.gz
fi
printf "%b\n" "${GREEN}Terminus font has been set for TTY.${RC}"
;;
fedora)
printf "%b\n" "${YELLOW}Updating FONT= line in /etc/vconsole.conf...${RC}"
"$ESCALATION_TOOL" sed -i 's/^FONT=.*/FONT=ter-v32b/' /etc/vconsole.conf
if [ -z "$DISPLAY" ] && [ -z "$WAYLAND_DISPLAY" ]; then
"$ESCALATION_TOOL" setfont -C /dev/tty1 ter-v32b
fi
printf "%b\n" "${GREEN}Terminus font has been set for TTY.${RC}"
;;
esac
}
checkEnv
InstallTermiusFonts
SetTermiusFonts

View File

@ -21,7 +21,7 @@ select_drive() {
# Function to get UUID and FSTYPE of the selected drive
get_uuid_fstype() {
UUID=$(blkid -s UUID -o value "${partition}")
UUID=$("$ESCALATION_TOOL" blkid -s UUID -o value "${partition}")
FSTYPE=$(lsblk -no FSTYPE "${partition}")
NAME=$(lsblk -no NAME "${partition}")

View File

@ -8,6 +8,7 @@
- **Gaming Setup**: Configures Steam, Lutris, etc.
- **Global Theming**: Sets up and manages global themes.
- **Remove Snaps**: Removes snap packages.
- **TTY Fonts**: This Script will set the default TTY font to Terminus size 32 Bold
### Arch Setup

View File

@ -15,16 +15,16 @@ default = ["tips"]
tips = ["rand"]
[dependencies]
clap = { version = "4.5.16", features = ["derive"] }
clap = { version = "4.5.18", features = ["derive"] }
crossterm = "0.28.1"
ego-tree = { workspace = true }
oneshot = "0.1.8"
portable-pty = "0.8.1"
ratatui = "0.28.1"
tui-term = "0.1.12"
unicode-width = "0.1.13"
unicode-width = "0.2.0"
rand = { version = "0.8.5", optional = true }
linutil_core = { path = "../core", version = "24.9.23" }
linutil_core = { path = "../core", version = "24.9.28" }
tree-sitter-highlight = "0.23.0"
tree-sitter-bash = "0.23.1"
anstyle = "1.0.8"

126
tui/src/confirmation.rs Normal file
View File

@ -0,0 +1,126 @@
use std::borrow::Cow;
use crate::{float::FloatContent, hint::Shortcut};
use crossterm::event::{KeyCode, KeyEvent};
use ratatui::{
layout::Alignment,
prelude::*,
widgets::{Block, Borders, Clear, List},
};
pub enum ConfirmStatus {
Confirm,
Abort,
None,
}
pub struct ConfirmPrompt {
pub names: Box<[String]>,
pub status: ConfirmStatus,
scroll: usize,
}
impl ConfirmPrompt {
pub fn new(names: &[&str]) -> Self {
let max_count_str = format!("{}", names.len());
let names = names
.iter()
.zip(1..)
.map(|(name, n)| {
let count_str = format!("{n}");
let space_str = (0..(max_count_str.len() - count_str.len()))
.map(|_| ' ')
.collect::<String>();
format!("{space_str}{n}. {name}")
})
.collect();
Self {
names,
status: ConfirmStatus::None,
scroll: 0,
}
}
pub fn scroll_down(&mut self) {
if self.scroll < self.names.len() - 1 {
self.scroll += 1;
}
}
pub fn scroll_up(&mut self) {
if self.scroll > 0 {
self.scroll -= 1;
}
}
}
impl FloatContent for ConfirmPrompt {
fn draw(&mut self, frame: &mut Frame, area: Rect) {
let block = Block::default()
.borders(Borders::ALL)
.title(" Confirm selections ")
.title_bottom(" [y] to continue, [n] to abort ")
.title_alignment(Alignment::Center)
.title_style(Style::default().bold())
.style(Style::default());
frame.render_widget(block.clone(), area);
let inner_area = block.inner(area);
let paths_text = self
.names
.iter()
.skip(self.scroll)
.map(|p| {
let span = Span::from(Cow::<'_, str>::Borrowed(p));
Line::from(span).style(Style::default())
})
.collect::<Text>();
frame.render_widget(Clear, inner_area);
frame.render_widget(List::new(paths_text), inner_area);
}
fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
use KeyCode::*;
self.status = match key.code {
Char('y') | Char('Y') => ConfirmStatus::Confirm,
Char('n') | Char('N') | Esc => ConfirmStatus::Abort,
Char('j') => {
self.scroll_down();
ConfirmStatus::None
}
Char('k') => {
self.scroll_up();
ConfirmStatus::None
}
_ => ConfirmStatus::None,
};
false
}
fn is_finished(&self) -> bool {
use ConfirmStatus::*;
match self.status {
Confirm | Abort => true,
None => false,
}
}
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>) {
(
"Confirmation prompt",
Box::new([
Shortcut::new("Continue", ["Y", "y"]),
Shortcut::new("Abort", ["N", "n"]),
Shortcut::new("Scroll up", ["j"]),
Shortcut::new("Scroll down", ["k"]),
Shortcut::new("Close linutil", ["CTRL-c", "q"]),
]),
)
}
}

View File

@ -13,14 +13,14 @@ pub trait FloatContent {
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>);
}
pub struct Float {
content: Box<dyn FloatContent>,
pub struct Float<Content: FloatContent + ?Sized> {
pub content: Box<Content>,
width_percent: u16,
height_percent: u16,
}
impl Float {
pub fn new(content: Box<dyn FloatContent>, width_percent: u16, height_percent: u16) -> Self {
impl<Content: FloatContent + ?Sized> Float<Content> {
pub fn new(content: Box<Content>, width_percent: u16, height_percent: u16) -> Self {
Self {
content,
width_percent,
@ -60,6 +60,7 @@ impl Float {
| KeyCode::Char('p')
| KeyCode::Char('d')
| KeyCode::Char('g')
| KeyCode::Char('q')
| KeyCode::Esc
if self.content.is_finished() =>
{

View File

@ -298,7 +298,7 @@ impl FloatContent for FloatingText {
Shortcut::new("Scroll up", ["k", "Up"]),
Shortcut::new("Scroll left", ["h", "Left"]),
Shortcut::new("Scroll right", ["l", "Right"]),
Shortcut::new("Close window", ["Enter", "p", "d", "g"]),
Shortcut::new("Close window", ["Enter", "p", "q", "d", "g"]),
]),
)
}

View File

@ -1,3 +1,4 @@
mod confirmation;
mod filter;
mod float;
mod floating_text;

View File

@ -37,6 +37,7 @@ pub struct RunningCommand {
writer: Box<dyn Write + Send>,
/// Only set after the process has ended
status: Option<ExitStatus>,
scroll_offset: usize,
}
impl FloatContent for RunningCommand {
@ -102,6 +103,12 @@ impl FloatContent for RunningCommand {
KeyCode::Enter if self.is_finished() => {
return true;
}
KeyCode::PageUp => {
self.scroll_offset = self.scroll_offset.saturating_add(10);
}
KeyCode::PageDown => {
self.scroll_offset = self.scroll_offset.saturating_sub(10);
}
// Pass other key events to the terminal
_ => self.handle_passthrough_key_event(key),
}
@ -121,12 +128,20 @@ impl FloatContent for RunningCommand {
if self.is_finished() {
(
"Finished command",
Box::new([Shortcut::new("Close window", ["Enter", "q"])]),
Box::new([
Shortcut::new("Close window", ["Enter", "q"]),
Shortcut::new("Scroll up", ["Page up"]),
Shortcut::new("Scroll down", ["Page down"]),
]),
)
} else {
(
"Running command",
Box::new([Shortcut::new("Kill the command", ["CTRL-c"])]),
Box::new([
Shortcut::new("Kill the command", ["CTRL-c"]),
Shortcut::new("Scroll up", ["Page up"]),
Shortcut::new("Scroll down", ["Page down"]),
]),
)
}
}
@ -220,6 +235,7 @@ impl RunningCommand {
pty_master: pair.master,
writer,
status: None,
scroll_offset: 0,
}
}
@ -237,10 +253,12 @@ impl RunningCommand {
// Process the buffer with a parser with the current screen size
// We don't actually need to create a new parser every time, but it is so much easier this
// way, and doesn't cost that much
let mut parser = vt100::Parser::new(size.height, size.width, 0);
let mut parser = vt100::Parser::new(size.height, size.width, 200);
let mutex = self.buffer.lock();
let buffer = mutex.as_ref().unwrap();
parser.process(buffer);
// Adjust the screen content based on the scroll offset
parser.set_scrollback(self.scroll_offset);
parser.screen().clone()
}
@ -297,8 +315,6 @@ impl RunningCommand {
KeyCode::Tab => vec![9],
KeyCode::Home => vec![27, 91, 72],
KeyCode::End => vec![27, 91, 70],
KeyCode::PageUp => vec![27, 91, 53, 126],
KeyCode::PageDown => vec![27, 91, 54, 126],
KeyCode::BackTab => vec![27, 91, 90],
KeyCode::Delete => vec![27, 91, 51, 126],
KeyCode::Insert => vec![27, 91, 50, 126],

View File

@ -1,4 +1,7 @@
use std::rc::Rc;
use crate::{
confirmation::{ConfirmPrompt, ConfirmStatus},
filter::{Filter, SearchAction},
float::{Float, FloatContent},
floating_text::{FloatingText, FloatingTextMode},
@ -8,7 +11,7 @@ use crate::{
};
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
use ego_tree::NodeId;
use linutil_core::{Command, ListNode, Tab};
use linutil_core::{ListNode, Tab};
#[cfg(feature = "tips")]
use rand::Rng;
use ratatui::{
@ -53,7 +56,7 @@ pub struct AppState {
selection: ListState,
filter: Filter,
multi_select: bool,
selected_commands: Vec<Command>,
selected_commands: Vec<Rc<ListNode>>,
drawable: bool,
#[cfg(feature = "tips")]
tip: &'static str,
@ -63,11 +66,12 @@ pub enum Focus {
Search,
TabList,
List,
FloatingWindow(Float),
FloatingWindow(Float<dyn FloatContent>),
ConfirmationPrompt(Float<ConfirmPrompt>),
}
pub struct ListEntry {
pub node: ListNode,
pub node: Rc<ListNode>,
pub id: NodeId,
pub has_children: bool,
}
@ -164,6 +168,7 @@ impl AppState {
),
Focus::FloatingWindow(ref float) => float.get_shortcut_list(),
Focus::ConfirmationPrompt(ref prompt) => prompt.get_shortcut_list(),
}
}
@ -308,7 +313,7 @@ impl AppState {
|ListEntry {
node, has_children, ..
}| {
let is_selected = self.selected_commands.contains(&node.command);
let is_selected = self.selected_commands.contains(node);
let (indicator, style) = if is_selected {
(self.theme.multi_select_icon(), Style::default().bold())
} else {
@ -389,8 +394,10 @@ impl AppState {
frame.render_stateful_widget(disclaimer_list, list_chunks[1], &mut self.selection);
if let Focus::FloatingWindow(float) = &mut self.focus {
float.draw(frame, chunks[1]);
match &mut self.focus {
Focus::FloatingWindow(float) => float.draw(frame, chunks[1]),
Focus::ConfirmationPrompt(prompt) => prompt.draw(frame, chunks[1]),
_ => {}
}
frame.render_widget(keybind_para, vertical[1]);
@ -400,9 +407,11 @@ impl AppState {
// This should be defined first to allow closing
// the application even when not drawable ( If terminal is small )
// Exit on 'q' or 'Ctrl-c' input
if matches!(self.focus, Focus::TabList | Focus::List)
&& (key.code == KeyCode::Char('q')
|| key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c'))
if matches!(
self.focus,
Focus::TabList | Focus::List | Focus::ConfirmationPrompt(_)
) && (key.code == KeyCode::Char('q')
|| key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c'))
{
return false;
}
@ -444,6 +453,22 @@ impl AppState {
}
}
Focus::ConfirmationPrompt(confirm) => {
confirm.content.handle_key_event(key);
match confirm.content.status {
ConfirmStatus::Abort => {
self.focus = Focus::List;
// selected command was pushed to selection list if multi-select was
// enabled, need to clear it to prevent state corruption
if !self.multi_select {
self.selected_commands.clear()
}
}
ConfirmStatus::Confirm => self.handle_confirm_command(),
ConfirmStatus::None => {}
}
}
Focus::Search => match self.filter.handle_key(key) {
SearchAction::Exit => self.exit_search(),
SearchAction::Update => self.update_items(),
@ -503,7 +528,7 @@ impl AppState {
}
fn toggle_selection(&mut self) {
if let Some(command) = self.get_selected_command() {
if let Some(command) = self.get_selected_node() {
if self.selected_commands.contains(&command) {
self.selected_commands.retain(|c| c != &command);
} else {
@ -552,7 +577,7 @@ impl AppState {
self.update_items();
}
fn get_selected_node(&self) -> Option<&ListNode> {
fn get_selected_node(&self) -> Option<Rc<ListNode>> {
let mut selected_index = self.selection.selected().unwrap_or(0);
if !self.at_root() && selected_index == 0 {
@ -564,18 +589,17 @@ impl AppState {
if let Some(item) = self.filter.item_list().get(selected_index) {
if !item.has_children {
return Some(&item.node);
return Some(item.node.clone());
}
}
None
}
pub fn get_selected_command(&self) -> Option<Command> {
self.get_selected_node().map(|node| node.command.clone())
}
fn get_selected_description(&self) -> Option<String> {
self.get_selected_node()
.map(|node| node.description.clone())
}
pub fn go_to_selected_dir(&mut self) {
let mut selected_index = self.selection.selected().unwrap_or(0);
@ -596,6 +620,7 @@ impl AppState {
}
}
}
pub fn selected_item_is_dir(&self) -> bool {
let mut selected_index = self.selection.selected().unwrap_or(0);
@ -615,20 +640,26 @@ impl AppState {
pub fn selected_item_is_cmd(&self) -> bool {
// Any item that is not a directory or up directory (..) must be a command
!(self.selected_item_is_up_dir() || self.selected_item_is_dir())
self.selection.selected().is_some()
&& !(self.selected_item_is_up_dir() || self.selected_item_is_dir())
}
pub fn selected_item_is_up_dir(&self) -> bool {
let selected_index = self.selection.selected().unwrap_or(0);
!self.at_root() && selected_index == 0
}
fn enable_preview(&mut self) {
if let Some(command) = self.get_selected_command() {
if let Some(preview) = FloatingText::from_command(&command, FloatingTextMode::Preview) {
if let Some(node) = self.get_selected_node() {
if let Some(preview) =
FloatingText::from_command(&node.command, FloatingTextMode::Preview)
{
self.spawn_float(preview, 80, 80);
}
}
}
fn enable_description(&mut self) {
if let Some(command_description) = self.get_selected_description() {
let description = FloatingText::new(command_description, FloatingTextMode::Description);
@ -639,31 +670,53 @@ impl AppState {
fn handle_enter(&mut self) {
if self.selected_item_is_cmd() {
if self.selected_commands.is_empty() {
if let Some(cmd) = self.get_selected_command() {
self.selected_commands.push(cmd);
if let Some(node) = self.get_selected_node() {
self.selected_commands.push(node);
}
}
let command = RunningCommand::new(self.selected_commands.clone());
self.spawn_float(command, 80, 80);
self.selected_commands.clear();
let cmd_names = self
.selected_commands
.iter()
.map(|node| node.name.as_str())
.collect::<Vec<_>>();
let prompt = ConfirmPrompt::new(&cmd_names[..]);
self.focus = Focus::ConfirmationPrompt(Float::new(Box::new(prompt), 40, 40));
} else {
self.go_to_selected_dir();
}
}
fn handle_confirm_command(&mut self) {
let commands = self
.selected_commands
.iter()
.map(|node| node.command.clone())
.collect();
let command = RunningCommand::new(commands);
self.spawn_float(command, 80, 80);
self.selected_commands.clear();
}
fn spawn_float<T: FloatContent + 'static>(&mut self, float: T, width: u16, height: u16) {
self.focus = Focus::FloatingWindow(Float::new(Box::new(float), width, height));
}
fn enter_search(&mut self) {
self.focus = Focus::Search;
self.filter.activate_search();
self.selection.select(None);
}
fn exit_search(&mut self) {
self.selection.select(Some(0));
self.focus = Focus::List;
self.filter.deactivate_search();
self.update_items();
}
fn refresh_tab(&mut self) {
self.visit_stack = vec![self.tabs[self.current_tab.selected().unwrap()]
.tree