From 5b415b656750395b3bc8115423dd0124044c64ae Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Thu, 5 Sep 2024 22:28:45 -0400 Subject: [PATCH 01/88] Reduce redundancy --- .github/PULL_REQUEST_TEMPLATE.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3b61761b3..093357d25 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,3 @@ -# Pull Request - -## Title - - ## Type of Change - [ ] New feature - [ ] Bug fix From fcc5a5fc0fc5a4d21cca66fb990b68d4b03383d0 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Tue, 10 Sep 2024 07:21:00 -0400 Subject: [PATCH 02/88] Remove unneeded scripts --- src/commands/test/lib.sh | 5 ----- src/commands/test/main.sh | 6 ------ 2 files changed, 11 deletions(-) delete mode 100755 src/commands/test/lib.sh delete mode 100755 src/commands/test/main.sh diff --git a/src/commands/test/lib.sh b/src/commands/test/lib.sh deleted file mode 100755 index 45e08b7a6..000000000 --- a/src/commands/test/lib.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -say_hello () { - echo Hi -} diff --git a/src/commands/test/main.sh b/src/commands/test/main.sh deleted file mode 100755 index 7af16b963..000000000 --- a/src/commands/test/main.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# The current working directory will always be inside "commands" -. test/lib.sh - -say_hello From 8235a36d4b43e209724de479d638f2f499a21b04 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Thu, 12 Sep 2024 15:50:29 -0400 Subject: [PATCH 03/88] Remove unneeded scripts --- tabs/test/lib.sh | 5 ----- tabs/test/main.sh | 6 ------ 2 files changed, 11 deletions(-) delete mode 100755 tabs/test/lib.sh delete mode 100755 tabs/test/main.sh diff --git a/tabs/test/lib.sh b/tabs/test/lib.sh deleted file mode 100755 index 45e08b7a6..000000000 --- a/tabs/test/lib.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -say_hello () { - echo Hi -} diff --git a/tabs/test/main.sh b/tabs/test/main.sh deleted file mode 100755 index 7af16b963..000000000 --- a/tabs/test/main.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# The current working directory will always be inside "commands" -. test/lib.sh - -say_hello From 725e22ff67e6311a1dea18d698425c0af283fd27 Mon Sep 17 00:00:00 2001 From: Rory Dunne Date: Sat, 7 Sep 2024 11:52:41 -0400 Subject: [PATCH 04/88] fix: Correctly Detect Pictures Directory and Clone Path for Background --- tabs/applications-setup/dwmtitus-setup.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index 8c0fc97ac..7d6398b4f 100644 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -142,29 +142,32 @@ clone_config_folders() { } configure_backgrounds() { + # Set the variable PIC_DIR which stores the path for images + PIC_DIR="$HOME/Pictures" + # Set the variable BG_DIR to the path where backgrounds will be stored - BG_DIR="$HOME/Pictures/backgrounds" + BG_DIR="$PIC_DIR/backgrounds" # Check if the ~/Pictures directory exists - if [ ! -d "~/Pictures" ]; then + if [ ! -d "$PIC_DIR" ]; then # If it doesn't exist, print an error message and return with a status of 1 (indicating failure) echo "Pictures directory does not exist" - mkdir ~/Pictures + mkdir "$PIC_DIR" echo "Directory was created in Home folder" fi - + # Check if the backgrounds directory (BG_DIR) exists if [ ! -d "$BG_DIR" ]; then # If the backgrounds directory doesn't exist, attempt to clone a repository containing backgrounds - if ! git clone https://github.com/ChrisTitusTech/nord-background.git ~/Pictures; then + if ! git clone https://github.com/ChrisTitusTech/nord-background.git "$PIC_DIR/nord-background"; then # If the git clone command fails, print an error message and return with a status of 1 echo "Failed to clone the repository" return 1 fi # Rename the cloned directory to 'backgrounds' - mv ~/Pictures/nord-background ~/Pictures/backgrounds + mv "$PIC_DIR/nord-background" "$PIC_DIR/backgrounds" # Print a success message indicating that the backgrounds have been downloaded - echo "Downloaded desktop backgrounds to $BG_DIR" + echo "Downloaded desktop backgrounds to $BG_DIR" else # If the backgrounds directory already exists, print a message indicating that the download is being skipped echo "Path $BG_DIR exists for desktop backgrounds, skipping download of backgrounds" @@ -290,9 +293,6 @@ setupDisplayManager() { echo "Auto-login configuration skipped" fi fi - - - } checkEnv From d560acac3ab89ce76a0fda5095eb6e8914f9be30 Mon Sep 17 00:00:00 2001 From: guruswarupa Date: Fri, 13 Sep 2024 14:08:30 +0530 Subject: [PATCH 05/88] docker setup added --- tabs/system-setup/6-docker-setup.sh | 87 +++++++++++++++++++++++++++++ tabs/system-setup/tab_data.toml | 4 ++ 2 files changed, 91 insertions(+) create mode 100755 tabs/system-setup/6-docker-setup.sh diff --git a/tabs/system-setup/6-docker-setup.sh b/tabs/system-setup/6-docker-setup.sh new file mode 100755 index 000000000..7f2a0b3f8 --- /dev/null +++ b/tabs/system-setup/6-docker-setup.sh @@ -0,0 +1,87 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to prompt the user for installation choice +choose_installation() { + clear + printf "%b\n" "${YELLOW}Choose what to install:${RC}" + printf "%b\n" "1. ${YELLOW}Docker${RC}" + printf "%b\n" "2. ${YELLOW}Docker Compose${RC}" + printf "%b\n" "3. ${YELLOW}Both${RC}" + read -p "Enter your choice [1-3]: " CHOICE + + case "$CHOICE" in + 1) INSTALL_DOCKER=1; INSTALL_COMPOSE=0 ;; + 2) INSTALL_DOCKER=0; INSTALL_COMPOSE=1 ;; + 3) INSTALL_DOCKER=1; INSTALL_COMPOSE=1 ;; + *) echo "Invalid choice. Exiting."; exit 1 ;; + esac +} + +install_docker() { + printf "%b\n" "${YELLOW}Installing Docker...${RC}" + case $PACKAGER in + apt-get | yum) + curl -fsSL https://get.docker.com | sh + ;; + zypper) + $ESCALATION_TOOL ${PACKAGER} --non-interactive install docker + $ESCALATION_TOOL systemctl enable docker + $ESCALATION_TOOL systemctl start docker + ;; + pacman) + $ESCALATION_TOOL ${PACKAGER} -S --noconfirm docker + $ESCALATION_TOOL systemctl enable docker + $ESCALATION_TOOL systemctl start docker + ;; + *) + printf "${RED}Unsupported package manager. Please install Docker manually.${RC}\n" + exit 1 + ;; + esac +} + +install_docker_compose() { + printf "%b\n" "${YELLOW}Installing Docker Compose...${RC}" + case $PACKAGER in + apt-get | yum) + $ESCALATION_TOOL ${PACKAGER} update + $ESCALATION_TOOL ${PACKAGER} install -y docker-compose-plugin + ;; + zypper) + $ESCALATION_TOOL ${PACKAGER} --non-interactive install docker-compose + ;; + pacman) + $ESCALATION_TOOL ${PACKAGER} -S --noconfirm docker-compose + ;; + *) + printf "${RED}Unsupported package manager. Please install Docker Compose manually.${RC}\n" + exit 1 + ;; + esac +} + +install_components() { + choose_installation + + if [ "$INSTALL_DOCKER" -eq 1 ]; then + if ! command_exists docker; then + install_docker + else + printf "%b\n" "${GREEN}Docker is already installed.${RC}" + fi + fi + + if [ "$INSTALL_COMPOSE" -eq 1 ]; then + if ! command_exists docker-compose || ! command_exists docker compose version; then + install_docker_compose + else + printf "%b\n" "${GREEN}Docker Compose is already installed.${RC}" + fi + fi +} + +checkEnv +checkEscalationTool +install_components diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 6743da3c7..c1c8f02b1 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -51,3 +51,7 @@ script = "3-global-theme.sh" [[data]] name = "Remove Snaps" script = "4-remove-snaps.sh" + +[[data]] +name = "Docker Setup" +script = "6-docker-setup.sh" From c3abd7e38ef3101dedf9742d52e0135ebc871a92 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sat, 14 Sep 2024 07:36:35 -0400 Subject: [PATCH 06/88] Increase Partition size --- tabs/system-setup/arch/server-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/arch/server-setup.sh b/tabs/system-setup/arch/server-setup.sh index 87400b228..a0a78cc4a 100755 --- a/tabs/system-setup/arch/server-setup.sh +++ b/tabs/system-setup/arch/server-setup.sh @@ -336,7 +336,7 @@ sgdisk -a 2048 -o ${DISK} # new gpt disk 2048 alignment # create partitions sgdisk -n 1::+1M --typecode=1:ef02 --change-name=1:'BIOSBOOT' ${DISK} # partition 1 (BIOS Boot Partition) -sgdisk -n 2::+300M --typecode=2:ef00 --change-name=2:'EFIBOOT' ${DISK} # partition 2 (UEFI Boot Partition) +sgdisk -n 2::+1GiB --typecode=2:ef00 --change-name=2:'EFIBOOT' ${DISK} # partition 2 (UEFI Boot Partition) sgdisk -n 3::-0 --typecode=3:8300 --change-name=3:'ROOT' ${DISK} # partition 3 (Root), default start, remaining if [[ ! -d "/sys/firmware/efi" ]]; then # Checking for bios system sgdisk -A 1:set:2 ${DISK} From 3f67abc9186e2fcbd06a602fa2cc2b6ce037a2d8 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sat, 14 Sep 2024 11:30:03 -0400 Subject: [PATCH 07/88] fix typos --- tui/src/hint.rs | 10 +++++----- tui/src/state.rs | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tui/src/hint.rs b/tui/src/hint.rs index 27474ea99..37947159e 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -16,7 +16,7 @@ pub struct ShortcutList { } pub struct Shortcut { - pub key_sequenses: Vec>, + pub key_sequences: Vec>, pub desc: &'static str, } @@ -75,7 +75,7 @@ impl ShortcutList { impl Shortcut { pub fn new(key_sequences: Vec<&'static str>, desc: &'static str) -> Self { Self { - key_sequenses: key_sequences + key_sequences: key_sequences .iter() .map(|s| Span::styled(*s, Style::default().bold())) .collect(), @@ -85,7 +85,7 @@ impl Shortcut { fn to_spans(&self) -> Vec { let mut ret: Vec<_> = self - .key_sequenses + .key_sequences .iter() .flat_map(|seq| { [ @@ -124,10 +124,10 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { if state.selected_item_is_up_dir() { hints.push(Shortcut::new( vec!["l", "Right", "Enter", "h", "Left"], - "Go to parrent directory", + "Go to parent directory", )); } else { - hints.push(Shortcut::new(vec!["h", "Left"], "Go to parrent directory")); + hints.push(Shortcut::new(vec!["h", "Left"], "Go to parent directory")); hints.push(get_list_item_shortcut(state)); if state.selected_item_is_cmd() { hints.push(Shortcut::new(vec!["p"], "Enable preview")); diff --git a/tui/src/state.rs b/tui/src/state.rs index 267e6769c..8d1e1d7bd 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -26,7 +26,7 @@ pub struct AppState { tabs: Vec, /// Current tab current_tab: ListState, - /// This stack keeps track of our "current dirrectory". You can think of it as `pwd`. but not + /// This stack keeps track of our "current directory". You can think of it as `pwd`. but not /// just the current directory, all paths that took us here, so we can "cd .." visit_stack: Vec, /// This is the state asociated with the list widget, used to display the selection in the @@ -246,7 +246,7 @@ impl AppState { *self.visit_stack.last().unwrap(), ); } - /// Checks ehther the current tree node is the root node (can we go up the tree or no) + /// Checks either the current tree node is the root node (can we go up the tree or no) /// Returns `true` if we can't go up the tree (we are at the tree root) /// else returns `false` pub fn at_root(&self) -> bool { From 4fa0079cb786c4ece1cf1349d3258fe649c654b3 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sun, 15 Sep 2024 20:32:37 -0400 Subject: [PATCH 08/88] Fix last bashism --- startdev.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/startdev.sh b/startdev.sh index 1070ea429..b58dc8f5e 100755 --- a/startdev.sh +++ b/startdev.sh @@ -35,7 +35,7 @@ check() { local message=$2 if [ $exit_code -ne 0 ]; then - echo -e "${RED}ERROR: $message${RC}" + printf "%b\n" "${RED}ERROR: $message${RC}" exit 1 fi } From 6753c80b06584b48394859eb7bef7dfa6bc0513a Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Sun, 15 Sep 2024 21:23:53 -0400 Subject: [PATCH 09/88] Use -e & Keep synergy with every other script --- start.sh | 2 +- startdev.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/start.sh b/start.sh index d1e7658ae..b6fe4fdc8 100755 --- a/start.sh +++ b/start.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -e rc='\033[0m' red='\033[0;31m' diff --git a/startdev.sh b/startdev.sh index 1070ea429..301eb798d 100755 --- a/startdev.sh +++ b/startdev.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh -e RC='\033[0m' RED='\033[0;31m' From 61cddeb2566f0c874c15428986381832203f3591 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Mon, 16 Sep 2024 19:34:15 +0530 Subject: [PATCH 10/88] Swap nala apt-get --- tabs/common-script.sh | 2 +- tabs/system-setup/3-global-theme.sh | 16 ++++++++-------- tabs/utils/monitor-control/utility_functions.sh | 5 +++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index aa4deae95..45d925e77 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -125,7 +125,7 @@ checkDistro() { checkEnv() { checkCommandRequirements 'curl groups sudo' - checkPackageManager 'apt-get nala dnf pacman zypper yum xbps-install nix-env' + checkPackageManager 'nala apt-get dnf pacman zypper yum xbps-install nix-env' checkCurrentDirectoryWritable checkSuperUser checkDistro diff --git a/tabs/system-setup/3-global-theme.sh b/tabs/system-setup/3-global-theme.sh index c3e360da5..d5b1c6670 100644 --- a/tabs/system-setup/3-global-theme.sh +++ b/tabs/system-setup/3-global-theme.sh @@ -5,20 +5,20 @@ install_theme_tools() { printf "%b\n" "${YELLOW}Installing theme tools (qt6ct and kvantum)...${RC}\n" case $PACKAGER in - apt-get) - $ESCALATION_TOOL apt-get update - $ESCALATION_TOOL apt-get install -y qt6ct kvantum + apt-get|nala) + $ESCALATION_TOOL "${PACKAGER}" update + $ESCALATION_TOOL "${PACKAGER}" install -y qt6ct kvantum ;; zypper) - $ESCALATION_TOOL zypper refresh - $ESCALATION_TOOL zypper --non-interactive install qt6ct kvantum + $ESCALATION_TOOL "${PACKAGER}" refresh + $ESCALATION_TOOL "${PACKAGER}" --non-interactive install qt6ct kvantum ;; dnf) - $ESCALATION_TOOL dnf update - $ESCALATION_TOOL dnf install -y qt6ct kvantum + $ESCALATION_TOOL "${PACKAGER}" update + $ESCALATION_TOOL "${PACKAGER}" install -y qt6ct kvantum ;; pacman) - $ESCALATION_TOOL pacman -S --needed --noconfirm qt6ct kvantum + $ESCALATION_TOOL "${PACKAGER}" -S --needed --noconfirm qt6ct kvantum ;; *) printf "%b\n" "${RED}Unsupported package manager. Please install qt6ct and kvantum manually.${RC}\n" diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index 48b4c8da9..d2bde1513 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -10,7 +10,7 @@ setup_xrandr() { pacman) $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm xorg-xrandr ;; - apt-get) + apt-get|nala) $ESCALATION_TOOL "${PACKAGER}" install -y x11-xserver-utils ;; *) @@ -83,4 +83,5 @@ confirm_action() { } checkEnv -setup_xrandr \ No newline at end of file +checkEscalationTool +setup_xrandr From 2c447f74913b6cc4c421e6480531c9f4e5990fd3 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Mon, 16 Sep 2024 22:10:02 -0400 Subject: [PATCH 11/88] Fix grammatical errors --- tabs/applications-setup/alacritty-setup.sh | 10 +++++----- tabs/applications-setup/fastfetch-setup.sh | 6 +++--- tabs/applications-setup/kitty-setup.sh | 8 ++++---- tabs/applications-setup/mybash-setup.sh | 2 +- tabs/applications-setup/neovim-setup.sh | 8 +++++--- tabs/applications-setup/rofi-setup.sh | 8 ++++---- tabs/applications-setup/zsh-setup.sh | 11 ++++++----- tabs/security/firewall-baselines.sh | 4 ++-- tabs/system-setup/system-update.sh | 2 +- 9 files changed, 31 insertions(+), 28 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 92e49d337..c808ce460 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -2,8 +2,8 @@ . ../common-script.sh -setupAlacritty() { - echo "Install Alacritty if not already installed..." +installAlacritty() { + echo "Installing Alacritty..." if ! command_exists alacritty; then case ${PACKAGER} in pacman) @@ -14,12 +14,12 @@ setupAlacritty() { ;; esac else - echo "alacritty is already installed." + echo "Alacritty is already installed." fi } setupAlacrittyConfig() { - echo "Copy alacritty config files" + echo "Copying Alacritty configuration files..." if [ -d "${HOME}/.config/alacritty" ] && [ ! -d "${HOME}/.config/alacritty-bak" ]; then cp -r "${HOME}/.config/alacritty" "${HOME}/.config/alacritty-bak" fi @@ -30,5 +30,5 @@ setupAlacrittyConfig() { checkEnv checkEscalationTool -setupAlacritty +installAlacritty setupAlacrittyConfig \ No newline at end of file diff --git a/tabs/applications-setup/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index e3f9a4f72..1fbe7472c 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -2,8 +2,8 @@ . ../common-script.sh -setupFastfetch() { - echo "Installing Fastfetch if not already installed..." +installFastfetch() { + echo "Installing Fastfetch..." if ! command_exists fastfetch; then case ${PACKAGER} in pacman) @@ -29,5 +29,5 @@ setupFastfetchConfig() { checkEnv checkEscalationTool -setupFastfetch +installFastfetch setupFastfetchConfig \ No newline at end of file diff --git a/tabs/applications-setup/kitty-setup.sh b/tabs/applications-setup/kitty-setup.sh index 7afbbe5d8..ab3f3e00c 100755 --- a/tabs/applications-setup/kitty-setup.sh +++ b/tabs/applications-setup/kitty-setup.sh @@ -2,8 +2,8 @@ . ../common-script.sh -setupKitty() { - echo "Install Kitty if not already installed..." +installKitty() { + echo "Installing Kitty..." if ! command_exists kitty; then case ${PACKAGER} in pacman) @@ -19,7 +19,7 @@ setupKitty() { } setupKittyConfig() { - echo "Copy Kitty config files" + echo "Copying Kitty configuration files..." if [ -d "${HOME}/.config/kitty" ] && [ ! -d "${HOME}/.config/kitty-bak" ]; then cp -r "${HOME}/.config/kitty" "${HOME}/.config/kitty-bak" fi @@ -30,5 +30,5 @@ setupKittyConfig() { checkEnv checkEscalationTool -setupKitty +installKitty setupKittyConfig \ No newline at end of file diff --git a/tabs/applications-setup/mybash-setup.sh b/tabs/applications-setup/mybash-setup.sh index 7bca14e2c..ad1e9c4e2 100644 --- a/tabs/applications-setup/mybash-setup.sh +++ b/tabs/applications-setup/mybash-setup.sh @@ -14,7 +14,7 @@ cloneMyBash() { } installDepend() { - echo "Install mybash if not already installed" + echo "Installing Bash..." case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 0d3a2578d..6d1cf5af4 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -13,8 +13,8 @@ cloneNeovim() { cd "$HOME" && git clone https://github.com/ChrisTitusTech/neovim.git "$HOME/.local/share/neovim" } -setupNeovim() { - echo "Install Neovim if not already installed" +installNeovim() { + echo "Installing Neovim..." case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck @@ -36,6 +36,7 @@ setupNeovim() { } backupNeovimConfig() { + echo "Backing up existing configuration files..." if [ -d "$HOME/.config/nvim" ] && [ ! -d "$HOME/.config/nvim-backup" ]; then cp -r "$HOME/.config/nvim" "$HOME/.config/nvim-backup" fi @@ -43,6 +44,7 @@ backupNeovimConfig() { } linkNeovimConfig() { + echo "Linking Neovim configuration files..." mkdir -p "$HOME/.config/nvim" ln -s "$gitpath/titus-kickstart/"* "$HOME/.config/nvim/" # Wild card is used here to link all contents of titus-kickstart. } @@ -50,6 +52,6 @@ linkNeovimConfig() { checkEnv checkEscalationTool cloneNeovim -setupNeovim +installNeovim backupNeovimConfig linkNeovimConfig \ No newline at end of file diff --git a/tabs/applications-setup/rofi-setup.sh b/tabs/applications-setup/rofi-setup.sh index c58745170..c2e1ff37f 100755 --- a/tabs/applications-setup/rofi-setup.sh +++ b/tabs/applications-setup/rofi-setup.sh @@ -2,8 +2,8 @@ . ../common-script.sh -setupRofi() { - echo "Install Rofi if not already installed..." +installRofi() { + echo "Installing Rofi..." if ! command_exists rofi; then case "$PACKAGER" in pacman) @@ -19,7 +19,7 @@ setupRofi() { } setupRofiConfig() { - echo "Copy Rofi config files" + echo "Copying Rofi configuration files..." if [ -d "$HOME/.config/rofi" ] && [ ! -d "$HOME/.config/rofi-bak" ]; then cp -r "$HOME/.config/rofi" "$HOME/.config/rofi-bak" fi @@ -35,5 +35,5 @@ setupRofiConfig() { checkEnv checkEscalationTool -setupRofi +installRofi setupRofiConfig diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index eaa608b5f..16423cf77 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -3,8 +3,8 @@ . ../common-script.sh # Function to install zsh -install_zsh() { - echo "Install ZSH if not already installed..." +installZsh() { + echo "Installing Zsh..." if ! command_exists zsh; then case "$PACKAGER" in pacman) @@ -20,7 +20,8 @@ install_zsh() { } # Function to setup zsh configuration -setup_zsh_config() { +setupZshConfig() { + echo "Setting up Zsh configuration..." CONFIG_DIR="$HOME/.config/zsh" ZSHRC_FILE="$CONFIG_DIR/.zshrc" @@ -48,5 +49,5 @@ EOL checkEnv checkEscalationTool -install_zsh -setup_zsh_config +installZsh +setupZshConfig diff --git a/tabs/security/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 5abb0c766..1ed974cc1 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -3,7 +3,7 @@ . ../common-script.sh installPkg() { - echo "Install UFW if not already installed..." + echo "Installing UFW..." if ! command_exists ufw; then case ${PACKAGER} in pacman) @@ -19,7 +19,7 @@ installPkg() { } configureUFW() { - printf "%b\n" "${GREEN}Using Chris Titus Recommended Firewall Rules${RC}" + printf "%b\n" "${YELLOW}Using Chris Titus Recommended Firewall Rules${RC}" echo "Disabling UFW" $ESCALATION_TOOL ufw disable diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index e6b32af6d..4529befee 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -61,7 +61,7 @@ fastUpdate() { } updateSystem() { - printf "%b\n" "${GREEN}Updating system${RC}" + printf "%b\n" "${YELLOW}Updating system${RC}" case ${PACKAGER} in nala|apt-get) $ESCALATION_TOOL "${PACKAGER}" update -y From c1c60aae7b9b64ce92db2ac5221141f69bb895e7 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Mon, 16 Sep 2024 22:44:20 -0400 Subject: [PATCH 12/88] Incorporate colors into current scripts --- tabs/applications-setup/alacritty-setup.sh | 7 +- tabs/applications-setup/dwmtitus-setup.sh | 94 +++++++++++----------- tabs/applications-setup/fastfetch-setup.sh | 6 +- tabs/applications-setup/kitty-setup.sh | 6 +- tabs/applications-setup/mybash-setup.sh | 14 ++-- tabs/applications-setup/neovim-setup.sh | 2 +- tabs/applications-setup/rofi-setup.sh | 6 +- tabs/applications-setup/zsh-setup.sh | 4 +- tabs/gaming/diablo-ii/d2r-loot-filters.sh | 12 +-- tabs/security/firewall-baselines.sh | 12 +-- tabs/system-setup/1-compile-setup.sh | 2 +- tabs/system-setup/4-remove-snaps.sh | 2 +- 12 files changed, 84 insertions(+), 83 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 92e49d337..796315d20 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -3,7 +3,7 @@ . ../common-script.sh setupAlacritty() { - echo "Install Alacritty if not already installed..." + printf "%b\n" "${YELLOW}Install Alacritty if not already installed...${RC}" if ! command_exists alacritty; then case ${PACKAGER} in pacman) @@ -14,18 +14,19 @@ setupAlacritty() { ;; esac else - echo "alacritty is already installed." + printf "%b\n" "${RED}alacritty is already installed.${RC}" fi } setupAlacrittyConfig() { - echo "Copy alacritty config files" + printf "%b\n" "${YELLOW}Copy alacritty config files${RC}" if [ -d "${HOME}/.config/alacritty" ] && [ ! -d "${HOME}/.config/alacritty-bak" ]; then cp -r "${HOME}/.config/alacritty" "${HOME}/.config/alacritty-bak" fi mkdir -p "${HOME}/.config/alacritty/" curl -sSLo "${HOME}/.config/alacritty/alacritty.toml" "https://github.com/ChrisTitusTech/dwm-titus/raw/main/config/alacritty/alacritty.toml" curl -sSLo "${HOME}/.config/alacritty/nordic.toml" "https://github.com/ChrisTitusTech/dwm-titus/raw/main/config/alacritty/nordic.toml" + printf "%b\n" "${GREEN}Alacritty configuration files copied.${RC}" } checkEnv diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index acc56c0e7..58b22fe10 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -10,7 +10,7 @@ makeDWM() { } setupDWM() { - echo "Installing DWM-Titus if not already installed" + printf "%b\n" "${YELLOW}Installing DWM-Titus if not already installed${RC}" case "$PACKAGER" in # Install pre-Requisites pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb @@ -23,7 +23,7 @@ setupDWM() { $ESCALATION_TOOL "$PACKAGER" install -y libX11-devel libXinerama-devel libXft-devel imlib2-devel libxcb-devel ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac @@ -37,56 +37,56 @@ install_nerd_font() { # Check if Meslo Nerd-font is already installed if [ -n "$FONT_INSTALLED" ]; then - echo "Meslo Nerd-fonts are already installed." + printf "%b\n" "${RED}Meslo Nerd-fonts are already installed.${RC}" return 0 fi - echo "Installing Meslo Nerd-fonts" + printf "%b\n" "${YELLOW}Installing Meslo Nerd-fonts${RC}" # Create the fonts directory if it doesn't exist if [ ! -d "$FONT_DIR" ]; then mkdir -p "$FONT_DIR" || { - echo "Failed to create directory: $FONT_DIR" + printf "%b\n" "${RED}Failed to create directory: $FONT_DIR${RC}" return 1 } else - echo "$FONT_DIR exists, skipping creation." + printf "%b\n" "${GREEN}$FONT_DIR exists, skipping creation.${RC}" fi # Check if the font zip file already exists if [ ! -f "$FONT_ZIP" ]; then # Download the font zip file curl -sSLo "$FONT_ZIP" "$FONT_URL" || { - echo "Failed to download Meslo Nerd-fonts from $FONT_URL" + printf "%b\n" "${RED}Failed to download Meslo Nerd-fonts from $FONT_URL${RC}" return 1 } else - echo "Meslo.zip already exists in $FONT_DIR, skipping download." + printf "%b\n" "${GREEN}Meslo.zip already exists in $FONT_DIR, skipping download.${RC}" fi # Unzip the font file if it hasn't been unzipped yet if [ ! -d "$FONT_DIR/Meslo" ]; then unzip "$FONT_ZIP" -d "$FONT_DIR" || { - echo "Failed to unzip $FONT_ZIP" + printf "%b\n" "${RED}Failed to unzip $FONT_ZIP${RC}" return 1 } else - echo "Meslo font files already unzipped in $FONT_DIR, skipping unzip." + printf "%b\n" "${GREEN}Meslo font files already unzipped in $FONT_DIR, skipping unzip.${RC}" fi # Remove the zip file rm "$FONT_ZIP" || { - echo "Failed to remove $FONT_ZIP" + printf "%b\n" "${RED}Failed to remove $FONT_ZIP${RC}" return 1 } # Rebuild the font cache fc-cache -fv || { - echo "Failed to rebuild font cache" + printf "%b\n" "${RED}Failed to rebuild font cache${RC}" return 1 } - echo "Meslo Nerd-fonts installed successfully" + printf "%b\n" "${GREEN}Meslo Nerd-fonts installed successfully${RC}" } picom_animations() { @@ -94,33 +94,33 @@ picom_animations() { mkdir -p ~/build if [ ! -d ~/build/picom ]; then if ! git clone https://github.com/FT-Labs/picom.git ~/build/picom; then - echo "Failed to clone the repository" + printf "%b\n" "${RED}Failed to clone the repository${RC}" return 1 fi else - echo "Repository already exists, skipping clone" + printf "%b\n" "${GREEN}Repository already exists, skipping clone${RC}" fi - cd ~/build/picom || { echo "Failed to change directory to picom"; return 1; } + cd ~/build/picom || { printf "%b\n" "${RED}Failed to change directory to picom${RC}"; return 1; } # Build the project if ! meson setup --buildtype=release build; then - echo "Meson setup failed" + printf "%b\n" "${RED}Meson setup failed${RC}" return 1 fi if ! ninja -C build; then - echo "Ninja build failed" + printf "%b\n" "${RED}Ninja build failed${RC}" return 1 fi # Install the built binary if ! $ESCALATION_TOOL ninja -C build install; then - echo "Failed to install the built binary" + printf "%b\n" "${RED}Failed to install the built binary${RC}" return 1 fi - echo "Picom animations installed successfully" + printf "%b\n" "${GREEN}Picom animations installed successfully${RC}" } clone_config_folders() { @@ -135,9 +135,9 @@ clone_config_folders() { # Clone the directory to ~/.config/ if [ -d "$dir" ]; then cp -r "$dir" ~/.config/ - echo "Cloned $dir_name to ~/.config/" + printf "%b\n" "${GREEN}Cloned $dir_name to ~/.config/${RC}" else - echo "Directory $dir_name does not exist, skipping" + printf "%b\n" "${RED}Directory $dir_name does not exist, skipping${RC}" fi done } @@ -149,9 +149,9 @@ configure_backgrounds() { # Check if the ~/Pictures directory exists if [ ! -d "~/Pictures" ]; then # If it doesn't exist, print an error message and return with a status of 1 (indicating failure) - echo "Pictures directory does not exist" + printf "%b\n" "${RED}Pictures directory does not exist${RC}" mkdir ~/Pictures - echo "Directory was created in Home folder" + printf "%b\n" "${GREEN}Directory was created in Home folder${RC}" fi # Check if the backgrounds directory (BG_DIR) exists @@ -159,21 +159,21 @@ configure_backgrounds() { # If the backgrounds directory doesn't exist, attempt to clone a repository containing backgrounds if ! git clone https://github.com/ChrisTitusTech/nord-background.git ~/Pictures; then # If the git clone command fails, print an error message and return with a status of 1 - echo "Failed to clone the repository" + printf "%b\n" "${RED}Failed to clone the repository${RC}" return 1 fi # Rename the cloned directory to 'backgrounds' mv ~/Pictures/nord-background ~/Pictures/backgrounds # Print a success message indicating that the backgrounds have been downloaded - echo "Downloaded desktop backgrounds to $BG_DIR" + printf "%b\n" "${GREEN}Downloaded desktop backgrounds to $BG_DIR${RC}" else # If the backgrounds directory already exists, print a message indicating that the download is being skipped - echo "Path $BG_DIR exists for desktop backgrounds, skipping download of backgrounds" + printf "%b\n" "${RED}Path $BG_DIR exists for desktop backgrounds, skipping download of backgrounds${RC}" fi } setupDisplayManager() { - echo "Setting up Xorg" + printf "%b\n" "${YELLOW}Setting up Xorg${RC}" case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm xorg-xinit xorg-server @@ -185,12 +185,12 @@ setupDisplayManager() { $ESCALATION_TOOL "$PACKAGER" install -y xorg-x11-xinit xorg-x11-server-Xorg ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac - echo "Xorg installed successfully" - echo "Setting up Display Manager" + printf "%b\n" "${GREEN}Xorg installed successfully${RC}" + printf "%b\n" "${YELLOW}Setting up Display Manager${RC}" currentdm="none" for dm in gdm sddm lightdm; do if systemctl is-active --quiet "$dm.service"; then @@ -198,10 +198,10 @@ setupDisplayManager() { break fi done - echo "Current display manager: $currentdm" + printf "%b\n" "${GREEN}Current display manager: $currentdm${RC}" if [ "$currentdm" = "none" ]; then DM="sddm" - echo "No display manager found, installing $DM" + printf "%b\n" "${YELLOW}No display manager found, installing $DM${RC}" case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm "$DM" @@ -213,11 +213,11 @@ setupDisplayManager() { $ESCALATION_TOOL "$PACKAGER" install -y "$DM" ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; esac - echo "$DM installed successfully" + printf "%b\n" "${GREEN}$DM installed successfully${RC}" systemctl enable "$DM" # Prompt user for auto-login @@ -226,7 +226,7 @@ setupDisplayManager() { read -r answer case "$answer" in [Yy]*) - echo "Configuring SDDM for autologin" + printf "%b\n" "${YELLOW}Configuring SDDM for autologin${RC}" SDDM_CONF="/etc/sddm.conf" if [ ! -f "$SDDM_CONF" ]; then echo "[Autologin]" | $ESCALATION_TOOL tee -a "$SDDM_CONF" @@ -240,24 +240,24 @@ setupDisplayManager() { echo "User=$USER" | $ESCALATION_TOOL tee -a "$SDDM_CONF" echo "Session=dwm" | $ESCALATION_TOOL tee -a "$SDDM_CONF" fi - echo "Checking if autologin group exists" + printf "%b\n" "{YELLOW}Checking if autologin group exists${RC}" if ! getent group autologin > /dev/null; then - echo "Creating autologin group" + printf "%b\n" "${YELLOW}Creating autologin group${RC}" $ESCALATION_TOOL groupadd autologin else - echo "Autologin group already exists" + printf "%b\n" "${RED}Autologin group already exists${RC}" fi - echo "Adding user with UID 1000 to autologin group" + printf "%b\n" "${YELLOW}Adding user with UID 1000 to autologin group${RC}" USER_UID_1000=$(getent passwd 1000 | cut -d: -f1) if [ -n "$USER_UID_1000" ]; then $ESCALATION_TOOL usermod -aG autologin "$USER_UID_1000" - echo "User $USER_UID_1000 added to autologin group" + printf "%b\n" "${GREEN}User $USER_UID_1000 added to autologin group${RC}" else - echo "No user with UID 1000 found - Auto login not possible" + printf "%b\n" "${RED}No user with UID 1000 found - Auto login not possible${RC}" fi ;; *) - echo "Auto-login configuration skipped" + printf "%b\n" "${GREEN}Auto-login configuration skipped${RC}" ;; esac fi @@ -270,16 +270,16 @@ install_slstatus() { printf "Do you want to install slstatus? (y/N): " # using printf instead of 'echo' to avoid newline, -n flag for 'echo' is not supported in POSIX read -r response # -r flag to prevent backslashes from being interpreted if [ "$response" = "y" ] || [ "$response" = "Y" ]; then - echo "Installing slstatus" + printf "%b\n" "${YELLOW}Installing slstatus${RC}" cd "$HOME/dwm-titus/slstatus" || { echo "Failed to change directory to slstatus"; return 1; } if $ESCALATION_TOOL make clean install; then - echo "slstatus installed successfully" + printf "%b\n" "${GREEN}slstatus installed successfully${RC}" else - echo "Failed to install slstatus" + printf "%b\n" "${RED}Failed to install slstatus${RC}" return 1 fi else - echo "Skipping slstatus installation" + printf "%b\n" "${GREEN}Skipping slstatus installation${RC}" fi cd "$HOME" } diff --git a/tabs/applications-setup/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index e3f9a4f72..20d756e2a 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -3,7 +3,7 @@ . ../common-script.sh setupFastfetch() { - echo "Installing Fastfetch if not already installed..." + printf "%b\n" "${YELLOW}Installing Fastfetch if not already installed...${RC}" if ! command_exists fastfetch; then case ${PACKAGER} in pacman) @@ -14,12 +14,12 @@ setupFastfetch() { ;; esac else - echo "Fastfetch is already installed." + printf "%b\n" "${GREEN}Fastfetch is already installed.${RC}" fi } setupFastfetchConfig() { - echo "Copying Fastfetch config files..." + printf "%b\n" "${YELLOW}Copying Fastfetch config files...${RC}" if [ -d "${HOME}/.config/fastfetch" ] && [ ! -d "${HOME}/.config/fastfetch-bak" ]; then cp -r "${HOME}/.config/fastfetch" "${HOME}/.config/fastfetch-bak" fi diff --git a/tabs/applications-setup/kitty-setup.sh b/tabs/applications-setup/kitty-setup.sh index 7afbbe5d8..b5b3bca98 100755 --- a/tabs/applications-setup/kitty-setup.sh +++ b/tabs/applications-setup/kitty-setup.sh @@ -3,7 +3,7 @@ . ../common-script.sh setupKitty() { - echo "Install Kitty if not already installed..." + printf "%b\n" "${YELLOW}Install Kitty if not already installed...${RC}" if ! command_exists kitty; then case ${PACKAGER} in pacman) @@ -14,12 +14,12 @@ setupKitty() { ;; esac else - echo "Kitty is already installed." + printf "%b\n" "${GREEN}Kitty is already installed.${RC}" fi } setupKittyConfig() { - echo "Copy Kitty config files" + printf "%b\n" "${YELLOW}Copy Kitty config files${RC}" if [ -d "${HOME}/.config/kitty" ] && [ ! -d "${HOME}/.config/kitty-bak" ]; then cp -r "${HOME}/.config/kitty" "${HOME}/.config/kitty-bak" fi diff --git a/tabs/applications-setup/mybash-setup.sh b/tabs/applications-setup/mybash-setup.sh index 7bca14e2c..526b3e8eb 100644 --- a/tabs/applications-setup/mybash-setup.sh +++ b/tabs/applications-setup/mybash-setup.sh @@ -14,7 +14,7 @@ cloneMyBash() { } installDepend() { - echo "Install mybash if not already installed" + printf "%b\n" "${YELLOW}Install mybash if not already installed${RC}" case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig @@ -39,9 +39,9 @@ installFont() { # Check to see if the MesloLGS Nerd Font is installed (Change this to whatever font you would like) FONT_NAME="MesloLGS Nerd Font Mono" if fc-list :family | grep -iq "$FONT_NAME"; then - echo "Font '$FONT_NAME' is installed." + printf "%b\n" "${GREEN}Font '$FONT_NAME' is installed.${RC}" else - echo "Installing font '$FONT_NAME'" + printf "%b\n" "${YELLOW}Installing font '$FONT_NAME'${RC}" # Change this URL to correspond with the correct font FONT_URL="https://github.com/ryanoasis/nerd-fonts/releases/latest/download/Meslo.zip" FONT_DIR="$HOME/.local/share/fonts" @@ -52,13 +52,13 @@ installFont() { mv "${TEMP_DIR}"/*.ttf "$FONT_DIR"/"$FONT_NAME" fc-cache -fv rm -rf "${TEMP_DIR}" - echo "'$FONT_NAME' installed successfully." + printf "%b\n" "${GREEN}'$FONT_NAME' installed successfully.${RC}" fi } installStarshipAndFzf() { if command_exists starship; then - echo "Starship already installed" + printf "%b\n" "${GREEN}Starship already installed${RC}" return fi @@ -67,7 +67,7 @@ installStarshipAndFzf() { exit 1 fi if command_exists fzf; then - echo "Fzf already installed" + printf "%b\n" "${GREEN}Fzf already installed${RC}" else git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf $ESCALATION_TOOL ~/.fzf/install @@ -76,7 +76,7 @@ installStarshipAndFzf() { installZoxide() { if command_exists zoxide; then - echo "Zoxide already installed" + printf "%b\n" "${GREEN}Zoxide already installed${RC}" return fi diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 0d3a2578d..042eea3da 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -14,7 +14,7 @@ cloneNeovim() { } setupNeovim() { - echo "Install Neovim if not already installed" + printf "%b\n" "${YELLOW}Install Neovim if not already installed${RC}" case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck diff --git a/tabs/applications-setup/rofi-setup.sh b/tabs/applications-setup/rofi-setup.sh index c58745170..58c463259 100755 --- a/tabs/applications-setup/rofi-setup.sh +++ b/tabs/applications-setup/rofi-setup.sh @@ -3,7 +3,7 @@ . ../common-script.sh setupRofi() { - echo "Install Rofi if not already installed..." + printf "%b\n" "${YELLOW}Install Rofi if not already installed...${RC}" if ! command_exists rofi; then case "$PACKAGER" in pacman) @@ -14,12 +14,12 @@ setupRofi() { ;; esac else - echo "Rofi is already installed." + printf "%b\n" "${GREEN}Rofi is already installed.${RC}" fi } setupRofiConfig() { - echo "Copy Rofi config files" + printf "%b\n" "${YELLOW}Copy Rofi config files${RC}" if [ -d "$HOME/.config/rofi" ] && [ ! -d "$HOME/.config/rofi-bak" ]; then cp -r "$HOME/.config/rofi" "$HOME/.config/rofi-bak" fi diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index eaa608b5f..991c38493 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -4,7 +4,7 @@ # Function to install zsh install_zsh() { - echo "Install ZSH if not already installed..." + printf "%b\n" "${YELLOW}Install ZSH if not already installed...${RC}" if ! command_exists zsh; then case "$PACKAGER" in pacman) @@ -15,7 +15,7 @@ install_zsh() { ;; esac else - echo "ZSH is already installed." + printf "%b\n" "${GREEN}ZSH is already installed.${RC}" fi } diff --git a/tabs/gaming/diablo-ii/d2r-loot-filters.sh b/tabs/gaming/diablo-ii/d2r-loot-filters.sh index 1fa43fabd..a7cd7694a 100755 --- a/tabs/gaming/diablo-ii/d2r-loot-filters.sh +++ b/tabs/gaming/diablo-ii/d2r-loot-filters.sh @@ -1,11 +1,11 @@ #!/bin/bash # Search for possible Diablo II Resurrected folder locations -echo "Searching for Diablo II Resurrected folders..." +printf "%b\n" "${YELLOW}Searching for Diablo II Resurrected folders...${RC}" possible_paths=$(find $HOME -type d -path "*/drive_c/Program Files (x86)/Diablo II Resurrected" 2>/dev/null) if [ -z "$possible_paths" ]; then - echo "Error: No Diablo II Resurrected folders found." + printf "%b\n" "${RED}Error: No Diablo II Resurrected folders found.${RC}" exit 1 fi @@ -23,7 +23,7 @@ print_menu() { if ((start + max_display > total)); then start=$((total - max_display)); fi if ((start < 0)); then start=0; fi - echo "Please select the Diablo II: Resurrected installation path:" + printf "%b\n" "${YELLOW}Please select the Diablo II: Resurrected installation path:${RC}" for i in $(seq 0 $((max_display - 1))); do if ((i + start >= total)); then break; fi if [ $((i + start)) -eq $selected ]; then @@ -84,17 +84,17 @@ mods_path="$d2r_path/mods" mkdir -p "$mods_path" # Download the latest release -echo "Downloading the latest loot filter..." +printf "%b\n" "${YELLOW}Downloading the latest loot filter...${RC}" curl -sSLo /tmp/lootfilter.zip https://github.com/ChrisTitusTech/d2r-loot-filter/releases/latest/download/lootfilter.zip # Extract the contents to the mods folder -echo "Extracting loot filter to $mods_path..." +printf "%b\n" "${YELLOW}Extracting loot filter to $mods_path...${RC}" unzip -q -o /tmp/lootfilter.zip -d "$mods_path" # Clean up rm /tmp/lootfilter.zip -echo "Loot filter installed successfully in $mods_path" +printf "%b\n" "${GREEN}Loot filter installed successfully in $mods_path${RC}" # Add instructions for setting launch options echo diff --git a/tabs/security/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 5abb0c766..0c73d08bd 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -21,22 +21,22 @@ installPkg() { configureUFW() { printf "%b\n" "${GREEN}Using Chris Titus Recommended Firewall Rules${RC}" - echo "Disabling UFW" + printf "%b\n" "${YELLOW}Disabling UFW${RC}" $ESCALATION_TOOL ufw disable - echo "Limiting port 22/tcp (UFW)" + printf "%b\n" "${YELLOW}Limiting port 22/tcp (UFW)${RC}" $ESCALATION_TOOL ufw limit 22/tcp - echo "Allowing port 80/tcp (UFW)" + printf "%b\n" "${YELLOW}Allowing port 80/tcp (UFW)${RC}" $ESCALATION_TOOL ufw allow 80/tcp - echo "Allowing port 443/tcp (UFW)" + printf "%b\n" "${YELLO}Allowing port 443/tcp (UFW)${RC}" $ESCALATION_TOOL ufw allow 443/tcp - echo "Denying Incoming Packets by Default(UFW)" + printf "%b\n" "${YELLOW}Denying Incoming Packets by Default(UFW)${RC}" $ESCALATION_TOOL ufw default deny incoming - echo "Allowing Outcoming Packets by Default(UFW)" + printf "%b\n" "${YELLOW}Allowing Outcoming Packets by Default(UFW)${RC}" $ESCALATION_TOOL ufw default allow outgoing $ESCALATION_TOOL ufw enable diff --git a/tabs/system-setup/1-compile-setup.sh b/tabs/system-setup/1-compile-setup.sh index a9d21890d..0ed8f05cd 100755 --- a/tabs/system-setup/1-compile-setup.sh +++ b/tabs/system-setup/1-compile-setup.sh @@ -13,7 +13,7 @@ installDepend() { echo "Include = /etc/pacman.d/mirrorlist" | $ESCALATION_TOOL tee -a /etc/pacman.conf $ESCALATION_TOOL "$PACKAGER" -Syu else - echo "Multilib is already enabled." + printf "%b\n" "${GREEN}Multilib is already enabled.${RC}" fi $AUR_HELPER -S --needed --noconfirm "$DEPENDENCIES" ;; diff --git a/tabs/system-setup/4-remove-snaps.sh b/tabs/system-setup/4-remove-snaps.sh index f804aa5b8..f72fd658a 100644 --- a/tabs/system-setup/4-remove-snaps.sh +++ b/tabs/system-setup/4-remove-snaps.sh @@ -20,7 +20,7 @@ removeSnaps() { $ESCALATION_TOOL ${PACKAGER} remove snapd ;; *) - echo "Removing snapd not implemented for this package manager" + printf "%b\n" "${RED}Removing snapd not implemented for this package manager${RC}" ;; esac } From fd126fbb5f56ca7d31e5447292d421b53c7ba701 Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Mon, 16 Sep 2024 22:58:17 -0400 Subject: [PATCH 13/88] Fix minor inconsistencies --- tabs/applications-setup/alacritty-setup.sh | 2 +- tabs/applications-setup/dwmtitus-setup.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 796315d20..61922a15d 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -14,7 +14,7 @@ setupAlacritty() { ;; esac else - printf "%b\n" "${RED}alacritty is already installed.${RC}" + printf "%b\n" "${GREEN}alacritty is already installed.${RC}" fi } diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index 58b22fe10..cf2f66eff 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -37,7 +37,7 @@ install_nerd_font() { # Check if Meslo Nerd-font is already installed if [ -n "$FONT_INSTALLED" ]; then - printf "%b\n" "${RED}Meslo Nerd-fonts are already installed.${RC}" + printf "%b\n" "${GREEN}Meslo Nerd-fonts are already installed.${RC}" return 0 fi @@ -168,7 +168,7 @@ configure_backgrounds() { printf "%b\n" "${GREEN}Downloaded desktop backgrounds to $BG_DIR${RC}" else # If the backgrounds directory already exists, print a message indicating that the download is being skipped - printf "%b\n" "${RED}Path $BG_DIR exists for desktop backgrounds, skipping download of backgrounds${RC}" + printf "%b\n" "${GREEN}Path $BG_DIR exists for desktop backgrounds, skipping download of backgrounds${RC}" fi } @@ -245,7 +245,7 @@ setupDisplayManager() { printf "%b\n" "${YELLOW}Creating autologin group${RC}" $ESCALATION_TOOL groupadd autologin else - printf "%b\n" "${RED}Autologin group already exists${RC}" + printf "%b\n" "${GREEN}Autologin group already exists${RC}" fi printf "%b\n" "${YELLOW}Adding user with UID 1000 to autologin group${RC}" USER_UID_1000=$(getent passwd 1000 | cut -d: -f1) From b329b572ae1c52f6a1adc212266cf1db0688083c Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Mon, 16 Sep 2024 23:11:04 -0400 Subject: [PATCH 14/88] Incorporate colors into added echo statements & replace those echo statements with printf %bn statements --- tabs/applications-setup/neovim-setup.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 6d1cf5af4..826fd5387 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -14,7 +14,7 @@ cloneNeovim() { } installNeovim() { - echo "Installing Neovim..." + printf "%b\n" "${YELLOW}Installing Neovim...${RC}" case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck @@ -36,7 +36,7 @@ installNeovim() { } backupNeovimConfig() { - echo "Backing up existing configuration files..." + printf "%b\n" "${YELLOW}Backing up existing configuration files...${RC}" if [ -d "$HOME/.config/nvim" ] && [ ! -d "$HOME/.config/nvim-backup" ]; then cp -r "$HOME/.config/nvim" "$HOME/.config/nvim-backup" fi @@ -44,7 +44,7 @@ backupNeovimConfig() { } linkNeovimConfig() { - echo "Linking Neovim configuration files..." + printf "%b\n" "${YELLOW}Linking Neovim configuration files...${RC}" mkdir -p "$HOME/.config/nvim" ln -s "$gitpath/titus-kickstart/"* "$HOME/.config/nvim/" # Wild card is used here to link all contents of titus-kickstart. } From 7c491bde98b0f22958226de741939c67c5eb73ac Mon Sep 17 00:00:00 2001 From: nnyyxxxx Date: Mon, 16 Sep 2024 23:14:49 -0400 Subject: [PATCH 15/88] Revert one of the changes in the last commit --- tabs/applications-setup/neovim-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 826fd5387..6c2a20bf2 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -14,7 +14,7 @@ cloneNeovim() { } installNeovim() { - printf "%b\n" "${YELLOW}Installing Neovim...${RC}" + echo "Installing Neovim..." case "$PACKAGER" in pacman) $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck From 5e83ca55e7ddc11cd9ab6af523e92b40b998d2a3 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Tue, 17 Sep 2024 12:43:39 +0200 Subject: [PATCH 16/88] fix stuff - enhance logic - fix logic to get PR body as plain text --- .github/workflows/pr-labels.yaml | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml index eab956f41..a5f1840e6 100644 --- a/.github/workflows/pr-labels.yaml +++ b/.github/workflows/pr-labels.yaml @@ -9,8 +9,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Analyze PR Body and manage labels + shell: bash run: | - body="${{ github.event.pull_request.body }}" + body=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH") labels_to_add=() labels_to_remove=() declare -A label_checks=( @@ -20,19 +21,23 @@ jobs: ["Refactoring"]="refactor" ["UI/UX improvement"]="UI/UX" ) - for key in "${!label_checks[@]}"; do - if echo "$body" | grep -q "\- \[x\] $key"; then - labels_to_add+=("${label_checks[$key]}") + for pattern in "${!label_checks[@]}"; do + label="${label_checks[$pattern]}" + if echo "$body" | grep -Eq "\- \[x\] ($pattern)"; then + labels_to_add+=("$label") else - labels_to_remove+=("${label_checks[$key]}") + labels_to_remove+=("$label") fi done - echo "LABELS_TO_ADD=${labels_to_add[*]}" >> $GITHUB_ENV - echo "LABELS_TO_REMOVE=${labels_to_remove[*]}" >> $GITHUB_ENV + + echo "LABELS_TO_ADD=$(IFS=,; echo "${labels_to_add[*]}")" >> $GITHUB_ENV + echo "LABELS_TO_REMOVE=$(IFS=,; echo "${labels_to_remove[*]}")" >> $GITHUB_ENV + - name: Add labels if necessary if: env.LABELS_TO_ADD != '' run: | - for label in ${{ env.LABELS_TO_ADD }}; do + IFS=',' read -ra labels <<< "${LABELS_TO_ADD}" + for label in "${labels[@]}"; do curl -s -X POST \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ @@ -42,7 +47,8 @@ jobs: - name: Remove labels if necessary if: env.LABELS_TO_REMOVE != '' run: | - for label in ${{ env.LABELS_TO_REMOVE }}; do + IFS=',' read -ra labels <<< "${LABELS_TO_REMOVE}" + for label in "${labels[@]}"; do curl -s -X DELETE \ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ From 63b7da40a41f500d879aacd5e625982da33e8b27 Mon Sep 17 00:00:00 2001 From: MyDrift Date: Tue, 17 Sep 2024 12:52:36 +0200 Subject: [PATCH 17/88] add _target for forked repo support --- .github/workflows/pr-labels.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml index a5f1840e6..82f9ac97d 100644 --- a/.github/workflows/pr-labels.yaml +++ b/.github/workflows/pr-labels.yaml @@ -1,7 +1,7 @@ name: Manage labels based on PR body on: - pull_request: + pull_request_target: types: [opened, edited, reopened, synchronize] jobs: @@ -53,4 +53,4 @@ jobs: -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ -H "Accept: application/vnd.github.v3+json" \ https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/$label - done \ No newline at end of file + done From 8df764a6e3f65a74ea0a58789c8374fb73d88b06 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Tue, 17 Sep 2024 17:53:23 +0530 Subject: [PATCH 18/88] Refactor remaining variables --- tabs/applications-setup/alacritty-setup.sh | 6 ++-- tabs/applications-setup/fastfetch-setup.sh | 6 ++-- tabs/applications-setup/kitty-setup.sh | 6 ++-- tabs/common-script.sh | 2 +- tabs/security/firewall-baselines.sh | 6 ++-- tabs/system-setup/1-compile-setup.sh | 2 +- tabs/system-setup/3-global-theme.sh | 16 ++++----- tabs/system-setup/4-remove-snaps.sh | 10 +++--- tabs/system-setup/arch/paru-setup.sh | 2 +- tabs/system-setup/arch/yay-setup.sh | 2 +- tabs/system-setup/fedora/rpm-fusion-setup.sh | 2 +- tabs/system-setup/system-update.sh | 36 +++++++++---------- tabs/utils/bluetooth-control.sh | 7 ++-- .../monitor-control/utility_functions.sh | 8 ++--- tabs/utils/numlock.sh | 1 + tabs/utils/wifi-control.sh | 9 ++--- 16 files changed, 62 insertions(+), 59 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 92e49d337..eb8a5d4bb 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -5,12 +5,12 @@ setupAlacritty() { echo "Install Alacritty if not already installed..." if ! command_exists alacritty; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL ${PACKAGER} -S --needed --noconfirm alacritty + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm alacritty ;; *) - $ESCALATION_TOOL ${PACKAGER} install -y alacritty + $ESCALATION_TOOL "$PACKAGER" install -y alacritty ;; esac else diff --git a/tabs/applications-setup/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index e3f9a4f72..1415f9a8c 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -5,12 +5,12 @@ setupFastfetch() { echo "Installing Fastfetch if not already installed..." if ! command_exists fastfetch; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --needed --noconfirm fastfetch + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm fastfetch ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y fastfetch + $ESCALATION_TOOL "$PACKAGER" install -y fastfetch ;; esac else diff --git a/tabs/applications-setup/kitty-setup.sh b/tabs/applications-setup/kitty-setup.sh index 7afbbe5d8..5195a9ccd 100755 --- a/tabs/applications-setup/kitty-setup.sh +++ b/tabs/applications-setup/kitty-setup.sh @@ -5,12 +5,12 @@ setupKitty() { echo "Install Kitty if not already installed..." if ! command_exists kitty; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --needed --noconfirm kitty + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm kitty ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y kitty + $ESCALATION_TOOL "$PACKAGER" install -y kitty ;; esac else diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 45d925e77..75e80db8f 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -81,7 +81,7 @@ checkPackageManager() { fi done - if [ -z "${PACKAGER}" ]; then + if [ -z "$PACKAGER" ]; then printf "%b\n" "${RED}Can't find a supported package manager${RC}" exit 1 fi diff --git a/tabs/security/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 5abb0c766..951b6415a 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -5,12 +5,12 @@ installPkg() { echo "Install UFW if not already installed..." if ! command_exists ufw; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --needed --noconfirm ufw + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm ufw ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y ufw + $ESCALATION_TOOL "$PACKAGER" install -y ufw ;; esac else diff --git a/tabs/system-setup/1-compile-setup.sh b/tabs/system-setup/1-compile-setup.sh index a9d21890d..14ef06cd6 100755 --- a/tabs/system-setup/1-compile-setup.sh +++ b/tabs/system-setup/1-compile-setup.sh @@ -6,7 +6,7 @@ installDepend() { ## Check for dependencies. DEPENDENCIES='tar tree multitail tldr trash-cli unzip cmake make jq' printf "%b\n" "${YELLOW}Installing dependencies...${RC}" - case $PACKAGER in + case "$PACKAGER" in pacman) if ! grep -q "^\s*\[multilib\]" /etc/pacman.conf; then echo "[multilib]" | $ESCALATION_TOOL tee -a /etc/pacman.conf diff --git a/tabs/system-setup/3-global-theme.sh b/tabs/system-setup/3-global-theme.sh index d5b1c6670..141d0dd22 100644 --- a/tabs/system-setup/3-global-theme.sh +++ b/tabs/system-setup/3-global-theme.sh @@ -4,21 +4,21 @@ install_theme_tools() { printf "%b\n" "${YELLOW}Installing theme tools (qt6ct and kvantum)...${RC}\n" - case $PACKAGER in + case "$PACKAGER" in apt-get|nala) - $ESCALATION_TOOL "${PACKAGER}" update - $ESCALATION_TOOL "${PACKAGER}" install -y qt6ct kvantum + $ESCALATION_TOOL "$PACKAGER" update + $ESCALATION_TOOL "$PACKAGER" install -y qt6ct kvantum ;; zypper) - $ESCALATION_TOOL "${PACKAGER}" refresh - $ESCALATION_TOOL "${PACKAGER}" --non-interactive install qt6ct kvantum + $ESCALATION_TOOL "$PACKAGER" refresh + $ESCALATION_TOOL "$PACKAGER" --non-interactive install qt6ct kvantum ;; dnf) - $ESCALATION_TOOL "${PACKAGER}" update - $ESCALATION_TOOL "${PACKAGER}" install -y qt6ct kvantum + $ESCALATION_TOOL "$PACKAGER" update + $ESCALATION_TOOL "$PACKAGER" install -y qt6ct kvantum ;; pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --needed --noconfirm qt6ct kvantum + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm qt6ct kvantum ;; *) printf "%b\n" "${RED}Unsupported package manager. Please install qt6ct and kvantum manually.${RC}\n" diff --git a/tabs/system-setup/4-remove-snaps.sh b/tabs/system-setup/4-remove-snaps.sh index f804aa5b8..5d8996487 100644 --- a/tabs/system-setup/4-remove-snaps.sh +++ b/tabs/system-setup/4-remove-snaps.sh @@ -3,21 +3,21 @@ . ../common-script.sh removeSnaps() { - case $PACKAGER in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL ${PACKAGER} -Rns snapd + $ESCALATION_TOOL "$PACKAGER" -Rns snapd ;; apt-get|nala) - $ESCALATION_TOOL ${PACKAGER} autoremove --purge snapd + $ESCALATION_TOOL "$PACKAGER" autoremove --purge snapd if [ "$ID" = ubuntu ]; then $ESCALATION_TOOL apt-mark hold snapd fi ;; dnf) - $ESCALATION_TOOL ${PACKAGER} remove snapd + $ESCALATION_TOOL "$PACKAGER" remove snapd ;; zypper) - $ESCALATION_TOOL ${PACKAGER} remove snapd + $ESCALATION_TOOL "$PACKAGER" remove snapd ;; *) echo "Removing snapd not implemented for this package manager" diff --git a/tabs/system-setup/arch/paru-setup.sh b/tabs/system-setup/arch/paru-setup.sh index 51edfb09e..490935157 100755 --- a/tabs/system-setup/arch/paru-setup.sh +++ b/tabs/system-setup/arch/paru-setup.sh @@ -3,7 +3,7 @@ . ../../common-script.sh installDepend() { - case $PACKAGER in + case "$PACKAGER" in pacman) if ! command_exists paru; then echo "Installing paru as AUR helper..." diff --git a/tabs/system-setup/arch/yay-setup.sh b/tabs/system-setup/arch/yay-setup.sh index 010192ce5..25fb2ee88 100755 --- a/tabs/system-setup/arch/yay-setup.sh +++ b/tabs/system-setup/arch/yay-setup.sh @@ -3,7 +3,7 @@ . ../../common-script.sh installDepend() { - case $PACKAGER in + case "$PACKAGER" in pacman) if ! command_exists yay; then echo "Installing yay as AUR helper..." diff --git a/tabs/system-setup/fedora/rpm-fusion-setup.sh b/tabs/system-setup/fedora/rpm-fusion-setup.sh index 52396d5df..f611a0be1 100644 --- a/tabs/system-setup/fedora/rpm-fusion-setup.sh +++ b/tabs/system-setup/fedora/rpm-fusion-setup.sh @@ -5,7 +5,7 @@ # https://rpmfusion.org/Configuration installRPMFusion() { - case $PACKAGER in + case "$PACKAGER" in dnf) if [ ! -e /etc/yum.repos.d/rpmfusion-free.repo ] || [ ! -e /etc/yum.repos.d/rpmfusion-nonfree.repo ]; then echo "Installing RPM Fusion..." diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index e6b32af6d..e961e5cc3 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -31,27 +31,27 @@ fastUpdate() { $ESCALATION_TOOL apt-get install -y nala || { printf "%b\n" "${YELLOW}Falling back to apt-get${RC}"; PACKAGER="apt-get"; } fi - if [ "${PACKAGER}" = "nala" ]; then + if [ "$PACKAGER" = "nala" ]; then $ESCALATION_TOOL cp /etc/apt/sources.list /etc/apt/sources.list.bak $ESCALATION_TOOL nala update PACKAGER="nala" fi - $ESCALATION_TOOL ${PACKAGER} upgrade -y + $ESCALATION_TOOL "$PACKAGER" upgrade -y ;; dnf) - $ESCALATION_TOOL ${PACKAGER} update -y + $ESCALATION_TOOL "$PACKAGER" update -y ;; zypper) - $ESCALATION_TOOL ${PACKAGER} ref - $ESCALATION_TOOL ${PACKAGER} --non-interactive dup + $ESCALATION_TOOL "$PACKAGER" ref + $ESCALATION_TOOL "$PACKAGER" --non-interactive dup ;; yum) - $ESCALATION_TOOL ${PACKAGER} update -y - $ESCALATION_TOOL ${PACKAGER} upgrade -y + $ESCALATION_TOOL "$PACKAGER" update -y + $ESCALATION_TOOL "$PACKAGER" upgrade -y ;; xbps-install) - $ESCALATION_TOOL ${PACKAGER} -Syu + $ESCALATION_TOOL "$PACKAGER" -Syu ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" @@ -62,25 +62,25 @@ fastUpdate() { updateSystem() { printf "%b\n" "${GREEN}Updating system${RC}" - case ${PACKAGER} in + case "$PACKAGER" in nala|apt-get) - $ESCALATION_TOOL "${PACKAGER}" update -y - $ESCALATION_TOOL "${PACKAGER}" upgrade -y + $ESCALATION_TOOL "$PACKAGER" update -y + $ESCALATION_TOOL "$PACKAGER" upgrade -y ;; yum|dnf) - $ESCALATION_TOOL "${PACKAGER}" update -y - $ESCALATION_TOOL "${PACKAGER}" upgrade -y + $ESCALATION_TOOL "$PACKAGER" update -y + $ESCALATION_TOOL "$PACKAGER" upgrade -y ;; pacman) - $ESCALATION_TOOL "${PACKAGER}" -Sy --noconfirm --needed archlinux-keyring - $ESCALATION_TOOL "${PACKAGER}" -Su --noconfirm + $ESCALATION_TOOL "$PACKAGER" -Sy --noconfirm --needed archlinux-keyring + $ESCALATION_TOOL "$PACKAGER" -Su --noconfirm ;; zypper) - $ESCALATION_TOOL ${PACKAGER} ref - $ESCALATION_TOOL ${PACKAGER} --non-interactive dup + $ESCALATION_TOOL "$PACKAGER" ref + $ESCALATION_TOOL "$PACKAGER" --non-interactive dup ;; xbps-install) - $ESCALATION_TOOL ${PACKAGER} -Syu + $ESCALATION_TOOL "$PACKAGER" -Syu ;; *) printf "%b\n" "${RED}Unsupported package manager: ${PACKAGER}${RC}" diff --git a/tabs/utils/bluetooth-control.sh b/tabs/utils/bluetooth-control.sh index 508d3708a..51aa16221 100644 --- a/tabs/utils/bluetooth-control.sh +++ b/tabs/utils/bluetooth-control.sh @@ -6,12 +6,12 @@ setupBluetooth() { printf "%b\n" "${YELLOW}Installing Bluez...${RC}" if ! command_exists bluetoothctl; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm bluez-utils + $ESCALATION_TOOL "$PACKAGER" -S --noconfirm bluez-utils ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y bluez + $ESCALATION_TOOL "$PACKAGER" install -y bluez ;; esac else @@ -147,5 +147,6 @@ remove_device() { # Initialize checkEnv +checkEscalationTool setupBluetooth main_menu diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index d2bde1513..28b4fad75 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -6,15 +6,15 @@ setup_xrandr() { echo "Install xrandr if not already installed..." if ! command_exists xrandr; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm xorg-xrandr + $ESCALATION_TOOL "$PACKAGER" -S --noconfirm xorg-xrandr ;; apt-get|nala) - $ESCALATION_TOOL "${PACKAGER}" install -y x11-xserver-utils + $ESCALATION_TOOL "$PACKAGER" install -y x11-xserver-utils ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y xorg-x11-server-utils + $ESCALATION_TOOL "$PACKAGER" install -y xorg-x11-server-utils ;; esac else diff --git a/tabs/utils/numlock.sh b/tabs/utils/numlock.sh index 2b23c3f16..79f2f6808 100755 --- a/tabs/utils/numlock.sh +++ b/tabs/utils/numlock.sh @@ -60,5 +60,6 @@ numlockSetup() { fi } +checkEnv checkEscalationTool numlockSetup diff --git a/tabs/utils/wifi-control.sh b/tabs/utils/wifi-control.sh index 036e2a28c..2a6686a81 100644 --- a/tabs/utils/wifi-control.sh +++ b/tabs/utils/wifi-control.sh @@ -6,15 +6,15 @@ setupNetworkManager() { printf "%b\n" "${YELLOW}Installing NetworkManager...${RC}" if ! command_exists nmcli; then - case ${PACKAGER} in + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm networkmanager + $ESCALATION_TOOL "$PACKAGER" -S --noconfirm networkmanager ;; dnf) - $ESCALATION_TOOL "${PACKAGER}" install -y NetworkManager-1 + $ESCALATION_TOOL "$PACKAGER" install -y NetworkManager-1 ;; *) - $ESCALATION_TOOL "${PACKAGER}" install -y network-manager + $ESCALATION_TOOL "$PACKAGER" install -y network-manager ;; esac else @@ -186,5 +186,6 @@ remove_network() { # Initialize checkEnv +checkEscalationTool setupNetworkManager main_menu From 16fbd336cee968a390f27cb7b7fd4728a44613cb Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Tue, 17 Sep 2024 18:19:41 +0530 Subject: [PATCH 19/88] Added missed packager --- tabs/system-setup/system-update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index e961e5cc3..7df96be0c 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -3,7 +3,7 @@ . ../common-script.sh fastUpdate() { - case ${PACKAGER} in + case "$PACKAGER" in pacman) $AUR_HELPER -S --needed --noconfirm rate-mirrors-bin From 418cb9db44eed260e5c2d9fe2e3ed9a96a34fed5 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:43:33 +0530 Subject: [PATCH 20/88] added auto-login --- tabs/utils/auto-login.sh | 179 +++++++++++++++++++++++++++++++++++++++ tabs/utils/tab_data.toml | 9 ++ 2 files changed, 188 insertions(+) create mode 100644 tabs/utils/auto-login.sh diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh new file mode 100644 index 000000000..69bd8611d --- /dev/null +++ b/tabs/utils/auto-login.sh @@ -0,0 +1,179 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to list common session options +list_sessions() { + echo "Select the session:" + echo "1) GNOME (gnome.desktop)" + echo "2) KDE Plasma (plasma.desktop)" + echo "3) XFCE (xfce.desktop)" + echo "4) LXDE (LXDE.desktop)" + echo "5) LXQt (lxqt.desktop)" + echo "6) Cinnamon (cinnamon.desktop)" + echo "7) MATE (mate.desktop)" + echo "8) Openbox (openbox.desktop)" + echo "9) i3 (i3.desktop)" + echo "10) Custom session" + echo "Enter your choice [1-10]: " + read session_choice + + case "$session_choice" in + 1) session="gnome.desktop" ;; + 2) session="plasma.desktop" ;; + 3) session="xfce.desktop" ;; + 4) session="LXDE.desktop" ;; + 5) session="lxqt.desktop" ;; + 6) session="cinnamon.desktop" ;; + 7) session="mate.desktop" ;; + 8) session="openbox.desktop" ;; + 9) session="i3.desktop" ;; + 10) + echo "Enter custom session name (e.g., mysession.desktop): " + read session ;; + *) + echo "Invalid option selected." + exit 1 ;; + esac +} + +# Function to configure LightDM +configure_lightdm() { + echo "Configuring LightDM for autologin..." + + echo "Enter username for LightDM autologin: " + read user + + $ESCALATION_TOOL "echo '[Seat:*]' > /etc/lightdm/lightdm.conf.d/50-autologin.conf" + $ESCALATION_TOOL "echo 'autologin-user=$user' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" + $ESCALATION_TOOL "echo 'autologin-user-timeout=0' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" + + echo "LightDM has been configured for autologin." +} + +# Function to remove LightDM autologin +remove_lightdm_autologin() { + echo "Removing LightDM autologin configuration..." + $ESCALATION_TOOL rm -f /etc/lightdm/lightdm.conf.d/50-autologin.conf + echo "LightDM autologin configuration has been removed." +} + +# Function to configure GDM +configure_gdm() { + echo "Configuring GDM for autologin..." + + echo "Enter username for GDM autologin: " + read user + + $ESCALATION_TOOL "echo '[daemon]' > /etc/gdm/custom.conf" + $ESCALATION_TOOL "echo 'AutomaticLoginEnable = true' >> /etc/gdm/custom.conf" + $ESCALATION_TOOL "echo 'AutomaticLogin = $user' >> /etc/gdm/custom.conf" + + echo "GDM has been configured for autologin." +} + +# Function to remove GDM autologin +remove_gdm_autologin() { + echo "Removing GDM autologin configuration..." + $ESCALATION_TOOL sed -i '/AutomaticLoginEnable/d' /etc/gdm/custom.conf + $ESCALATION_TOOL sed -i '/AutomaticLogin/d' /etc/gdm/custom.conf + echo "GDM autologin configuration has been removed." +} + +# Function to configure SDDM +configure_sddm() { + echo "Configuring SDDM for autologin..." + + echo "Enter username for SDDM autologin: " + read user + list_sessions # Show session options + + $ESCALATION_TOOL "echo '[Autologin]' > /etc/sddm.conf" + $ESCALATION_TOOL "echo 'User=$user' >> /etc/sddm.conf" + $ESCALATION_TOOL "echo 'Session=$session' >> /etc/sddm.conf" + + echo "SDDM has been configured for autologin." +} + +# Function to remove SDDM autologin +remove_sddm_autologin() { + echo "Removing SDDM autologin configuration..." + $ESCALATION_TOOL sed -i '/\[Autologin\]/,+2d' /etc/sddm.conf + echo "SDDM autologin configuration has been removed." +} + +# Function to configure LXDM +configure_lxdm() { + echo "Configuring LXDM for autologin..." + + echo "Enter username for LXDM autologin: " + read user + list_sessions # Show session options + + $ESCALATION_TOOL sed -i "s/^#.*autologin=.*$/autologin=${user}/" /etc/lxdm/lxdm.conf + $ESCALATION_TOOL sed -i "s|^#.*session=.*$|session=/usr/bin/${session}|; s|^session=.*$|session=/usr/bin/${session}|" /etc/lxdm/lxdm.conf + + echo "LXDM has been configured for autologin." +} + +# Function to remove LXDM autologin +remove_lxdm_autologin() { + echo "Removing LXDM autologin configuration..." + $ESCALATION_TOOL sed -i "s/^autologin=.*$/#autologin=/" /etc/lxdm/lxdm.conf + $ESCALATION_TOOL sed -i "s/^session=.*$/#session=/" /etc/lxdm/lxdm.conf + echo "LXDM autologin configuration has been removed." +} + +# Function to configure or remove autologin based on user choice +configure_or_remove_autologin() { + echo "Do you want to add or remove autologin?" + echo "1) Add autologin" + echo "2) Remove autologin" + echo "Enter your choice [1-2]: " + read action_choice + + if [ "$action_choice" = "1" ]; then + echo "Choose the display manager to configure:" + echo "1) LightDM" + echo "2) GDM" + echo "3) SDDM" + echo "4) LXDM" + echo "Enter your choice [1-4]: " + read choice + + case "$choice" in + 1) configure_lightdm ;; + 2) configure_gdm ;; + 3) configure_sddm ;; + 4) configure_lxdm ;; + *) echo "Invalid option selected." ;; + esac + elif [ "$action_choice" = "2" ]; then + echo "Choose the display manager to remove autologin:" + echo "1) LightDM" + echo "2) GDM" + echo "3) SDDM" + echo "4) LXDM" + echo "Enter your choice [1-4]: " + read choice + + case "$choice" in + 1) remove_lightdm_autologin ;; + 2) remove_gdm_autologin ;; + 3) remove_sddm_autologin ;; + 4) remove_lxdm_autologin ;; + *) echo "Invalid option selected." ;; + esac + else + echo "Invalid choice. Exiting..." + exit 1 + fi + + echo "Action completed. Exiting..." + exit 0 +} + + +checkEnv +checkEscalationTool +configure_or_remove_autologin diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index bf05a1b36..53224c524 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -20,6 +20,10 @@ script = "ollama.sh" name = "Service Manager" script = "service-control.sh" +[[data]] +name = "Auto Login" +script = "auto-login.sh" + [[data]] name = "Monitor Control" @@ -73,3 +77,8 @@ script = "monitor-control/scale_monitor.sh" name = "Reset Scaling" script = "monitor-control/reset_scaling.sh" matches = true + +[[data.entries]] +name = "Set Brightness" +script = "monitor-control/set_brightness.sh" +matches = true \ No newline at end of file From 0b8a649d07b9a01a01e0e461fe632342cb7e6c75 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:44:52 +0530 Subject: [PATCH 21/88] added pendrive maker script --- tabs/utils/create-bootable-usb.sh | 191 ++++++++++++++++++++++++++++++ tabs/utils/tab_data.toml | 4 + 2 files changed, 195 insertions(+) create mode 100644 tabs/utils/create-bootable-usb.sh diff --git a/tabs/utils/create-bootable-usb.sh b/tabs/utils/create-bootable-usb.sh new file mode 100644 index 000000000..80dab1025 --- /dev/null +++ b/tabs/utils/create-bootable-usb.sh @@ -0,0 +1,191 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to display usage instructions +usage() { + printf "%b\n" "${RED} Usage: $0 ${RC}" + echo "No arguments needed. The script will prompt for ISO path and USB device." + exit 1 +} + +# Function to display all available block devices +list_devices() { + printf "%b\n" "${YELLOW} Available devices and partitions: ${RC}" + echo "" + $ESCALATION_TOOL lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL + echo "" +} + +# Function to fetch the latest Arch Linux ISO +fetch_arch_latest_iso() { + ARCH_BASE_URL="https://archive.archlinux.org/iso/" + ARCH_LATEST=$(curl -s "$ARCH_BASE_URL" | grep -oP '(?<=href=")[0-9]{4}\.[0-9]{2}\.[0-9]{2}(?=/)' | sort -V | tail -1) + ARCH_URL="${ARCH_BASE_URL}${ARCH_LATEST}/archlinux-${ARCH_LATEST}-x86_64.iso" + printf "%b\n" "${GREEN} Selected Arch Linux (latest) ISO URL: ${RC} $ARCH_URL" +} + +# Function to fetch older Arch Linux ISOs and display in a table format +fetch_arch_older_isos() { + ARCH_BASE_URL="https://archive.archlinux.org/iso/" + ARCH_VERSIONS=$(curl -s "$ARCH_BASE_URL" | grep -oP '(?<=href=")[0-9]{4}\.[0-9]{2}\.[0-9]{2}(?=/)' | sort -V) + + # Filter versions to include only those from 2017-04-01 and later + MIN_DATE="2017.04.01" + ARCH_VERSIONS=$(echo "$ARCH_VERSIONS" | awk -v min_date="$MIN_DATE" '$0 >= min_date') + + if [ -z "$ARCH_VERSIONS" ]; then + printf "%b\n" "${RED}No Arch Linux versions found from ${MIN_DATE} onwards.${RC}" + exit 1 + fi + + printf "%b\n" "${YELLOW}Available Arch Linux versions from ${MIN_DATE} onwards:${RC}" + + COUNTER=1 + ROW_ITEMS=6 # Number of versions to show per row + for VERSION in $ARCH_VERSIONS; do + printf "%-5s${YELLOW}%-15s ${RC}" "$COUNTER)" "$VERSION" + + if [ $(( COUNTER % ROW_ITEMS )) -eq 0 ]; then + echo "" # New line after every 6 versions + fi + + COUNTER=$((COUNTER + 1)) + done + echo "" # New line after the last row + + read -p "Select an Arch Linux version (1-$((COUNTER - 1))): " ARCH_OPTION + ARCH_DIR=$(echo "$ARCH_VERSIONS" | sed -n "${ARCH_OPTION}p") + ARCH_URL="${ARCH_BASE_URL}${ARCH_DIR}/archlinux-${ARCH_DIR}-x86_64.iso" + printf "%b\n" "${GREEN}Selected Arch Linux (older) ISO URL: $ARCH_URL${RC}" +} + + +# Function to fetch the latest Debian Linux ISO +fetch_debian_latest_iso() { + DEBIAN_URL=$(curl -s https://www.debian.org/distrib/netinst | grep -oP '(?<=href=")[^"]+debian-[0-9.]+-amd64-netinst.iso(?=")' | head -1) + printf "%b\n" "${GREEN} Selected Debian Linux (latest) ISO URL: ${RC} $DEBIAN_URL" +} + +# Function to ask whether to use local or online ISO +choose_iso_source() { + printf "%b\n" "${YELLOW} Do you want to use a local ISO or download online? ${RC}" + echo "1) Download online" + echo "2) Use local ISO" + echo "" + read -p "Select option (1-2): " ISO_SOURCE_OPTION + + case $ISO_SOURCE_OPTION in + 1) + fetch_iso_urls # Call the function to fetch online ISO URLs + ;; + 2) + read -p "Enter the path to the already downloaded ISO file: " ISO_PATH + if [ ! -f "$ISO_PATH" ]; then + printf "%b\n" "${RED} ISO file not found: $ISO_PATH ${RC}" + exit 1 + fi + ;; + *) + printf "%b\n" "${RED}Invalid option selected. ${RC}" + exit 1 + ;; + esac +} + +# Function to fetch ISO URLs +fetch_iso_urls() { + clear + printf "%b\n" "${YELLOW}Available ISOs for download:${RC}" + echo "1) Arch Linux (latest)" + echo "2) Arch Linux (older versions)" + echo "3) Debian Linux (latest)" + echo "" + read -p "Select the ISO you want to download (1-3): " ISO_OPTION + + case $ISO_OPTION in + 1) + fetch_arch_latest_iso + ISO_URL=$ARCH_URL + ;; + 2) + fetch_arch_older_isos + ISO_URL=$ARCH_URL + ;; + 3) + fetch_debian_latest_iso + ISO_URL=$DEBIAN_URL + ;; + *) + printf "%b\n" "${RED}Invalid option selected.${RC}" + exit 1 + ;; + esac + + ISO_PATH=$(basename "$ISO_URL") + printf "%b\n" "${YELLOW}Downloading ISO...${RC}" + curl -L -o "$ISO_PATH" "$ISO_URL" + if [ $? -ne 0 ]; then + printf "%b\n" "${RED}Failed to download the ISO file.${RC}" + exit 1 + fi +} + +write_iso(){ + clear + + # Ask whether to use a local or online ISO + choose_iso_source + + clear + # Display all available devices + list_devices + + # Prompt user for USB device + read -p "Enter the USB device (e.g., /dev/sdX): " USB_DEVICE + + # Verify that the USB device exists + if [ ! -b "$USB_DEVICE" ]; then + printf "%b\n" "${RED}USB device not found: $USB_DEVICE${RC}" + exit 1 + fi + + # Confirm the device selection with the user + printf "%b\n" "${RED}WARNING: This will erase all data on ${USB_DEVICE}. Are you sure you want to continue? (yes/no)${RC}" + read -r CONFIRMATION + + if [ "$CONFIRMATION" != "yes" ]; then + printf "%b\n" "${YELLOW}Operation cancelled.${RC}" + exit 1 + fi + + # Display progress and create the bootable USB drive + printf "%b\n" "${YELLOW}Creating bootable USB drive...${RC}" + if ! $ESCALATION_TOOL dd if="$ISO_PATH" of="$USB_DEVICE" bs=4M status=progress oflag=sync; then + printf "%b\n" "${RED}Failed to create bootable USB drive${RC}" + exit 1 + fi + + # Sync to ensure all data is written + if ! $ESCALATION_TOOL sync; then + printf "%b\n" "${RED}Failed to sync data${RC}" + exit 1 + fi + + printf "%b\n" "${GREEN}Bootable USB drive created successfully!${RC}" + + # Eject the USB device + printf "%b\n" "${YELLOW}Ejecting ${USB_DEVICE}...${RC}" + if ! $ESCALATION_TOOL umount "${USB_DEVICE}"* 2>/dev/null; then + printf "%b\n" "${RED}Failed to unmount ${USB_DEVICE}${RC}" + fi + if ! $ESCALATION_TOOL eject "$USB_DEVICE"; then + printf "%b\n" "${RED}Failed to eject ${USB_DEVICE}${RC}" + fi + + printf "%b\n" "${GREEN}You can safely remove your USB drive. Reinsert the drive to be detected.${RC}" +} + +checkEnv +checkEscalationTool +write_iso \ No newline at end of file diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 53224c524..8ed1779c4 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -24,6 +24,10 @@ script = "service-control.sh" name = "Auto Login" script = "auto-login.sh" +[[data]] +name = "Bootable Pendrive Maker" +script = "create-bootable-usb.sh" + [[data]] name = "Monitor Control" From 4bb3ba545881ba3f4f12c9d0a78b96683ca9f6c0 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:45:29 +0530 Subject: [PATCH 22/88] added power profile script --- tabs/utils/power-profile.sh | 99 +++++++++++++++++++++++++++++++++++++ tabs/utils/tab_data.toml | 4 ++ 2 files changed, 103 insertions(+) create mode 100644 tabs/utils/power-profile.sh diff --git a/tabs/utils/power-profile.sh b/tabs/utils/power-profile.sh new file mode 100644 index 000000000..5c614d3f1 --- /dev/null +++ b/tabs/utils/power-profile.sh @@ -0,0 +1,99 @@ +#!/bin/sh -e + +. ../common-script.sh + +installAutoCpufreq() { + clear + printf "%b\n" "${YELLOW}Checking if auto-cpufreq is already installed...${RC}" + + # Check if auto-cpufreq is already installed + if command_exists auto-cpufreq; then + printf "%b\n" "${GREEN}auto-cpufreq is already installed.${RC}" + else + printf "%b\n" "${YELLOW}Installing auto-cpufreq...${RC}" + + # Install git if not already installed + if ! command_exists git; then + printf "%b\n" "${YELLOW}git not found. Installing git...${RC}" + case ${PACKAGER} in + pacman) + $ESCALATION_TOOL ${PACKAGER} -S --needed --noconfirm git + ;; + *) + $ESCALATION_TOOL ${PACKAGER} install -y git + ;; + esac + fi + + # Clone the auto-cpufreq repository and run the installer + if [ ! -d "auto-cpufreq" ]; then + printf "%b\n" "${YELLOW}Cloning auto-cpufreq repository...${RC}" + git clone https://github.com/AdnanHodzic/auto-cpufreq.git + fi + + case ${PACKAGER} in + *) + cd auto-cpufreq + printf "%b\n" "${YELLOW}Running auto-cpufreq installer...${RC}" + $ESCALATION_TOOL ./auto-cpufreq-installer + ;; + esac + cd .. + fi +} + +configureAutoCpufreq() { + printf "%b\n" "${YELLOW}Configuring auto-cpufreq...${RC}" + + if command_exists auto-cpufreq; then + # Check if the system has a battery to determine if it's a laptop + if [ -d /sys/class/power_supply/BAT0 ]; then + printf "%b\n" "${GREEN}System detected as laptop. Updating auto-cpufreq for laptop...${RC}" + $ESCALATION_TOOL auto-cpufreq --force powersave + else + printf "%b\n" "${GREEN}System detected as desktop. Updating auto-cpufreq for desktop...${RC}" + $ESCALATION_TOOL auto-cpufreq --force performance + fi + else + printf "%b\n" "${RED}auto-cpufreq is not installed, skipping configuration.${RC}" + fi +} + +removeAutoCpufreqTweak() { + printf "%b\n" "${YELLOW}Removing auto-cpufreq tweak...${RC}" + + if command_exists auto-cpufreq; then + printf "%b\n" "${YELLOW}Resetting auto-cpufreq configuration...${RC}" + $ESCALATION_TOOL auto-cpufreq --force reset + else + printf "%b\n" "${RED}auto-cpufreq is not installed, skipping removal.${RC}" + fi +} + +apply_or_remove_auto_cpufreq() { + # Prompt user for action + printf "%b\n" "${YELLOW}Do you want to apply the auto-cpufreq tweak or remove it?${RC}" + printf "%b\n" "${YELLOW}1) Apply tweak${RC}" + printf "%b\n" "${YELLOW}2) Remove tweak${RC}" + read -rp "Enter your choice [1/2]: " choice + + case $choice in + 1) + configureAutoCpufreq + ;; + 2) + removeAutoCpufreqTweak + ;; + *) + printf "%b\n" "${RED}Invalid choice. Exiting.${RC}" + exit 1 + ;; + esac + + printf "%b\n" "${GREEN}auto-cpufreq setup complete.${RC}" +} + +checkEnv +checkEscalationTool +installAutoCpufreq +apply_or_remove_auto_cpufreq \ No newline at end of file diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 8ed1779c4..9efd0aa05 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -28,6 +28,10 @@ script = "auto-login.sh" name = "Bootable Pendrive Maker" script = "create-bootable-usb.sh" +[[data]] +name = "Auto Power Profiling" +script = "power-profile.sh" + [[data]] name = "Monitor Control" From d99d26d910385d756c58e3a04ebc0559278cee39 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:45:57 +0530 Subject: [PATCH 23/88] added timeshift backup script --- tabs/utils/tab_data.toml | 4 + tabs/utils/timeshift.sh | 153 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 157 insertions(+) create mode 100644 tabs/utils/timeshift.sh diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 9efd0aa05..2559d5dce 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -32,6 +32,10 @@ script = "create-bootable-usb.sh" name = "Auto Power Profiling" script = "power-profile.sh" +[[data]] +name = "Timeshift Backup" +script = "timeshift.sh" + [[data]] name = "Monitor Control" diff --git a/tabs/utils/timeshift.sh b/tabs/utils/timeshift.sh new file mode 100644 index 000000000..9ff18892c --- /dev/null +++ b/tabs/utils/timeshift.sh @@ -0,0 +1,153 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to install Timeshift +install_timeshift() { + clear + printf "%b\n" "${YELLOW}Checking if Timeshift is installed...${RC}" + + if ! command_exists timeshift; then + case ${PACKAGER} in + pacman) + $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm timeshift + ;; + *) + $ESCALATION_TOOL "${PACKAGER}" install -y timeshift + ;; + esac + else + echo "Timeshift is already installed." + fi +} + +# Function to display the menu +display_menu() { + clear + echo "Timeshift CLI Automation" + echo "-------------------------" + echo "1) List Snapshots" + echo "2) List Devices" + echo "3) Create Snapshot" + echo "4) Restore Snapshot" + echo "5) Delete Snapshot" + echo "6) Delete All Snapshots" + echo "7) Exit" + echo "" +} + +# Function to list snapshots +list_snapshots() { + echo "Listing snapshots..." + $ESCALATION_TOOL timeshift --list-snapshots +} + +# Function to list devices +list_devices() { + echo "Listing available devices..." + $ESCALATION_TOOL timeshift --list-devices +} + +# Function to create a new snapshot +create_snapshot() { + read -p "Enter a comment for the snapshot (optional): " COMMENT + read -p "Enter snapshot tag (O,B,H,D,W,M) (leave empty for no tag): " TAG + + if [ -z "$COMMENT" ] && [ -z "$TAG" ]; then + echo "Creating snapshot with no comment or tag..." + $ESCALATION_TOOL timeshift --create + elif [ -z "$TAG" ]; then + echo "Creating snapshot with no tag..." + $ESCALATION_TOOL timeshift --create --comments "$COMMENT" + else + echo "Creating snapshot with tag: $TAG..." + $ESCALATION_TOOL timeshift --create --comments "$COMMENT" --tags "$TAG" + fi + + if [ $? -eq 0 ]; then + echo "Snapshot created successfully." + else + echo "Snapshot creation failed." + fi +} + +# Function to restore a snapshot +restore_snapshot() { + list_snapshots + + read -p "Enter the snapshot name you want to restore: " SNAPSHOT + read -p "Enter the target device (e.g., /dev/sda1): " TARGET_DEVICE + read -p "Do you want to skip GRUB reinstall? (yes/no): " SKIP_GRUB + + if [ "$SKIP_GRUB" = "yes" ]; then + $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --skip-grub --yes + else + read -p "Enter GRUB device (e.g., /dev/sda): " GRUB_DEVICE + $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes + fi + + if [ $? -eq 0 ]; then + echo "Snapshot restored successfully." + else + echo "Snapshot restore failed." + fi +} + +# Function to delete a snapshot +delete_snapshot() { + list_snapshots + + read -p "Enter the snapshot name you want to delete: " SNAPSHOT + + echo "Deleting snapshot $SNAPSHOT..." + $ESCALATION_TOOL timeshift --delete --snapshot "$SNAPSHOT" --yes + + if [ $? -eq 0 ]; then + echo "Snapshot deleted successfully." + else + echo "Snapshot deletion failed." + fi +} + +# Function to delete all snapshots +delete_all_snapshots() { + echo "WARNING: This will delete all snapshots!" + read -p "Are you sure? (yes/no): " CONFIRMATION + + if [ "$CONFIRMATION" = "yes" ]; then + echo "Deleting all snapshots..." + $ESCALATION_TOOL timeshift --delete-all --yes + if [ $? -eq 0 ]; then + printf "%b\n" "${GREEN}All snapshots deleted successfully.${RC}" + else + printf "%b\n" "${RED}Failed to delete snapshots.${RC}" + fi + else + printf "%b\n" "${RED}Operation cancelled.${RC}" + fi +} + +main_menu() { +while true; do + display_menu + read -p "Select an option (1-7): " OPTION + + case $OPTION in + 1) list_snapshots ;; + 2) list_devices ;; + 3) create_snapshot ;; + 4) restore_snapshot ;; + 5) delete_snapshot ;; + 6) delete_all_snapshots ;; + 7) echo "Exiting..."; exit 0 ;; + *) echo "Invalid option. Please try again." ;; + esac + + read -p "Press Enter to continue..." +done +} + +checkEnv +checkEscalationTool +install_timeshift +main_menu From 71beabd6d6d3b7c4bcbf4223856bf7730c7bbce3 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:50:52 +0530 Subject: [PATCH 24/88] set brightness monitor scontrol script --- tabs/utils/monitor-control/set_brightness.sh | 85 +++++++++++++++++++ .../monitor-control/utility_functions.sh | 6 ++ 2 files changed, 91 insertions(+) create mode 100644 tabs/utils/monitor-control/set_brightness.sh diff --git a/tabs/utils/monitor-control/set_brightness.sh b/tabs/utils/monitor-control/set_brightness.sh new file mode 100644 index 000000000..8265ded73 --- /dev/null +++ b/tabs/utils/monitor-control/set_brightness.sh @@ -0,0 +1,85 @@ +#!/bin/sh -e + +. ./utility_functions.sh + +# Function to adjust brightness for a selected monitor +adjust_monitor_brightness() { + while true; do + monitor_list=$(detect_connected_monitors) + monitor_array=$(echo "$monitor_list" | tr '\n' ' ') + set -- $monitor_array + count=1 + + clear + printf "%b\n" "${YELLOW}=========================================${RC}" + printf "%b\n" "${YELLOW} Adjust Monitor Brightness${RC}" + printf "%b\n" "${YELLOW}=========================================${RC}" + printf "%b\n" "${YELLOW}Choose a monitor to adjust brightness:${RC}" + for monitor in "$@"; do + echo "$count. $monitor" + count=$((count + 1)) + done + + echo "Enter the number of the monitor (or 'q' to quit): " + read monitor_choice + + if [ "$monitor_choice" = "q" ]; then + printf "%b\n" "${RED}Exiting...${RC}" + return + fi + + if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then + echo "Invalid selection. Please try again." + echo "Press [Enter] to continue..." + read + continue + fi + + if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$#" ]; then + printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" + echo "Press [Enter] to continue..." + read + continue + fi + + monitor_name=$(eval echo "\${$monitor_choice}") + current_brightness=$(get_current_brightness "$monitor_name") + + # Correctly calculate the brightness percentage + current_brightness_percentage=$(awk "BEGIN {printf \"%.0f\", $current_brightness * 100}") + printf "%b\n" "${YELLOW}Current brightness for $monitor_name${RC}: ${GREEN}$current_brightness_percentage%${RC}" + + while true; do + echo "Enter the new brightness value as a percentage (10 to 100, or 'q' to quit): " + read new_brightness_percentage + + if [ "$new_brightness_percentage" = "q" ]; then + printf "%b\n" "${RED}Exiting...${RC}" + return + fi + + # Validate brightness input: accept only values above 10 + if ! echo "$new_brightness_percentage" | grep -qE '^[0-9]+$' || [ "$new_brightness_percentage" -lt 10 ] || [ "$new_brightness_percentage" -gt 100 ]; then + printf "%b\n" "${RED}Invalid brightness value. Please enter a value between 10 and 100.${RC}" + continue + fi + + # Convert percentage to xrandr brightness value (10% to 0.10) + new_brightness=$(awk "BEGIN {printf \"%.2f\", $new_brightness_percentage / 100}") + + echo "Set brightness for $monitor_name to $new_brightness_percentage%? (y/n): " + read confirm + if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then + printf "%b\n" "${GREEN}Setting brightness for $monitor_name to $new_brightness_percentage%${RC}" + execute_command "xrandr --output $monitor_name --brightness $new_brightness" + printf "%b\n" "${GREEN}Brightness for $monitor_name set to $new_brightness_percentage% successfully.${RC}" + break + else + printf "%b\n" "${RED}Action canceled. Please choose a different brightness value.${RC}" + fi + done + done +} + +# Call the adjust_monitor_brightness function +adjust_monitor_brightness diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index 48b4c8da9..00e01af07 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -38,6 +38,12 @@ detect_connected_monitors() { echo "$xrandr_output" | grep " connected" | awk '{print $1}' } +# Function to get the current brightness for a monitor +get_current_brightness() { + monitor="$1" + xrandr --verbose | grep -A 10 "^$monitor connected" | grep "Brightness:" | awk '{print $2}' +} + # Function to get resolutions for a monitor get_unique_resolutions() { monitor="$1" From ea9d6d7ddc04297d69e268ebd40f1a1416c11207 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:52:10 +0530 Subject: [PATCH 25/88] samba ssh setup script added --- tabs/system-setup/5-samba-ssh-setup.sh | 201 +++++++++++++++++++++++++ tabs/system-setup/tab_data.toml | 4 + 2 files changed, 205 insertions(+) create mode 100755 tabs/system-setup/5-samba-ssh-setup.sh diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh new file mode 100755 index 000000000..d9f7855c0 --- /dev/null +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -0,0 +1,201 @@ +#!/bin/sh -e + +# Load common script functions +. ../common-script.sh + +# Function to install packages based on the package manager +install_package() { + PACKAGE=$1 + if ! command_exists "$PACKAGE"; then + case "$PACKAGER" in + pacman) + $ESCALATION_TOOL "$PACKAGER" -S --noconfirm "$PACKAGE" + ;; + *) + $ESCALATION_TOOL "$PACKAGER" install -y "$PACKAGE" + ;; + esac + else + echo "$PACKAGE is already installed." + fi +} + +# Function to setup and configure SSH +setup_ssh() { + printf "%b\n" "${YELLOW}Setting up SSH...${RC}" + + # Detect package manager and install appropriate SSH package + if [ "$PACKAGER" = "apt-get" ]; then + install_package openssh-server + SSH_SERVICE="ssh" + elif [ "$PACKAGER" = "pacman" ]; then + install_package openssh + SSH_SERVICE="sshd" + else + install_package openssh-server + SSH_SERVICE="sshd" + fi + + # Enable and start the appropriate SSH service + $ESCALATION_TOOL systemctl enable "$SSH_SERVICE" + $ESCALATION_TOOL systemctl start "$SSH_SERVICE" + + # Get the local IP address + LOCAL_IP=$(ip -4 addr show | awk '/inet / {print $2}' | tail -n 1) + + printf "%b\n" "${GREEN}Your local IP address is: $LOCAL_IP${RC}" + + # Check if SSH is running + if systemctl is-active --quiet "$SSH_SERVICE"; then + printf "%b\n" "${GREEN}SSH is up and running.${RC}" + else + printf "%b\n" "${RED}Failed to start SSH.${RC}" + fi +} + +# Function to setup and configure Samba +setup_samba() { + printf "%b\n" "${YELLOW}Setting up Samba...${RC}" + + # Install Samba if not installed + install_package samba + + SAMBA_CONFIG="/etc/samba/smb.conf" + + if [ -f "$SAMBA_CONFIG" ]; then + printf "%b\n" "${YELLOW}Samba configuration file already exists at $SAMBA_CONFIG.${RC}" + echo "Do you want to modify the existing Samba configuration? (yes/no): " + read MODIFY_SAMBA + if [ "$MODIFY_SAMBA" = "yes" ]; then + $ESCALATION_TOOL nano "$SAMBA_CONFIG" + fi + else + printf "%b\n" "${YELLOW}No existing Samba configuration found. Setting up a new one...${RC}" + + # Prompt user for shared directory path + echo "Enter the path for the Samba share (default: /srv/samba/share): " + read SHARED_DIR + SHARED_DIR=${SHARED_DIR:-/srv/samba/share} + + # Create the shared directory if it doesn't exist + $ESCALATION_TOOL mkdir -p "$SHARED_DIR" + $ESCALATION_TOOL chmod -R 0777 "$SHARED_DIR" + + # Add a new Samba user + echo "Enter Samba username: " + read SAMBA_USER + + # Loop until the passwords match + while true; do + echo "Enter Samba password: " + stty -echo + read SAMBA_PASSWORD + stty echo + echo "Confirm Samba password: " + stty -echo + read SAMBA_PASSWORD_CONFIRM + stty echo + echo "" + if [ "$SAMBA_PASSWORD" = "$SAMBA_PASSWORD_CONFIRM" ]; then + printf "%b\n" "${GREEN}Passwords match.${RC}" + break + else + printf "%b\n" "${RED}Passwords do not match. Please try again.${RC}" + fi + done + + # Add the user and set the password + $ESCALATION_TOOL smbpasswd -a "$SAMBA_USER" + + # Configure Samba settings + $ESCALATION_TOOL sh -c "cat > $SAMBA_CONFIG" < Date: Wed, 18 Sep 2024 21:54:48 +0530 Subject: [PATCH 26/88] Update tabs/utils/tab_data.toml Co-authored-by: Adam Perkowski --- tabs/utils/tab_data.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 2559d5dce..d5783fc0e 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -25,7 +25,7 @@ name = "Auto Login" script = "auto-login.sh" [[data]] -name = "Bootable Pendrive Maker" +name = "Bootable USB Creator" script = "create-bootable-usb.sh" [[data]] From 60405aae80fe9d24badcc1c8c4899c667e8f817f Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:55:55 +0530 Subject: [PATCH 27/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index d9f7855c0..81d081b8d 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -63,7 +63,7 @@ setup_samba() { SAMBA_CONFIG="/etc/samba/smb.conf" if [ -f "$SAMBA_CONFIG" ]; then - printf "%b\n" "${YELLOW}Samba configuration file already exists at $SAMBA_CONFIG.${RC}" + printf "%b\n" "${YELLOW}Samba configuration file already exists in $SAMBA_CONFIG.${RC}" echo "Do you want to modify the existing Samba configuration? (yes/no): " read MODIFY_SAMBA if [ "$MODIFY_SAMBA" = "yes" ]; then From 1d59a555bfa67bec3a9606ff7b7e6a76152e47a7 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:56:45 +0530 Subject: [PATCH 28/88] Update tabs/utils/auto-login.sh Co-authored-by: Adam Perkowski --- tabs/utils/auto-login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index 69bd8611d..e73c41004 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -107,7 +107,7 @@ configure_lxdm() { echo "Configuring LXDM for autologin..." echo "Enter username for LXDM autologin: " - read user + read -r user list_sessions # Show session options $ESCALATION_TOOL sed -i "s/^#.*autologin=.*$/autologin=${user}/" /etc/lxdm/lxdm.conf From 1b0b9bbf12646adc259960cdc9b8780c30a8605b Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:58:56 +0530 Subject: [PATCH 29/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index 81d081b8d..c540e6b38 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -25,16 +25,20 @@ setup_ssh() { printf "%b\n" "${YELLOW}Setting up SSH...${RC}" # Detect package manager and install appropriate SSH package - if [ "$PACKAGER" = "apt-get" ]; then + case "$PACKAGER" in + "apt-get") install_package openssh-server SSH_SERVICE="ssh" - elif [ "$PACKAGER" = "pacman" ]; then + ;; + "pacman") install_package openssh SSH_SERVICE="sshd" - else + ;; + *) install_package openssh-server SSH_SERVICE="sshd" - fi + ;; + esac # Enable and start the appropriate SSH service $ESCALATION_TOOL systemctl enable "$SSH_SERVICE" From 0d7213d36adc0e2eb20f687d555b4e47475cee87 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:04:10 +0530 Subject: [PATCH 30/88] Update tabs/utils/auto-login.sh Co-authored-by: Adam Perkowski --- tabs/utils/auto-login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index e73c41004..9b88dd999 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -85,7 +85,7 @@ configure_sddm() { echo "Configuring SDDM for autologin..." echo "Enter username for SDDM autologin: " - read user + read -r user list_sessions # Show session options $ESCALATION_TOOL "echo '[Autologin]' > /etc/sddm.conf" From 8fdb1050785e0dd91ba1eef829b87ebf3bf63e2e Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:04:19 +0530 Subject: [PATCH 31/88] Update tabs/utils/auto-login.sh Co-authored-by: Adam Perkowski --- tabs/utils/auto-login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index 9b88dd999..212992106 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -63,7 +63,7 @@ configure_gdm() { echo "Configuring GDM for autologin..." echo "Enter username for GDM autologin: " - read user + read -r user $ESCALATION_TOOL "echo '[daemon]' > /etc/gdm/custom.conf" $ESCALATION_TOOL "echo 'AutomaticLoginEnable = true' >> /etc/gdm/custom.conf" From 6646c4d81cf25df880fca4cf50d3ac5d776a0824 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:04:30 +0530 Subject: [PATCH 32/88] Update tabs/utils/auto-login.sh Co-authored-by: Adam Perkowski --- tabs/utils/auto-login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index 212992106..9fa28bf53 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -42,7 +42,7 @@ configure_lightdm() { echo "Configuring LightDM for autologin..." echo "Enter username for LightDM autologin: " - read user + read -r user $ESCALATION_TOOL "echo '[Seat:*]' > /etc/lightdm/lightdm.conf.d/50-autologin.conf" $ESCALATION_TOOL "echo 'autologin-user=$user' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" From d0ccb236875478a5085397416fe5707438b15e6f Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:04:43 +0530 Subject: [PATCH 33/88] Update tabs/utils/auto-login.sh Co-authored-by: Adam Perkowski --- tabs/utils/auto-login.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index 9fa28bf53..835ca7469 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -30,7 +30,7 @@ list_sessions() { 9) session="i3.desktop" ;; 10) echo "Enter custom session name (e.g., mysession.desktop): " - read session ;; + read -r session ;; *) echo "Invalid option selected." exit 1 ;; From dc268906b8b483ae3d97d277a416811765200c97 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:05:24 +0530 Subject: [PATCH 34/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index c540e6b38..677cadb79 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -93,7 +93,7 @@ setup_samba() { while true; do echo "Enter Samba password: " stty -echo - read SAMBA_PASSWORD + read -r SAMBA_PASSWORD stty echo echo "Confirm Samba password: " stty -echo From d30ba118858e16e9ebeb400760d74864b0247ce8 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:05:42 +0530 Subject: [PATCH 35/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index 677cadb79..317b59e37 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -87,7 +87,7 @@ setup_samba() { # Add a new Samba user echo "Enter Samba username: " - read SAMBA_USER + read -r SAMBA_USER # Loop until the passwords match while true; do From 59fafbbc2e24d6c7b10635af99dd1952b73be4a7 Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Wed, 18 Sep 2024 22:05:56 +0530 Subject: [PATCH 36/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index 317b59e37..c8a4d69e3 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -78,7 +78,7 @@ setup_samba() { # Prompt user for shared directory path echo "Enter the path for the Samba share (default: /srv/samba/share): " - read SHARED_DIR + read -r SHARED_DIR SHARED_DIR=${SHARED_DIR:-/srv/samba/share} # Create the shared directory if it doesn't exist From 28ee76b9b0e51d00a178ee82c5d7ff855ba3f745 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 11:57:44 -0500 Subject: [PATCH 37/88] Update tabs/system-setup/5-samba-ssh-setup.sh Co-authored-by: Adam Perkowski --- tabs/system-setup/5-samba-ssh-setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index c8a4d69e3..94de1e0d5 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -71,7 +71,7 @@ setup_samba() { echo "Do you want to modify the existing Samba configuration? (yes/no): " read MODIFY_SAMBA if [ "$MODIFY_SAMBA" = "yes" ]; then - $ESCALATION_TOOL nano "$SAMBA_CONFIG" + "$ESCALATION_TOOL" "$EDITOR" "$SAMBA_CONFIG" fi else printf "%b\n" "${YELLOW}No existing Samba configuration found. Setting up a new one...${RC}" From 7f286461b11d2b1952c28d7621e781bc73f390a7 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 12:03:04 -0500 Subject: [PATCH 38/88] Update tabs/utils/monitor-control/set_brightness.sh Co-authored-by: Adam Perkowski --- tabs/utils/monitor-control/set_brightness.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/monitor-control/set_brightness.sh b/tabs/utils/monitor-control/set_brightness.sh index 8265ded73..bcb8c1043 100644 --- a/tabs/utils/monitor-control/set_brightness.sh +++ b/tabs/utils/monitor-control/set_brightness.sh @@ -31,7 +31,7 @@ adjust_monitor_brightness() { if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then echo "Invalid selection. Please try again." echo "Press [Enter] to continue..." - read + read dummy continue fi From 3f6209e7f6c7007e26fd1ffc2765e7441eab4748 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 12:04:37 -0500 Subject: [PATCH 39/88] Update tabs/utils/monitor-control/set_brightness.sh Co-authored-by: Adam Perkowski --- tabs/utils/monitor-control/set_brightness.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/utils/monitor-control/set_brightness.sh b/tabs/utils/monitor-control/set_brightness.sh index bcb8c1043..16f3da3b6 100644 --- a/tabs/utils/monitor-control/set_brightness.sh +++ b/tabs/utils/monitor-control/set_brightness.sh @@ -38,7 +38,7 @@ adjust_monitor_brightness() { if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$#" ]; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" echo "Press [Enter] to continue..." - read + read dummy continue fi From 60d4d4b380cf1a0188cf16da2bb45483bda82e85 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 12:53:47 -0500 Subject: [PATCH 40/88] Remove bashisms --- tabs/common-script.sh | 1 + tabs/system-setup/5-samba-ssh-setup.sh | 26 +++---- tabs/utils/create-bootable-usb.sh | 18 ++--- .../monitor-control/utility_functions.sh | 5 +- tabs/utils/power-profile.sh | 3 +- tabs/utils/timeshift.sh | 71 +++++++++++-------- 6 files changed, 69 insertions(+), 55 deletions(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index aa4deae95..678a45162 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -5,6 +5,7 @@ RC='\033[0m' RED='\033[31m' YELLOW='\033[33m' +CYAN='\033[36m' GREEN='\033[32m' command_exists() { diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index 94de1e0d5..ddd43c994 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -68,8 +68,8 @@ setup_samba() { if [ -f "$SAMBA_CONFIG" ]; then printf "%b\n" "${YELLOW}Samba configuration file already exists in $SAMBA_CONFIG.${RC}" - echo "Do you want to modify the existing Samba configuration? (yes/no): " - read MODIFY_SAMBA + printf "Do you want to modify the existing Samba configuration? (yes/no): " + read -r MODIFY_SAMBA if [ "$MODIFY_SAMBA" = "yes" ]; then "$ESCALATION_TOOL" "$EDITOR" "$SAMBA_CONFIG" fi @@ -77,7 +77,7 @@ setup_samba() { printf "%b\n" "${YELLOW}No existing Samba configuration found. Setting up a new one...${RC}" # Prompt user for shared directory path - echo "Enter the path for the Samba share (default: /srv/samba/share): " + printf "Enter the path for the Samba share (default: /srv/samba/share): " read -r SHARED_DIR SHARED_DIR=${SHARED_DIR:-/srv/samba/share} @@ -157,19 +157,19 @@ configure_firewall() { } setup_ssh_samba(){ - echo "Samba and SSH Setup Script" - echo "----------------------------" + printf "Samba and SSH Setup Script\n" + printf "----------------------------\n" clear # Display menu - echo "Select an option:" - echo "1. Setup SSH" - echo "2. Setup Samba" - echo "3. Configure Firewall" - echo "4. Setup All" - echo "5. Exit" - - echo "Enter your choice [1-5]: " + printf "Select an option:\n" + printf "1. Setup SSH\n" + printf "2. Setup Samba\n" + printf "3. Configure Firewall\n" + printf "4. Setup All\n" + printf "5. Exit\n" + + printf "Enter your choice [1-5]: " read CHOICE case "$CHOICE" in diff --git a/tabs/utils/create-bootable-usb.sh b/tabs/utils/create-bootable-usb.sh index 80dab1025..6feae2dac 100644 --- a/tabs/utils/create-bootable-usb.sh +++ b/tabs/utils/create-bootable-usb.sh @@ -52,9 +52,9 @@ fetch_arch_older_isos() { COUNTER=$((COUNTER + 1)) done - echo "" # New line after the last row - - read -p "Select an Arch Linux version (1-$((COUNTER - 1))): " ARCH_OPTION + printf "\n" # New line after the last row + printf "Select an Arch Linux version (1-%d): " "$((COUNTER - 1))" + read -r ARCH_OPTION ARCH_DIR=$(echo "$ARCH_VERSIONS" | sed -n "${ARCH_OPTION}p") ARCH_URL="${ARCH_BASE_URL}${ARCH_DIR}/archlinux-${ARCH_DIR}-x86_64.iso" printf "%b\n" "${GREEN}Selected Arch Linux (older) ISO URL: $ARCH_URL${RC}" @@ -70,17 +70,19 @@ fetch_debian_latest_iso() { # Function to ask whether to use local or online ISO choose_iso_source() { printf "%b\n" "${YELLOW} Do you want to use a local ISO or download online? ${RC}" - echo "1) Download online" - echo "2) Use local ISO" - echo "" - read -p "Select option (1-2): " ISO_SOURCE_OPTION + printf "1) Download online\n" + printf "2) Use local ISO\n" + printf "\n" + printf "Select option (1-2): " + read -r ISO_SOURCE_OPTION case $ISO_SOURCE_OPTION in 1) fetch_iso_urls # Call the function to fetch online ISO URLs ;; 2) - read -p "Enter the path to the already downloaded ISO file: " ISO_PATH + printf "Enter the path to the already downloaded ISO file: " + read -r ISO_PATH if [ ! -f "$ISO_PATH" ]; then printf "%b\n" "${RED} ISO file not found: $ISO_PATH ${RC}" exit 1 diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index 00e01af07..6c811a84f 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -79,8 +79,9 @@ get_unique_resolutions() { # Function to prompt for confirmation confirm_action() { action="$1" - echo "$action" - read -p "Are you sure? (y/n): " confirm + printf "%b\n" "${CYAN}$action${RC}" + printf "%b" "${CYAN}Are you sure? (y/n): ${RC}" + read -r confirm if echo "$confirm" | grep -qE '^[Yy]$'; then return 0 else diff --git a/tabs/utils/power-profile.sh b/tabs/utils/power-profile.sh index 5c614d3f1..3cc1823fc 100644 --- a/tabs/utils/power-profile.sh +++ b/tabs/utils/power-profile.sh @@ -75,7 +75,8 @@ apply_or_remove_auto_cpufreq() { printf "%b\n" "${YELLOW}Do you want to apply the auto-cpufreq tweak or remove it?${RC}" printf "%b\n" "${YELLOW}1) Apply tweak${RC}" printf "%b\n" "${YELLOW}2) Remove tweak${RC}" - read -rp "Enter your choice [1/2]: " choice + printf "%b" "Enter your choice [1/2]: " + read -r choice case $choice in 1) diff --git a/tabs/utils/timeshift.sh b/tabs/utils/timeshift.sh index 9ff18892c..2d4a5a780 100644 --- a/tabs/utils/timeshift.sh +++ b/tabs/utils/timeshift.sh @@ -24,34 +24,36 @@ install_timeshift() { # Function to display the menu display_menu() { clear - echo "Timeshift CLI Automation" - echo "-------------------------" - echo "1) List Snapshots" - echo "2) List Devices" - echo "3) Create Snapshot" - echo "4) Restore Snapshot" - echo "5) Delete Snapshot" - echo "6) Delete All Snapshots" - echo "7) Exit" - echo "" + printf "%b\n" "${CYAN}Timeshift CLI Automation${RC}" + printf "%b\n" "${CYAN}\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-" + printf "%b\n" "${CYAN}1) List Snapshots${RC}" + printf "%b\n" "${CYAN}2) List Devices${RC}" + printf "%b\n" "${CYAN}3) Create Snapshot${RC}" + printf "%b\n" "${CYAN}4) Restore Snapshot${RC}" + printf "%b\n" "${CYAN}5) Delete Snapshot${RC}" + printf "%b\n" "${CYAN}6) Delete All Snapshots${RC}" + printf "%b\n" "${CYAN}7) Exit${RC}" + printf "%b\n" "${CYAN}\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-" } # Function to list snapshots list_snapshots() { - echo "Listing snapshots..." + printf "%b\n" "${CYAN}Listing snapshots...${RC}" $ESCALATION_TOOL timeshift --list-snapshots } # Function to list devices list_devices() { - echo "Listing available devices..." + printf "%b\n" "${CYAN}Listing available devices...${RC}" $ESCALATION_TOOL timeshift --list-devices } # Function to create a new snapshot create_snapshot() { - read -p "Enter a comment for the snapshot (optional): " COMMENT - read -p "Enter snapshot tag (O,B,H,D,W,M) (leave empty for no tag): " TAG + printf "%b" "${CYAN}Enter a comment for the snapshot (optional): ${RC}" + read -r COMMENT + printf "%b" "${CYAN}Enter snapshot tag (O,B,H,D,W,M) (leave empty for no tag): ${RC}" + read -r TAG if [ -z "$COMMENT" ] && [ -z "$TAG" ]; then echo "Creating snapshot with no comment or tag..." @@ -75,21 +77,25 @@ create_snapshot() { restore_snapshot() { list_snapshots - read -p "Enter the snapshot name you want to restore: " SNAPSHOT - read -p "Enter the target device (e.g., /dev/sda1): " TARGET_DEVICE - read -p "Do you want to skip GRUB reinstall? (yes/no): " SKIP_GRUB + printf "%b" "${CYAN}Enter the snapshot name you want to restore: ${RC}" + read -r SNAPSHOT + printf "%b" "${CYAN}Enter the target device (e.g., /dev/sda1): ${RC}" + read -r TARGET_DEVICE + printf "%b" "${CYAN}Do you want to skip GRUB reinstall? (yes/no): ${RC}" + read -r SKIP_GRUB if [ "$SKIP_GRUB" = "yes" ]; then $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --skip-grub --yes else - read -p "Enter GRUB device (e.g., /dev/sda): " GRUB_DEVICE + printf "%b" "${CYAN}Enter GRUB device (e.g., /dev/sda): ${RC}" + read -r GRUB_DEVICE $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes fi if [ $? -eq 0 ]; then - echo "Snapshot restored successfully." + printf "%b\n" "${GREEN}Snapshot restored successfully.${RC}" else - echo "Snapshot restore failed." + printf "%b\n" "${RED}Snapshot restore failed.${RC}" fi } @@ -97,22 +103,24 @@ restore_snapshot() { delete_snapshot() { list_snapshots - read -p "Enter the snapshot name you want to delete: " SNAPSHOT + printf "%b" "${CYAN}Enter the snapshot name you want to delete: ${RC}" + read -r SNAPSHOT - echo "Deleting snapshot $SNAPSHOT..." + printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}" $ESCALATION_TOOL timeshift --delete --snapshot "$SNAPSHOT" --yes if [ $? -eq 0 ]; then - echo "Snapshot deleted successfully." + printf "%b\n" "${GREEN}Snapshot deleted successfully.${RC}" else - echo "Snapshot deletion failed." + printf "%b\n" "${RED}Snapshot deletion failed.${RC}" fi } # Function to delete all snapshots delete_all_snapshots() { - echo "WARNING: This will delete all snapshots!" - read -p "Are you sure? (yes/no): " CONFIRMATION + printf "%b\n" "${RED}WARNING: This will delete all snapshots!${RC}" + printf "%b" "${CYAN}Are you sure? (yes/no): ${RC}" + read -r CONFIRMATION if [ "$CONFIRMATION" = "yes" ]; then echo "Deleting all snapshots..." @@ -130,7 +138,8 @@ delete_all_snapshots() { main_menu() { while true; do display_menu - read -p "Select an option (1-7): " OPTION + printf "%b" "${CYAN}Select an option (1-7): ${RC}" + read -r OPTION case $OPTION in 1) list_snapshots ;; @@ -139,11 +148,11 @@ while true; do 4) restore_snapshot ;; 5) delete_snapshot ;; 6) delete_all_snapshots ;; - 7) echo "Exiting..."; exit 0 ;; - *) echo "Invalid option. Please try again." ;; + 7) printf "%b\n" "${GREEN}Exiting...${RC}"; exit 0 ;; + *) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;; esac - - read -p "Press Enter to continue..." + printf "%b" "${CYAN}Press Enter to continue...${RC}" + read -r dummy done } From 69b61e72658a71e31d299580faff32b0e0b4c29b Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:29:51 -0400 Subject: [PATCH 41/88] Fix wifi-manager (#456) Co-authored-by: nnyyxxxx --- tabs/utils/wifi-control.sh | 62 +++++++++++++++----------------------- 1 file changed, 25 insertions(+), 37 deletions(-) diff --git a/tabs/utils/wifi-control.sh b/tabs/utils/wifi-control.sh index 2a6686a81..5518f25b9 100644 --- a/tabs/utils/wifi-control.sh +++ b/tabs/utils/wifi-control.sh @@ -65,15 +65,15 @@ main_menu() { scan_networks() { clear printf "%b\n" "${YELLOW}Scanning for WiFi networks...${RC}" - networks=$(nmcli -t -f SSID,BSSID,SIGNAL dev wifi list | head -n 10) + networks=$(nmcli -t -f SSID,BSSID,SIGNAL dev wifi list | awk -F: '!seen[$1]++' | head -n 10) if [ -z "$networks" ]; then printf "%b\n" "${RED}No networks found.${RC}" else printf "%b\n" "${GREEN}Top 10 Networks found:${RC}" - echo "$networks" | sed 's/\\//g' | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}' + echo "$networks" | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}' fi echo "Press any key to return to the main menu..." - read -n 1 + read -r dummy } # Function to turn WiFi on @@ -86,7 +86,7 @@ wifi_on() { printf "%b\n" "${RED}Failed to turn on WiFi.${RC}" } echo "Press any key to return to the main menu..." - read -n 1 + read -r dummy } # Function to turn WiFi off @@ -99,7 +99,7 @@ wifi_off() { printf "%b\n" "${RED}Failed to turn off WiFi.${RC}" } echo "Press any key to return to the main menu..." - read -n 1 + read -r dummy } # Function to prompt for WiFi network selection @@ -108,65 +108,53 @@ prompt_for_network() { prompt_msg=$2 success_msg=$3 failure_msg=$4 + temp_file=$(mktemp) while true; do clear - networks=$(nmcli -t -f SSID dev wifi list | head -n 10) + networks=$(nmcli -t -f SSID dev wifi list | awk -F: '!seen[$1]++' | grep -v '^$') if [ -z "$networks" ]; then printf "%b\n" "${RED}No networks available. Please scan for networks first.${RC}" echo "Press any key to return to the main menu..." - read -n 1 + read -r dummy + rm -f "$temp_file" return fi - - # Display networks with numbers + + echo "$networks" > "$temp_file" + i=1 - echo "$networks" | while IFS= read -r network; do + while IFS= read -r network; do ssid=$(echo "$network" | awk -F: '{print $1}') - echo "$i. SSID: $ssid" + printf "%d. SSID: %s\n" "$i" "$ssid" i=$((i + 1)) - done + done < "$temp_file" + echo "0. Exit to main menu" echo -n "$prompt_msg" read choice - # Validate the choice - if echo "$choice" | grep -qE '^[0-9]+$' && [ "$choice" -le "$((i - 1))" ] && [ "$choice" -gt 0 ]; then - network=$(echo "$networks" | sed -n "${choice}p") - ssid=$(echo "$network" | awk -F: '{print $1}') + if [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then + ssid=$(sed -n "${choice}p" "$temp_file" | awk -F: '{print $1}') if [ "$action" = "connect" ]; then echo -n "Enter password for SSID $ssid: " - read -s password + read password echo nmcli dev wifi connect "$ssid" password "$password" && { printf "%b\n" "${GREEN}$success_msg${RC}" - break - } || { - printf "%b\n" "${RED}$failure_msg${RC}" - } - elif [ "$action" = "disconnect" ]; then - nmcli connection down "$ssid" && { - printf "%b\n" "${GREEN}$success_msg${RC}" - break - } || { - printf "%b\n" "${RED}$failure_msg${RC}" - } - elif [ "$action" = "remove" ]; then - nmcli connection delete "$ssid" && { - printf "%b\n" "${GREEN}$success_msg${RC}" - break } || { printf "%b\n" "${RED}$failure_msg${RC}" } fi - elif [ "$choice" -eq 0 ]; then - return else printf "%b\n" "${RED}Invalid choice. Please try again.${RC}" fi + + echo "Press any key to return to the selection menu..." + read -r dummy done - echo "Press any key to return to the main menu..." - read -n 1 + + rm -f "$temp_file" } # Function to connect to a WiFi network @@ -188,4 +176,4 @@ remove_network() { checkEnv checkEscalationTool setupNetworkManager -main_menu +main_menu \ No newline at end of file From 093883e1bfbdf98b3db4fbc6142bea223818aac0 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:30:27 -0400 Subject: [PATCH 42/88] Remove bashisms out of bluetooth-control (#462) Co-authored-by: nnyyxxxx --- tabs/utils/bluetooth-control.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tabs/utils/bluetooth-control.sh b/tabs/utils/bluetooth-control.sh index 51aa16221..36c1d35c8 100644 --- a/tabs/utils/bluetooth-control.sh +++ b/tabs/utils/bluetooth-control.sh @@ -68,8 +68,8 @@ scan_devices() { printf "%b\n" "${GREEN}Devices found:${RC}" echo "$devices" fi - echo "Press any key to return to the main menu..." - read -n 1 + printf "Press any key to return to the main menu..." + read -r dummy } # Function to prompt for MAC address using numbers @@ -85,8 +85,8 @@ prompt_for_mac() { devices=$(bluetoothctl devices) if [ -z "$devices" ]; then printf "%b\n" "${RED}No devices available. Please scan for devices first.${RC}" - echo "Press any key to return to the main menu..." - read -n 1 + printf "Press any key to return to the main menu..." + read -r dummy return fi @@ -121,8 +121,8 @@ prompt_for_mac() { printf "%b\n" "${RED}Invalid choice. Please try again.${RC}" fi done - echo "Press any key to return to the main menu..." - read -n 1 + printf "Press any key to return to the main menu..." + read -r dummy } # Function to pair with a device From c805c46dfc1c591e42405954a45f5f561d6e88c2 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:30:49 -0400 Subject: [PATCH 43/88] Remove bashisms out of managearrangement (#463) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/manage_arrangement.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tabs/utils/monitor-control/manage_arrangement.sh b/tabs/utils/monitor-control/manage_arrangement.sh index 268b930f0..684dbfd4c 100755 --- a/tabs/utils/monitor-control/manage_arrangement.sh +++ b/tabs/utils/monitor-control/manage_arrangement.sh @@ -20,7 +20,8 @@ manage_arrangement() { i=$((i + 1)) done - read -p "Enter the number of the monitor to arrange: " monitor_choice + printf "Enter the number of the monitor to arrange: " + read -r monitor_choice if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" @@ -36,7 +37,8 @@ manage_arrangement() { printf "%b\n" "3. ${YELLOW}Above${RC}" printf "%b\n" "4. ${YELLOW}Below${RC}" - read -p "Enter the number of the position: " position_choice + printf "Enter the number of the position: " + read -r position_choice case $position_choice in 1) position="--left-of" ;; @@ -53,7 +55,8 @@ manage_arrangement() { fi done - read -p "Enter the number of the reference monitor: " ref_choice + printf "Enter the number of the reference monitor: " + read -r ref_choice if ! echo "$ref_choice" | grep -qE '^[0-9]+$' || [ "$ref_choice" -lt 1 ] || [ "$ref_choice" -gt "$((i - 1))" ] || [ "$ref_choice" -eq "$monitor_choice" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" From a516c9e5febedc52f2127413830926a1fc3459a2 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:31:07 -0400 Subject: [PATCH 44/88] Remove bashism from enable monitor (#467) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/enable_monitor.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tabs/utils/monitor-control/enable_monitor.sh b/tabs/utils/monitor-control/enable_monitor.sh index 6d6ec5b63..2173f7f1b 100755 --- a/tabs/utils/monitor-control/enable_monitor.sh +++ b/tabs/utils/monitor-control/enable_monitor.sh @@ -21,7 +21,8 @@ enable_monitor() { i=$((i + 1)) done - read -p "Enter the number of the monitor: " monitor_choice + printf "Enter the number of the monitor: " + read -r monitor_choice if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" From e049d3c6aa2438962d097d586ba95dba529cdabd Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:32:12 -0400 Subject: [PATCH 45/88] Fix Chris fat finger (#468) Co-authored-by: nnyyxxxx --- tabs/applications-setup/alacritty-setup.sh | 4 ++-- tabs/applications-setup/fastfetch-setup.sh | 3 +-- tabs/applications-setup/zsh-setup.sh | 26 +++++++++++----------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 3625ca966..4c1c58d7d 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -3,7 +3,7 @@ . ../common-script.sh installAlacritty() { - echo "Installing Alacritty..." + printf "%b\n" "${YELLOW}Installing Alacritty...${RC}" if ! command_exists alacritty; then case "$PACKAGER" in pacman) @@ -14,7 +14,7 @@ installAlacritty() { ;; esac else - printf "%b\n" "${GREEN}alacritty is already installed.${RC}" + printf "%b\n" "${GREEN}Alacritty is already installed.${RC}" fi } diff --git a/tabs/applications-setup/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index 83fb52fa6..60077f145 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -3,8 +3,7 @@ . ../common-script.sh installFastfetch() { - printf "%b\n" "${YELLOW}Installing Fastfetch if not already installed...${RC}" - + printf "%b\n" "${YELLOW}Installing Fastfetch...${RC}" if ! command_exists fastfetch; then case "$PACKAGER" in pacman) diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index 5d4661365..626099db9 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -4,19 +4,19 @@ # Function to install zsh installZsh() { - printf "%b\n" "${YELLOWInstalling Zsh...${RC}" - if ! command_exists zsh; then - case "$PACKAGER" in - pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm zsh - ;; - *) - $ESCALATION_TOOL "$PACKAGER" install -y zsh - ;; - esac - else - printf "%b\n" "${GREEN}ZSH is already installed.${RC}" - fi + printf "%b\n" "${YELLOW}Installing Zsh...${RC}" + if ! command_exists zsh; then + case "$PACKAGER" in + pacman) + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm zsh + ;; + *) + $ESCALATION_TOOL "$PACKAGER" install -y zsh + ;; + esac + else + printf "%b\n" "${GREEN}ZSH is already installed.${RC}" + fi } # Function to setup zsh configuration From d2b4875751991b0d4d160eb22564ae7dab4148a1 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:32:35 -0400 Subject: [PATCH 46/88] Remove bashisms out of change orientation (#466) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/change_orientation.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tabs/utils/monitor-control/change_orientation.sh b/tabs/utils/monitor-control/change_orientation.sh index 8d8679659..19e085f48 100755 --- a/tabs/utils/monitor-control/change_orientation.sh +++ b/tabs/utils/monitor-control/change_orientation.sh @@ -20,7 +20,8 @@ change_orientation() { i=$((i + 1)) done - read -p "Enter the number of the monitor: " monitor_choice + printf "Enter the number of the monitor: " + read -r monitor_choice if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" @@ -39,8 +40,8 @@ change_orientation() { printf "%b\n" "3. ${GREEN}Right${RC}" printf "%b\n" "4. ${GREEN}Inverted${RC}" - read -p "Enter the number of the orientation: " orientation_choice - + printf "Enter the number of the orientation: " + read -r orientation_choice case $orientation_choice in 1) orientation="normal" ;; 2) orientation="left" ;; From 0e1ee966ae7e0abf1f1d3266a18dfaa796330992 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:32:53 -0400 Subject: [PATCH 47/88] Remove bashism out of setprimarymonitor (#464) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/set_primary_monitor.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tabs/utils/monitor-control/set_primary_monitor.sh b/tabs/utils/monitor-control/set_primary_monitor.sh index 143a8379d..c1a704168 100755 --- a/tabs/utils/monitor-control/set_primary_monitor.sh +++ b/tabs/utils/monitor-control/set_primary_monitor.sh @@ -20,7 +20,8 @@ set_primary_monitor() { i=$((i + 1)) done - read -p "Enter the number of the monitor: " monitor_choice + printf "Enter the number of the monitor to arrange: " + read -r monitor_choice if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" From 075b54f5fb39f73c5460c1e6aa32695ab7d91333 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:38:36 -0400 Subject: [PATCH 48/88] Add git as a dependency for scripts that use it (#436) * Add git as a dependency for scripts that use it * apt -> apt|nala * Refactor the remaining apt-gets and add nala to them * Remove refactored apts from this PR --------- Co-authored-by: nnyyxxxx Co-authored-by: Chris Titus --- tabs/applications-setup/dwmtitus-setup.sh | 20 ++++++++-------- tabs/applications-setup/mybash-setup.sh | 28 +++++++++++------------ tabs/applications-setup/neovim-setup.sh | 10 ++++---- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index 9017639d6..9ae234455 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -2,21 +2,14 @@ . ../common-script.sh -makeDWM() { - cd "$HOME" && git clone https://github.com/ChrisTitusTech/dwm-titus.git # CD to Home directory to install dwm-titus - # This path can be changed (e.g. to linux-toolbox directory) - cd dwm-titus/ # Hardcoded path, maybe not the best. - $ESCALATION_TOOL make clean install # Run make clean install -} - setupDWM() { printf "%b\n" "${YELLOW}Installing DWM-Titus if not already installed${RC}" case "$PACKAGER" in # Install pre-Requisites pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb git ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libx11-xcb-dev libfontconfig1 libx11-6 libxft2 libxinerama1 libxcb-res0-dev + $ESCALATION_TOOL "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libx11-xcb-dev libfontconfig1 libx11-6 libxft2 libxinerama1 libxcb-res0-dev git ;; dnf) $ESCALATION_TOOL "$PACKAGER" groupinstall -y "Development Tools" @@ -29,6 +22,13 @@ setupDWM() { esac } +makeDWM() { + cd "$HOME" && git clone https://github.com/ChrisTitusTech/dwm-titus.git # CD to Home directory to install dwm-titus + # This path can be changed (e.g. to linux-toolbox directory) + cd dwm-titus/ # Hardcoded path, maybe not the best. + $ESCALATION_TOOL make clean install # Run make clean install +} + install_nerd_font() { FONT_DIR="$HOME/.local/share/fonts" FONT_ZIP="$FONT_DIR/Meslo.zip" @@ -292,4 +292,4 @@ makeDWM install_slstatus install_nerd_font clone_config_folders -configure_backgrounds +configure_backgrounds \ No newline at end of file diff --git a/tabs/applications-setup/mybash-setup.sh b/tabs/applications-setup/mybash-setup.sh index 380f1e2b2..7449072aa 100644 --- a/tabs/applications-setup/mybash-setup.sh +++ b/tabs/applications-setup/mybash-setup.sh @@ -4,29 +4,20 @@ gitpath="$HOME/.local/share/mybash" -cloneMyBash() { - # Check if the dir exists before attempting to clone into it. - if [ -d "$gitpath" ]; then - rm -rf "$gitpath" - fi - mkdir -p "$HOME/.local/share" # Only create the dir if it doesn't exist. - cd "$HOME" && git clone https://github.com/ChrisTitusTech/mybash.git "$gitpath" -} - installDepend() { printf "%b\n" "${YELLOW}Installing Bash...${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig git ;; apt) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig + $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig + $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; zypper) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig + $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" # The packages above were grabbed out of the original mybash-setup-script. @@ -35,6 +26,15 @@ installDepend() { esac } +cloneMyBash() { + # Check if the dir exists before attempting to clone into it. + if [ -d "$gitpath" ]; then + rm -rf "$gitpath" + fi + mkdir -p "$HOME/.local/share" # Only create the dir if it doesn't exist. + cd "$HOME" && git clone https://github.com/ChrisTitusTech/mybash.git "$gitpath" +} + installFont() { # Check to see if the MesloLGS Nerd Font is installed (Change this to whatever font you would like) FONT_NAME="MesloLGS Nerd Font Mono" @@ -110,8 +110,8 @@ linkConfig() { checkEnv checkEscalationTool -cloneMyBash installDepend +cloneMyBash installFont installStarshipAndFzf installZoxide diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 826fd5387..36d43c881 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -17,16 +17,16 @@ installNeovim() { printf "%b\n" "${YELLOW}Installing Neovim...${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck git ;; apt) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fd-find python3-venv luarocks golang-go shellcheck + $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fd-find python3-venv luarocks golang-go shellcheck git ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck + $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git ;; zypper) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck + $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" # The packages above were grabbed out of the original nvim-setup-script. @@ -51,7 +51,7 @@ linkNeovimConfig() { checkEnv checkEscalationTool -cloneNeovim installNeovim +cloneNeovim backupNeovimConfig linkNeovimConfig \ No newline at end of file From 54786a719ea837a0bee39e842ea5e8de4638faf2 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:40:31 -0400 Subject: [PATCH 49/88] git to bin for faster installation (#378) Co-authored-by: nnyyxxxx --- tabs/common-script.sh | 4 ++-- tabs/system-setup/arch/yay-setup.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 97721eaf3..6bcab74da 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -28,8 +28,8 @@ checkAURHelper() { echo "Installing yay as AUR helper..." $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel - cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-git.git && $ESCALATION_TOOL chown -R "$USER":"$USER" ./yay-git - cd yay-git && makepkg --noconfirm -si + cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-bin.git && $ESCALATION_TOOL chown -R "$USER":"$USER" ./yay-bin + cd yay-bin && makepkg --noconfirm -si if command_exists yay; then AUR_HELPER="yay" diff --git a/tabs/system-setup/arch/yay-setup.sh b/tabs/system-setup/arch/yay-setup.sh index 25fb2ee88..4fd561736 100755 --- a/tabs/system-setup/arch/yay-setup.sh +++ b/tabs/system-setup/arch/yay-setup.sh @@ -8,8 +8,8 @@ installDepend() { if ! command_exists yay; then echo "Installing yay as AUR helper..." $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel - cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-git.git && $ESCALATION_TOOL chown -R "$USER": ./yay-git - cd yay-git && makepkg --noconfirm -si + cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-bin.git && $ESCALATION_TOOL chown -R "$USER": ./yay-bin + cd yay-bin && makepkg --noconfirm -si echo "Yay installed" else echo "Aur helper already installed" From fde25afcbd550ad896fb2ea49d96e0d09ba2027b Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 00:19:33 +0530 Subject: [PATCH 50/88] feat: Implement minimum TUI size (#425) * Implement minimum size * Update tui/src/state.rs Co-authored-by: Adam Perkowski --------- Co-authored-by: Chris Titus Co-authored-by: Adam Perkowski --- tui/src/state.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tui/src/state.rs b/tui/src/state.rs index ca405162b..c495e2bef 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -33,6 +33,7 @@ pub struct AppState { /// widget selection: ListState, filter: Filter, + drawable: bool, } pub enum Focus { @@ -60,11 +61,55 @@ impl AppState { visit_stack: vec![root_id], selection: ListState::default().with_selected(Some(0)), filter: Filter::new(), + drawable: false, }; state.update_items(); state } pub fn draw(&mut self, frame: &mut Frame) { + let terminal_size = frame.area(); + let min_width = 77; // Minimum width threshold + let min_height = 19; // Minimum height threshold + + if terminal_size.width < min_width || terminal_size.height < min_height { + let size_warning_message = format!( + "Terminal size too small:\nWidth = {} Height = {}\n\nMinimum size:\nWidth = {} Height = {}", + terminal_size.width, + terminal_size.height, + min_width, + min_height, + ); + + let warning_paragraph = Paragraph::new(size_warning_message.clone()) + .alignment(Alignment::Center) + .style(Style::default().fg(ratatui::style::Color::Red).bold()) + .wrap(ratatui::widgets::Wrap { trim: true }); + + // Get the maximum width and height of text lines + let text_lines: Vec = size_warning_message + .lines() + .map(|line| line.to_string()) + .collect(); + let max_line_length = text_lines.iter().map(|line| line.len()).max().unwrap_or(0); + let num_lines = text_lines.len(); + + // Calculate the centered area + let centered_area = ratatui::layout::Rect { + x: terminal_size.x + (terminal_size.width - max_line_length as u16) / 2, + y: terminal_size.y + (terminal_size.height - num_lines as u16) / 2, + width: max_line_length as u16, + height: num_lines as u16, + }; + frame.render_widget(warning_paragraph, centered_area); + self.drawable = false; + } else { + self.drawable = true; + } + + if !self.drawable { + return; + } + let label_block = Block::default() .borders(Borders::all()) @@ -187,6 +232,21 @@ impl AppState { } pub fn handle_key(&mut self, key: &KeyEvent) -> bool { + // This should be defined first to allow closing + // the application even when not drawable ( If terminal is small ) + if matches!(self.focus, Focus::TabList | Focus::List) { + if key.code == KeyCode::Char('q') + || key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL) + { + return false; + } + } + + // If UI is not drawable returning true will mark as the key handled + if !self.drawable { + return true; + } + match &mut self.focus { Focus::FloatingWindow(command) => { if command.handle_key_event(key) { From f50c0e5c0d51f9782d41c95312ef75e8683c4d8e Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 13:54:51 -0500 Subject: [PATCH 51/88] remove auto label --- .github/workflows/pr-labels.yaml | 56 -------------------------------- 1 file changed, 56 deletions(-) delete mode 100644 .github/workflows/pr-labels.yaml diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml deleted file mode 100644 index 82f9ac97d..000000000 --- a/.github/workflows/pr-labels.yaml +++ /dev/null @@ -1,56 +0,0 @@ -name: Manage labels based on PR body - -on: - pull_request_target: - types: [opened, edited, reopened, synchronize] - -jobs: - manage-labels: - runs-on: ubuntu-latest - steps: - - name: Analyze PR Body and manage labels - shell: bash - run: | - body=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH") - labels_to_add=() - labels_to_remove=() - declare -A label_checks=( - ["New feature"]="enhancement" - ["Bug fix|Hotfix|Security patch"]="bug" - ["Documentation update"]="documentation" - ["Refactoring"]="refactor" - ["UI/UX improvement"]="UI/UX" - ) - for pattern in "${!label_checks[@]}"; do - label="${label_checks[$pattern]}" - if echo "$body" | grep -Eq "\- \[x\] ($pattern)"; then - labels_to_add+=("$label") - else - labels_to_remove+=("$label") - fi - done - - echo "LABELS_TO_ADD=$(IFS=,; echo "${labels_to_add[*]}")" >> $GITHUB_ENV - echo "LABELS_TO_REMOVE=$(IFS=,; echo "${labels_to_remove[*]}")" >> $GITHUB_ENV - - - name: Add labels if necessary - if: env.LABELS_TO_ADD != '' - run: | - IFS=',' read -ra labels <<< "${LABELS_TO_ADD}" - for label in "${labels[@]}"; do - curl -s -X POST \ - -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - -H "Accept: application/vnd.github.v3+json" \ - -d "{\"labels\": [\"$label\"]}" \ - https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels - done - - name: Remove labels if necessary - if: env.LABELS_TO_REMOVE != '' - run: | - IFS=',' read -ra labels <<< "${LABELS_TO_REMOVE}" - for label in "${labels[@]}"; do - curl -s -X DELETE \ - -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ - -H "Accept: application/vnd.github.v3+json" \ - https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels/$label - done From 83d88f7a1b52d9fd967c99a08dab259f29c5236d Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Wed, 18 Sep 2024 20:56:46 +0200 Subject: [PATCH 52/88] Created the workflow (#469) --- .github/workflows/bashisms.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/bashisms.yml diff --git a/.github/workflows/bashisms.yml b/.github/workflows/bashisms.yml new file mode 100644 index 000000000..6d3510987 --- /dev/null +++ b/.github/workflows/bashisms.yml @@ -0,0 +1,27 @@ +name: Check for bashisms + +on: + push: + paths: + - tabs/** + branches: [ "main" ] + pull_request: + paths: + - tabs/** + merge_group: + workflow_dispatch: + +jobs: + check-bashisms: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install devscripts + run: sudo apt install devscripts + + - name: Concatenate all .sh files and check for bashisms + working-directory: tabs + run: | + find . -name '*.sh' -exec checkbashisms {} + > all_scripts.sh From ad9d1662daa92ab957a31676936bacfc1859dff4 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 13:59:10 -0500 Subject: [PATCH 53/88] only run rust lint on rs files --- .github/workflows/rust.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index afbaf4bb3..b42553c2d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -3,6 +3,10 @@ name: Rust Checks on: pull_request: branches: ["main"] + paths: + - '**/*.rs' + - 'Cargo.toml' + - 'Cargo.lock' env: CARGO_TERM_COLOR: always From 44d9360448b25363f8e794a675701629cceb7227 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Wed, 18 Sep 2024 21:10:21 +0200 Subject: [PATCH 54/88] Refactor `gaming-setup.sh` (#380) * Refactored + removed bashisms - revieved all packages - changed the structure to have synergy with other scripts - updated dnf & zypper commands - added nala * use apt-get instead of apt Co-authored-by: Nyx <144965845+nnyyxxxx@users.noreply.github.com> * small refactor (#3) Co-authored-by: nnyyxxxx * apt-get + quote escalation --------- Co-authored-by: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Co-authored-by: nnyyxxxx --- tabs/system-setup/2-gaming-setup.sh | 135 ++++++++++++++-------------- 1 file changed, 69 insertions(+), 66 deletions(-) diff --git a/tabs/system-setup/2-gaming-setup.sh b/tabs/system-setup/2-gaming-setup.sh index fea382285..f414928fa 100755 --- a/tabs/system-setup/2-gaming-setup.sh +++ b/tabs/system-setup/2-gaming-setup.sh @@ -3,35 +3,59 @@ . ../common-script.sh installDepend() { - ## Check for dependencies. + # Check for dependencies + DEPENDENCIES='wine dbus' printf "%b\n" "${YELLOW}Installing dependencies...${RC}" - if [ "$PACKAGER" = "pacman" ]; then - if ! grep -q "^\s*\[multilib\]" /etc/pacman.conf; then - echo "[multilib]" | $ESCALATION_TOOL tee -a /etc/pacman.conf - echo "Include = /etc/pacman.d/mirrorlist" | $ESCALATION_TOOL tee -a /etc/pacman.conf - $ESCALATION_TOOL ${PACKAGER} -Syu - else - echo "Multilib is already enabled." - fi - $AUR_HELPER -S --needed --noconfirm wine giflib lib32-giflib libpng lib32-libpng libldap lib32-libldap gnutls lib32-gnutls \ -mpg123 lib32-mpg123 openal lib32-openal v4l-utils lib32-v4l-utils libpulse lib32-libpulse libgpg-error \ -lib32-libgpg-error alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib libjpeg-turbo lib32-libjpeg-turbo \ -sqlite lib32-sqlite libxcomposite lib32-libxcomposite libxinerama lib32-libgcrypt libgcrypt lib32-libxinerama \ -ncurses lib32-ncurses ocl-icd lib32-ocl-icd libxslt lib32-libxslt libva lib32-libva gtk3 \ -lib32-gtk3 gst-plugins-base-libs lib32-gst-plugins-base-libs vulkan-icd-loader lib32-vulkan-icd-loader - elif [ "$PACKAGER" = "apt-get" ]; then - $ESCALATION_TOOL ${PACKAGER} update - $ESCALATION_TOOL ${PACKAGER} install -y wine64 wine32 libasound2-plugins:i386 libsdl2-2.0-0:i386 libdbus-1-3:i386 libsqlite3-0:i386 - elif [ "$PACKAGER" = "dnf" ] || [ "$PACKAGER" = "zypper" ]; then - $ESCALATION_TOOL ${PACKAGER} install -y wine - else - $ESCALATION_TOOL ${PACKAGER} install -y ${DEPENDENCIES} - fi + case "$PACKAGER" in + pacman) + #Check for multilib + if ! grep -q "^\s*$$multilib$$" /etc/pacman.conf; then + echo "[multilib]" | "$ESCALATION_TOOL" tee -a /etc/pacman.conf + echo "Include = /etc/pacman.d/mirrorlist" | "$ESCALATION_TOOL" tee -a /etc/pacman.conf + "$ESCALATION_TOOL" "$PACKAGER" -Syu + else + printf "%b\n" "${GREEN}Multilib is already enabled.${RC}" + fi + + DISTRO_DEPS="gnutls lib32-gnutls base-devel gtk2 gtk3 lib32-gtk2 lib32-gtk3 libpulse lib32-libpulse alsa-lib lib32-alsa-lib \ + alsa-utils alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib giflib lib32-giflib libpng lib32-libpng \ + libldap lib32-libldap openal lib32-openal libxcomposite lib32-libxcomposite libxinerama lib32-libxinerama \ + ncurses lib32-ncurses vulkan-icd-loader lib32-vulkan-icd-loader ocl-icd lib32-ocl-icd libva lib32-libva \ + gst-plugins-base-libs lib32-gst-plugins-base-libs sdl2" + + $AUR_HELPER -S --needed --noconfirm "$DEPENDENCIES" $DISTRO_DEPS + ;; + apt-get|nala) + DISTRO_DEPS="libasound2 libsdl2 wine64 wine32" + + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" dpkg --add-architecture i386 + "$ESCALATION_TOOL" "$PACKAGER" install -y software-properties-common + "$ESCALATION_TOOL" apt-add-repository contrib -y + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" $DISTRO_DEPS + ;; + dnf) + "$ESCALATION_TOOL" "$PACKAGER" install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm -y + "$ESCALATION_TOOL" "$PACKAGER" config-manager --enable fedora-cisco-openh264 -y + "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES + ;; + zypper) + "$ESCALATION_TOOL" "$PACKAGER" -n install $DEPENDENCIES + ;; + *) + "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES + ;; + esac } -install_additional_dependencies() { - case $(command -v apt-get || command -v zypper || command -v dnf || command -v pacman) in - *apt-get) +installAdditionalDepend() { + case "$PACKAGER" in + pacman) + DISTRO_DEPS='steam lutris goverlay' + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm $DISTRO_DEPS + ;; + apt-get|nala) version=$(git -c 'versionsort.suffix=-' ls-remote --tags --sort='v:refname' https://github.com/lutris/lutris | grep -v 'beta' | tail -n1 | @@ -39,55 +63,34 @@ install_additional_dependencies() { version_no_v=$(echo "$version" | tr -d v) curl -sSLo "lutris_${version_no_v}_all.deb" "https://github.com/lutris/lutris/releases/download/${version}/lutris_${version_no_v}_all.deb" - # Install the downloaded .deb package using apt-get - echo "Installing lutris_${version_no_v}_all.deb" - $ESCALATION_TOOL apt-get update - $ESCALATION_TOOL apt-get install ./lutris_${version_no_v}_all.deb + + printf "%b\n" "${YELLOW}Installing Lutris...${RC}" + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" install ./lutris_${version_no_v}_all.deb - # Clean up the downloaded .deb file rm lutris_${version_no_v}_all.deb - echo "Lutris Installation complete." - echo "Installing steam..." + printf "%b\n" "${GREEN}Lutris Installation complete.${RC}" + printf "%b\n" "${YELLOW}Installing steam...${RC}" - #Install steam on Debian - if (lsb_release -i | grep -qi Debian); then - #Enable i386 repos - $ESCALATION_TOOL dpkg --add-architecture i386 - # Install software-properties-common to be able to add repos - $ESCALATION_TOOL apt-get install -y software-properties-common - # Add repos necessary for installing steam - $ESCALATION_TOOL apt-add-repository contrib -y - $ESCALATION_TOOL apt-add-repository non-free -y - #Install steam - $ESCALATION_TOOL apt-get install steam-installer -y + if lsb_release -i | grep -qi Debian; then + "$ESCALATION_TOOL" apt-add-repository non-free -y + "$ESCALATION_TOOL" "$PACKAGER" install steam-installer -y else - #Install steam on Ubuntu - $ESCALATION_TOOL apt-get install -y steam + "$ESCALATION_TOOL" "$PACKAGER" install -y steam fi ;; - *zypper) - - ;; - *dnf) - + dnf) + DISTRO_DEPS='steam lutris' + "$ESCALATION_TOOL" "$PACKAGER" install -y $DISTRO_DEPS ;; - *pacman) - echo "Installing Steam for Arch Linux..." - $ESCALATION_TOOL pacman -S --needed --noconfirm steam - echo "Steam installation complete." - - echo "Installing Lutris for Arch Linux..." - $ESCALATION_TOOL pacman -S --needed --noconfirm lutris - echo "Lutris installation complete." - - echo "Installing GOverlay for Arch Linux..." - $ESCALATION_TOOL pacman -S --needed --noconfirm goverlay - echo "GOverlay installation complete." + zypper) + # Flatpak + DISTRO_DEPS='lutris' + "$ESCALATION_TOOL" "$PACKAGER" -n install $DISTRO_DEPS ;; *) - - ;; + ;; esac } @@ -95,4 +98,4 @@ checkEnv checkAURHelper checkEscalationTool installDepend -install_additional_dependencies \ No newline at end of file +installAdditionalDepend From ab543fdc93f76dd104aa4fbd728a5d71c5dc61ae Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Wed, 18 Sep 2024 21:12:04 +0200 Subject: [PATCH 55/88] Added checklists to issue templates (#459) --- .github/ISSUE_TEMPLATE/bug_report.md | 6 ++++++ .github/ISSUE_TEMPLATE/feature_request.md | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index ebac8ea98..abae89e7b 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -24,3 +24,9 @@ If applicable, add screenshots to help explain your problem. ## Additional context Add any other context about the problem here. + +## Checklist +- [ ] I checked for duplicate issues. +- [ ] I checked already existing discussions. +- [ ] This issue is not included in the roadmap. +- [ ] This issue is present on both stable and development branches. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 36014cde5..84d9de8cb 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,17 +4,21 @@ about: Suggest an idea for this project title: '' labels: 'enhancement' assignees: '' - --- -**Is your feature request related to a problem? Please describe.** +## Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -**Describe the solution you'd like** +## Describe the solution you'd like A clear and concise description of what you want to happen. -**Describe alternatives you've considered** +## Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered. -**Additional context** +## Additional context Add any other context or screenshots about the feature request here. + +## Checklist +- [ ] I checked for duplicate issues. +- [ ] I checked already existing discussions. +- [ ] This feature is not included in the roadmap. From 1d2d51e6e0d5b8da9be68acef38140cb2ba9e90e Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Wed, 18 Sep 2024 21:13:03 +0200 Subject: [PATCH 56/88] Fix a typo & grammar in pull request template (#461) * Fixed a typo * Fixed grammar --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 093357d25..0e399f7b7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,7 @@ ## Type of Change - [ ] New feature - [ ] Bug fix -- [ ] Documentation Update +- [ ] Documentation update - [ ] Refactoring - [ ] Hotfix - [ ] Security patch @@ -16,7 +16,7 @@ ## Impact -## Issue related to PR +## Issues / other PRs related - Resolves # From 719548f971cd69c9f4339c65130624154b45d021 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Wed, 18 Sep 2024 21:18:00 +0200 Subject: [PATCH 57/88] Add code understanding & testing point to Contributing Guidelines (#451) * Added `Understand and Test the Code You Write` to contributing guidelines. Co-authored-by: CodingWonders Co-authored-by: nnyyxxxx * Added a notice in `PULL_REQUEST_TEMPLATE.md` * Merge `upstream/main` --------- Co-authored-by: CodingWonders Co-authored-by: nnyyxxxx --- .github/CONTRIBUTING.md | 14 ++++++++++---- .github/PULL_REQUEST_TEMPLATE.md | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5a76af0c3..5a2c71b1e 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -40,22 +40,28 @@ cd linutil - **Make small, targeted PRs**: Focus on one feature or fix per pull request. This makes it easier to review and increases the likelihood of acceptance. - **Avoid combining unrelated changes**: PRs that tackle multiple unrelated issues are harder to review and might be rejected because of a single problem. -## 8. Code Review and Feedback +## 8. Understand and Test the Code You Write + +- **Review your code**: Before submitting your changes, take the time to review your code for readability, efficiency and performance. Consider how your changes affect the project. +- **Avoid using LLMs**: Don't submit AI-generated code without reviewing and testing it first. Ensure that any code you submit is thoroughly understood and meets the project's standards. +- **Testing Requirements**: Failure to conduct testing after multiple requests may result in the closure of your Pull Request. + +## 9. Code Review and Feedback - **Expect feedback**: PRs will undergo code review. Be open to feedback and willing to make adjustments as needed. - **Participate in reviews**: If you feel comfortable, review other contributors' PRs as well. Peer review is a great way to learn and ensure high-quality contributions. -## 9. Contributing Is More Than Just Code +## 10. Contributing Is More Than Just Code - **Test the tool**: Running tests and providing feedback on how the tool works in different environments is a valuable contribution. - **Write well-formed issues**: Clearly describe bugs or problems you encounter, providing as much detail as possible, including steps to reproduce the issue. - **Propose reasonable feature requests**: When suggesting new features, ensure they fit within the scope, style, and design of the project. Provide clear reasoning and use cases. -## 10. Documentation +## 11. Documentation - **Update the documentation**: If your change affects the functionality, please update the relevant documentation files to reflect this. -## 11. License +## 12. License - **Agree to the license**: By contributing to Linutil, you agree that your contributions will be licensed under the project's MIT license. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0e399f7b7..4cc787c47 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,3 +1,8 @@ + + ## Type of Change - [ ] New feature - [ ] Bug fix From e78351244a9e4e4ec2c6aa56404afeeb9687d134 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:01:18 -0400 Subject: [PATCH 58/88] Remove bashisms from disable monitor (#472) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/disable_monitor.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tabs/utils/monitor-control/disable_monitor.sh b/tabs/utils/monitor-control/disable_monitor.sh index a1eafc527..8a400701c 100755 --- a/tabs/utils/monitor-control/disable_monitor.sh +++ b/tabs/utils/monitor-control/disable_monitor.sh @@ -20,7 +20,8 @@ disable_monitor() { i=$((i + 1)) done - read -p "Enter the number of the monitor: " monitor_choice + printf "%b\n" "Enter the number of the monitor: " + read -r monitor_choice if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection.${RC}" @@ -44,7 +45,8 @@ disable_monitor() { confirm_action() { action="$1" printf "%b\n" "${YELLOW}$action${RC}" - read -p "Are you sure? (y/n): " confirm + printf "%b\n" "Are you sure? (y/n): " + read -r confirm if echo "$confirm" | grep -qE '^[Yy]$'; then return 0 else From f473cdedc9174daac32ef8f197a158be7481299f Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:01:56 -0400 Subject: [PATCH 59/88] Remove bashisms from set resolutions (#473) Co-authored-by: nnyyxxxx --- tabs/utils/monitor-control/set_resolutions.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/tabs/utils/monitor-control/set_resolutions.sh b/tabs/utils/monitor-control/set_resolutions.sh index 1a6c6fa71..4772b163d 100755 --- a/tabs/utils/monitor-control/set_resolutions.sh +++ b/tabs/utils/monitor-control/set_resolutions.sh @@ -22,7 +22,8 @@ set_resolutions() { i=$((i + 1)) done - read -p "Enter the choice (or 'q' to quit): " monitor_choice + printf "%b\n" "Enter the choice (or 'q' to quit): " + read -r monitor_choice if [ "$monitor_choice" = "q" ]; then printf "%b\n" "${RED}Exiting...${RC}" @@ -31,7 +32,8 @@ set_resolutions() { if ! echo "$monitor_choice" | grep -qE '^[0-9]+$' || [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$((i - 1))" ]; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" - read -p "Press [Enter] to continue..." + printf "%b\n" "Press [Enter] to continue..." + read -r dummy continue fi @@ -43,7 +45,7 @@ set_resolutions() { i=1 while read -r resolution; do - resolution_map[$i]="$resolution" + echo "$resolution" >> "$temp_res_file" i=$((i + 1)) done < "$temp_res_file" @@ -54,7 +56,8 @@ set_resolutions() { awk '{print $1 ". " $2}' "$temp_res_file" while true; do - read -p "Enter the choice (or 'q' to quit): " resolution_choice + printf "%b\n" "Enter the choice (or 'q' to quit): " + read -r resolution_choice if [ "$resolution_choice" = "q" ]; then printf "%b\n" "${RED}Exiting...${RC}" @@ -67,10 +70,10 @@ set_resolutions() { continue fi - # Map the index to the actual resolution - selected_resolution=${resolution_map[$resolution_choice]} + selected_resolution=$(awk "NR==$resolution_choice" "$temp_res_file") - read -p "Set resolution for $monitor_name to $selected_resolution? (y/n): " confirm + printf "%b\n" "Set resolution for $monitor_name to $selected_resolution? (y/n): " + read -r confirm if echo "$confirm" | grep -qE '^[Yy]$'; then printf "%b\n" "${GREEN}Setting resolution for $monitor_name to $selected_resolution${RC}" execute_command "xrandr --output $monitor_name --mode $selected_resolution" From 903c9152604bb867fd478116a9bf87c299db8851 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:02:30 -0400 Subject: [PATCH 60/88] Fix bashism in checkaurhelper function (#475) Co-authored-by: nnyyxxxx --- tabs/common-script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 6bcab74da..7f27f6f25 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -35,7 +35,7 @@ checkAURHelper() { AUR_HELPER="yay" AUR_HELPER_CHECKED=true else - echo -e "${RED}Failed to install AUR helper.${RC}" + printf "%b\n" "${RED}Failed to install AUR helper.${RC}" exit 1 fi fi From 1175f7d236e89668a49fc6c3d5d2f0f038e1ab4c Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:02:52 -0400 Subject: [PATCH 61/88] Fix bashism in docker-setup (#476) Co-authored-by: nnyyxxxx --- tabs/system-setup/6-docker-setup.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tabs/system-setup/6-docker-setup.sh b/tabs/system-setup/6-docker-setup.sh index 7f2a0b3f8..43e8a5079 100755 --- a/tabs/system-setup/6-docker-setup.sh +++ b/tabs/system-setup/6-docker-setup.sh @@ -9,7 +9,8 @@ choose_installation() { printf "%b\n" "1. ${YELLOW}Docker${RC}" printf "%b\n" "2. ${YELLOW}Docker Compose${RC}" printf "%b\n" "3. ${YELLOW}Both${RC}" - read -p "Enter your choice [1-3]: " CHOICE + printf "Enter your choice [1-3]: " + read -r CHOICE case "$CHOICE" in 1) INSTALL_DOCKER=1; INSTALL_COMPOSE=0 ;; From 0d4f0a8a4e6c0049733895c6bf4ae77b3e3aa46b Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:03:32 -0400 Subject: [PATCH 62/88] Quote the remaining variables (#454) Co-authored-by: nnyyxxxx --- tabs/applications-setup/alacritty-setup.sh | 4 +- tabs/applications-setup/dwmtitus-setup.sh | 48 +++++++++---------- tabs/applications-setup/fastfetch-setup.sh | 4 +- tabs/applications-setup/kitty-setup.sh | 4 +- tabs/applications-setup/mybash-setup.sh | 10 ++-- tabs/applications-setup/neovim-setup.sh | 8 ++-- tabs/applications-setup/rofi-setup.sh | 4 +- tabs/applications-setup/zsh-setup.sh | 6 +-- tabs/common-script.sh | 4 +- tabs/security/firewall-baselines.sh | 18 +++---- tabs/system-setup/1-compile-setup.sh | 32 ++++++------- tabs/system-setup/3-global-theme.sh | 16 +++---- tabs/system-setup/4-remove-snaps.sh | 10 ++-- tabs/system-setup/fedora/rpm-fusion-setup.sh | 4 +- tabs/system-setup/system-update.sh | 46 +++++++++--------- tabs/utils/bluetooth-control.sh | 6 +-- .../monitor-control/utility_functions.sh | 6 +-- tabs/utils/numlock.sh | 10 ++-- tabs/utils/ollama.sh | 2 +- tabs/utils/service-control.sh | 46 +++++++++--------- tabs/utils/wifi-control.sh | 8 ++-- 21 files changed, 148 insertions(+), 148 deletions(-) diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 4c1c58d7d..2d9143401 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -7,10 +7,10 @@ installAlacritty() { if ! command_exists alacritty; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm alacritty + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm alacritty ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y alacritty + "$ESCALATION_TOOL" "$PACKAGER" install -y alacritty ;; esac else diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index 9ae234455..98d759fb6 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -6,14 +6,14 @@ setupDWM() { printf "%b\n" "${YELLOW}Installing DWM-Titus if not already installed${RC}" case "$PACKAGER" in # Install pre-Requisites pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb git + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm base-devel libx11 libxinerama libxft imlib2 libxcb git ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libx11-xcb-dev libfontconfig1 libx11-6 libxft2 libxinerama1 libxcb-res0-dev git + "$ESCALATION_TOOL" "$PACKAGER" install -y build-essential libx11-dev libxinerama-dev libxft-dev libimlib2-dev libx11-xcb-dev libfontconfig1 libx11-6 libxft2 libxinerama1 libxcb-res0-dev git ;; dnf) - $ESCALATION_TOOL "$PACKAGER" groupinstall -y "Development Tools" - $ESCALATION_TOOL "$PACKAGER" install -y libX11-devel libXinerama-devel libXft-devel imlib2-devel libxcb-devel + "$ESCALATION_TOOL" "$PACKAGER" groupinstall -y "Development Tools" + "$ESCALATION_TOOL" "$PACKAGER" install -y libX11-devel libXinerama-devel libXft-devel imlib2-devel libxcb-devel ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" @@ -26,7 +26,7 @@ makeDWM() { cd "$HOME" && git clone https://github.com/ChrisTitusTech/dwm-titus.git # CD to Home directory to install dwm-titus # This path can be changed (e.g. to linux-toolbox directory) cd dwm-titus/ # Hardcoded path, maybe not the best. - $ESCALATION_TOOL make clean install # Run make clean install + "$ESCALATION_TOOL" make clean install # Run make clean install } install_nerd_font() { @@ -115,7 +115,7 @@ picom_animations() { fi # Install the built binary - if ! $ESCALATION_TOOL ninja -C build install; then + if ! "$ESCALATION_TOOL" ninja -C build install; then printf "%b\n" "${RED}Failed to install the built binary${RC}" return 1 fi @@ -179,13 +179,13 @@ setupDisplayManager() { printf "%b\n" "${YELLOW}Setting up Xorg${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm xorg-xinit xorg-server + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm xorg-xinit xorg-server ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" install -y xorg xinit + "$ESCALATION_TOOL" "$PACKAGER" install -y xorg xinit ;; dnf) - $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}" @@ -207,13 +207,13 @@ setupDisplayManager() { printf "%b\n" "${YELLOW}No display manager found, installing $DM${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm "$DM" + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm "$DM" ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" install -y "$DM" + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DM" ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y "$DM" + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DM" ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" @@ -232,28 +232,28 @@ setupDisplayManager() { printf "%b\n" "${YELLOW}Configuring SDDM for autologin${RC}" SDDM_CONF="/etc/sddm.conf" if [ ! -f "$SDDM_CONF" ]; then - echo "[Autologin]" | $ESCALATION_TOOL tee -a "$SDDM_CONF" - echo "User=$USER" | $ESCALATION_TOOL tee -a "$SDDM_CONF" - echo "Session=dwm" | $ESCALATION_TOOL tee -a "$SDDM_CONF" + echo "[Autologin]" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" + echo "User=$USER" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" + echo "Session=dwm" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" else - $ESCALATION_TOOL sed -i '/^\[Autologin\]/d' "$SDDM_CONF" - $ESCALATION_TOOL sed -i '/^User=/d' "$SDDM_CONF" - $ESCALATION_TOOL sed -i '/^Session=/d' "$SDDM_CONF" - echo "[Autologin]" | $ESCALATION_TOOL tee -a "$SDDM_CONF" - echo "User=$USER" | $ESCALATION_TOOL tee -a "$SDDM_CONF" - echo "Session=dwm" | $ESCALATION_TOOL tee -a "$SDDM_CONF" + "$ESCALATION_TOOL" sed -i '/^\[Autologin\]/d' "$SDDM_CONF" + "$ESCALATION_TOOL" sed -i '/^User=/d' "$SDDM_CONF" + "$ESCALATION_TOOL" sed -i '/^Session=/d' "$SDDM_CONF" + echo "[Autologin]" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" + echo "User=$USER" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" + echo "Session=dwm" | "$ESCALATION_TOOL" tee -a "$SDDM_CONF" fi printf "%b\n" "{YELLOW}Checking if autologin group exists${RC}" if ! getent group autologin > /dev/null; then printf "%b\n" "${YELLOW}Creating autologin group${RC}" - $ESCALATION_TOOL groupadd autologin + "$ESCALATION_TOOL" groupadd autologin else printf "%b\n" "${GREEN}Autologin group already exists${RC}" fi printf "%b\n" "${YELLOW}Adding user with UID 1000 to autologin group${RC}" USER_UID_1000=$(getent passwd 1000 | cut -d: -f1) if [ -n "$USER_UID_1000" ]; then - $ESCALATION_TOOL usermod -aG autologin "$USER_UID_1000" + "$ESCALATION_TOOL" usermod -aG autologin "$USER_UID_1000" printf "%b\n" "${GREEN}User $USER_UID_1000 added to autologin group${RC}" else printf "%b\n" "${RED}No user with UID 1000 found - Auto login not possible${RC}" @@ -272,7 +272,7 @@ install_slstatus() { if [ "$response" = "y" ] || [ "$response" = "Y" ]; then printf "%b\n" "${YELLOW}Installing slstatus${RC}" cd "$HOME/dwm-titus/slstatus" || { echo "Failed to change directory to slstatus"; return 1; } - if $ESCALATION_TOOL make clean install; then + if "$ESCALATION_TOOL" make clean install; then printf "%b\n" "${GREEN}slstatus installed successfully${RC}" else printf "%b\n" "${RED}Failed to install slstatus${RC}" diff --git a/tabs/applications-setup/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index 60077f145..dd6ca483a 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -7,10 +7,10 @@ installFastfetch() { if ! command_exists fastfetch; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm fastfetch + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm fastfetch ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y fastfetch + "$ESCALATION_TOOL" "$PACKAGER" install -y fastfetch ;; esac else diff --git a/tabs/applications-setup/kitty-setup.sh b/tabs/applications-setup/kitty-setup.sh index 480eed829..0131b4bb4 100755 --- a/tabs/applications-setup/kitty-setup.sh +++ b/tabs/applications-setup/kitty-setup.sh @@ -7,10 +7,10 @@ installKitty() { if ! command_exists kitty; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm kitty + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm kitty ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y kitty + "$ESCALATION_TOOL" "$PACKAGER" install -y kitty ;; esac else diff --git a/tabs/applications-setup/mybash-setup.sh b/tabs/applications-setup/mybash-setup.sh index 7449072aa..04772cf7f 100644 --- a/tabs/applications-setup/mybash-setup.sh +++ b/tabs/applications-setup/mybash-setup.sh @@ -8,16 +8,16 @@ installDepend() { printf "%b\n" "${YELLOW}Installing Bash...${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig git + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm bash bash-completion tar bat tree unzip fontconfig git ;; apt) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git + "$ESCALATION_TOOL" "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git + "$ESCALATION_TOOL" "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; zypper) - $ESCALATION_TOOL "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git + "$ESCALATION_TOOL" "$PACKAGER" install -y bash bash-completion tar bat tree unzip fontconfig git ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" # The packages above were grabbed out of the original mybash-setup-script. @@ -70,7 +70,7 @@ installStarshipAndFzf() { printf "%b\n" "${GREEN}Fzf already installed${RC}" else git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf - $ESCALATION_TOOL ~/.fzf/install + "$ESCALATION_TOOL" ~/.fzf/install fi } diff --git a/tabs/applications-setup/neovim-setup.sh b/tabs/applications-setup/neovim-setup.sh index 36d43c881..040587736 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -17,16 +17,16 @@ installNeovim() { printf "%b\n" "${YELLOW}Installing Neovim...${RC}" case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck git + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm neovim ripgrep fzf python-virtualenv luarocks go shellcheck git ;; apt) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fd-find python3-venv luarocks golang-go shellcheck git + "$ESCALATION_TOOL" "$PACKAGER" install -y neovim ripgrep fd-find python3-venv luarocks golang-go shellcheck git ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git + "$ESCALATION_TOOL" "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git ;; zypper) - $ESCALATION_TOOL "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git + "$ESCALATION_TOOL" "$PACKAGER" install -y neovim ripgrep fzf python3-virtualenv luarocks golang ShellCheck git ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" # The packages above were grabbed out of the original nvim-setup-script. diff --git a/tabs/applications-setup/rofi-setup.sh b/tabs/applications-setup/rofi-setup.sh index cd5c644af..e779066ac 100755 --- a/tabs/applications-setup/rofi-setup.sh +++ b/tabs/applications-setup/rofi-setup.sh @@ -7,10 +7,10 @@ installRofi() { if ! command_exists rofi; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm rofi + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm rofi ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y rofi + "$ESCALATION_TOOL" "$PACKAGER" install -y rofi ;; esac else diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index 626099db9..7100d01ba 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -8,10 +8,10 @@ installZsh() { if ! command_exists zsh; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm zsh + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm zsh ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y zsh + "$ESCALATION_TOOL" "$PACKAGER" install -y zsh ;; esac else @@ -44,7 +44,7 @@ RPROMPT='%F{15}(%F{166}%D{%H:%M}%F{15})%f' EOL # Ensure /etc/zsh/zshenv sets ZDOTDIR to the user's config directory - echo 'export ZDOTDIR="$HOME/.config/zsh"' | $ESCALATION_TOOL tee -a /etc/zsh/zshenv + echo 'export ZDOTDIR="$HOME/.config/zsh"' | "$ESCALATION_TOOL" tee -a /etc/zsh/zshenv } checkEnv diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 7f27f6f25..84ff660d7 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -27,8 +27,8 @@ checkAURHelper() { done echo "Installing yay as AUR helper..." - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel - cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-bin.git && $ESCALATION_TOOL chown -R "$USER":"$USER" ./yay-bin + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm base-devel + cd /opt && "$ESCALATION_TOOL" git clone https://aur.archlinux.org/yay-bin.git && "$ESCALATION_TOOL" chown -R "$USER":"$USER" ./yay-bin cd yay-bin && makepkg --noconfirm -si if command_exists yay; then diff --git a/tabs/security/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 8ce390486..196428be5 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -7,10 +7,10 @@ installPkg() { if ! command_exists ufw; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm ufw + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm ufw ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y ufw + "$ESCALATION_TOOL" "$PACKAGER" install -y ufw ;; esac else @@ -22,24 +22,24 @@ configureUFW() { printf "%b\n" "${YELLOW}Using Chris Titus Recommended Firewall Rules${RC}" printf "%b\n" "${YELLOW}Disabling UFW${RC}" - $ESCALATION_TOOL ufw disable + "$ESCALATION_TOOL" ufw disable printf "%b\n" "${YELLOW}Limiting port 22/tcp (UFW)${RC}" - $ESCALATION_TOOL ufw limit 22/tcp + "$ESCALATION_TOOL" ufw limit 22/tcp printf "%b\n" "${YELLOW}Allowing port 80/tcp (UFW)${RC}" - $ESCALATION_TOOL ufw allow 80/tcp + "$ESCALATION_TOOL" ufw allow 80/tcp printf "%b\n" "${YELLO}Allowing port 443/tcp (UFW)${RC}" - $ESCALATION_TOOL ufw allow 443/tcp + "$ESCALATION_TOOL" ufw allow 443/tcp printf "%b\n" "${YELLOW}Denying Incoming Packets by Default(UFW)${RC}" - $ESCALATION_TOOL ufw default deny incoming + "$ESCALATION_TOOL" ufw default deny incoming printf "%b\n" "${YELLOW}Allowing Outcoming Packets by Default(UFW)${RC}" - $ESCALATION_TOOL ufw default allow outgoing + "$ESCALATION_TOOL" ufw default allow outgoing - $ESCALATION_TOOL ufw enable + "$ESCALATION_TOOL" ufw enable printf "%b\n" "${GREEN}Enabled Firewall with Baselines!${RC}" } diff --git a/tabs/system-setup/1-compile-setup.sh b/tabs/system-setup/1-compile-setup.sh index 7f1b3f733..94ccf7da1 100755 --- a/tabs/system-setup/1-compile-setup.sh +++ b/tabs/system-setup/1-compile-setup.sh @@ -9,36 +9,36 @@ installDepend() { case "$PACKAGER" in pacman) if ! grep -q "^\s*\[multilib\]" /etc/pacman.conf; then - echo "[multilib]" | $ESCALATION_TOOL tee -a /etc/pacman.conf - echo "Include = /etc/pacman.d/mirrorlist" | $ESCALATION_TOOL tee -a /etc/pacman.conf - $ESCALATION_TOOL "$PACKAGER" -Syu + echo "[multilib]" | "$ESCALATION_TOOL" tee -a /etc/pacman.conf + echo "Include = /etc/pacman.d/mirrorlist" | "$ESCALATION_TOOL" tee -a /etc/pacman.conf + "$ESCALATION_TOOL" "$PACKAGER" -Syu else printf "%b\n" "${GREEN}Multilib is already enabled.${RC}" fi - $AUR_HELPER -S --needed --noconfirm "$DEPENDENCIES" + "$AUR_HELPER" -S --needed --noconfirm "$DEPENDENCIES" ;; apt-get|nala) COMPILEDEPS='build-essential' - $ESCALATION_TOOL "$PACKAGER" update - $ESCALATION_TOOL dpkg --add-architecture i386 - $ESCALATION_TOOL "$PACKAGER" update - $ESCALATION_TOOL "$PACKAGER" install -y $DEPENDENCIES $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" dpkg --add-architecture i386 + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES $COMPILEDEPS ;; dnf) COMPILEDEPS='@development-tools' - $ESCALATION_TOOL "$PACKAGER" update - $ESCALATION_TOOL "$PACKAGER" config-manager --set-enabled powertools - $ESCALATION_TOOL "$PACKAGER" install -y "$DEPENDENCIES" $COMPILEDEPS - $ESCALATION_TOOL "$PACKAGER" install -y glibc-devel.i686 libgcc.i686 + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" config-manager --set-enabled powertools + "$ESCALATION_TOOL" "$PACKAGER" install -y "$DEPENDENCIES" $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" install -y glibc-devel.i686 libgcc.i686 ;; zypper) COMPILEDEPS='patterns-devel-base-devel_basis' - $ESCALATION_TOOL "$PACKAGER" refresh - $ESCALATION_TOOL "$PACKAGER" --non-interactive install "$DEPENDENCIES" $COMPILEDEPS - $ESCALATION_TOOL "$PACKAGER" --non-interactive install libgcc_s1-gcc7-32bit glibc-devel-32bit + "$ESCALATION_TOOL" "$PACKAGER" refresh + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install "$DEPENDENCIES" $COMPILEDEPS + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install libgcc_s1-gcc7-32bit glibc-devel-32bit ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y $DEPENDENCIES # Fixed bug where no packages found on debian-based + "$ESCALATION_TOOL" "$PACKAGER" install -y $DEPENDENCIES # Fixed bug where no packages found on debian-based ;; esac } diff --git a/tabs/system-setup/3-global-theme.sh b/tabs/system-setup/3-global-theme.sh index 141d0dd22..471441518 100644 --- a/tabs/system-setup/3-global-theme.sh +++ b/tabs/system-setup/3-global-theme.sh @@ -6,19 +6,19 @@ install_theme_tools() { printf "%b\n" "${YELLOW}Installing theme tools (qt6ct and kvantum)...${RC}\n" case "$PACKAGER" in apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" update - $ESCALATION_TOOL "$PACKAGER" install -y qt6ct kvantum + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" install -y qt6ct kvantum ;; zypper) - $ESCALATION_TOOL "$PACKAGER" refresh - $ESCALATION_TOOL "$PACKAGER" --non-interactive install qt6ct kvantum + "$ESCALATION_TOOL" "$PACKAGER" refresh + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive install qt6ct kvantum ;; dnf) - $ESCALATION_TOOL "$PACKAGER" update - $ESCALATION_TOOL "$PACKAGER" install -y qt6ct kvantum + "$ESCALATION_TOOL" "$PACKAGER" update + "$ESCALATION_TOOL" "$PACKAGER" install -y qt6ct kvantum ;; pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm qt6ct kvantum + "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm qt6ct kvantum ;; *) printf "%b\n" "${RED}Unsupported package manager. Please install qt6ct and kvantum manually.${RC}\n" @@ -41,7 +41,7 @@ EOF # Add QT_QPA_PLATFORMTHEME to /etc/environment if ! grep -q "QT_QPA_PLATFORMTHEME=qt6ct" /etc/environment; then printf "%b\n" "${YELLOW}Adding QT_QPA_PLATFORMTHEME to /etc/environment...${RC}\n" - echo "QT_QPA_PLATFORMTHEME=qt6ct" | $ESCALATION_TOOL tee -a /etc/environment > /dev/null + echo "QT_QPA_PLATFORMTHEME=qt6ct" | "$ESCALATION_TOOL" tee -a /etc/environment > /dev/null printf "%b\n" "${GREEN}QT_QPA_PLATFORMTHEME added to /etc/environment.${RC}\n" else printf "%b\n" "${GREEN}QT_QPA_PLATFORMTHEME already set in /etc/environment.${RC}\n" diff --git a/tabs/system-setup/4-remove-snaps.sh b/tabs/system-setup/4-remove-snaps.sh index 2cba860bb..75804ca03 100644 --- a/tabs/system-setup/4-remove-snaps.sh +++ b/tabs/system-setup/4-remove-snaps.sh @@ -5,19 +5,19 @@ removeSnaps() { case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -Rns snapd + "$ESCALATION_TOOL" "$PACKAGER" -Rns snapd ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" autoremove --purge snapd + "$ESCALATION_TOOL" "$PACKAGER" autoremove --purge snapd if [ "$ID" = ubuntu ]; then - $ESCALATION_TOOL apt-mark hold snapd + "$ESCALATION_TOOL" apt-mark hold snapd fi ;; dnf) - $ESCALATION_TOOL "$PACKAGER" remove snapd + "$ESCALATION_TOOL" "$PACKAGER" remove snapd ;; zypper) - $ESCALATION_TOOL "$PACKAGER" remove snapd + "$ESCALATION_TOOL" "$PACKAGER" remove snapd ;; *) printf "%b\n" "${RED}Removing snapd not implemented for this package manager${RC}" diff --git a/tabs/system-setup/fedora/rpm-fusion-setup.sh b/tabs/system-setup/fedora/rpm-fusion-setup.sh index f611a0be1..7fb052ea4 100644 --- a/tabs/system-setup/fedora/rpm-fusion-setup.sh +++ b/tabs/system-setup/fedora/rpm-fusion-setup.sh @@ -9,8 +9,8 @@ installRPMFusion() { dnf) if [ ! -e /etc/yum.repos.d/rpmfusion-free.repo ] || [ ! -e /etc/yum.repos.d/rpmfusion-nonfree.repo ]; then echo "Installing RPM Fusion..." - $ESCALATION_TOOL "$PACKAGER" install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm - $ESCALATION_TOOL "$PACKAGER" config-manager --enable fedora-cisco-openh264 + "$ESCALATION_TOOL" "$PACKAGER" install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm + "$ESCALATION_TOOL" "$PACKAGER" config-manager --enable fedora-cisco-openh264 echo "RPM Fusion installed" else echo "RPM Fusion already installed" diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index 7df96be0c..c672a948e 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -9,7 +9,7 @@ fastUpdate() { $AUR_HELPER -S --needed --noconfirm rate-mirrors-bin if [ -s /etc/pacman.d/mirrorlist ]; then - $ESCALATION_TOOL cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak + "$ESCALATION_TOOL" cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak fi # If for some reason DTYPE is still unknown use always arch so the rate-mirrors does not fail @@ -18,40 +18,40 @@ fastUpdate() { dtype_local="arch" fi - $ESCALATION_TOOL rate-mirrors --top-mirrors-number-to-retest=5 --disable-comments --save /etc/pacman.d/mirrorlist --allow-root ${dtype_local} + "$ESCALATION_TOOL" rate-mirrors --top-mirrors-number-to-retest=5 --disable-comments --save /etc/pacman.d/mirrorlist --allow-root ${dtype_local} if [ $? -ne 0 ] || [ ! -s /etc/pacman.d/mirrorlist ]; then printf "%b\n" "${RED}Rate-mirrors failed, restoring backup.${RC}" - $ESCALATION_TOOL cp /etc/pacman.d/mirrorlist.bak /etc/pacman.d/mirrorlist + "$ESCALATION_TOOL" cp /etc/pacman.d/mirrorlist.bak /etc/pacman.d/mirrorlist fi ;; apt-get|nala) - $ESCALATION_TOOL apt-get update + "$ESCALATION_TOOL" apt-get update if ! command_exists nala; then - $ESCALATION_TOOL apt-get install -y nala || { printf "%b\n" "${YELLOW}Falling back to apt-get${RC}"; PACKAGER="apt-get"; } + "$ESCALATION_TOOL" apt-get install -y nala || { printf "%b\n" "${YELLOW}Falling back to apt-get${RC}"; PACKAGER="apt-get"; } fi if [ "$PACKAGER" = "nala" ]; then - $ESCALATION_TOOL cp /etc/apt/sources.list /etc/apt/sources.list.bak - $ESCALATION_TOOL nala update + "$ESCALATION_TOOL" cp /etc/apt/sources.list /etc/apt/sources.list.bak + "$ESCALATION_TOOL" nala update PACKAGER="nala" fi - $ESCALATION_TOOL "$PACKAGER" upgrade -y + "$ESCALATION_TOOL" "$PACKAGER" upgrade -y ;; dnf) - $ESCALATION_TOOL "$PACKAGER" update -y + "$ESCALATION_TOOL" "$PACKAGER" update -y ;; zypper) - $ESCALATION_TOOL "$PACKAGER" ref - $ESCALATION_TOOL "$PACKAGER" --non-interactive dup + "$ESCALATION_TOOL" "$PACKAGER" ref + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive dup ;; yum) - $ESCALATION_TOOL "$PACKAGER" update -y - $ESCALATION_TOOL "$PACKAGER" upgrade -y + "$ESCALATION_TOOL" "$PACKAGER" update -y + "$ESCALATION_TOOL" "$PACKAGER" upgrade -y ;; xbps-install) - $ESCALATION_TOOL "$PACKAGER" -Syu + "$ESCALATION_TOOL" "$PACKAGER" -Syu- ;; *) printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" @@ -64,23 +64,23 @@ updateSystem() { printf "%b\n" "${GREEN}Updating system${RC}" case "$PACKAGER" in nala|apt-get) - $ESCALATION_TOOL "$PACKAGER" update -y - $ESCALATION_TOOL "$PACKAGER" upgrade -y + "$ESCALATION_TOOL" "$PACKAGER" update -y + "$ESCALATION_TOOL" "$PACKAGER" upgrade -y ;; yum|dnf) - $ESCALATION_TOOL "$PACKAGER" update -y - $ESCALATION_TOOL "$PACKAGER" upgrade -y + "$ESCALATION_TOOL" "$PACKAGER" update -y + "$ESCALATION_TOOL" "$PACKAGER" upgrade -y ;; pacman) - $ESCALATION_TOOL "$PACKAGER" -Sy --noconfirm --needed archlinux-keyring - $ESCALATION_TOOL "$PACKAGER" -Su --noconfirm + "$ESCALATION_TOOL" "$PACKAGER" -Sy --noconfirm --needed archlinux-keyring + "$ESCALATION_TOOL" "$PACKAGER" -Su --noconfirm ;; zypper) - $ESCALATION_TOOL "$PACKAGER" ref - $ESCALATION_TOOL "$PACKAGER" --non-interactive dup + "$ESCALATION_TOOL" "$PACKAGER" ref + "$ESCALATION_TOOL" "$PACKAGER" --non-interactive dup ;; xbps-install) - $ESCALATION_TOOL "$PACKAGER" -Syu + "$ESCALATION_TOOL" "$PACKAGER" -Syu ;; *) printf "%b\n" "${RED}Unsupported package manager: ${PACKAGER}${RC}" diff --git a/tabs/utils/bluetooth-control.sh b/tabs/utils/bluetooth-control.sh index 36c1d35c8..367979df4 100644 --- a/tabs/utils/bluetooth-control.sh +++ b/tabs/utils/bluetooth-control.sh @@ -8,10 +8,10 @@ setupBluetooth() { if ! command_exists bluetoothctl; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --noconfirm bluez-utils + "$ESCALATION_TOOL" "$PACKAGER" -S --noconfirm bluez-utils ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y bluez + "$ESCALATION_TOOL" "$PACKAGER" install -y bluez ;; esac else @@ -21,7 +21,7 @@ setupBluetooth() { # Check if bluetooth service is running if ! systemctl is-active --quiet bluetooth; then printf "%b\n" "${YELLOW}Bluetooth service is not running. Starting it now...${RC}" - $ESCALATION_TOOL systemctl start bluetooth + "$ESCALATION_TOOL" systemctl start bluetooth if systemctl is-active --quiet bluetooth; then printf "%b\n" "${GREEN}Bluetooth service started successfully.${RC}" diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index 42b324c2e..c1d01be79 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -8,13 +8,13 @@ setup_xrandr() { if ! command_exists xrandr; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --noconfirm xorg-xrandr + "$ESCALATION_TOOL" "$PACKAGER" -S --noconfirm xorg-xrandr ;; apt-get|nala) - $ESCALATION_TOOL "$PACKAGER" install -y x11-xserver-utils + "$ESCALATION_TOOL" "$PACKAGER" install -y x11-xserver-utils ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y xorg-x11-server-utils + "$ESCALATION_TOOL" "$PACKAGER" install -y xorg-x11-server-utils ;; esac else diff --git a/tabs/utils/numlock.sh b/tabs/utils/numlock.sh index 79f2f6808..d1f7822af 100755 --- a/tabs/utils/numlock.sh +++ b/tabs/utils/numlock.sh @@ -9,7 +9,7 @@ create_file() { echo "Creating script..." - $ESCALATION_TOOL tee "/usr/local/bin/numlock" >/dev/null <<'EOF' + "$ESCALATION_TOOL" tee "/usr/local/bin/numlock" >/dev/null <<'EOF' #!/bin/bash for tty in /dev/tty{1..6} @@ -18,13 +18,13 @@ do done EOF - $ESCALATION_TOOL chmod +x /usr/local/bin/numlock + "$ESCALATION_TOOL" chmod +x /usr/local/bin/numlock } # Create a systemd service to run the script on boot create_service() { echo "Creating service..." - $ESCALATION_TOOL tee "/etc/systemd/system/numlock.service" >/dev/null <<'EOF' + "$ESCALATION_TOOL" tee "/etc/systemd/system/numlock.service" >/dev/null <<'EOF' [Unit] Description=numlock @@ -51,10 +51,10 @@ numlockSetup() { printf "Do you want to enable Numlock on boot? (y/n): " read -r confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then - $ESCALATION_TOOL systemctl enable numlock.service --quiet + "$ESCALATION_TOOL" systemctl enable numlock.service --quiet echo "Numlock will be enabled on boot" else - $ESCALATION_TOOL systemctl disable numlock.service --quiet + "$ESCALATION_TOOL" systemctl disable numlock.service --quiet echo "Numlock will not be enabled on boot" fi diff --git a/tabs/utils/ollama.sh b/tabs/utils/ollama.sh index 969d62a3b..8c2861e7b 100644 --- a/tabs/utils/ollama.sh +++ b/tabs/utils/ollama.sh @@ -12,7 +12,7 @@ installollama() { else printf "%b\n" "${YELLOW}Installing ollama...${RC}" curl -fsSL https://ollama.com/install.sh | sh - $ESCALATION_TOOL systemctl start ollama + "$ESCALATION_TOOL" systemctl start ollama fi } diff --git a/tabs/utils/service-control.sh b/tabs/utils/service-control.sh index 96aba4fcd..8bc6da19f 100644 --- a/tabs/utils/service-control.sh +++ b/tabs/utils/service-control.sh @@ -29,25 +29,25 @@ show_menu() { # Function to view all services view_all_services() { echo "Listing all services..." - $ESCALATION_TOOL systemctl list-units --type=service --all --no-legend | awk '{print $1}' | sed 's/\.service//' | more + "$ESCALATION_TOOL" systemctl list-units --type=service --all --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view enabled services view_enabled_services() { echo "Listing enabled services..." - $ESCALATION_TOOL systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more + "$ESCALATION_TOOL" systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view disabled services view_disabled_services() { echo "Listing disabled services..." - $ESCALATION_TOOL systemctl list-unit-files --type=service --state=disabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more + "$ESCALATION_TOOL" systemctl list-unit-files --type=service --state=disabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view started services view_started_services() { echo "Listing started services:" - $ESCALATION_TOOL systemctl list-units --type=service --state=running --no-pager | head -n -6 | awk 'NR>1 {print $1}' | more + "$ESCALATION_TOOL" systemctl list-units --type=service --state=running --no-pager | head -n -6 | awk 'NR>1 {print $1}' | more } # Function to add a new service @@ -56,7 +56,7 @@ add_service() { echo "Enter the name of the new service (e.g., my_service):" read -r SERVICE_NAME - if $ESCALATION_TOOL systemctl list-units --type=service --all --no-legend | grep -q "$SERVICE_NAME.service"; then + if "$ESCALATION_TOOL" systemctl list-units --type=service --all --no-legend | grep -q "$SERVICE_NAME.service"; then echo "Service already exists!" SERVICE_NAME="" fi @@ -93,11 +93,11 @@ add_service() { echo "" echo "[Install]" echo "WantedBy=multi-user.target" - } | $ESCALATION_TOOL tee "$SERVICE_FILE" > /dev/null + } | "$ESCALATION_TOOL" tee "$SERVICE_FILE" > /dev/null # Set permissions and reload systemd - $ESCALATION_TOOL chmod 644 "$SERVICE_FILE" - $ESCALATION_TOOL systemctl daemon-reload + "$ESCALATION_TOOL" chmod 644 "$SERVICE_FILE" + "$ESCALATION_TOOL" systemctl daemon-reload echo "Service $SERVICE_NAME has been created and is ready to be started." # Optionally, enable and start the service @@ -105,8 +105,8 @@ add_service() { read -r START_ENABLE if [ "$START_ENABLE" = "y" ]; then - $ESCALATION_TOOL systemctl start "$SERVICE_NAME" - $ESCALATION_TOOL systemctl enable "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME" echo "Service $SERVICE_NAME has been started and enabled." else echo "Service $SERVICE_NAME has been created but not started." @@ -122,12 +122,12 @@ remove_service() { if [ -f "$SERVICE_FILE" ]; then echo "Stopping and disabling the service..." - $ESCALATION_TOOL systemctl stop "$SERVICE_NAME" - $ESCALATION_TOOL systemctl disable "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl stop "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl disable "$SERVICE_NAME" echo "Removing the service file..." - $ESCALATION_TOOL rm -f "$SERVICE_FILE" - $ESCALATION_TOOL systemctl daemon-reload + "$ESCALATION_TOOL" rm -f "$SERVICE_FILE" + "$ESCALATION_TOOL" systemctl daemon-reload echo "Service $SERVICE_NAME has been removed." else @@ -141,7 +141,7 @@ start_service() { echo "Enter the name of the service to start (e.g., my_service):" read -r SERVICE_NAME - if $ESCALATION_TOOL systemctl start "$SERVICE_NAME"; then + if "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME"; then echo "Service $SERVICE_NAME has been started." else echo "Failed to start service: $SERVICE_NAME." @@ -154,7 +154,7 @@ stop_service() { echo "Enter the name of the service to stop (e.g., my_service):" read -r SERVICE_NAME - if $ESCALATION_TOOL systemctl stop "$SERVICE_NAME"; then + if "$ESCALATION_TOOL" systemctl stop "$SERVICE_NAME"; then echo "Service $SERVICE_NAME has been stopped." else echo "Failed to stop service: $SERVICE_NAME." @@ -167,7 +167,7 @@ enable_service() { echo "Enter the name of the service to enable (e.g., my_service):" read -r SERVICE_NAME - if $ESCALATION_TOOL systemctl enable "$SERVICE_NAME"; then + if "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME"; then echo "Service $SERVICE_NAME has been enabled." else echo "Failed to enable service: $SERVICE_NAME." @@ -180,7 +180,7 @@ disable_service() { echo "Enter the name of the service to disable (e.g., my_service):" read -r SERVICE_NAME - if $ESCALATION_TOOL systemctl disable "$SERVICE_NAME"; then + if "$ESCALATION_TOOL" systemctl disable "$SERVICE_NAME"; then echo "Service $SERVICE_NAME has been enabled." else echo "Failed to enable service: $SERVICE_NAME." @@ -227,11 +227,11 @@ create_service_from_external() { fi # Copy the modified service file to /etc/systemd/system/ - $ESCALATION_TOOL cp "$SERVICE_FILE" "$SYSTEMD_SERVICE_FILE" + "$ESCALATION_TOOL" cp "$SERVICE_FILE" "$SYSTEMD_SERVICE_FILE" # Set permissions and reload systemd - $ESCALATION_TOOL chmod 644 "$SYSTEMD_SERVICE_FILE" - $ESCALATION_TOOL systemctl daemon-reload + "$ESCALATION_TOOL" chmod 644 "$SYSTEMD_SERVICE_FILE" + "$ESCALATION_TOOL" systemctl daemon-reload echo "Service $SERVICE_NAME has been created and is ready to be started." # Optionally, enable and start the service @@ -239,8 +239,8 @@ create_service_from_external() { read -r START_ENABLE if [ "$START_ENABLE" = "y" ]; then - $ESCALATION_TOOL systemctl start "$SERVICE_NAME" - $ESCALATION_TOOL systemctl enable "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME" + "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME" echo "Service $SERVICE_NAME has been started and enabled." else echo "Service $SERVICE_NAME has been created but not started." diff --git a/tabs/utils/wifi-control.sh b/tabs/utils/wifi-control.sh index 5518f25b9..ed2feefa0 100644 --- a/tabs/utils/wifi-control.sh +++ b/tabs/utils/wifi-control.sh @@ -8,13 +8,13 @@ setupNetworkManager() { if ! command_exists nmcli; then case "$PACKAGER" in pacman) - $ESCALATION_TOOL "$PACKAGER" -S --noconfirm networkmanager + "$ESCALATION_TOOL" "$PACKAGER" -S --noconfirm networkmanager ;; dnf) - $ESCALATION_TOOL "$PACKAGER" install -y NetworkManager-1 + "$ESCALATION_TOOL" "$PACKAGER" install -y NetworkManager-1 ;; *) - $ESCALATION_TOOL "$PACKAGER" install -y network-manager + "$ESCALATION_TOOL" "$PACKAGER" install -y network-manager ;; esac else @@ -24,7 +24,7 @@ setupNetworkManager() { # Check if NetworkManager service is running if ! systemctl is-active --quiet NetworkManager; then printf "%b\n" "${YELLOW}NetworkManager service is not running. Starting it now...${RC}" - $ESCALATION_TOOL systemctl start NetworkManager + "$ESCALATION_TOOL" systemctl start NetworkManager if systemctl is-active --quiet NetworkManager; then printf "%b\n" "${GREEN}NetworkManager service started successfully.${RC}" From d586b6e1bd3b9521d39201452ce296f65d05aea1 Mon Sep 17 00:00:00 2001 From: Adam Perkowski Date: Thu, 19 Sep 2024 02:04:08 +0200 Subject: [PATCH 63/88] Packages metadata update [AUR] (#471) * LINUTIL ON AUR!!! * Added hyperlinks --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c3a2ef68b..9892d5aa7 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ ![GitHub Downloads (specific asset, all releases)](https://img.shields.io/github/downloads/ChrisTitusTech/linutil/linutil?label=Total%20Downloads&style=for-the-badge) [![](https://dcbadge.limes.pink/api/server/https://discord.gg/bujFYKAHSp)](https://discord.gg/bujFYKAHSp) + +[![linutil AUR Version](https://img.shields.io/aur/version/linutil?style=for-the-badge&label=%5BAUR%5D%20linutil&color=%23230567ff)](https://aur.archlinux.org/packages/linutil) [![linutil-bin AUR Version](https://img.shields.io/aur/version/linutil-bin?style=for-the-badge&label=%5BAUR%5D%20linutil-bin&color=%23230567ff)](https://aur.archlinux.org/packages/linutil-bin) + ![Preview](docs/assets/preview.png) **Linutil** is a distro-agnostic toolbox designed to simplify everyday Linux tasks. It helps you set up applications and optimize your system for specific use cases. The utility is actively developed in Rust 🦀, providing performance and reliability. From cca4fd1ced795e619951219fb9f1fcf9c7000067 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:04:27 -0400 Subject: [PATCH 64/88] Fix bashisms in create bootable usb (#477) Co-authored-by: nnyyxxxx --- tabs/utils/create-bootable-usb.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tabs/utils/create-bootable-usb.sh b/tabs/utils/create-bootable-usb.sh index 6feae2dac..36954cfb7 100644 --- a/tabs/utils/create-bootable-usb.sh +++ b/tabs/utils/create-bootable-usb.sh @@ -103,7 +103,8 @@ fetch_iso_urls() { echo "2) Arch Linux (older versions)" echo "3) Debian Linux (latest)" echo "" - read -p "Select the ISO you want to download (1-3): " ISO_OPTION + printf "Select the ISO you want to download (1-3): " + read -r ISO_OPTION case $ISO_OPTION in 1) @@ -144,7 +145,8 @@ write_iso(){ list_devices # Prompt user for USB device - read -p "Enter the USB device (e.g., /dev/sdX): " USB_DEVICE + printf "Enter the USB device (e.g., /dev/sdX): " + read -r USB_DEVICE # Verify that the USB device exists if [ ! -b "$USB_DEVICE" ]; then From 969c83dda67f2efb2572a520be719d63b035889d Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:13:35 -0400 Subject: [PATCH 65/88] Replace echos with printf (utils) (#479) Co-authored-by: nnyyxxxx Co-authored-by: Chris Titus --- tabs/utils/auto-login.sh | 127 +++++++++++---------- tabs/utils/bluetooth-control.sh | 22 ++-- tabs/utils/create-bootable-usb.sh | 17 ++- tabs/utils/numlock.sh | 9 +- tabs/utils/ollama.sh | 39 +++---- tabs/utils/service-control.sh | 180 +++++++++++++++--------------- tabs/utils/timeshift.sh | 70 ++++++------ tabs/utils/wifi-control.sh | 34 +++--- 8 files changed, 244 insertions(+), 254 deletions(-) mode change 100644 => 100755 tabs/utils/wifi-control.sh diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh index 835ca7469..aa73211c5 100644 --- a/tabs/utils/auto-login.sh +++ b/tabs/utils/auto-login.sh @@ -4,18 +4,18 @@ # Function to list common session options list_sessions() { - echo "Select the session:" - echo "1) GNOME (gnome.desktop)" - echo "2) KDE Plasma (plasma.desktop)" - echo "3) XFCE (xfce.desktop)" - echo "4) LXDE (LXDE.desktop)" - echo "5) LXQt (lxqt.desktop)" - echo "6) Cinnamon (cinnamon.desktop)" - echo "7) MATE (mate.desktop)" - echo "8) Openbox (openbox.desktop)" - echo "9) i3 (i3.desktop)" - echo "10) Custom session" - echo "Enter your choice [1-10]: " + printf "Select the session:\n" + printf "1) GNOME (gnome.desktop)\n" + printf "2) KDE Plasma (plasma.desktop)\n" + printf "3) XFCE (xfce.desktop)\n" + printf "4) LXDE (LXDE.desktop)\n" + printf "5) LXQt (lxqt.desktop)\n" + printf "6) Cinnamon (cinnamon.desktop)\n" + printf "7) MATE (mate.desktop)\n" + printf "8) Openbox (openbox.desktop)\n" + printf "9) i3 (i3.desktop)\n" + printf "10) Custom session\n" + printf "Enter your choice [1-10]: " read session_choice case "$session_choice" in @@ -29,116 +29,116 @@ list_sessions() { 8) session="openbox.desktop" ;; 9) session="i3.desktop" ;; 10) - echo "Enter custom session name (e.g., mysession.desktop): " + printf "Enter custom session name (e.g., mysession.desktop): " read -r session ;; *) - echo "Invalid option selected." + printf "Invalid option selected.\n" exit 1 ;; esac } # Function to configure LightDM configure_lightdm() { - echo "Configuring LightDM for autologin..." + printf "Configuring LightDM for autologin...\n" - echo "Enter username for LightDM autologin: " + printf "Enter username for LightDM autologin: " read -r user - $ESCALATION_TOOL "echo '[Seat:*]' > /etc/lightdm/lightdm.conf.d/50-autologin.conf" - $ESCALATION_TOOL "echo 'autologin-user=$user' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" - $ESCALATION_TOOL "echo 'autologin-user-timeout=0' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" + $ESCALATION_TOOL "printf '[Seat:*]' > /etc/lightdm/lightdm.conf.d/50-autologin.conf" + $ESCALATION_TOOL "printf 'autologin-user=$user' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" + $ESCALATION_TOOL "printf 'autologin-user-timeout=0' >> /etc/lightdm/lightdm.conf.d/50-autologin.conf" - echo "LightDM has been configured for autologin." + printf "LightDM has been configured for autologin.\n" } # Function to remove LightDM autologin remove_lightdm_autologin() { - echo "Removing LightDM autologin configuration..." + printf "Removing LightDM autologin configuration...\n" $ESCALATION_TOOL rm -f /etc/lightdm/lightdm.conf.d/50-autologin.conf - echo "LightDM autologin configuration has been removed." + printf "LightDM autologin configuration has been removed.\n" } # Function to configure GDM configure_gdm() { - echo "Configuring GDM for autologin..." + printf "Configuring GDM for autologin...\n" - echo "Enter username for GDM autologin: " + printf "Enter username for GDM autologin: " read -r user - $ESCALATION_TOOL "echo '[daemon]' > /etc/gdm/custom.conf" - $ESCALATION_TOOL "echo 'AutomaticLoginEnable = true' >> /etc/gdm/custom.conf" - $ESCALATION_TOOL "echo 'AutomaticLogin = $user' >> /etc/gdm/custom.conf" + $ESCALATION_TOOL "printf '[daemon]' > /etc/gdm/custom.conf" + $ESCALATION_TOOL "printf 'AutomaticLoginEnable = true' >> /etc/gdm/custom.conf" + $ESCALATION_TOOL "printf 'AutomaticLogin = $user' >> /etc/gdm/custom.conf" - echo "GDM has been configured for autologin." + printf "GDM has been configured for autologin.\n" } # Function to remove GDM autologin remove_gdm_autologin() { - echo "Removing GDM autologin configuration..." + printf "Removing GDM autologin configuration...\n" $ESCALATION_TOOL sed -i '/AutomaticLoginEnable/d' /etc/gdm/custom.conf $ESCALATION_TOOL sed -i '/AutomaticLogin/d' /etc/gdm/custom.conf - echo "GDM autologin configuration has been removed." + printf "GDM autologin configuration has been removed.\n" } # Function to configure SDDM configure_sddm() { - echo "Configuring SDDM for autologin..." + printf "Configuring SDDM for autologin...\n" - echo "Enter username for SDDM autologin: " + printf "Enter username for SDDM autologin: " read -r user list_sessions # Show session options - $ESCALATION_TOOL "echo '[Autologin]' > /etc/sddm.conf" - $ESCALATION_TOOL "echo 'User=$user' >> /etc/sddm.conf" - $ESCALATION_TOOL "echo 'Session=$session' >> /etc/sddm.conf" + $ESCALATION_TOOL "printf '[Autologin]' > /etc/sddm.conf" + $ESCALATION_TOOL "printf 'User=$user' >> /etc/sddm.conf" + $ESCALATION_TOOL "printf 'Session=$session' >> /etc/sddm.conf" - echo "SDDM has been configured for autologin." + printf "SDDM has been configured for autologin.\n" } # Function to remove SDDM autologin remove_sddm_autologin() { - echo "Removing SDDM autologin configuration..." + printf "Removing SDDM autologin configuration...\n" $ESCALATION_TOOL sed -i '/\[Autologin\]/,+2d' /etc/sddm.conf - echo "SDDM autologin configuration has been removed." + printf "SDDM autologin configuration has been removed.\n" } # Function to configure LXDM configure_lxdm() { - echo "Configuring LXDM for autologin..." + printf "Configuring LXDM for autologin...\n" - echo "Enter username for LXDM autologin: " + printf "Enter username for LXDM autologin: " read -r user list_sessions # Show session options $ESCALATION_TOOL sed -i "s/^#.*autologin=.*$/autologin=${user}/" /etc/lxdm/lxdm.conf $ESCALATION_TOOL sed -i "s|^#.*session=.*$|session=/usr/bin/${session}|; s|^session=.*$|session=/usr/bin/${session}|" /etc/lxdm/lxdm.conf - echo "LXDM has been configured for autologin." + printf "LXDM has been configured for autologin.\n" } # Function to remove LXDM autologin remove_lxdm_autologin() { - echo "Removing LXDM autologin configuration..." + printf "Removing LXDM autologin configuration...\n" $ESCALATION_TOOL sed -i "s/^autologin=.*$/#autologin=/" /etc/lxdm/lxdm.conf $ESCALATION_TOOL sed -i "s/^session=.*$/#session=/" /etc/lxdm/lxdm.conf - echo "LXDM autologin configuration has been removed." + printf "LXDM autologin configuration has been removed.\n" } # Function to configure or remove autologin based on user choice configure_or_remove_autologin() { - echo "Do you want to add or remove autologin?" - echo "1) Add autologin" - echo "2) Remove autologin" - echo "Enter your choice [1-2]: " + printf "Do you want to add or remove autologin?\n" + printf "1) Add autologin\n" + printf "2) Remove autologin\n" + printf "Enter your choice [1-2]: " read action_choice if [ "$action_choice" = "1" ]; then - echo "Choose the display manager to configure:" - echo "1) LightDM" - echo "2) GDM" - echo "3) SDDM" - echo "4) LXDM" - echo "Enter your choice [1-4]: " + printf "Choose the display manager to configure:\n" + printf "1) LightDM\n" + printf "2) GDM\n" + printf "3) SDDM\n" + printf "4) LXDM\n" + printf "Enter your choice [1-4]: " read choice case "$choice" in @@ -146,15 +146,15 @@ configure_or_remove_autologin() { 2) configure_gdm ;; 3) configure_sddm ;; 4) configure_lxdm ;; - *) echo "Invalid option selected." ;; + *) printf "Invalid option selected.\n" ;; esac elif [ "$action_choice" = "2" ]; then - echo "Choose the display manager to remove autologin:" - echo "1) LightDM" - echo "2) GDM" - echo "3) SDDM" - echo "4) LXDM" - echo "Enter your choice [1-4]: " + printf "Choose the display manager to remove autologin:\n" + printf "1) LightDM\n" + printf "2) GDM\n" + printf "3) SDDM\n" + printf "4) LXDM\n" + printf "Enter your choice [1-4]: " read choice case "$choice" in @@ -162,18 +162,17 @@ configure_or_remove_autologin() { 2) remove_gdm_autologin ;; 3) remove_sddm_autologin ;; 4) remove_lxdm_autologin ;; - *) echo "Invalid option selected." ;; + *) printf "Invalid option selected.\n" ;; esac else - echo "Invalid choice. Exiting..." + printf "Invalid choice. Exiting...\n" exit 1 fi - echo "Action completed. Exiting..." + printf "Action completed. Exiting...\n" exit 0 } - checkEnv checkEscalationTool configure_or_remove_autologin diff --git a/tabs/utils/bluetooth-control.sh b/tabs/utils/bluetooth-control.sh index 367979df4..ba8c8c9f0 100644 --- a/tabs/utils/bluetooth-control.sh +++ b/tabs/utils/bluetooth-control.sh @@ -35,13 +35,13 @@ main_menu() { clear printf "%b\n" "${YELLOW}Bluetooth Manager${RC}" printf "%b\n" "${YELLOW}=================${RC}" - echo "1. Scan for devices" - echo "2. Pair with a device" - echo "3. Connect to a device" - echo "4. Disconnect from a device" - echo "5. Remove a device" - echo "0. Exit" - echo -n "Choose an option: " + printf "1. Scan for devices\n" + printf "2. Pair with a device\n" + printf "3. Connect to a device\n" + printf "4. Disconnect from a device\n" + printf "5. Remove a device\n" + printf "0. Exit\n" + printf -n "Choose an option: " read choice case $choice in @@ -66,7 +66,7 @@ scan_devices() { printf "%b\n" "${RED}No devices found.${RC}" else printf "%b\n" "${GREEN}Devices found:${RC}" - echo "$devices" + printf "%s\n" "$devices" fi printf "Press any key to return to the main menu..." read -r dummy @@ -94,11 +94,11 @@ prompt_for_mac() { device_list=$(echo "$devices" | tr '\n' '\n') i=1 echo "$device_list" | while IFS= read -r device; do - echo "$i. $device" + printf "%d. %s\n" "$i" "$device" i=$((i + 1)) done - echo "0. Exit to main menu" - echo -n "$prompt_msg" + printf "0. Exit to main menu\n" + printf "%s\n" "$prompt_msg" read choice # Validate the choice diff --git a/tabs/utils/create-bootable-usb.sh b/tabs/utils/create-bootable-usb.sh index 36954cfb7..e96c73a93 100644 --- a/tabs/utils/create-bootable-usb.sh +++ b/tabs/utils/create-bootable-usb.sh @@ -5,16 +5,16 @@ # Function to display usage instructions usage() { printf "%b\n" "${RED} Usage: $0 ${RC}" - echo "No arguments needed. The script will prompt for ISO path and USB device." + printf "No arguments needed. The script will prompt for ISO path and USB device.\n" exit 1 } # Function to display all available block devices list_devices() { printf "%b\n" "${YELLOW} Available devices and partitions: ${RC}" - echo "" + printf "\n" $ESCALATION_TOOL lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL - echo "" + printf "\n" } # Function to fetch the latest Arch Linux ISO @@ -47,7 +47,7 @@ fetch_arch_older_isos() { printf "%-5s${YELLOW}%-15s ${RC}" "$COUNTER)" "$VERSION" if [ $(( COUNTER % ROW_ITEMS )) -eq 0 ]; then - echo "" # New line after every 6 versions + printf "\n" # New line after every 6 versions fi COUNTER=$((COUNTER + 1)) @@ -60,7 +60,6 @@ fetch_arch_older_isos() { printf "%b\n" "${GREEN}Selected Arch Linux (older) ISO URL: $ARCH_URL${RC}" } - # Function to fetch the latest Debian Linux ISO fetch_debian_latest_iso() { DEBIAN_URL=$(curl -s https://www.debian.org/distrib/netinst | grep -oP '(?<=href=")[^"]+debian-[0-9.]+-amd64-netinst.iso(?=")' | head -1) @@ -99,10 +98,10 @@ choose_iso_source() { fetch_iso_urls() { clear printf "%b\n" "${YELLOW}Available ISOs for download:${RC}" - echo "1) Arch Linux (latest)" - echo "2) Arch Linux (older versions)" - echo "3) Debian Linux (latest)" - echo "" + printf "1) Arch Linux (latest)\n" + printf "2) Arch Linux (older versions)\n" + printf "3) Debian Linux (latest)\n" + printf "\n" printf "Select the ISO you want to download (1-3): " read -r ISO_OPTION diff --git a/tabs/utils/numlock.sh b/tabs/utils/numlock.sh index d1f7822af..cbae21f35 100755 --- a/tabs/utils/numlock.sh +++ b/tabs/utils/numlock.sh @@ -8,7 +8,7 @@ # Create a script to toggle numlock create_file() { - echo "Creating script..." + printf "Creating script...\n" "$ESCALATION_TOOL" tee "/usr/local/bin/numlock" >/dev/null <<'EOF' #!/bin/bash @@ -23,7 +23,7 @@ EOF # Create a systemd service to run the script on boot create_service() { - echo "Creating service..." + printf "Creating service...\n" "$ESCALATION_TOOL" tee "/etc/systemd/system/numlock.service" >/dev/null <<'EOF' [Unit] Description=numlock @@ -52,11 +52,10 @@ numlockSetup() { read -r confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then "$ESCALATION_TOOL" systemctl enable numlock.service --quiet - echo "Numlock will be enabled on boot" + printf "Numlock will be enabled on boot\n" else "$ESCALATION_TOOL" systemctl disable numlock.service --quiet - echo "Numlock will not be enabled on boot" - + printf "Numlock will not be enabled on boot\n" fi } diff --git a/tabs/utils/ollama.sh b/tabs/utils/ollama.sh index 8c2861e7b..f93cc7416 100644 --- a/tabs/utils/ollama.sh +++ b/tabs/utils/ollama.sh @@ -6,7 +6,6 @@ installollama() { clear printf "%b\n" "${YELLOW}Checking if ollama is already installed...${RC}" - # Check if ollama is already installed if command_exists ollama; then printf "%b\n" "${GREEN}ollama is already installed.${RC}" else @@ -32,7 +31,6 @@ show_model_info() { ollama show "$model_name" } -# Function to display available models display_models() { clear printf "%b\n" "${RED}Available Models${RC}" @@ -58,23 +56,23 @@ display_models() { select_model() { local choice="$1" case $choice in - 1) echo "llama3.1";; - 2) echo "llama3.1:70b";; - 3) echo "llama3.1:405b";; - 4) echo "phi3";; - 5) echo "phi3:medium";; - 6) echo "gemma2:2b";; - 7) echo "gemma2";; - 8) echo "gemma2:27b";; - 9) echo "mistral";; - 10) echo "moondream";; - 11) echo "neural-chat";; - 12) echo "starling-lm";; - 13) echo "codellama";; - 14) echo "llama2-uncensored";; - 15) echo "llava";; - 16) echo "solar";; - *) echo "$choice";; # Treat any other input as a custom model name + 1) printf "%b\n" "llama3.1";; + 2) printf "%b\n" "llama3.1:70b";; + 3) printf "%b\n" "llama3.1:405b";; + 4) printf "%b\n" "phi3";; + 5) printf "%b\n" "phi3:medium";; + 6) printf "%b\n" "gemma2:2b";; + 7) printf "%b\n" "gemma2";; + 8) printf "%b\n" "gemma2:27b";; + 9) printf "%b\n" "mistral";; + 10) printf "%b\n" "moondream";; + 11) printf "%b\n" "neural-chat";; + 12) printf "%b\n" "starling-lm";; + 13) printf "%b\n" "codellama";; + 14) printf "%b\n" "llama2-uncensored";; + 15) printf "%b\n" "llava";; + 16) printf "%b\n" "solar";; + *) printf "%b\n" "$choice";; esac } @@ -98,7 +96,6 @@ run_model() { printf "%b\n" "${YELLOW}Running the model: $model...${RC}" ollama run "$model" - } create_model() { @@ -184,7 +181,7 @@ menu() { printf "5) Remove a model\n" printf "6) Exit\n" - printf "%b" "${YELLOW}Enter your choice (1-5): ${RC}" + printf "%b\n" "${YELLOW}Enter your choice (1-5): ${RC}" read -r choice case $choice in diff --git a/tabs/utils/service-control.sh b/tabs/utils/service-control.sh index 8bc6da19f..119e45f31 100644 --- a/tabs/utils/service-control.sh +++ b/tabs/utils/service-control.sh @@ -9,72 +9,71 @@ SCRIPT_DIR="./services" # Function to show the main menu show_menu() { clear - echo "============================" - echo " Service Management Menu" - echo "============================" - echo "1. View all services" - echo "2. View enabled services" - echo "3. View disabled services" - echo "4. Add a new service" - echo "5. Remove a service" - echo "6. Start a service" - echo "7. Stop a service" - echo "8. Enable a service" - echo "9. Disable a service" - echo "10. Create a service from external scripts" - echo "11. Exit" - echo "============================" + printf "============================\n" + printf " Service Management Menu\n" + printf "============================\n" + printf "1. View all services\n" + printf "2. View enabled services\n" + printf "3. View disabled services\n" + printf "4. Add a new service\n" + printf "5. Remove a service\n" + printf "6. Start a service\n" + printf "7. Stop a service\n" + printf "8. Enable a service\n" + printf "9. Disable a service\n" + printf "10. Create a service from external scripts\n" + printf "11. Exit\n" + printf "============================\n" } # Function to view all services view_all_services() { - echo "Listing all services..." + printf "Listing all services...\n" "$ESCALATION_TOOL" systemctl list-units --type=service --all --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view enabled services view_enabled_services() { - echo "Listing enabled services..." + printf "Listing enabled services...\n" "$ESCALATION_TOOL" systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view disabled services view_disabled_services() { - echo "Listing disabled services..." + printf "Listing disabled services...\n" "$ESCALATION_TOOL" systemctl list-unit-files --type=service --state=disabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more } # Function to view started services view_started_services() { - echo "Listing started services:" + printf "Listing started services:\n" "$ESCALATION_TOOL" systemctl list-units --type=service --state=running --no-pager | head -n -6 | awk 'NR>1 {print $1}' | more } # Function to add a new service add_service() { while [ -z "$SERVICE_NAME" ]; do - echo "Enter the name of the new service (e.g., my_service):" + printf "Enter the name of the new service (e.g., my_service):\n" read -r SERVICE_NAME - if "$ESCALATION_TOOL" systemctl list-units --type=service --all --no-legend | grep -q "$SERVICE_NAME.service"; then - echo "Service already exists!" + printf "Service already exists!\n" SERVICE_NAME="" fi done - echo "Enter the description of the service:" + printf "Enter the description of the service:\n" read -r SERVICE_DESCRIPTION - echo "Enter the command to execute the service (e.g., /usr/local/bin/my_service.sh):" + printf "Enter the command to execute the service (e.g., /usr/local/bin/my_service.sh):\n" read -r EXEC_START - echo "Enter the user to run the service as (leave empty for default):" + printf "Enter the user to run the service as (leave empty for default):\n" read -r SERVICE_USER - echo "Enter the working directory for the service (leave empty for default):" + printf "Enter the working directory for the service (leave empty for default):\n" read -r WORKING_DIRECTORY - echo "Enter the restart policy (e.g., always, on-failure; leave empty for no restart):" + printf "Enter the restart policy (e.g., always, on-failure; leave empty for no restart):\n" read -r RESTART_POLICY # Create the service unit file @@ -82,108 +81,107 @@ add_service() { # Create the service file with conditionals for optional fields { - echo "[Unit]" - echo "Description=$SERVICE_DESCRIPTION" - echo "" - echo "[Service]" - echo "ExecStart=$EXEC_START" - [ -n "$SERVICE_USER" ] && echo "User=$SERVICE_USER" - [ -n "$WORKING_DIRECTORY" ] && echo "WorkingDirectory=$WORKING_DIRECTORY" - [ -n "$RESTART_POLICY" ] && echo "Restart=$RESTART_POLICY" - echo "" - echo "[Install]" - echo "WantedBy=multi-user.target" - } | "$ESCALATION_TOOL" tee "$SERVICE_FILE" > /dev/null + printf "[Unit]\n" + printf "Description=$SERVICE_DESCRIPTION\n" + printf "\n" + printf "[Service]\n" + printf "ExecStart=$EXEC_START\n" + [ -n "$SERVICE_USER" ] && printf "User=$SERVICE_USER\n" + [ -n "$WORKING_DIRECTORY" ] && printf "WorkingDirectory=$WORKING_DIRECTORY\n" + [ -n "$RESTART_POLICY" ] && printf "Restart=$RESTART_POLICY\n" + printf "\n" + printf "[Install]\n" + printf "WantedBy=multi-user.target\n" + } | $ESCALATION_TOOL tee "$SERVICE_FILE" > /dev/null # Set permissions and reload systemd - "$ESCALATION_TOOL" chmod 644 "$SERVICE_FILE" - "$ESCALATION_TOOL" systemctl daemon-reload - echo "Service $SERVICE_NAME has been created and is ready to be started." + $ESCALATION_TOOL chmod 644 "$SERVICE_FILE" + $ESCALATION_TOOL systemctl daemon-reload + printf "Service $SERVICE_NAME has been created and is ready to be started.\n" # Optionally, enable and start the service - echo "Do you want to start and enable the service now? (y/n)" + printf "Do you want to start and enable the service now? (y/n)\n" read -r START_ENABLE if [ "$START_ENABLE" = "y" ]; then "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME" "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME" - echo "Service $SERVICE_NAME has been started and enabled." + printf "Service $SERVICE_NAME has been started and enabled.\n" else - echo "Service $SERVICE_NAME has been created but not started." + printf "Service $SERVICE_NAME has been created but not started.\n" fi } # Function to remove a service remove_service() { - echo "Enter the name of the service to remove (e.g., my_service):" + printf "Enter the name of the service to remove (e.g., my_service):\n" read -r SERVICE_NAME SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service" if [ -f "$SERVICE_FILE" ]; then - echo "Stopping and disabling the service..." - "$ESCALATION_TOOL" systemctl stop "$SERVICE_NAME" - "$ESCALATION_TOOL" systemctl disable "$SERVICE_NAME" - - echo "Removing the service file..." - "$ESCALATION_TOOL" rm -f "$SERVICE_FILE" - "$ESCALATION_TOOL" systemctl daemon-reload - - echo "Service $SERVICE_NAME has been removed." + printf "Stopping and disabling the service...\n" + $ESCALATION_TOOL systemctl stop "$SERVICE_NAME" + $ESCALATION_TOOL systemctl disable "$SERVICE_NAME" + + printf "Removing the service file...\n" + $ESCALATION_TOOL rm -f "$SERVICE_FILE" + $ESCALATION_TOOL systemctl daemon-reload + printf "Service $SERVICE_NAME has been removed.\n" else - echo "Service $SERVICE_NAME does not exist." + printf "Service $SERVICE_NAME does not exist.\n" fi } # Function to start a service start_service() { view_disabled_services - echo "Enter the name of the service to start (e.g., my_service):" + printf "Enter the name of the service to start (e.g., my_service):\n" read -r SERVICE_NAME - if "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME"; then - echo "Service $SERVICE_NAME has been started." + if $ESCALATION_TOOL systemctl start "$SERVICE_NAME"; then + printf "Service $SERVICE_NAME has been started.\n" else - echo "Failed to start service: $SERVICE_NAME." + printf "Failed to start service: $SERVICE_NAME.\n" fi } # Function to stop a service stop_service() { view_started_services - echo "Enter the name of the service to stop (e.g., my_service):" + printf "Enter the name of the service to stop (e.g., my_service):\n" read -r SERVICE_NAME - if "$ESCALATION_TOOL" systemctl stop "$SERVICE_NAME"; then - echo "Service $SERVICE_NAME has been stopped." + if $ESCALATION_TOOL systemctl stop "$SERVICE_NAME"; then + printf "Service $SERVICE_NAME has been stopped.\n" else - echo "Failed to stop service: $SERVICE_NAME." + printf "Failed to stop service: $SERVICE_NAME.\n" fi } # Function to enable a service enable_service() { view_disabled_services - echo "Enter the name of the service to enable (e.g., my_service):" + printf "Enter the name of the service to enable (e.g., my_service):\n" read -r SERVICE_NAME - if "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME"; then - echo "Service $SERVICE_NAME has been enabled." + if $ESCALATION_TOOL systemctl enable "$SERVICE_NAME"; then + printf "Service $SERVICE_NAME has been enabled.\n" else - echo "Failed to enable service: $SERVICE_NAME." + printf "Failed to enable service: $SERVICE_NAME.\n" fi } # Function to enable a service disable_service() { view_enabled_services - echo "Enter the name of the service to disable (e.g., my_service):" + printf "Enter the name of the service to disable (e.g., my_service):\n" read -r SERVICE_NAME - if "$ESCALATION_TOOL" systemctl disable "$SERVICE_NAME"; then - echo "Service $SERVICE_NAME has been enabled." + if $ESCALATION_TOOL systemctl disable "$SERVICE_NAME"; then + printf "Service $SERVICE_NAME has been enabled.\n" else - echo "Failed to enable service: $SERVICE_NAME." + printf "Failed to enable service: $SERVICE_NAME.\n" fi } @@ -191,24 +189,24 @@ disable_service() { create_service_from_external() { # List all .service files in the SCRIPT_DIR - echo "============================" - echo "Listing available service files" - echo "============================" + printf "============================\n" + printf "Listing available service files\n" + printf "============================\n" for FILE in "$SCRIPT_DIR"/*.service; do - echo "$(basename "$FILE")" + printf "%s\n" "$(basename "$FILE")" done - echo "Enter the filename (without the .service extension) of the service to create:" + printf "Enter the filename (without the .service extension) of the service to create:\n" read -r SERVICE_NAME SERVICE_FILE="$SCRIPT_DIR/$SERVICE_NAME.service" if [ ! -f "$SERVICE_FILE" ]; then - echo "Service file $SERVICE_FILE does not exist." + printf "Service file $SERVICE_FILE does not exist.\n" return fi - echo "Enter the username to run the service as (leave empty for no specific user):" + printf "Enter the username to run the service as (leave empty for no specific user):\n" read -r SERVICE_USER # Create the systemd service file path @@ -230,27 +228,27 @@ create_service_from_external() { "$ESCALATION_TOOL" cp "$SERVICE_FILE" "$SYSTEMD_SERVICE_FILE" # Set permissions and reload systemd - "$ESCALATION_TOOL" chmod 644 "$SYSTEMD_SERVICE_FILE" - "$ESCALATION_TOOL" systemctl daemon-reload - echo "Service $SERVICE_NAME has been created and is ready to be started." + $ESCALATION_TOOL chmod 644 "$SYSTEMD_SERVICE_FILE" + $ESCALATION_TOOL systemctl daemon-reload + printf "Service $SERVICE_NAME has been created and is ready to be started.\n" # Optionally, enable and start the service - echo "Do you want to start and enable the service now? (y/n)" + printf "Do you want to start and enable the service now? (y/n)\n" read -r START_ENABLE if [ "$START_ENABLE" = "y" ]; then - "$ESCALATION_TOOL" systemctl start "$SERVICE_NAME" - "$ESCALATION_TOOL" systemctl enable "$SERVICE_NAME" - echo "Service $SERVICE_NAME has been started and enabled." + $ESCALATION_TOOL systemctl start "$SERVICE_NAME" + $ESCALATION_TOOL systemctl enable "$SERVICE_NAME" + printf "Service $SERVICE_NAME has been started and enabled.\n" else - echo "Service $SERVICE_NAME has been created but not started." + printf "Service $SERVICE_NAME has been created but not started.\n" fi } main() { while true; do show_menu - echo "Enter your choice:" + printf "Enter your choice:\n" read -r CHOICE case $CHOICE in @@ -264,11 +262,11 @@ main() { 8) enable_service ;; 9) disable_service ;; 10) create_service_from_external ;; - 11) echo "Exiting..."; exit 0 ;; - *) echo "Invalid choice. Please try again." ;; + 11) printf "Exiting...\n"; exit 0 ;; + *) printf "Invalid choice. Please try again.\n" ;; esac - echo "Press [Enter] to continue..." + printf "Press [Enter] to continue...\n" read -r dummy done } diff --git a/tabs/utils/timeshift.sh b/tabs/utils/timeshift.sh index 2d4a5a780..ec69081f2 100644 --- a/tabs/utils/timeshift.sh +++ b/tabs/utils/timeshift.sh @@ -7,7 +7,7 @@ install_timeshift() { clear printf "%b\n" "${YELLOW}Checking if Timeshift is installed...${RC}" - if ! command_exists timeshift; then + if ! command_exists timeshift; then case ${PACKAGER} in pacman) $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm timeshift @@ -17,7 +17,7 @@ install_timeshift() { ;; esac else - echo "Timeshift is already installed." + printf "%b\n" "${GREEN}Timeshift is already installed.${RC}" fi } @@ -25,7 +25,6 @@ install_timeshift() { display_menu() { clear printf "%b\n" "${CYAN}Timeshift CLI Automation${RC}" - printf "%b\n" "${CYAN}\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-" printf "%b\n" "${CYAN}1) List Snapshots${RC}" printf "%b\n" "${CYAN}2) List Devices${RC}" printf "%b\n" "${CYAN}3) Create Snapshot${RC}" @@ -33,7 +32,6 @@ display_menu() { printf "%b\n" "${CYAN}5) Delete Snapshot${RC}" printf "%b\n" "${CYAN}6) Delete All Snapshots${RC}" printf "%b\n" "${CYAN}7) Exit${RC}" - printf "%b\n" "${CYAN}\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-" } # Function to list snapshots @@ -50,26 +48,26 @@ list_devices() { # Function to create a new snapshot create_snapshot() { - printf "%b" "${CYAN}Enter a comment for the snapshot (optional): ${RC}" + printf "%b\n" "${CYAN}Enter a comment for the snapshot (optional): ${RC}" read -r COMMENT - printf "%b" "${CYAN}Enter snapshot tag (O,B,H,D,W,M) (leave empty for no tag): ${RC}" + printf "%b\n" "${CYAN}Enter snapshot tag (O,B,H,D,W,M) (leave empty for no tag): ${RC}" read -r TAG if [ -z "$COMMENT" ] && [ -z "$TAG" ]; then - echo "Creating snapshot with no comment or tag..." + printf "%b\n" "${CYAN}Creating snapshot with no comment or tag...${RC}" $ESCALATION_TOOL timeshift --create elif [ -z "$TAG" ]; then - echo "Creating snapshot with no tag..." + printf "%b\n" "${CYAN}Creating snapshot with no tag...${RC}" $ESCALATION_TOOL timeshift --create --comments "$COMMENT" else - echo "Creating snapshot with tag: $TAG..." + printf "%b\n" "${CYAN}Creating snapshot with tag: $TAG...${RC}" $ESCALATION_TOOL timeshift --create --comments "$COMMENT" --tags "$TAG" fi if [ $? -eq 0 ]; then - echo "Snapshot created successfully." + printf "%b\n" "${GREEN}Snapshot created successfully.${RC}" else - echo "Snapshot creation failed." + printf "%b\n" "${RED}Snapshot creation failed.${RC}" fi } @@ -77,17 +75,17 @@ create_snapshot() { restore_snapshot() { list_snapshots - printf "%b" "${CYAN}Enter the snapshot name you want to restore: ${RC}" + printf "%b\n" "${CYAN}Enter the snapshot name you want to restore: ${RC}" read -r SNAPSHOT - printf "%b" "${CYAN}Enter the target device (e.g., /dev/sda1): ${RC}" + printf "%b\n" "${CYAN}Enter the target device (e.g., /dev/sda1): ${RC}" read -r TARGET_DEVICE - printf "%b" "${CYAN}Do you want to skip GRUB reinstall? (yes/no): ${RC}" + printf "%b\n" "${CYAN}Do you want to skip GRUB reinstall? (yes/no): ${RC}" read -r SKIP_GRUB if [ "$SKIP_GRUB" = "yes" ]; then $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --skip-grub --yes else - printf "%b" "${CYAN}Enter GRUB device (e.g., /dev/sda): ${RC}" + printf "%b\n" "${CYAN}Enter GRUB device (e.g., /dev/sda): ${RC}" read -r GRUB_DEVICE $ESCALATION_TOOL timeshift --restore --snapshot "$SNAPSHOT" --target-device "$TARGET_DEVICE" --grub-device "$GRUB_DEVICE" --yes fi @@ -103,7 +101,7 @@ restore_snapshot() { delete_snapshot() { list_snapshots - printf "%b" "${CYAN}Enter the snapshot name you want to delete: ${RC}" + printf "%b\n" "${CYAN}Enter the snapshot name you want to delete: ${RC}" read -r SNAPSHOT printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}" @@ -119,11 +117,11 @@ delete_snapshot() { # Function to delete all snapshots delete_all_snapshots() { printf "%b\n" "${RED}WARNING: This will delete all snapshots!${RC}" - printf "%b" "${CYAN}Are you sure? (yes/no): ${RC}" + printf "%b\n" "${CYAN}Are you sure? (yes/no): ${RC}" read -r CONFIRMATION if [ "$CONFIRMATION" = "yes" ]; then - echo "Deleting all snapshots..." + printf "%b\n" "${CYAN}Deleting all snapshots...${RC}" $ESCALATION_TOOL timeshift --delete-all --yes if [ $? -eq 0 ]; then printf "%b\n" "${GREEN}All snapshots deleted successfully.${RC}" @@ -136,24 +134,24 @@ delete_all_snapshots() { } main_menu() { -while true; do - display_menu - printf "%b" "${CYAN}Select an option (1-7): ${RC}" - read -r OPTION - - case $OPTION in - 1) list_snapshots ;; - 2) list_devices ;; - 3) create_snapshot ;; - 4) restore_snapshot ;; - 5) delete_snapshot ;; - 6) delete_all_snapshots ;; - 7) printf "%b\n" "${GREEN}Exiting...${RC}"; exit 0 ;; - *) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;; - esac - printf "%b" "${CYAN}Press Enter to continue...${RC}" - read -r dummy -done + while true; do + display_menu + printf "%b\n" "${CYAN}Select an option (1-7): ${RC}" + read -r OPTION + + case $OPTION in + 1) list_snapshots ;; + 2) list_devices ;; + 3) create_snapshot ;; + 4) restore_snapshot ;; + 5) delete_snapshot ;; + 6) delete_all_snapshots ;; + 7) printf "%b\n" "${GREEN}Exiting...${RC}"; exit 0 ;; + *) printf "%b\n" "${RED}Invalid option. Please try again.${RC}" ;; + esac + printf "%b\n" "${CYAN}Press Enter to continue...${RC}" + read -r dummy + done } checkEnv diff --git a/tabs/utils/wifi-control.sh b/tabs/utils/wifi-control.sh old mode 100644 new mode 100755 index ed2feefa0..71abcce51 --- a/tabs/utils/wifi-control.sh +++ b/tabs/utils/wifi-control.sh @@ -38,14 +38,14 @@ main_menu() { clear printf "%b\n" "${YELLOW}WiFi Manager${RC}" printf "%b\n" "${YELLOW}============${RC}" - echo "1. Turn WiFi On" - echo "2. Turn WiFi Off" - echo "3. Scan for WiFi networks" - echo "4. Connect to a WiFi network" - echo "5. Disconnect from a WiFi network" - echo "6. Remove a WiFi connection" - echo "0. Exit" - echo -n "Choose an option: " + printf "1. Turn WiFi On\n" + printf "2. Turn WiFi Off\n" + printf "3. Scan for WiFi networks\n" + printf "4. Connect to a WiFi network\n" + printf "5. Disconnect from a WiFi network\n" + printf "6. Remove a WiFi connection\n" + printf "0. Exit\n" + printf "Choose an option: " read choice case $choice in @@ -72,7 +72,7 @@ scan_networks() { printf "%b\n" "${GREEN}Top 10 Networks found:${RC}" echo "$networks" | awk -F: '{printf("%d. SSID: %-25s \n", NR, $1)}' fi - echo "Press any key to return to the main menu..." + printf "Press any key to return to the main menu...\n" read -r dummy } @@ -85,7 +85,7 @@ wifi_on() { } || { printf "%b\n" "${RED}Failed to turn on WiFi.${RC}" } - echo "Press any key to return to the main menu..." + printf "Press any key to return to the main menu...\n" read -r dummy } @@ -98,7 +98,7 @@ wifi_off() { } || { printf "%b\n" "${RED}Failed to turn off WiFi.${RC}" } - echo "Press any key to return to the main menu..." + printf "Press any key to return to the main menu...\n" read -r dummy } @@ -115,7 +115,7 @@ prompt_for_network() { networks=$(nmcli -t -f SSID dev wifi list | awk -F: '!seen[$1]++' | grep -v '^$') if [ -z "$networks" ]; then printf "%b\n" "${RED}No networks available. Please scan for networks first.${RC}" - echo "Press any key to return to the main menu..." + printf "Press any key to return to the main menu...\n" read -r dummy rm -f "$temp_file" return @@ -130,16 +130,16 @@ prompt_for_network() { i=$((i + 1)) done < "$temp_file" - echo "0. Exit to main menu" - echo -n "$prompt_msg" + printf "0. Exit to main menu\n" + printf "%s" "$prompt_msg" read choice if [ "$choice" -ge 1 ] && [ "$choice" -lt "$i" ]; then ssid=$(sed -n "${choice}p" "$temp_file" | awk -F: '{print $1}') if [ "$action" = "connect" ]; then - echo -n "Enter password for SSID $ssid: " + printf "Enter password for SSID %s: " "$ssid" read password - echo + printf "\n" nmcli dev wifi connect "$ssid" password "$password" && { printf "%b\n" "${GREEN}$success_msg${RC}" } || { @@ -150,7 +150,7 @@ prompt_for_network() { printf "%b\n" "${RED}Invalid choice. Please try again.${RC}" fi - echo "Press any key to return to the selection menu..." + printf "Press any key to return to the selection menu...\n" read -r dummy done From a7e6ea0246c8a0f5b8ef7b2119b1ed92d8b2c822 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 05:47:08 +0530 Subject: [PATCH 66/88] feat: Command Description (#437) * Implement about page Add title Add hints * Add descriptions for commands * Refactor about to description --- core/src/inner.rs | 4 ++++ core/src/lib.rs | 1 + tabs/applications-setup/tab_data.toml | 10 +++++++- tabs/gaming/tab_data.toml | 1 + tabs/security/tab_data.toml | 1 + tabs/system-setup/tab_data.toml | 9 +++++++ tabs/utils/tab_data.toml | 15 ++++++++++++ tui/src/float.rs | 4 +++- tui/src/floating_text.rs | 32 ++++++++++++++++++++----- tui/src/hint.rs | 1 + tui/src/state.rs | 34 +++++++++++++++++++++++++-- 11 files changed, 102 insertions(+), 10 deletions(-) diff --git a/core/src/inner.rs b/core/src/inner.rs index f23d21044..e965a3725 100644 --- a/core/src/inner.rs +++ b/core/src/inner.rs @@ -24,6 +24,7 @@ pub fn get_tabs(validate: bool) -> Vec { .map(|(TabEntry { name, data }, directory)| { let mut tree = Tree::new(ListNode { name: "root".to_string(), + description: "".to_string(), command: Command::None, }); let mut root = tree.root_mut(); @@ -146,12 +147,14 @@ fn create_directory(data: Vec, node: &mut NodeMut, command_dir: if let Some(entries) = entry.entries { let mut node = node.append(ListNode { name: entry.name, + description: entry.description, command: Command::None, }); create_directory(entries, &mut node, command_dir); } else if let Some(command) = entry.command { node.append(ListNode { name: entry.name, + description: entry.description, command: Command::Raw(command), }); } else if let Some(script) = entry.script { @@ -161,6 +164,7 @@ fn create_directory(data: Vec, node: &mut NodeMut, command_dir: } node.append(ListNode { name: entry.name, + description: entry.description, command: Command::LocalFile(dir), }); } else { diff --git a/core/src/lib.rs b/core/src/lib.rs index 93ce0619e..164e4e42a 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -21,5 +21,6 @@ pub struct Tab { #[derive(Clone, Hash, Eq, PartialEq)] pub struct ListNode { pub name: String, + pub description: String, pub command: Command, } diff --git a/tabs/applications-setup/tab_data.toml b/tabs/applications-setup/tab_data.toml index ce8f1b92b..0a9be9fbf 100644 --- a/tabs/applications-setup/tab_data.toml +++ b/tabs/applications-setup/tab_data.toml @@ -2,32 +2,40 @@ name = "Applications Setup" [[data]] name = "Alacritty" +description = "Alacritty is a modern terminal emulator that comes with sensible defaults, but allows for extensive configuration. By integrating with other applications, rather than reimplementing their functionality, it manages to provide a flexible set of features with high performance. The supported platforms currently consist of BSD, Linux, macOS and Windows.\nThis command installs and condifures alacritty terminal emulator." script = "alacritty-setup.sh" [[data]] name = "Bash Prompt" +description = "The .bashrc file is a script that runs every time a new terminal session is started in Unix-like operating systems.\nIt is used to configure the shell session, set up aliases, define functions, and more, making the terminal easier to use and more powerful.\nThis command configures the key sections and functionalities defined in the .bashrc file from CTT's mybash repository.\nhttps://github.com/ChrisTitusTech/mybash" script = "mybash-setup.sh" [[data]] name = "DWM-Titus" +description = "DWM is a dynamic window manager for X.\nIt manages windows in tiled, monocle and floating layouts.\nAll of the layouts can be applied dynamically, optimising the environment for the application in use and the task performed.\nThis command installs and configures DWM and a desktop manager.\nThe list of patches applied can be found in CTT's DWM repository\nhttps://github.com/ChrisTitusTech/dwm-titus" script = "dwmtitus-setup.sh" [[data]] name = "Kitty" +description = "kitty is a free and open-source GPU-accelerated terminal emulator for Linux, macOS, and some BSD distributions, focused on performance and features.\nkitty is written in a mix of C and Python programming languages.\n This command installs and configures kitty." script = "kitty-setup.sh" [[data]] name = "Neovim" +description = "Neovim is a refactor, and sometimes redactor, in the tradition of Vim.\nIt is not a rewrite but a continuation and extension of Vim.\nThis command configures neovim from CTT's neovim configuration.\nhttps://github.com/ChrisTitusTech/neovim" script = "neovim-setup.sh" [[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" script = "rofi-setup.sh" [[data]] 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.\nThis command installs ZSH prompt and provides basic configuration." script = "zsh-setup.sh" [[data]] name = "Fastfetch" -script = "fastfetch-setup.sh" \ No newline at end of file +description = "Fastfetch is a neofetch-like tool for fetching system information and displaying it prettily.\nIt is written mainly in C, with performance and customizability in mind.\nThis command installs fastfetch and configures from CTT's mybash repository.\nhttps://github.com/ChrisTitusTech/mybash" +script = "fastfetch-setup.sh" diff --git a/tabs/gaming/tab_data.toml b/tabs/gaming/tab_data.toml index b460683f4..6fc7aa378 100644 --- a/tabs/gaming/tab_data.toml +++ b/tabs/gaming/tab_data.toml @@ -5,4 +5,5 @@ name = "Diablo II Resurrected" [[data.entries]] name = "Loot Filter Install" +description = "This is a loot filter for Diablo II Resurrected.\nIt's designed to be a simple, clean, and easy to read loot filter that highlights the most important items.\nWorks on battle.net and single player.\nNo frills, no config, just highlights high runes and other valuable items.\nFor more information visit: https://github.com/ChrisTitusTech/d2r-loot-filter" script = "diablo-ii/d2r-loot-filters.sh" diff --git a/tabs/security/tab_data.toml b/tabs/security/tab_data.toml index 6d81cc36e..c899d4d93 100644 --- a/tabs/security/tab_data.toml +++ b/tabs/security/tab_data.toml @@ -2,4 +2,5 @@ name = "Security" [[data]] name = "Firewall Baselines (CTT)" +description = "Developed to ease iptables firewall configuration, UFW provides a user friendly way to create an IPv4 or IPv6 host-based firewall.\nThis command installs UFW and configures UFW based on CTT's recommended rules.\nFor more information visit: https://christitus.com/linux-security-mistakes" script = "firewall-baselines.sh" diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 0f903e020..6d1307b49 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -10,14 +10,17 @@ values = ["pacman"] [[data.entries]] name = "Arch Server Setup" +description = "This command installs a minimal arch server setup under 5 minutes." script = "arch/server-setup.sh" [[data.entries]] name = "Paru AUR Helper" +description = "Paru is your standard pacman wrapping AUR helper with lots of features and minimal interaction.\nTo know more about AUR helpers visit: https://wiki.archlinux.org/title/AUR_helpers" script = "arch/paru-setup.sh" [[data.entries]] name = "Yay AUR Helper" +description = "Yet Another Yogurt - An AUR Helper Written in Go.\nTo know more about AUR helpers visit: https://wiki.archlinux.org/title/AUR_helpers" script = "arch/yay-setup.sh" [[data]] @@ -30,26 +33,32 @@ values = ["dnf"] [[data.entries]] name = "RPM Fusion Setup" +description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" script = "fedora/rpm-fusion-setup.sh" [[data]] name = "Full System Update" +description = "This command updates your system to the latest packages available for your distro" script = "system-update.sh" [[data]] name = "Build Prerequisites" +description = "This script is designed to handle the installation of various software dependencies across different Linux distributions" script = "1-compile-setup.sh" [[data]] name = "Gaming Dependencies" +description = "This script is designed to handle the installation of gaming dependencies across different Linux distributions" script = "2-gaming-setup.sh" [[data]] name = "Global Theme" +description = "This script is designed to handle the installation and configuration of global theming" script = "3-global-theme.sh" [[data]] name = "Remove Snaps" +description = "This script is designed to remove snap" script = "4-remove-snaps.sh" [[data]] diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index d5783fc0e..2ccec8b9c 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -2,22 +2,27 @@ name = "Utilities" [[data]] name = "WiFi Manager" +description = "This utility is designed to manage wifi in your system" script = "wifi-control.sh" [[data]] name = "Bluetooth Manager" +description = "This utility is designed to manage bluetooth in your system" script = "bluetooth-control.sh" [[data]] name = "Numlock on Startup" +description = "This utility is designed to configure auto enabling of numlock on boot" script = "numlock.sh" [[data]] name = "Ollama" +description = "This utility is designed to manage ollama in your system" script = "ollama.sh" [[data]] name = "Service Manager" +description = "This utility is designed to manage services in your system" script = "service-control.sh" [[data]] @@ -51,42 +56,52 @@ values = [":0", ":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8", ":9"] [[data.entries]] name = "Duplicate Displays" +description = "This utility is designed to duplicate display among multi-monitor setup in your system" script = "monitor-control/duplicate_displays.sh" [[data.entries]] name = "Extend Displays" +description = "This utility is designed to extend display among multi-monitor setup in your system" script = "monitor-control/extend_displays.sh" [[data.entries]] name = "Auto Detect Displays" +description = "This utility is designed to detect and apply recommended configuration for monitors connected with your system" script = "monitor-control/auto_detect_displays.sh" [[data.entries]] name = "Enable Monitor" +description = "This utility is designed to enable a monitor in your system" script = "monitor-control/enable_monitor.sh" [[data.entries]] name = "Disable Monitor" +description = "This utility is designed to disable a monitor in your system" script = "monitor-control/disable_monitor.sh" [[data.entries]] name = "Set Primary Monitor" +description = "This utility is designed to set a Primary monitor in your system" script = "monitor-control/set_primary_monitor.sh" [[data.entries]] name = "Change Orientation" +description = "This utility is designed to change the orientation of monitors in your system" script = "monitor-control/change_orientation.sh" [[data.entries]] name = "Manage Arrangement" +description = "This utility is designed to arrange monitors in multi-monitor setup in your system" script = "monitor-control/manage_arrangement.sh" [[data.entries]] name = "Scale Monitors" +description = "This utility is designed to change the scaling of monitors in your system" script = "monitor-control/scale_monitor.sh" [[data.entries]] name = "Reset Scaling" +description = "This utility is designed to reset scaling of a monitor in your system" script = "monitor-control/reset_scaling.sh" matches = true diff --git a/tui/src/float.rs b/tui/src/float.rs index bfdea73da..3df63ae91 100644 --- a/tui/src/float.rs +++ b/tui/src/float.rs @@ -64,7 +64,9 @@ impl Float { // Returns true if the floating window is finished. pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool { match key.code { - KeyCode::Enter | KeyCode::Char('p') | KeyCode::Esc if self.content.is_finished() => { + KeyCode::Enter | KeyCode::Char('p') | KeyCode::Char('d') | KeyCode::Esc + if self.content.is_finished() => + { true } _ => self.content.handle_key_event(key), diff --git a/tui/src/floating_text.rs b/tui/src/floating_text.rs index ccf796ee1..fd53ed074 100644 --- a/tui/src/floating_text.rs +++ b/tui/src/floating_text.rs @@ -11,18 +11,26 @@ use ratatui::{ widgets::{Block, Borders, List}, Frame, }; - +pub enum FloatingTextMode { + Preview, + Description, +} pub struct FloatingText { text: Vec, + mode: FloatingTextMode, scroll: usize, } impl FloatingText { - pub fn new(text: Vec) -> Self { - Self { text, scroll: 0 } + pub fn new(text: Vec, mode: FloatingTextMode) -> Self { + Self { + text, + scroll: 0, + mode, + } } - pub fn from_command(command: &Command) -> Option { + pub fn from_command(command: &Command, mode: FloatingTextMode) -> Option { let lines = match command { Command::Raw(cmd) => { // Reconstruct the line breaks and file formatting after the @@ -38,7 +46,7 @@ impl FloatingText { // If command is a folder, we don't display a preview Command::None => return None, }; - Some(Self::new(lines)) + Some(Self::new(lines, mode)) } fn scroll_down(&mut self) { @@ -57,8 +65,16 @@ impl FloatingText { impl FloatContent for FloatingText { fn draw(&mut self, frame: &mut Frame, area: Rect) { // Define the Block with a border and background color + let block_title = match self.mode { + FloatingTextMode::Preview => "Command Preview", + FloatingTextMode::Description => "Command Description", + }; + let block = Block::default() .borders(Borders::ALL) + .title(block_title) + .title_alignment(ratatui::layout::Alignment::Center) + .title_style(Style::default().reversed()) .style(Style::default()); // Draw the Block first @@ -68,7 +84,7 @@ impl FloatContent for FloatingText { let inner_area = block.inner(area); // Create the list of lines to be displayed - let lines: Vec = self + let mut lines: Vec = self .text .iter() .skip(self.scroll) @@ -86,6 +102,10 @@ impl FloatContent for FloatingText { .map(Line::from) .collect(); + // Prevents background text from appearing after the floating content + while lines.len() < inner_area.height as usize { + lines.push(Line::from(" ".repeat(inner_area.width as usize))); + } // Create list widget let list = List::new(lines) .block(Block::default()) diff --git a/tui/src/hint.rs b/tui/src/hint.rs index 37947159e..a1b924cd0 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -131,6 +131,7 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { hints.push(get_list_item_shortcut(state)); if state.selected_item_is_cmd() { hints.push(Shortcut::new(vec!["p"], "Enable preview")); + hints.push(Shortcut::new(vec!["d"], "Command Description")); } } hints.push(Shortcut::new(vec!["Tab"], "Focus tab list")); diff --git a/tui/src/state.rs b/tui/src/state.rs index c495e2bef..4613be182 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -1,7 +1,7 @@ use crate::{ filter::{Filter, SearchAction}, float::{Float, FloatContent}, - floating_text::FloatingText, + floating_text::{FloatingText, FloatingTextMode}, hint::{draw_shortcuts, SHORTCUT_LINES}, running_command::RunningCommand, theme::Theme, @@ -294,6 +294,7 @@ impl AppState { KeyCode::Char('j') | KeyCode::Down => self.selection.select_next(), KeyCode::Char('k') | KeyCode::Up => self.selection.select_previous(), KeyCode::Char('p') => self.enable_preview(), + KeyCode::Char('d') => self.enable_description(), KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => self.handle_enter(), KeyCode::Char('h') | KeyCode::Left => { if self.at_root() { @@ -351,6 +352,23 @@ impl AppState { } None } + fn get_selected_description(&mut self) -> Option { + let mut selected_index = self.selection.selected().unwrap_or(0); + + if !self.at_root() && selected_index == 0 { + return None; + } + if !self.at_root() { + selected_index = selected_index.saturating_sub(1); + } + + if let Some(item) = self.filter.item_list().get(selected_index) { + if !item.has_children { + return Some(item.node.description.clone()); + } + } + None + } pub fn go_to_selected_dir(&mut self) { let mut selected_index = self.selection.selected().unwrap_or(0); @@ -413,11 +431,23 @@ impl AppState { } fn enable_preview(&mut self) { if let Some(command) = self.get_selected_command() { - if let Some(preview) = FloatingText::from_command(&command) { + if let Some(preview) = FloatingText::from_command(&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_content: Vec = vec![] + .into_iter() + .chain(command_description.lines().map(|line| line.to_string())) // New line when \n is given in toml + .collect(); + + let description = FloatingText::new(description_content, FloatingTextMode::Description); + self.spawn_float(description, 80, 80); + } + } + fn handle_enter(&mut self) { if let Some(cmd) = self.get_selected_command() { let command = RunningCommand::new(cmd); From 6e477fceebf9edf686ef484ab47178ab50f2ef91 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 05:48:22 +0530 Subject: [PATCH 67/88] Update bashisms.yml (#480) --- .github/workflows/bashisms.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/bashisms.yml b/.github/workflows/bashisms.yml index 6d3510987..e667f6d23 100644 --- a/.github/workflows/bashisms.yml +++ b/.github/workflows/bashisms.yml @@ -19,9 +19,8 @@ jobs: - uses: actions/checkout@v2 - name: Install devscripts - run: sudo apt install devscripts + run: sudo apt-get update && sudo apt-get install devscripts - - name: Concatenate all .sh files and check for bashisms + - name: Check for bashisms working-directory: tabs - run: | - find . -name '*.sh' -exec checkbashisms {} + > all_scripts.sh + run: find . -name '*.sh' | xargs -P 4 -n 1 checkbashisms From 70dd8d74e55f7c0fc9401f4d27e345f386226a67 Mon Sep 17 00:00:00 2001 From: Mashruk Kabir <120426030+mashrukk@users.noreply.github.com> Date: Thu, 19 Sep 2024 00:31:54 +0000 Subject: [PATCH 68/88] cleanup (#478) --- tabs/system-setup/system-cleanup.sh | 62 +++++++++++++++++++++++++++++ tabs/system-setup/tab_data.toml | 4 ++ 2 files changed, 66 insertions(+) create mode 100644 tabs/system-setup/system-cleanup.sh diff --git a/tabs/system-setup/system-cleanup.sh b/tabs/system-setup/system-cleanup.sh new file mode 100644 index 000000000..625bc5bf4 --- /dev/null +++ b/tabs/system-setup/system-cleanup.sh @@ -0,0 +1,62 @@ +#!/bin/sh -e + +. ../common-script.sh + +cleanup_system() { + printf "%b\n" "${YELLOW}Performing system cleanup...${RC}" + case "$PACKAGER" in + apt-get|nala) + "$ESCALATION_TOOL" "$PACKAGER" clean + "$ESCALATION_TOOL" "$PACKAGER" autoremove -y + "$ESCALATION_TOOL" "$PACKAGER" autoclean + "$ESCALATION_TOOL" du -h /var/cache/apt + "$ESCALATION_TOOL" "$PACKAGER" clean + ;; + zypper) + "$ESCALATION_TOOL" "$PACKAGER" clean -a + "$ESCALATION_TOOL" "$PACKAGER" tidy + "$ESCALATION_TOOL" "$PACKAGER" cc -a + ;; + dnf) + "$ESCALATION_TOOL" "$PACKAGER" clean all + "$ESCALATION_TOOL" "$PACKAGER" autoremove -y + ;; + pacman) + "$ESCALATION_TOOL" "$PACKAGER" -Sc --noconfirm + "$ESCALATION_TOOL" "$PACKAGER" -Rns "$(pacman -Qtdq)" --noconfirm + ;; + *) + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" + return 1 + ;; + esac +} + +common_cleanup() { + "$ESCALATION_TOOL" find /var/tmp -type f -atime +5 -delete + "$ESCALATION_TOOL" find /tmp -type f -atime +5 -delete + "$ESCALATION_TOOL" find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; + "$ESCALATION_TOOL" journalctl --vacuum-time=3d +} + +clean_data() { + printf "%b\n" "${YELLOW}Clean up old cache files and empty the trash? (y/N): ${RC}" + read -r clean_response + case $clean_response in + y|Y) + printf "%b\n" "${YELLOW}Cleaning up old cache files and emptying trash...${RC}" + find "$HOME/.cache/" -type f -atime +5 -delete + find "$HOME/.local/share/Trash" -mindepth 1 -delete + printf "%b\n" "${GREEN}Cache and trash cleanup completed.${RC}" + ;; + *) + printf "%b\n" "${YELLOW}Skipping cache and trash cleanup.${RC}" + ;; + esac +} + +checkEnv +checkEscalationTool +cleanup_system +common_cleanup +clean_data diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 6d1307b49..19dd00efd 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -36,6 +36,10 @@ name = "RPM Fusion Setup" description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" script = "fedora/rpm-fusion-setup.sh" +[[data]] +name = "Full System Cleanup" +script = "system-cleanup.sh" + [[data]] name = "Full System Update" description = "This command updates your system to the latest packages available for your distro" From a32f56632598bcc9650f1f6e337896b7b3334204 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:33:54 -0400 Subject: [PATCH 69/88] Use sh shebang and source common-script (#486) Co-authored-by: nnyyxxxx --- tabs/gaming/diablo-ii/d2r-loot-filters.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tabs/gaming/diablo-ii/d2r-loot-filters.sh b/tabs/gaming/diablo-ii/d2r-loot-filters.sh index a7cd7694a..8112a995d 100755 --- a/tabs/gaming/diablo-ii/d2r-loot-filters.sh +++ b/tabs/gaming/diablo-ii/d2r-loot-filters.sh @@ -1,4 +1,6 @@ -#!/bin/bash +#!/bin/sh -e + +. ../../common-script.sh # Search for possible Diablo II Resurrected folder locations printf "%b\n" "${YELLOW}Searching for Diablo II Resurrected folders...${RC}" From f4eddd551d43ea2134b9ea19cdf39ea1a7f2695c Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:35:00 -0400 Subject: [PATCH 70/88] Change echo to printf in applications-setup (#485) Co-authored-by: nnyyxxxx Co-authored-by: Chris Titus --- tabs/applications-setup/dwmtitus-setup.sh | 2 +- tabs/applications-setup/zsh-setup.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index 98d759fb6..598a0c63e 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -271,7 +271,7 @@ install_slstatus() { read -r response # -r flag to prevent backslashes from being interpreted if [ "$response" = "y" ] || [ "$response" = "Y" ]; then printf "%b\n" "${YELLOW}Installing slstatus${RC}" - cd "$HOME/dwm-titus/slstatus" || { echo "Failed to change directory to slstatus"; return 1; } + cd "$HOME/dwm-titus/slstatus" || { printf "%b\n" "${RED}Failed to change directory to slstatus${RC}"; return 1; } if "$ESCALATION_TOOL" make clean install; then printf "%b\n" "${GREEN}slstatus installed successfully${RC}" else diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index 7100d01ba..c3577e5e8 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -21,7 +21,7 @@ installZsh() { # Function to setup zsh configuration setupZshConfig() { - echo "Setting up Zsh configuration..." + printf "%b\n" "${YELLOW}Setting up Zsh configuration...${RC}" CONFIG_DIR="$HOME/.config/zsh" ZSHRC_FILE="$CONFIG_DIR/.zshrc" From a151a15f1d289f0ec21e64db02cbd7ab3f27c6a7 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:37:59 -0400 Subject: [PATCH 71/88] Replace echos with printf in monitor-control (#481) Co-authored-by: nnyyxxxx --- .../monitor-control/auto_detect_displays.sh | 9 +++---- tabs/utils/monitor-control/set_brightness.sh | 12 ++++----- tabs/utils/monitor-control/set_resolutions.sh | 2 +- .../monitor-control/utility_functions.sh | 25 ++++++++----------- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/tabs/utils/monitor-control/auto_detect_displays.sh b/tabs/utils/monitor-control/auto_detect_displays.sh index 175ed4dda..c72d23b32 100755 --- a/tabs/utils/monitor-control/auto_detect_displays.sh +++ b/tabs/utils/monitor-control/auto_detect_displays.sh @@ -18,8 +18,8 @@ auto_detect_displays() { temp_common_resolutions=$(mktemp) temp_resolutions=$(mktemp) - echo "$common_resolutions" > "$temp_common_resolutions" - echo "$resolutions" > "$temp_resolutions" + printf "%s" "$common_resolutions" > "$temp_common_resolutions" + printf "%s" "$resolutions" > "$temp_resolutions" common_resolutions=$(comm -12 "$temp_common_resolutions" "$temp_resolutions") @@ -27,14 +27,13 @@ auto_detect_displays() { done if [ -z "$common_resolutions" ]; then - echo "No common resolution found among connected monitors." + printf "%b\n" "${RED}No common resolution found among connected monitors.${RC}" return - fi highest_resolution=$(echo "$common_resolutions" | sort -n -t'x' -k1,1 -k2,2 | tail -n 1) for monitor in $monitors; do - echo "Setting resolution for $monitor to $highest_resolution" + printf "%b\n" "${YELLOW}Setting resolution for $monitor to $highest_resolution...${RC}" execute_command "xrandr --output $monitor --mode $highest_resolution" done fi diff --git a/tabs/utils/monitor-control/set_brightness.sh b/tabs/utils/monitor-control/set_brightness.sh index 16f3da3b6..ab97b70a0 100644 --- a/tabs/utils/monitor-control/set_brightness.sh +++ b/tabs/utils/monitor-control/set_brightness.sh @@ -20,7 +20,7 @@ adjust_monitor_brightness() { count=$((count + 1)) done - echo "Enter the number of the monitor (or 'q' to quit): " + printf "Enter the number of the monitor (or 'q' to quit): " read monitor_choice if [ "$monitor_choice" = "q" ]; then @@ -29,15 +29,15 @@ adjust_monitor_brightness() { fi if ! echo "$monitor_choice" | grep -qE '^[0-9]+$'; then - echo "Invalid selection. Please try again." - echo "Press [Enter] to continue..." + printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" + printf "Press [Enter] to continue..." read dummy continue fi if [ "$monitor_choice" -lt 1 ] || [ "$monitor_choice" -gt "$#" ]; then printf "%b\n" "${RED}Invalid selection. Please try again.${RC}" - echo "Press [Enter] to continue..." + printf "Press [Enter] to continue..." read dummy continue fi @@ -50,7 +50,7 @@ adjust_monitor_brightness() { printf "%b\n" "${YELLOW}Current brightness for $monitor_name${RC}: ${GREEN}$current_brightness_percentage%${RC}" while true; do - echo "Enter the new brightness value as a percentage (10 to 100, or 'q' to quit): " + printf "Enter the new brightness value as a percentage (10 to 100, or 'q' to quit): " read new_brightness_percentage if [ "$new_brightness_percentage" = "q" ]; then @@ -67,7 +67,7 @@ adjust_monitor_brightness() { # Convert percentage to xrandr brightness value (10% to 0.10) new_brightness=$(awk "BEGIN {printf \"%.2f\", $new_brightness_percentage / 100}") - echo "Set brightness for $monitor_name to $new_brightness_percentage%? (y/n): " + printf "Set brightness for $monitor_name to $new_brightness_percentage%? (y/n): " read confirm if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then printf "%b\n" "${GREEN}Setting brightness for $monitor_name to $new_brightness_percentage%${RC}" diff --git a/tabs/utils/monitor-control/set_resolutions.sh b/tabs/utils/monitor-control/set_resolutions.sh index 4772b163d..85d7e0cb5 100755 --- a/tabs/utils/monitor-control/set_resolutions.sh +++ b/tabs/utils/monitor-control/set_resolutions.sh @@ -41,7 +41,7 @@ set_resolutions() { resolutions=$(get_unique_resolutions "$monitor_name" | sort -rn -t'x' -k1,1 -k2,2) temp_res_file=$(mktemp) - echo "$resolutions" | awk '{print NR " " $0}' > "$temp_res_file" + printf "%b\n" "$resolutions" | awk '{print NR " " $0}' > "$temp_res_file" i=1 while read -r resolution; do diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index c1d01be79..5bccd94da 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -4,7 +4,7 @@ # Function to check xrandr is installed setup_xrandr() { - echo "Install xrandr if not already installed..." + printf "%b\n" "${YELLOW}Installing xrandr...${RC}" if ! command_exists xrandr; then case "$PACKAGER" in pacman) @@ -18,24 +18,24 @@ setup_xrandr() { ;; esac else - echo "xrandr is already installed." + printf "%b\n" "${GREEN}xrandr is already installed.${RC}" fi } # Function to execute xrandr commands and handle errors execute_command() { command="$1" - echo "Executing: $command" + printf "Executing: %s\n" "$command" eval "$command" 2>&1 | tee /tmp/xrandr.log | tail -n 20 if [ $? -ne 0 ]; then - echo "An error occurred while executing the command. Check /tmp/xrandr.log for details." + printf "%b\n" "${RED}An error occurred while executing the command. Check /tmp/xrandr.log for details.${RC}" fi } # Function to detect connected monitors detect_connected_monitors() { xrandr_output=$(xrandr) - echo "$xrandr_output" | grep " connected" | awk '{print $1}' + printf "%s\n" "$xrandr_output" | grep " connected" | awk '{print $1}' } # Function to get the current brightness for a monitor @@ -48,31 +48,26 @@ get_current_brightness() { get_unique_resolutions() { monitor="$1" xrandr_output=$(xrandr) - # Get available resolutions from xrandr without line limit - available_resolutions=$(echo "$xrandr_output" | sed -n "/$monitor connected/,/^[^ ]/p" | grep -oP '\d+x\d+' | sort -u) + available_resolutions=$(printf "%s" "$xrandr_output" | sed -n "/$monitor connected/,/^[^ ]/p" | grep -oP '\d+x\d+' | sort -u) - # Define standard resolutions standard_resolutions="1920x1080 1280x720 1600x900 2560x1440 3840x2160" temp_file=$(mktemp) - echo "$available_resolutions" > "$temp_file" + printf "%s" "$available_resolutions" > "$temp_file" - # Filter standard resolutions to include only those available for the monitor - filtered_standard_resolutions=$(echo "$standard_resolutions" | tr ' ' '\n' | grep -xF -f "$temp_file") + filtered_standard_resolutions=$(printf "%s" "$standard_resolutions" | tr ' ' '\n' | grep -xF -f "$temp_file") rm "$temp_file" available_res_file=$(mktemp) filtered_standard_res_file=$(mktemp) - echo "$available_resolutions" | sort > "$available_res_file" - echo "$filtered_standard_resolutions" | sort > "$filtered_standard_res_file" + printf "%s" "$available_resolutions" | sort > "$available_res_file" + printf "%s" "$filtered_standard_resolutions" | sort > "$filtered_standard_res_file" - # Get remaining available resolutions (excluding standard ones) remaining_resolutions=$(comm -23 "$available_res_file" "$filtered_standard_res_file") rm "$available_res_file" "$filtered_standard_res_file" - # Combine filtered standard resolutions and remaining resolutions, and limit to 10 results printf "%b\n" "$filtered_standard_resolutions\n$remaining_resolutions" | head -n 10 } From b62b14da31e39c249ecaf241194e449222dc8d9d Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:39:03 -0400 Subject: [PATCH 72/88] Replace echos with printf and general improvements (#482) Co-authored-by: nnyyxxxx Co-authored-by: Chris Titus --- tabs/common-script.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 84ff660d7..769ae905a 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -20,13 +20,13 @@ checkAURHelper() { for helper in ${AUR_HELPERS}; do if command_exists "${helper}"; then AUR_HELPER=${helper} - echo "Using ${helper} as AUR helper" + printf "Using ${helper} as AUR helper" AUR_HELPER_CHECKED=true return 0 fi done - echo "Installing yay as AUR helper..." + printf "%b\n" "${YELLOW}Installing yay as AUR helper...${RC}" "$ESCALATION_TOOL" "$PACKAGER" -S --needed --noconfirm base-devel cd /opt && "$ESCALATION_TOOL" git clone https://aur.archlinux.org/yay-bin.git && "$ESCALATION_TOOL" chown -R "$USER":"$USER" ./yay-bin cd yay-bin && makepkg --noconfirm -si @@ -49,7 +49,7 @@ checkEscalationTool() { for tool in ${ESCALATION_TOOLS}; do if command_exists "${tool}"; then ESCALATION_TOOL=${tool} - echo "Using ${tool} for privilege escalation" + printf "Using ${tool} for privilege escalation" ESCALATION_TOOL_CHECKED=true return 0 fi @@ -65,7 +65,7 @@ checkCommandRequirements() { REQUIREMENTS=$1 for req in ${REQUIREMENTS}; do if ! command_exists "${req}"; then - echo "${RED}To run me, you need: ${REQUIREMENTS}${RC}" + printf "%b\n" "${RED}To run me, you need: ${REQUIREMENTS}${RC}" exit 1 fi done @@ -77,7 +77,7 @@ checkPackageManager() { for pgm in ${PACKAGEMANAGER}; do if command_exists "${pgm}"; then PACKAGER=${pgm} - echo "Using ${pgm}" + printf "Using ${pgm}" break fi done @@ -94,14 +94,14 @@ checkSuperUser() { for sug in ${SUPERUSERGROUP}; do if groups | grep -q "${sug}"; then SUGROUP=${sug} - echo "Super user group ${SUGROUP}" + printf "Super user group ${SUGROUP}" break fi done ## Check if member of the sudo group. if ! groups | grep -q "${SUGROUP}"; then - echo "${RED}You need to be a member of the sudo group to run me!${RC}" + printf "%b\n" "${RED}You need to be a member of the sudo group to run me!${RC}" exit 1 fi } @@ -110,7 +110,7 @@ checkCurrentDirectoryWritable() { ## Check if the current directory is writable. GITPATH="$(dirname "$(realpath "$0")")" if [ ! -w "$GITPATH" ]; then - echo "${RED}Can't write to $GITPATH${RC}" + printf "%b\n" "${RED}Can't write to $GITPATH${RC}" exit 1 fi } From 41817c333c4d5cdfe701b3a6c79f51b2c50727b0 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:40:05 -0400 Subject: [PATCH 73/88] Replace echos with printf in system-setup (#483) Co-authored-by: nnyyxxxx Co-authored-by: Chris Titus --- tabs/system-setup/5-samba-ssh-setup.sh | 8 ++++---- tabs/system-setup/6-docker-setup.sh | 2 +- tabs/system-setup/arch/paru-setup.sh | 8 ++++---- tabs/system-setup/arch/yay-setup.sh | 8 ++++---- tabs/system-setup/fedora/rpm-fusion-setup.sh | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tabs/system-setup/5-samba-ssh-setup.sh b/tabs/system-setup/5-samba-ssh-setup.sh index ddd43c994..7e22f2624 100755 --- a/tabs/system-setup/5-samba-ssh-setup.sh +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -86,20 +86,20 @@ setup_samba() { $ESCALATION_TOOL chmod -R 0777 "$SHARED_DIR" # Add a new Samba user - echo "Enter Samba username: " + printf "Enter Samba username: " read -r SAMBA_USER # Loop until the passwords match while true; do - echo "Enter Samba password: " + printf "Enter Samba password: " stty -echo read -r SAMBA_PASSWORD stty echo - echo "Confirm Samba password: " + printf "Confirm Samba password: " stty -echo read SAMBA_PASSWORD_CONFIRM stty echo - echo "" + printf "\n" if [ "$SAMBA_PASSWORD" = "$SAMBA_PASSWORD_CONFIRM" ]; then printf "%b\n" "${GREEN}Passwords match.${RC}" break diff --git a/tabs/system-setup/6-docker-setup.sh b/tabs/system-setup/6-docker-setup.sh index 43e8a5079..6a5a14d3a 100755 --- a/tabs/system-setup/6-docker-setup.sh +++ b/tabs/system-setup/6-docker-setup.sh @@ -16,7 +16,7 @@ choose_installation() { 1) INSTALL_DOCKER=1; INSTALL_COMPOSE=0 ;; 2) INSTALL_DOCKER=0; INSTALL_COMPOSE=1 ;; 3) INSTALL_DOCKER=1; INSTALL_COMPOSE=1 ;; - *) echo "Invalid choice. Exiting."; exit 1 ;; + *) printf "%b\n" "${RED}Invalid choice. Exiting.${RC}"; exit 1 ;; esac } diff --git a/tabs/system-setup/arch/paru-setup.sh b/tabs/system-setup/arch/paru-setup.sh index 490935157..05b78c80c 100755 --- a/tabs/system-setup/arch/paru-setup.sh +++ b/tabs/system-setup/arch/paru-setup.sh @@ -6,17 +6,17 @@ installDepend() { case "$PACKAGER" in pacman) if ! command_exists paru; then - echo "Installing paru as AUR helper..." + printf "%b\n" "${YELLOW}Installing paru as AUR helper...${RC}" $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/paru.git && $ESCALATION_TOOL chown -R "$USER": ./paru cd paru && makepkg --noconfirm -si - echo "Paru installed" + printf "%b\n" "${GREEN}Paru installed${RC}" else - echo "Paru already installed" + printf "%b\n" "${GREEN}Paru already installed${RC}" fi ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" ;; esac } diff --git a/tabs/system-setup/arch/yay-setup.sh b/tabs/system-setup/arch/yay-setup.sh index 4fd561736..f7f9fa6aa 100755 --- a/tabs/system-setup/arch/yay-setup.sh +++ b/tabs/system-setup/arch/yay-setup.sh @@ -6,17 +6,17 @@ installDepend() { case "$PACKAGER" in pacman) if ! command_exists yay; then - echo "Installing yay as AUR helper..." + printf "%b\n" "${YELLOW}Installing yay as AUR helper...${RC}" $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm base-devel cd /opt && $ESCALATION_TOOL git clone https://aur.archlinux.org/yay-bin.git && $ESCALATION_TOOL chown -R "$USER": ./yay-bin cd yay-bin && makepkg --noconfirm -si - echo "Yay installed" + printf "%b\n" "${GREEN}Yay installed${RC}" else - echo "Aur helper already installed" + printf "%b\n" "${GREEN}Aur helper already installed${RC}" fi ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" ;; esac } diff --git a/tabs/system-setup/fedora/rpm-fusion-setup.sh b/tabs/system-setup/fedora/rpm-fusion-setup.sh index 7fb052ea4..e73bc0013 100644 --- a/tabs/system-setup/fedora/rpm-fusion-setup.sh +++ b/tabs/system-setup/fedora/rpm-fusion-setup.sh @@ -8,16 +8,16 @@ installRPMFusion() { case "$PACKAGER" in dnf) if [ ! -e /etc/yum.repos.d/rpmfusion-free.repo ] || [ ! -e /etc/yum.repos.d/rpmfusion-nonfree.repo ]; then - echo "Installing RPM Fusion..." + printf "%b\n" "${YELLOW}Installing RPM Fusion...${RC}" "$ESCALATION_TOOL" "$PACKAGER" install https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm "$ESCALATION_TOOL" "$PACKAGER" config-manager --enable fedora-cisco-openh264 - echo "RPM Fusion installed" + printf "%b\n" "${GREEN}RPM Fusion installed${RC}" else - echo "RPM Fusion already installed" + printf "%b\n" "${GREEN}RPM Fusion already installed${RC}" fi ;; *) - echo "Unsupported distribution: $DTYPE" + printf "%b\n" "${RED}Unsupported distribution: $DTYPE${RC}" ;; esac } From eb4cca8946535e6a0656e3de43d553af0413dce7 Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:40:25 -0400 Subject: [PATCH 74/88] Change echo to printf in gaming and security (#484) Co-authored-by: nnyyxxxx --- tabs/gaming/diablo-ii/d2r-loot-filters.sh | 23 ++++++++++------------- tabs/security/firewall-baselines.sh | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tabs/gaming/diablo-ii/d2r-loot-filters.sh b/tabs/gaming/diablo-ii/d2r-loot-filters.sh index 8112a995d..9534108d1 100755 --- a/tabs/gaming/diablo-ii/d2r-loot-filters.sh +++ b/tabs/gaming/diablo-ii/d2r-loot-filters.sh @@ -12,7 +12,7 @@ if [ -z "$possible_paths" ]; then fi # Display possible paths and allow selection -echo "Possible Diablo II Resurrected folder locations:" +printf "%b\n" "${YELLOW}Possible Diablo II Resurrected folder locations:${RC}" mapfile -t paths_array <<< "$possible_paths" selected=0 total=${#paths_array[@]} @@ -77,7 +77,7 @@ select_path # Validate the path if [ ! -d "$d2r_path" ]; then - echo "Error: The specified path does not exist." + printf "%b\n" "${RED}Error: The specified path does not exist.${RC}" exit 1 fi @@ -98,14 +98,11 @@ rm /tmp/lootfilter.zip printf "%b\n" "${GREEN}Loot filter installed successfully in $mods_path${RC}" -# Add instructions for setting launch options -echo -echo "To complete the setup, please follow these steps to add launch options in Battle.net:" -echo "1. Open the Battle.net launcher" -echo "2. Select Diablo II: Resurrected" -echo "3. Click the gear icon next to the 'Play' button" -echo "4. Select 'Game Settings'" -echo "5. In the 'Additional command line arguments' field, enter: -mod lootfilter -txt" -echo "6. Click 'Done' to save the changes" -echo -echo "After completing these steps, launch Diablo II: Resurrected through Battle.net to use the loot filter." \ No newline at end of file +printf "\nTo complete the setup, please follow these steps to add launch options in Battle.net:\n" +printf "1. Open the Battle.net launcher\n" +printf "2. Select Diablo II: Resurrected\n" +printf "3. Click the gear icon next to the 'Play' button\n" +printf "4. Select 'Game Settings'\n" +printf "5. In the 'Additional command line arguments' field, enter: -mod lootfilter -txt\n" +printf "6. Click 'Done' to save the changes\n" +printf "\nAfter completing these steps, launch Diablo II: Resurrected through Battle.net to use the loot filter.\n" \ No newline at end of file diff --git a/tabs/security/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 196428be5..2f7a2529c 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -3,7 +3,7 @@ . ../common-script.sh installPkg() { - echo "Installing UFW..." + printf "%b\n" "${YELLOW}Installing UFW...${RC}" if ! command_exists ufw; then case "$PACKAGER" in pacman) @@ -14,7 +14,7 @@ installPkg() { ;; esac else - echo "UFW is already installed." + printf "%b\n" "${GREEN}UFW is already installed${RC}" fi } From 533204902aeb3b3715fda9d55c408d936afc9a1b Mon Sep 17 00:00:00 2001 From: Nyx <144965845+nnyyxxxx@users.noreply.github.com> Date: Wed, 18 Sep 2024 20:41:38 -0400 Subject: [PATCH 75/88] Update preview (#487) Co-authored-by: nnyyxxxx --- docs/assets/preview.png | Bin 34662 -> 67792 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/assets/preview.png b/docs/assets/preview.png index de4b54e387349076fdf4e3f403d15b7755a03cd6..bb8b7037901bee6f17cc42172a4d03153b233914 100644 GIT binary patch literal 67792 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

|*d~W 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 literal 34662 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 From 97576d2087ec15ef9121ed5d836f30804f9ca906 Mon Sep 17 00:00:00 2001 From: Angaddeep Singh Date: Thu, 19 Sep 2024 07:04:27 +0530 Subject: [PATCH 76/88] Added DNF configuration and Multimedia Support for fedora and other Redhat Distros (#438) * First commit * Small enhancements * Update configure-dnf.sh * update * Update configure-dnf.sh * update * Update multimedia-codecs.sh * Update multimedia-codecs.sh --- tabs/system-setup/fedora/configure-dnf.sh | 23 ++++++++++++++++ tabs/system-setup/fedora/multimedia-codecs.sh | 26 +++++++++++++++++++ tabs/system-setup/fedora/rpm-fusion-setup.sh | 1 + tabs/system-setup/tab_data.toml | 8 ++++++ 4 files changed, 58 insertions(+) create mode 100644 tabs/system-setup/fedora/configure-dnf.sh create mode 100644 tabs/system-setup/fedora/multimedia-codecs.sh diff --git a/tabs/system-setup/fedora/configure-dnf.sh b/tabs/system-setup/fedora/configure-dnf.sh new file mode 100644 index 000000000..af460545a --- /dev/null +++ b/tabs/system-setup/fedora/configure-dnf.sh @@ -0,0 +1,23 @@ +#!/bin/sh -e + +. ../../common-script.sh + +configureDNF() { + case $PACKAGER in + dnf) + printf "%b\n" ${YELLOW}"Configuring DNF...${RC}" + $ESCALATION_TOOL sed -i '/^max_parallel_downloads=/c\max_parallel_downloads=10' /etc/dnf/dnf.conf || echo 'max_parallel_downloads=10' >> /etc/dnf/dnf.conf + echo "fastestmirror=True" | $ESCALATION_TOOL tee -a /etc/dnf/dnf.conf > /dev/null + echo "defaultyes=True" | $ESCALATION_TOOL tee -a /etc/dnf/dnf.conf > /dev/null + $ESCALATION_TOOL "$PACKAGER" -y install dnf-plugins-core + printf "%b\n" "${GREEN}DNF Configured Succesfully...${RC}" + ;; + *) + printf "%b\n" "${RED}Unsupported distribution: $DTYPE${RC}" + ;; + esac +} + +checkEnv +checkEscalationTool +configureDNF diff --git a/tabs/system-setup/fedora/multimedia-codecs.sh b/tabs/system-setup/fedora/multimedia-codecs.sh new file mode 100644 index 000000000..a5db96a79 --- /dev/null +++ b/tabs/system-setup/fedora/multimedia-codecs.sh @@ -0,0 +1,26 @@ +#!/bin/sh -e + +. ../../common-script.sh + +multimedia() { + case $PACKAGER in + dnf) + if [ -e /etc/yum.repos.d/rpmfusion-free.repo ] && [ -e /etc/yum.repos.d/rpmfusion-nonfree.repo ]; then + printf "%b\n" "${YELLOW}Installing Multimedia Codecs...${RC}" + $ESCALATION_TOOL "$PACKAGER" swap ffmpeg-free ffmpeg --allowerasing -y + $ESCALATION_TOOL "$PACKAGER" update @multimedia --setopt="install_weak_deps=False" --exclude=PackageKit-gstreamer-plugin -y + $ESCALATION_TOOL "$PACKAGER" update @sound-and-video -y + printf "%b\n" "${GREEN}Multimedia Codecs Installed...${RC}" + else + printf "%b\n" "${RED}RPM Fusion repositories not found. Please set up RPM Fusion first!${RC}" + fi + ;; + *) + printf "%b\n" "${RED}Unsupported distribution: $DTYPE${RC}" + ;; + esac +} + +checkEnv +checkEscalationTool +multimedia \ No newline at end of file diff --git a/tabs/system-setup/fedora/rpm-fusion-setup.sh b/tabs/system-setup/fedora/rpm-fusion-setup.sh index e73bc0013..d8b0e2ace 100644 --- a/tabs/system-setup/fedora/rpm-fusion-setup.sh +++ b/tabs/system-setup/fedora/rpm-fusion-setup.sh @@ -23,4 +23,5 @@ installRPMFusion() { } checkEnv +checkEscalationTool installRPMFusion diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 19dd00efd..178a5680e 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -36,6 +36,14 @@ name = "RPM Fusion Setup" description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" script = "fedora/rpm-fusion-setup.sh" +[[data.entries]] +name = "Configure DNF" +script = "fedora/configure-dnf.sh" + +[[data.entries]] +name = "Multimedia Setup" +script = "fedora/multimedia-codecs.sh" + [[data]] name = "Full System Cleanup" script = "system-cleanup.sh" From 67a19b06e89b3911c2c25bd568caf9738e2967fb Mon Sep 17 00:00:00 2001 From: Guru Swarupa <112751363+guruswarupa@users.noreply.github.com> Date: Thu, 19 Sep 2024 07:06:51 +0530 Subject: [PATCH 77/88] encrypt decrypt files and dir script (#399) Co-authored-by: Chris Titus --- tabs/utils/encrypt_decrypt_tool.sh | 155 +++++++++++++++++++++++++++++ tabs/utils/tab_data.toml | 4 + 2 files changed, 159 insertions(+) create mode 100644 tabs/utils/encrypt_decrypt_tool.sh diff --git a/tabs/utils/encrypt_decrypt_tool.sh b/tabs/utils/encrypt_decrypt_tool.sh new file mode 100644 index 000000000..48945b717 --- /dev/null +++ b/tabs/utils/encrypt_decrypt_tool.sh @@ -0,0 +1,155 @@ +#!/bin/sh -e + +. ../common-script.sh +# Function to display the menu +printf "%b\n" "${YELLOW}Ensuring OpenSSL is installed...${RC}" + +# Install OpenSSL +if ! command_exists openssl; then + case $PACKAGER in + pacman) + $ESCALATION_TOOL ${PACKAGER} -Syu --noconfirm openssl + ;; + apt-get) + $ESCALATION_TOOL ${PACKAGER} update && $ESCALATION_TOOL ${PACKAGER} install -y openssl + ;; + dnf) + $ESCALATION_TOOL ${PACKAGER} install -y openssl + ;; + zypper) + $ESCALATION_TOOL ${PACKAGER} install openssl + ;; + *) + printf "%b\n" "${RED}Your Linux distribution is not supported by this script.${RC}" + printf "%b\n" "${YELLOW}You can try installing OpenSSL manually:${RC}" + echo "1. Refer to your distribution's documentation." + ;; + esac +fi + +show_menu() { + echo "========================================================" + echo " File/Directory Encryption/Decryption" + echo "========================================================" + echo "How to use:-" + echo "if you encrypt or decrypt a file include new file name for successful operation" + echo "if you encrypt or decrypt a folder include new directory name for successful operation" + echo "========================================================" + echo "1. Encrypt a file or directory" + echo "2. Decrypt a file or directory" + echo "3. Exit" + echo "========================================================" +} + +# Function to encrypt a file +encrypt_file() { + echo "Enter the path to the file or directory to encrypt:" + read -r INPUT_PATH + + if [ ! -e "$INPUT_PATH" ]; then + echo "Path does not exist!" + return + fi + + echo "Enter the path for the encrypted file or directory:" + read -r OUTPUT_PATH + + echo "Enter the encryption password:" + read -s -r PASSWORD + + if [ -d "$INPUT_PATH" ]; then + # Encrypt each file in the directory + find "$INPUT_PATH" -type f | while read -r FILE; do + REL_PATH="${FILE#$INPUT_PATH/}" + OUTPUT_FILE="$OUTPUT_PATH/$REL_PATH.enc" + mkdir -p "$(dirname "$OUTPUT_FILE")" + openssl enc -aes-256-cbc -salt -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD" + if [ $? -eq 0 ]; then + echo "Encrypted: $OUTPUT_FILE" + else + echo "Failed to encrypt: $FILE" + fi + done + else + # Encrypt a single file + if [ -d "$OUTPUT_PATH" ]; then + echo "Output path must be a file for single file encryption." + return + fi + mkdir -p "$(dirname "$OUTPUT_PATH")" + openssl enc -aes-256-cbc -salt -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD" + if [ $? -eq 0 ]; then + echo "Encrypted: $OUTPUT_PATH" + else + echo "Failed to encrypt: $INPUT_PATH" + fi + fi +} + +# Function to decrypt a file +decrypt_file() { + echo "Enter the path to the file or directory to decrypt:" + read -r INPUT_PATH + + if [ ! -e "$INPUT_PATH" ]; then + echo "Path does not exist!" + return + fi + + echo "Enter the path for the decrypted file or directory:" + read -r OUTPUT_PATH + + echo "Enter the decryption password:" + read -s -r PASSWORD + + if [ -d "$INPUT_PATH" ]; then + # Decrypt each file in the directory + find "$INPUT_PATH" -type f -name '*.enc' | while read -r FILE; do + REL_PATH="${FILE#$INPUT_PATH/}" + OUTPUT_FILE="$OUTPUT_PATH/${REL_PATH%.enc}" + mkdir -p "$(dirname "$OUTPUT_FILE")" + openssl enc -aes-256-cbc -d -pbkdf2 -in "$FILE" -out "$OUTPUT_FILE" -k "$PASSWORD" + if [ $? -eq 0 ]; then + echo "Decrypted: $OUTPUT_FILE" + else + echo "Failed to decrypt: $FILE" + fi + done + else + # Decrypt a single file + if [ -d "$OUTPUT_PATH" ]; then + echo "Output path must be a file for single file decryption." + return + fi + mkdir -p "$(dirname "$OUTPUT_PATH")" + openssl enc -aes-256-cbc -d -pbkdf2 -in "$INPUT_PATH" -out "$OUTPUT_PATH" -k "$PASSWORD" + if [ $? -eq 0 ]; then + echo "Decrypted: $OUTPUT_PATH" + else + echo "Failed to decrypt: $INPUT_PATH" + fi + fi +} + +main(){ + clear + while true; do + show_menu + echo "Enter your choice:" + read -r CHOICE + + case $CHOICE in + 1) encrypt_file ;; + 2) decrypt_file ;; + 3) echo "Exiting..."; exit 0 ;; + *) echo "Invalid choice. Please try again." ;; + esac + + echo "Press [Enter] to continue..." + read -r + done +} + +checkEnv +checkEscalationTool +main \ No newline at end of file diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 2ccec8b9c..012ec3413 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -15,6 +15,10 @@ name = "Numlock on Startup" description = "This utility is designed to configure auto enabling of numlock on boot" script = "numlock.sh" +[[data]] +name = "Crypto tool" +script = "encrypt_decrypt_tool.sh" + [[data]] name = "Ollama" description = "This utility is designed to manage ollama in your system" From 7640a99062642c8bb4defebf95a4f325d387c0ca Mon Sep 17 00:00:00 2001 From: Angaddeep Singh Date: Thu, 19 Sep 2024 07:14:33 +0530 Subject: [PATCH 78/88] Added Virtualization Setup for Fedora (#395) * Added Virtualization Setup * Space FIx * small fix fix * Update virtualization.sh * Update virtualization.sh --------- Co-authored-by: Chris Titus --- tabs/system-setup/fedora/virtualization.sh | 21 +++++++++++++++++++++ tabs/system-setup/tab_data.toml | 16 +++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 tabs/system-setup/fedora/virtualization.sh diff --git a/tabs/system-setup/fedora/virtualization.sh b/tabs/system-setup/fedora/virtualization.sh new file mode 100644 index 000000000..35a72b7d0 --- /dev/null +++ b/tabs/system-setup/fedora/virtualization.sh @@ -0,0 +1,21 @@ +#!/bin/sh -e + +. ../../common-script.sh + +# Install virtualization tools to enable virtual machines +configureVirtualization() { + case $PACKAGER in + dnf) + printf "%b\n" ${YELLOW}"Installing virtualization tools...${RC}" + $ESCALATION_TOOL "$PACKAGER" install -y @virtualization + printf "%b\n" "${GREEN}Installed virtualization tools...${RC}" + ;; + *) + printf "%b\n" "${RED}Unsupported distribution: $DTYPE${RC}" + ;; + esac +} + +checkEnv +checkEscalationTool +configureVirtualization diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 178a5680e..7565c1481 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -31,19 +31,25 @@ matches = true data = "command_exists" values = ["dnf"] -[[data.entries]] -name = "RPM Fusion Setup" -description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" -script = "fedora/rpm-fusion-setup.sh" - [[data.entries]] name = "Configure DNF" +description = "Optimizes DNF for parallel downloads" script = "fedora/configure-dnf.sh" [[data.entries]] name = "Multimedia Setup" script = "fedora/multimedia-codecs.sh" +[[data.entries]] +name = "RPM Fusion Setup" +description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" +script = "fedora/rpm-fusion-setup.sh" + +[[data.entries]] +name = "Virtualization Setup" +description = "Enables Virtualization through dnf" +script = "fedora/virtualization.sh" + [[data]] name = "Full System Cleanup" script = "system-cleanup.sh" From 265fbbbd54cd359bfbea3678c6e8d868f3157a24 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 07:16:41 +0530 Subject: [PATCH 79/88] Fix bug (#394) --- tabs/common-script.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tabs/common-script.sh b/tabs/common-script.sh index 769ae905a..d0c0c4705 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -9,7 +9,7 @@ CYAN='\033[36m' GREEN='\033[32m' command_exists() { - which "$1" >/dev/null 2>&1 + command -v "$1" >/dev/null 2>&1 } checkAURHelper() { From f64fa2bd1251280d148379e06d09800aca0a7fe4 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 07:18:42 +0530 Subject: [PATCH 80/88] feat: Add User Manager (#393) * Add User Control Panel * Fix non posix * Split script * Update userguide.md * Update utility_functions.sh * Remove clear * Add checkEnv --- docs/userguide.md | 8 ++ tabs/utils/tab_data.toml | 25 ++++- .../user-account-manager/add_to_group.sh | 35 ++++++ tabs/utils/user-account-manager/add_user.sh | 26 +++++ .../user-account-manager/change_password.sh | 19 ++++ .../utils/user-account-manager/delete_user.sh | 26 +++++ .../user-account-manager/remove_from_group.sh | 30 ++++++ .../user-account-manager/utility_functions.sh | 100 ++++++++++++++++++ 8 files changed, 268 insertions(+), 1 deletion(-) create mode 100755 tabs/utils/user-account-manager/add_to_group.sh create mode 100755 tabs/utils/user-account-manager/add_user.sh create mode 100755 tabs/utils/user-account-manager/change_password.sh create mode 100755 tabs/utils/user-account-manager/delete_user.sh create mode 100755 tabs/utils/user-account-manager/remove_from_group.sh create mode 100755 tabs/utils/user-account-manager/utility_functions.sh diff --git a/docs/userguide.md b/docs/userguide.md index 8fc385f58..57af97e10 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -30,3 +30,11 @@ ## Security Features - **Firewall Baselines**: Sets up firewall rules. + +## Utilities + +- **Monitor Control**: Controls monitor settings on X11. +- **Bluetooth Control**: Controls Bluetooth settings. +- **Wifi Control**: Controls WiFi settings. +- **Numlock Control**: Sets up Numlock on boot. +- **User Account Manager**: Manage users and groups. diff --git a/tabs/utils/tab_data.toml b/tabs/utils/tab_data.toml index 012ec3413..d09496ff5 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -112,4 +112,27 @@ matches = true [[data.entries]] name = "Set Brightness" script = "monitor-control/set_brightness.sh" -matches = true \ No newline at end of file +matches = true + +[[data]] +name = "User Account Manager" + +[[data.entries]] +name = "Add User" +script = "user-account-manager/add_user.sh" + +[[data.entries]] +name = "Change Password" +script = "user-account-manager/change_password.sh" + +[[data.entries]] +name = "Delete User" +script = "user-account-manager/delete_user.sh" + +[[data.entries]] +name = "Add User To Groups" +script = "user-account-manager/add_to_group.sh" + +[[data.entries]] +name = "Remove User From Groups" +script = "user-account-manager/remove_from_group.sh" \ No newline at end of file diff --git a/tabs/utils/user-account-manager/add_to_group.sh b/tabs/utils/user-account-manager/add_to_group.sh new file mode 100755 index 000000000..dd8a2a743 --- /dev/null +++ b/tabs/utils/user-account-manager/add_to_group.sh @@ -0,0 +1,35 @@ +#!/bin/sh -e + +. ../../common-script.sh +. ./utility_functions.sh + +clear +printf "%b\n" "${YELLOW}Add to group${RC}" +printf "%b\n" "${YELLOW}=================${RC}" + +username=$(promptUsername "" "non-root") || exit 1 +user_groups=$(groups "$username" | cut -d: -f2 | sort | tr '\n' ' ') + +printf "%b\n" "${YELLOW}Groups user $username is in:${RC} $user_groups" +printf "%b\n" "${YELLOW}=================${RC}" + +available_groups=$(cut -d: -f1 /etc/group | sort | tr '\n' ' ') + +printf "%b\n" "${YELLOW}Available groups:${RC} $available_groups" +printf "%b\n" "${YELLOW}=================${RC}" + +read -p "Enter the groups you want to add user $username to (space-separated): " groups + +checkEmpty "$groups" || exit 1 +checkGroupAvailabe "$groups" "$available_groups" || exit 1 + +groups_to_add=$(echo "$groups" | tr ' ' ',') + +read -p "Are you sure you want to add user $username to $groups_to_add? [Y/N]: " confirm +confirmAction || exit 1 + +$ESCALATION_TOOL usermod -aG $groups_to_add "$username" + +printf "%b\n" "${GREEN}User successfully added to the $groups_to_add${RC}" + +checkEnv \ No newline at end of file diff --git a/tabs/utils/user-account-manager/add_user.sh b/tabs/utils/user-account-manager/add_user.sh new file mode 100755 index 000000000..83f31ca44 --- /dev/null +++ b/tabs/utils/user-account-manager/add_user.sh @@ -0,0 +1,26 @@ +#!/bin/sh -e + +. ../../common-script.sh +. ./utility_functions.sh + +clear +printf "%b\n" "${YELLOW}Create a new user${RC}" +printf "%b\n" "${YELLOW}=================${RC}" + +username=$(promptUsername "add" "non-root") || exit 1 + +# Check if username is valid +if ! echo "$username" | grep '^[a-z][-a-z0-9_]*$' > /dev/null; then + printf "%b\n" "${RED}Username must only contain letters, numbers, hyphens, and underscores. It cannot start with a number or contain spaces.${RC}" + exit 1 +fi + +password=$(promptPassword) || exit 1 + +$ESCALATION_TOOL useradd -m "$username" -g users -s /bin/bash +echo "$username:$password" | $ESCALATION_TOOL chpasswd + +printf "%b\n" "${GREEN}User $username created successfully${RC}" +printf "%b\n" "${GREEN}To add additional groups use Add User To Groups${RC}" + +checkEnv diff --git a/tabs/utils/user-account-manager/change_password.sh b/tabs/utils/user-account-manager/change_password.sh new file mode 100755 index 000000000..ef05a55b7 --- /dev/null +++ b/tabs/utils/user-account-manager/change_password.sh @@ -0,0 +1,19 @@ +#!/bin/sh -e + +. ../../common-script.sh +. ./utility_functions.sh + +clear +printf "%b\n" "${YELLOW}Change password${RC}" +printf "%b\n" "${YELLOW}=================${RC}" + +username=$(promptUsername "" "root") || exit 1 +password=$(promptPassword) || exit 1 + +read -p "Are you sure you want to change password for $username? [Y/N]: " confirm +confirmAction || exit 1 + +echo "$username:$password" | $ESCALATION_TOOL chpasswd +printf "%b\n" "${GREEN}Password changed successfully${RC}" + +checkEnv \ No newline at end of file diff --git a/tabs/utils/user-account-manager/delete_user.sh b/tabs/utils/user-account-manager/delete_user.sh new file mode 100755 index 000000000..cb68bdf91 --- /dev/null +++ b/tabs/utils/user-account-manager/delete_user.sh @@ -0,0 +1,26 @@ +#!/bin/sh -e + +. ../../common-script.sh +. ./utility_functions.sh + +clear +printf "%b\n" "${YELLOW}Delete a user${RC}" +printf "%b\n" "${YELLOW}=================${RC}" + +username=$(promptUsername "" "non-root") || exit 1 + +# Check if current user +if [ "$username" = "$USER" ]; then + printf "%b\n" "${RED}Cannot delete the current user${RC}" + printf "%b\n" "${RED}Press [Enter] to continue...${RC}" + read dummy + return +fi + +read -p "Are you sure you want to delete user $username? [Y/N]: " confirm +confirmAction || exit 1 + +$ESCALATION_TOOL userdel --remove "$username" 2>/dev/null +printf "%b\n" "${GREEN}User $username deleted successfully${RC}" + +checkEnv \ No newline at end of file diff --git a/tabs/utils/user-account-manager/remove_from_group.sh b/tabs/utils/user-account-manager/remove_from_group.sh new file mode 100755 index 000000000..4d3c65c37 --- /dev/null +++ b/tabs/utils/user-account-manager/remove_from_group.sh @@ -0,0 +1,30 @@ +#!/bin/sh -e + +. ../../common-script.sh +. ./utility_functions.sh + +clear +printf "%b\n" "${YELLOW}Remove from group${RC}" +printf "%b\n" "${YELLOW}=================${RC}" + +username=$(promptUsername "" "non-root") || exit 1 +user_groups=$(groups "$username" | cut -d: -f2 | sort | tr '\n' ' ') + +printf "%b\n" "${YELLOW}Groups user $username is in:${RC} $user_groups" +printf "%b\n" "${YELLOW}=================${RC}" + +read -p "Enter the groups you want to remove user from $username (space-separated): " groups + +checkEmpty "$groups" || exit 1 +checkGroupAvailabe "$groups" "$user_groups" || exit 1 + +groups_to_remove=$(echo "$groups" | tr ' ' ',') + +read -p "Are you sure you want to remove user $username from $groups_to_remove? [Y/N]: " confirm +confirmAction || exit 1 + +$ESCALATION_TOOL usermod -rG $groups_to_remove "$username" + +printf "%b\n" "${GREEN}User successfully removed from $groups_to_remove${RC}" + +checkEnv \ No newline at end of file diff --git a/tabs/utils/user-account-manager/utility_functions.sh b/tabs/utils/user-account-manager/utility_functions.sh new file mode 100755 index 000000000..0dedd7e67 --- /dev/null +++ b/tabs/utils/user-account-manager/utility_functions.sh @@ -0,0 +1,100 @@ +#!/bin/sh -e + +. ../../common-script.sh + +# Prompt for username +promptUsername() { + read -p "Enter the username: " username + + checkEmpty "$username"; + + if [ "$1" = "add" ]; then + checkUserExistence "$username" "$1" + else + checkUserExistence "$username" "$1" + checkReservedUsername "$username" "$2" + fi + echo "$username" +} + + +# Prompt for password +promptPassword() { + stty -echo + read -p "Enter the password (PASSWORD IS HIDDEN): " password1 + echo >&2 + read -p "Re-enter the password (PASSWORD IS HIDDEN): " password2 + echo >&2 + stty echo + + if ! checkEmpty "$password1"; then + promptPassword + fi + + if [ "$password1" != "$password2" ]; then + printf "%b\n" "${RED}Passwords do not match${RC}" >&2 + promptPassword + else + echo $password1 + fi +} + +# Check if input is empty +checkEmpty() { + if [ -z "$1" ]; then + printf "%b\n" "${RED}Empty value is not allowed${RC}" >&2 + exit 1 + fi +} + +# Check if user exists +checkUserExistence() { + if [ "$2" = "add" ]; then + if id "$1" > /dev/null 2>&1; then + printf "%b\n" "${RED}User already exists${RC}" >&2 + exit 1 + fi + else + if ! id "$1" > /dev/null 2>&1; then + printf "%b\n" "${RED}User does not exist${RC}" >&2 + exit 1 + fi + fi +} + +# Check if user is reserved +checkReservedUsername() { + uid=$(id -u "$1") + if [ "$2" = "root" ]; then + if [ "$uid" -le 999 ] && [ "$uid" -ne 0 ]; then + printf "%b\n" "${RED}Cannot modify system users${RC}" >&2 + exit 1 + fi + else + if [ "$(id -u "$1")" -le 999 ]; then + printf "%b\n" "${RED}Cannot modify system users${RC}" >&2 + exit 1 + fi + fi +} + +# Check if user is reserved +confirmAction() { + if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then + printf "%b\n" "${RED}Cancelled operation...${RC}" >&2 + exit 1 + fi +} + +# Check if group is available +checkGroupAvailabe() { + for group in $1; do + if ! echo "$2" | grep -wq "$group"; then + printf "%b\n" "${RED}Group $group not avaiable${RC}" >&2 + exit 1 + fi + done +} + +checkEnv +checkEscalationTool From 04537216d47da262004a0950fb67553ebb2d0f32 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 07:19:24 +0530 Subject: [PATCH 81/88] fix: Add wrapper around script (#388) * Add wrapper * Update start.sh * Update startdev.sh --- start.sh | 3 +++ startdev.sh | 3 +++ 2 files changed, 6 insertions(+) diff --git a/start.sh b/start.sh index b6fe4fdc8..fd69cbece 100755 --- a/start.sh +++ b/start.sh @@ -1,5 +1,7 @@ #!/bin/sh -e +# Prevent execution if this script was only partially downloaded +{ rc='\033[0m' red='\033[0;31m' @@ -46,3 +48,4 @@ check $? "Executing linutil" rm -f "$temp_file" check $? "Deleting the temporary file" +} # End of wrapping diff --git a/startdev.sh b/startdev.sh index 0df8ce53a..5fb2f1b2b 100755 --- a/startdev.sh +++ b/startdev.sh @@ -1,5 +1,7 @@ #!/bin/sh -e +# Prevent execution if this script was only partially downloaded +{ RC='\033[0m' RED='\033[0;31m' @@ -73,3 +75,4 @@ check $? "Executing linutil" rm -f $TMPFILE check $? "Deleting the temporary file" +} # End of wrapping From 1ea326747a9b54e5bf7bdd54e09d429600747d12 Mon Sep 17 00:00:00 2001 From: cartercanedy <99052281+cartercanedy@users.noreply.github.com> Date: Wed, 18 Sep 2024 19:00:09 -0700 Subject: [PATCH 82/88] fix: Fixup preview rendering and logic of preview key binding being shown in shortcut list (#387) * always check if selection is a command if list is focused * clear float widget render area before rendering content * Update hint.rs * Update floating_text.rs Thanks to @jeevithakannan2 for idea --------- Co-authored-by: Chris Titus --- tui/src/floating_text.rs | 9 ++++----- tui/src/hint.rs | 6 ++++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/tui/src/floating_text.rs b/tui/src/floating_text.rs index fd53ed074..ad77c36f2 100644 --- a/tui/src/floating_text.rs +++ b/tui/src/floating_text.rs @@ -8,7 +8,7 @@ use ratatui::{ layout::Rect, style::{Style, Stylize}, text::Line, - widgets::{Block, Borders, List}, + widgets::{Block, Borders, Clear, List}, Frame, }; pub enum FloatingTextMode { @@ -102,15 +102,14 @@ impl FloatContent for FloatingText { .map(Line::from) .collect(); - // Prevents background text from appearing after the floating content - while lines.len() < inner_area.height as usize { - lines.push(Line::from(" ".repeat(inner_area.width as usize))); - } // Create list widget let list = List::new(lines) .block(Block::default()) .highlight_style(Style::default().reversed()); + // Clear the text underneath the floats rendered area + frame.render_widget(Clear, inner_area); + // Render the list inside the bordered area frame.render_widget(list, inner_area); } diff --git a/tui/src/hint.rs b/tui/src/hint.rs index a1b924cd0..00ac4fae5 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -114,9 +114,11 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { scope_name: "Search bar", hints: vec![Shortcut::new(vec!["Enter"], "Finish search")], }, + Focus::List => { let mut hints = Vec::new(); hints.push(Shortcut::new(vec!["q", "CTRL-c"], "Exit linutil")); + if state.at_root() { hints.push(Shortcut::new(vec!["h", "Left", "Tab"], "Focus tab list")); hints.push(get_list_item_shortcut(state)); @@ -136,15 +138,18 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { } hints.push(Shortcut::new(vec!["Tab"], "Focus tab list")); }; + hints.push(Shortcut::new(vec!["k", "Up"], "Select item above")); hints.push(Shortcut::new(vec!["j", "Down"], "Select item below")); hints.push(Shortcut::new(vec!["t"], "Next theme")); hints.push(Shortcut::new(vec!["T"], "Previous theme")); + ShortcutList { scope_name: "Item list", hints, } } + Focus::TabList => ShortcutList { scope_name: "Tab list", hints: vec![ @@ -156,6 +161,7 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { Shortcut::new(vec!["T"], "Previous theme"), ], }, + Focus::FloatingWindow(ref float) => float.get_shortcut_list(), } .draw(frame, area); From b35ad5baccf8f40112222d8f75089f16ec540b69 Mon Sep 17 00:00:00 2001 From: Harsh Vyapari Date: Thu, 19 Sep 2024 07:43:41 +0530 Subject: [PATCH 83/88] feat(fedora/nvidia-*.sh): nvidia proprietary driver setup (continued from PR #319) (#370) * feat(fedora/nvidia-*.sh): adding nvidia proprietary driver setup * fix(fedora/nvidia-*.sh): removing update line That update line crashed my system while testing, since it also installed new kernal where I didn't build my driver. So new user can also get confused. * refactor(fedora/nvidia-*.sh): adding a new warning while starting the script I faced this issue yesterday, So It's better to warn user before installing this driver * refactor(fedora/nvidia-*.sh): removing uninstalation option For now, as suggested by @nnyyxxxx and @adamperkowski, I'm removing the uninstall option until #362 gets resolved. * Fix bashism --------- Co-authored-by: Chris Titus --- .../fedora/nvidia-proprietary-driver-setup.sh | 94 +++++++++++++++++++ tabs/system-setup/tab_data.toml | 6 +- 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100755 tabs/system-setup/fedora/nvidia-proprietary-driver-setup.sh diff --git a/tabs/system-setup/fedora/nvidia-proprietary-driver-setup.sh b/tabs/system-setup/fedora/nvidia-proprietary-driver-setup.sh new file mode 100755 index 000000000..ef0ada8dd --- /dev/null +++ b/tabs/system-setup/fedora/nvidia-proprietary-driver-setup.sh @@ -0,0 +1,94 @@ +#!/bin/sh -e + +. ../../common-script.sh +# This script allows user to download proprietary drivers for nvidia in fedora + +# It also disables noveau nvidia drivers + +# Installation guide link: https://rpmfusion.org/Howto/NVIDIA + +# NOTE: Currently script only provides drivers for gpu 2014 and above (510+ and above) + +checkRepo() { + REPO_ID="rpmfusion-nonfree-nvidia-driver" + + if [ $(dnf repolist enabled 2>/dev/null | grep "$REPO_ID" | wc -l) -gt 0 ]; then + printf "%b\n" "${GREEN}Nvidia non-free repository is already enabled.${RC}" + else + printf "%b\n" "${YELLOW}Nvidia non-free repository is not enabled. Enabling now...${RC}" + + # Enable the repository + $ESCALATION_TOOL dnf config-manager --set-enabled "$REPO_ID" + + # Refreshing repository list + $ESCALATION_TOOL dnf makecache + + # Verify if the repository is enabled + if [ $(dnf repolist enabled 2>/dev/null | grep "$REPO_ID" | wc -l) -gt 0 ]; then + printf "%b\n" "${GREEN}Nvidia non-free repository is now enabled...${RC}" + else + printf "%b\n" "${RED}Failed to enable nvidia non-free repository...${RC}" + exit 1 + fi + fi +} + +checkDriverInstallation() { + if modinfo -F version nvidia >/dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +installDriver() { + + if checkDriverInstallation; then + printf "%b\n" "${GREEN}NVIDIA driver is already installed.${RC}" + exit 0 + fi + + # NOTE:: Installing graphics driver. + $ESCALATION_TOOL dnf install akmod-nvidia xorg-x11-drv-nvidia-cuda -y + printf "%b\n" "${YELLOW}Building the drivers may take upto 5 minutes. Please don't kill the script!\n If the build failed try running the script again, select \"Remove Nvidia Drivers\" and reboot the system, then try installing drivers again.${RC}" + + for i in {1..5}; do + if checkDriverInstallation; then + printf "%b\n" "${GREEN}Driver installed successfully.${RC}" + printf "%b\n" "${GREEN}Installed driver version $(modinfo -F version nvidia)${RC}" + break + fi + printf "%b\n" "${YELLOW}Waiting for driver to be built..." + sleep 1m + done + + printf "%b\n" "${GREEN}Now you can reboot the system.${RC}" + +} + +# NOTE: A confirmation option to proceed or not +userConfirmation() { + printf "%b" "${YELLOW}Do you want to continue? (Y/N): ${RC}" + read -r choice + case "$choice" in + y | Y) + checkRepo + installDriver + return + ;; + n | N) + printf "%b\n" "${RED} Exiting the Script ${RC}" + return + ;; + *) + printf "%b\n" "${RED} Invalid Option! ${RC}" + userConfirmation + ;; + esac +} + +printf "%b\n" "${YELLOW}Warning! This script will enable Nvidia non-free repository and only install drivers for GPUs from 2014 or later. It works on fedora 34 and above.\n It is recommended remove this driver while updating your kernel packages to newer version.${RC}" + +checkEnv +checkEscalationTool +userConfirmation diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index 7565c1481..4eabb4d5e 100644 --- a/tabs/system-setup/tab_data.toml +++ b/tabs/system-setup/tab_data.toml @@ -29,7 +29,7 @@ name = "Fedora" [[data.preconditions]] matches = true data = "command_exists" -values = ["dnf"] +values = ["dnf"] [[data.entries]] name = "Configure DNF" @@ -40,6 +40,10 @@ script = "fedora/configure-dnf.sh" name = "Multimedia Setup" script = "fedora/multimedia-codecs.sh" +[[data.entries]] +name = "Nvidia Proprietary Driver Setup" +script = "fedora/nvidia-proprietary-driver-setup.sh" + [[data.entries]] name = "RPM Fusion Setup" description = "RPM Fusion provides software that the Fedora Project or Red Hat doesn't want to ship.\nThat software is provided as precompiled RPMs for all current Fedora versions and current Red Hat Enterprise Linux or clones versions; you can use the RPM Fusion repositories with tools like yum and PackageKit.\nFor more information visit: https://rpmfusion.org/" From 9ed0a48281ae39a9b1d8f3c4b1390f846fda1c70 Mon Sep 17 00:00:00 2001 From: zdiff Date: Wed, 18 Sep 2024 22:14:52 -0400 Subject: [PATCH 84/88] Remove unused features from core/Cargo.toml (#365) Co-authored-by: zdiff --- core/Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/Cargo.toml b/core/Cargo.toml index ebe1091df..fdabe6091 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -7,7 +7,7 @@ license.workspace = true [dependencies] include_dir = "0.7.4" tempdir = "0.3.7" -serde = { version = "1.0.205", features = ["derive"] } -toml = "0.8.19" +serde = { version = "1.0.205", features = ["derive"], default-features = false } +toml = { version = "0.8.19", features = ["parse"], default-features = false } which = "6.0.3" ego-tree = { workspace = true } From 197f359c45c6f819e9411cb358107c46e56c5e44 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 07:52:43 +0530 Subject: [PATCH 85/88] Refactor tab (#347) Co-authored-by: Chris Titus --- tui/src/hint.rs | 10 ++++++---- tui/src/state.rs | 30 ++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/tui/src/hint.rs b/tui/src/hint.rs index 00ac4fae5..9d10e4dac 100644 --- a/tui/src/hint.rs +++ b/tui/src/hint.rs @@ -120,7 +120,7 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { hints.push(Shortcut::new(vec!["q", "CTRL-c"], "Exit linutil")); if state.at_root() { - hints.push(Shortcut::new(vec!["h", "Left", "Tab"], "Focus tab list")); + hints.push(Shortcut::new(vec!["h", "Left"], "Focus tab list")); hints.push(get_list_item_shortcut(state)); } else { if state.selected_item_is_up_dir() { @@ -136,14 +136,14 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { hints.push(Shortcut::new(vec!["d"], "Command Description")); } } - hints.push(Shortcut::new(vec!["Tab"], "Focus tab list")); }; hints.push(Shortcut::new(vec!["k", "Up"], "Select item above")); hints.push(Shortcut::new(vec!["j", "Down"], "Select item below")); hints.push(Shortcut::new(vec!["t"], "Next theme")); hints.push(Shortcut::new(vec!["T"], "Previous theme")); - + hints.push(Shortcut::new(vec!["Tab"], "Next tab")); + hints.push(Shortcut::new(vec!["Shift-Tab"], "Previous tab")); ShortcutList { scope_name: "Item list", hints, @@ -154,11 +154,13 @@ pub fn draw_shortcuts(state: &AppState, frame: &mut Frame, area: Rect) { scope_name: "Tab list", hints: vec![ Shortcut::new(vec!["q", "CTRL-c"], "Exit linutil"), - Shortcut::new(vec!["l", "Right", "Tab", "Enter"], "Focus action list"), + Shortcut::new(vec!["l", "Right", "Enter"], "Focus action list"), Shortcut::new(vec!["k", "Up"], "Select item above"), Shortcut::new(vec!["j", "Down"], "Select item below"), Shortcut::new(vec!["t"], "Next theme"), Shortcut::new(vec!["T"], "Previous theme"), + Shortcut::new(vec!["Tab"], "Next tab"), + Shortcut::new(vec!["Shift-Tab"], "Previous tab"), ], }, diff --git a/tui/src/state.rs b/tui/src/state.rs index 4613be182..d5d943a71 100644 --- a/tui/src/state.rs +++ b/tui/src/state.rs @@ -247,6 +247,31 @@ impl AppState { return true; } + // Handle key only when Tablist or List is focused + // Prevents exiting the application even when a command is running + // Add keys here which should work on both TabList and List + if matches!(self.focus, Focus::TabList | Focus::List) { + match key.code { + KeyCode::Tab => { + if self.current_tab.selected().unwrap() == self.tabs.len() - 1 { + self.current_tab.select_first(); // Select first tab when it is at last + } else { + self.current_tab.select_next(); + } + self.refresh_tab(); + } + KeyCode::BackTab => { + if self.current_tab.selected().unwrap() == 0 { + self.current_tab.select(Some(self.tabs.len() - 1)); // Select last tab when it is at first + } else { + self.current_tab.select_previous(); + } + self.refresh_tab(); + } + _ => {} + } + } + match &mut self.focus { Focus::FloatingWindow(command) => { if command.handle_key_event(key) { @@ -268,9 +293,7 @@ impl AppState { } Focus::TabList => match key.code { - KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right | KeyCode::Tab => { - self.focus = Focus::List - } + KeyCode::Enter | KeyCode::Char('l') | KeyCode::Right => self.focus = Focus::List, KeyCode::Char('j') | KeyCode::Down if self.current_tab.selected().unwrap() + 1 < self.tabs.len() => @@ -304,7 +327,6 @@ impl AppState { } } KeyCode::Char('/') => self.enter_search(), - KeyCode::Tab => self.focus = Focus::TabList, KeyCode::Char('t') => self.theme.next(), KeyCode::Char('T') => self.theme.prev(), _ => {} From 23156bcbf4991c70a2bc574a35d0a700b331fa00 Mon Sep 17 00:00:00 2001 From: JEEVITHA KANNAN K S Date: Thu, 19 Sep 2024 08:02:44 +0530 Subject: [PATCH 86/88] Add rate mirrors headsup (#343) --- tabs/system-setup/system-update.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index c672a948e..d5dcf08aa 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -6,7 +6,9 @@ fastUpdate() { case "$PACKAGER" in pacman) - $AUR_HELPER -S --needed --noconfirm rate-mirrors-bin + $AUR_HELPER -S --needed --noconfirm rate-mirrors-bin + + printf "%b\n" "${YELLOW}Generating a new list of mirrors using rate-mirrors. This process may take a few seconds...${RC}" if [ -s /etc/pacman.d/mirrorlist ]; then "$ESCALATION_TOOL" cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.bak @@ -100,4 +102,4 @@ checkAURHelper checkEscalationTool fastUpdate updateSystem -updateFlatpaks \ No newline at end of file +updateFlatpaks From 6cd7818bed5801a49ae3db29a7be7a25cd93637a Mon Sep 17 00:00:00 2001 From: kleidis <167202775+kleidis@users.noreply.github.com> Date: Thu, 19 Sep 2024 04:34:42 +0200 Subject: [PATCH 87/88] Initial support for flathub management (#341) * Add flatpak / flathub setup & uninstall script * systemUpdate: Improve flatpak updates * Update docs * Fix order on uninstall script * Remove uninstall script --- docs/userguide.md | 1 + tabs/applications-setup/setup-flatpak.sh | 91 ++++++++++++++++++++++++ tabs/applications-setup/tab_data.toml | 4 ++ tabs/system-setup/system-update.sh | 13 +++- 4 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 tabs/applications-setup/setup-flatpak.sh diff --git a/docs/userguide.md b/docs/userguide.md index 57af97e10..d17155689 100644 --- a/docs/userguide.md +++ b/docs/userguide.md @@ -21,6 +21,7 @@ ## Applications Setup +- **Flathub**: Installs / Uninstalls Flatpak and Flathub. - **Alacritty Setup**: Installs and configures Alacritty for you. - **DwmTitus Setup**: Sets up the Dwm window manager. - **Kitty Setup**: Installs and configures Kitty for you. diff --git a/tabs/applications-setup/setup-flatpak.sh b/tabs/applications-setup/setup-flatpak.sh new file mode 100644 index 000000000..749ddf1ba --- /dev/null +++ b/tabs/applications-setup/setup-flatpak.sh @@ -0,0 +1,91 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Used to detect the desktop environment, Only used for the If statement in the setup_flatpak function. +# Perhaps this should be moved to common-script.sh later on? +detect_de() { + if [ -n "$XDG_CURRENT_DESKTOP" ]; then + case "$XDG_CURRENT_DESKTOP" in + *GNOME*) + DE="GNOME" + ;; + *KDE*) + DE="KDE" + ;; + esac + fi +} + +# Install Flatpak if not already installed. +setup_flatpak() { + if ! command_exists flatpak; then + printf "%b\n" "${YELLOW}Installing Flatpak...${RC}" + case "$PACKAGER" in + pacman) + $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm flatpak + ;; + apt-get|nala) + $ESCALATION_TOOL "$PACKAGER" install -y flatpak + ;; + dnf) + $ESCALATION_TOOL "$PACKAGER" install -y flatpak # Fedora should have flatpak already installed, this is just a failsafe + ;; + zypper) + $ESCALATION_TOOL "$PACKAGER" install -y flatpak + ;; + yum) + $ESCALATION_TOOL "$PACKAGER" install -y flatpak + ;; + xbps-install) + $ESCALATION_TOOL "$PACKAGER" install -S flatpak + ;; + *) + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" + exit 1 + ;; + esac + printf "%b\n" "Adding Flathub remote..." + $ESCALATION_TOOL flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + else + if command -v flatpak >/dev/null 2>&1; then + if ! flatpak remotes | grep -q "flathub"; then + printf "%b\n" "${YELLOW}Detected Flatpak package manager but Flathub remote is not added. Would you like to add it? (y/n)${RC}" + read add_remote + case "$add_remote" in + [Yy]*) + printf "%b\n" "Adding Flathub remote..." + $ESCALATION_TOOL flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo + ;; + esac + else + # Needed mostly for systems without a polkit agent running (Error: updating: Unable to connect to system bus) + printf "%b\n" "${GREEN}Flathub already setup. You can quit.${RC}" + fi + fi + fi + + if [ "$PACKAGER" = "apt-get" ] || [ "$PACKAGER" = "nala" ]; then + detect_de + # Only used for Ubuntu GNOME. Ubuntu GNOME doesnt allow flathub to be added as a remote to their store. + # So in case the user wants to use a GUI siftware manager they can setup it here + if [ "$DE" = "GNOME" ]; then + printf "%b\n" "${YELLOW}Detected GNOME desktop environment. Would you like to install GNOME Software plugin for Flatpak? (y/n)${RC}" + read install_gnome + if [ "$install_gnome" = "y" ] || [ "$install_gnome" = "Y" ]; then + $ESCALATION_TOOL "$PACKAGER" install -y gnome-software-plugin-flatpak + fi + # Useful for Debian KDE spin as well + elif [ "$DE" = "KDE" ]; then + printf "%b\n" "${YELLOW}Detected KDE desktop environment. Would you like to install KDE Plasma Discover backend for Flatpak? (y/n)${RC}" + read install_kde + if [ "$install_kde" = "y" ] || [ "$install_kde" = "Y" ]; then + $ESCALATION_TOOL "$PACKAGER" install -y plasma-discover-backend-flatpak + fi + fi + fi +} + +checkEnv +checkEscalationTool +setup_flatpak diff --git a/tabs/applications-setup/tab_data.toml b/tabs/applications-setup/tab_data.toml index 0a9be9fbf..fad13af50 100644 --- a/tabs/applications-setup/tab_data.toml +++ b/tabs/applications-setup/tab_data.toml @@ -1,5 +1,9 @@ name = "Applications Setup" +[[data]] +name = "Setup Flatpak / Flathub" +script = "setup-flatpak.sh" + [[data]] name = "Alacritty" description = "Alacritty is a modern terminal emulator that comes with sensible defaults, but allows for extensive configuration. By integrating with other applications, rather than reimplementing their functionality, it manages to provide a flexible set of features with high performance. The supported platforms currently consist of BSD, Linux, macOS and Windows.\nThis command installs and condifures alacritty terminal emulator." diff --git a/tabs/system-setup/system-update.sh b/tabs/system-setup/system-update.sh index d5dcf08aa..6bcaf99ae 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -93,7 +93,18 @@ updateSystem() { updateFlatpaks() { if command_exists flatpak; then - flatpak update -y + printf "%b\n" "${YELLOW}Updating installed Flathub apps...${RC}" + installed_apps=$(flatpak list --app --columns=application) + + if [ -z "$installed_apps" ]; then + printf "%b\n" "${RED}No Flathub apps are installed.${RC}" + return + fi + + for app in $installed_apps; do + printf "%b\n" "${YELLOW}Updating $app...${RC}" + flatpak update -y "$app" + done fi } From 596f278993242247650b1b45f28460e87fece868 Mon Sep 17 00:00:00 2001 From: Chris Titus Date: Wed, 18 Sep 2024 21:54:34 -0500 Subject: [PATCH 88/88] alpha the app list --- tabs/applications-setup/tab_data.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tabs/applications-setup/tab_data.toml b/tabs/applications-setup/tab_data.toml index fad13af50..750239c99 100644 --- a/tabs/applications-setup/tab_data.toml +++ b/tabs/applications-setup/tab_data.toml @@ -1,9 +1,5 @@ name = "Applications Setup" -[[data]] -name = "Setup Flatpak / Flathub" -script = "setup-flatpak.sh" - [[data]] name = "Alacritty" description = "Alacritty is a modern terminal emulator that comes with sensible defaults, but allows for extensive configuration. By integrating with other applications, rather than reimplementing their functionality, it manages to provide a flexible set of features with high performance. The supported platforms currently consist of BSD, Linux, macOS and Windows.\nThis command installs and condifures alacritty terminal emulator." @@ -19,6 +15,11 @@ name = "DWM-Titus" description = "DWM is a dynamic window manager for X.\nIt manages windows in tiled, monocle and floating layouts.\nAll of the layouts can be applied dynamically, optimising the environment for the application in use and the task performed.\nThis command installs and configures DWM and a desktop manager.\nThe list of patches applied can be found in CTT's DWM repository\nhttps://github.com/ChrisTitusTech/dwm-titus" script = "dwmtitus-setup.sh" +[[data]] +name = "Fastfetch" +description = "Fastfetch is a neofetch-like tool for fetching system information and displaying it prettily.\nIt is written mainly in C, with performance and customizability in mind.\nThis command installs fastfetch and configures from CTT's mybash repository.\nhttps://github.com/ChrisTitusTech/mybash" +script = "fastfetch-setup.sh" + [[data]] name = "Kitty" description = "kitty is a free and open-source GPU-accelerated terminal emulator for Linux, macOS, and some BSD distributions, focused on performance and features.\nkitty is written in a mix of C and Python programming languages.\n This command installs and configures kitty." @@ -34,12 +35,11 @@ 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" script = "rofi-setup.sh" +[[data]] +name = "Setup Flatpak / Flathub" +script = "setup-flatpak.sh" + [[data]] 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.\nThis command installs ZSH prompt and provides basic configuration." script = "zsh-setup.sh" - -[[data]] -name = "Fastfetch" -description = "Fastfetch is a neofetch-like tool for fetching system information and displaying it prettily.\nIt is written mainly in C, with performance and customizability in mind.\nThis command installs fastfetch and configures from CTT's mybash repository.\nhttps://github.com/ChrisTitusTech/mybash" -script = "fastfetch-setup.sh"