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/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. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 3b61761b3..4cc787c47 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,12 +1,12 @@ -# Pull Request - -## Title - + ## Type of Change - [ ] New feature - [ ] Bug fix -- [ ] Documentation Update +- [ ] Documentation update - [ ] Refactoring - [ ] Hotfix - [ ] Security patch @@ -21,7 +21,7 @@ ## Impact -## Issue related to PR +## Issues / other PRs related - Resolves # diff --git a/.github/workflows/bashisms.yml b/.github/workflows/bashisms.yml new file mode 100644 index 000000000..e667f6d23 --- /dev/null +++ b/.github/workflows/bashisms.yml @@ -0,0 +1,26 @@ +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-get update && sudo apt-get install devscripts + + - name: Check for bashisms + working-directory: tabs + run: find . -name '*.sh' | xargs -P 4 -n 1 checkbashisms diff --git a/.github/workflows/pr-labels.yaml b/.github/workflows/pr-labels.yaml deleted file mode 100644 index eab956f41..000000000 --- a/.github/workflows/pr-labels.yaml +++ /dev/null @@ -1,50 +0,0 @@ -name: Manage labels based on PR body - -on: - pull_request: - types: [opened, edited, reopened, synchronize] - -jobs: - manage-labels: - runs-on: ubuntu-latest - steps: - - name: Analyze PR Body and manage labels - run: | - body="${{ github.event.pull_request.body }}" - 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 key in "${!label_checks[@]}"; do - if echo "$body" | grep -q "\- \[x\] $key"; then - labels_to_add+=("${label_checks[$key]}") - else - labels_to_remove+=("${label_checks[$key]}") - fi - done - echo "LABELS_TO_ADD=${labels_to_add[*]}" >> $GITHUB_ENV - echo "LABELS_TO_REMOVE=${labels_to_remove[*]}" >> $GITHUB_ENV - - name: Add labels if necessary - if: env.LABELS_TO_ADD != '' - run: | - for label in ${{ env.LABELS_TO_ADD }}; 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: | - for label in ${{ env.LABELS_TO_REMOVE }}; 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 \ No newline at end of file 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 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. 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 } 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/docs/assets/preview.png b/docs/assets/preview.png index de4b54e38..bb8b70379 100644 Binary files a/docs/assets/preview.png and b/docs/assets/preview.png differ diff --git a/docs/userguide.md b/docs/userguide.md index 8fc385f58..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. @@ -30,3 +31,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/start.sh b/start.sh index d1e7658ae..fd69cbece 100755 --- a/start.sh +++ b/start.sh @@ -1,5 +1,7 @@ -#!/bin/sh +#!/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 1070ea429..5fb2f1b2b 100755 --- a/startdev.sh +++ b/startdev.sh @@ -1,5 +1,7 @@ -#!/bin/sh +#!/bin/sh -e +# Prevent execution if this script was only partially downloaded +{ RC='\033[0m' RED='\033[0;31m' @@ -35,7 +37,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 } @@ -73,3 +75,4 @@ check $? "Executing linutil" rm -f $TMPFILE check $? "Deleting the temporary file" +} # End of wrapping diff --git a/tabs/applications-setup/alacritty-setup.sh b/tabs/applications-setup/alacritty-setup.sh index 92e49d337..2d9143401 100755 --- a/tabs/applications-setup/alacritty-setup.sh +++ b/tabs/applications-setup/alacritty-setup.sh @@ -2,33 +2,34 @@ . ../common-script.sh -setupAlacritty() { - echo "Install Alacritty if not already installed..." +installAlacritty() { + printf "%b\n" "${YELLOW}Installing Alacritty...${RC}" 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 - echo "alacritty is already installed." + printf "%b\n" "${GREEN}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 checkEscalationTool -setupAlacritty +installAlacritty setupAlacrittyConfig \ No newline at end of file diff --git a/tabs/applications-setup/dwmtitus-setup.sh b/tabs/applications-setup/dwmtitus-setup.sh index acc56c0e7..598a0c63e 100755 --- a/tabs/applications-setup/dwmtitus-setup.sh +++ b/tabs/applications-setup/dwmtitus-setup.sh @@ -2,33 +2,33 @@ . ../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() { - 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 + "$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" - $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 ;; *) - echo "Unsupported package manager: $PACKAGER" + printf "%b\n" "${RED}Unsupported package manager: $PACKAGER${RC}" exit 1 ;; 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" @@ -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" "${GREEN}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" + if ! "$ESCALATION_TOOL" ninja -C build install; then + 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,62 +135,65 @@ 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 } 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" + 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 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" + 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 + 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" + 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" "${GREEN}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 + "$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 ;; *) - 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,26 +201,26 @@ 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" + "$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" ;; *) - 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,60 +229,57 @@ 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" - 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 - 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" - $ESCALATION_TOOL groupadd autologin + printf "%b\n" "${YELLOW}Creating autologin group${RC}" + "$ESCALATION_TOOL" groupadd autologin else - echo "Autologin group already exists" + printf "%b\n" "${GREEN}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" + "$ESCALATION_TOOL" usermod -aG autologin "$USER_UID_1000" + 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 - - - } 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" - 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" "${YELLOW}Installing slstatus${RC}" + 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 - 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" } @@ -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/fastfetch-setup.sh b/tabs/applications-setup/fastfetch-setup.sh index e3f9a4f72..dd6ca483a 100644 --- a/tabs/applications-setup/fastfetch-setup.sh +++ b/tabs/applications-setup/fastfetch-setup.sh @@ -2,24 +2,24 @@ . ../common-script.sh -setupFastfetch() { - echo "Installing Fastfetch if not already installed..." +installFastfetch() { + printf "%b\n" "${YELLOW}Installing Fastfetch...${RC}" 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 - 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 @@ -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..0131b4bb4 100755 --- a/tabs/applications-setup/kitty-setup.sh +++ b/tabs/applications-setup/kitty-setup.sh @@ -2,24 +2,24 @@ . ../common-script.sh -setupKitty() { - echo "Install Kitty if not already installed..." +installKitty() { + printf "%b\n" "${YELLOW}Install Kitty if not already installed...${RC}" 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 - 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}Copying Kitty configuration files...${RC}" 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..04772cf7f 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() { - echo "Install mybash if not already installed" + 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,13 +26,22 @@ 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" 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,16 +67,16 @@ 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 + "$ESCALATION_TOOL" ~/.fzf/install fi } installZoxide() { if command_exists zoxide; then - echo "Zoxide already installed" + printf "%b\n" "${GREEN}Zoxide already installed${RC}" return fi @@ -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 0d3a2578d..040587736 100755 --- a/tabs/applications-setup/neovim-setup.sh +++ b/tabs/applications-setup/neovim-setup.sh @@ -13,20 +13,20 @@ cloneNeovim() { cd "$HOME" && git clone https://github.com/ChrisTitusTech/neovim.git "$HOME/.local/share/neovim" } -setupNeovim() { - echo "Install Neovim if not already installed" +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. @@ -36,6 +36,7 @@ setupNeovim() { } backupNeovimConfig() { + 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 @@ -43,13 +44,14 @@ backupNeovimConfig() { } linkNeovimConfig() { + 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. } checkEnv checkEscalationTool +installNeovim cloneNeovim -setupNeovim 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..e779066ac 100755 --- a/tabs/applications-setup/rofi-setup.sh +++ b/tabs/applications-setup/rofi-setup.sh @@ -2,24 +2,24 @@ . ../common-script.sh -setupRofi() { - echo "Install Rofi if not already installed..." +installRofi() { + printf "%b\n" "${YELLOW}Installing Rofi...${RC}" 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 - 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}Copying Rofi configuration files...${RC}" 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/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 ce8f1b92b..750239c99 100644 --- a/tabs/applications-setup/tab_data.toml +++ b/tabs/applications-setup/tab_data.toml @@ -2,32 +2,44 @@ 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 = "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." 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" -script = "zsh-setup.sh" +name = "Setup Flatpak / Flathub" +script = "setup-flatpak.sh" [[data]] -name = "Fastfetch" -script = "fastfetch-setup.sh" \ No newline at end of file +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" diff --git a/tabs/applications-setup/zsh-setup.sh b/tabs/applications-setup/zsh-setup.sh index eaa608b5f..c3577e5e8 100644 --- a/tabs/applications-setup/zsh-setup.sh +++ b/tabs/applications-setup/zsh-setup.sh @@ -3,24 +3,25 @@ . ../common-script.sh # Function to install zsh -install_zsh() { - echo "Install ZSH if not already installed..." - if ! command_exists zsh; then - case "$PACKAGER" in - pacman) - $ESCALATION_TOOL "$PACKAGER" -S --needed --noconfirm zsh - ;; - *) - $ESCALATION_TOOL "$PACKAGER" install -y zsh - ;; - esac - else - echo "ZSH is already installed." - fi +installZsh() { + 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 -setup_zsh_config() { +setupZshConfig() { + printf "%b\n" "${YELLOW}Setting up Zsh configuration...${RC}" CONFIG_DIR="$HOME/.config/zsh" ZSHRC_FILE="$CONFIG_DIR/.zshrc" @@ -43,10 +44,10 @@ 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 checkEscalationTool -install_zsh -setup_zsh_config +installZsh +setupZshConfig diff --git a/tabs/common-script.sh b/tabs/common-script.sh index aa4deae95..d0c0c4705 100644 --- a/tabs/common-script.sh +++ b/tabs/common-script.sh @@ -5,10 +5,11 @@ RC='\033[0m' RED='\033[31m' YELLOW='\033[33m' +CYAN='\033[36m' GREEN='\033[32m' command_exists() { - which "$1" >/dev/null 2>&1 + command -v "$1" >/dev/null 2>&1 } checkAURHelper() { @@ -19,22 +20,22 @@ 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..." - $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 + 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 if command_exists yay; then 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 @@ -48,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 @@ -64,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 @@ -76,12 +77,12 @@ checkPackageManager() { for pgm in ${PACKAGEMANAGER}; do if command_exists "${pgm}"; then PACKAGER=${pgm} - echo "Using ${pgm}" + printf "Using ${pgm}" break 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 @@ -93,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 } @@ -109,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 } @@ -125,7 +126,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/gaming/diablo-ii/d2r-loot-filters.sh b/tabs/gaming/diablo-ii/d2r-loot-filters.sh index 1fa43fabd..9534108d1 100755 --- a/tabs/gaming/diablo-ii/d2r-loot-filters.sh +++ b/tabs/gaming/diablo-ii/d2r-loot-filters.sh @@ -1,16 +1,18 @@ -#!/bin/bash +#!/bin/sh -e + +. ../../common-script.sh # 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 # 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[@]} @@ -23,7 +25,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 @@ -75,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 @@ -84,26 +86,23 @@ 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" - -# 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 "%b\n" "${GREEN}Loot filter installed successfully in $mods_path${RC}" + +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/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/firewall-baselines.sh b/tabs/security/firewall-baselines.sh index 5abb0c766..2f7a2529c 100644 --- a/tabs/security/firewall-baselines.sh +++ b/tabs/security/firewall-baselines.sh @@ -3,43 +3,43 @@ . ../common-script.sh installPkg() { - echo "Install UFW if not already installed..." + printf "%b\n" "${YELLOW}Installing UFW...${RC}" 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 - echo "UFW is already installed." + printf "%b\n" "${GREEN}UFW is already installed${RC}" fi } 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 + printf "%b\n" "${YELLOW}Disabling UFW${RC}" + "$ESCALATION_TOOL" ufw disable - echo "Limiting port 22/tcp (UFW)" - $ESCALATION_TOOL ufw limit 22/tcp + printf "%b\n" "${YELLOW}Limiting port 22/tcp (UFW)${RC}" + "$ESCALATION_TOOL" ufw limit 22/tcp - echo "Allowing port 80/tcp (UFW)" - $ESCALATION_TOOL ufw allow 80/tcp + printf "%b\n" "${YELLOW}Allowing port 80/tcp (UFW)${RC}" + "$ESCALATION_TOOL" ufw allow 80/tcp - echo "Allowing port 443/tcp (UFW)" - $ESCALATION_TOOL ufw allow 443/tcp + printf "%b\n" "${YELLO}Allowing port 443/tcp (UFW)${RC}" + "$ESCALATION_TOOL" ufw allow 443/tcp - echo "Denying Incoming Packets by Default(UFW)" - $ESCALATION_TOOL ufw default deny incoming + printf "%b\n" "${YELLOW}Denying Incoming Packets by Default(UFW)${RC}" + "$ESCALATION_TOOL" ufw default deny incoming - echo "Allowing Outcoming Packets by Default(UFW)" - $ESCALATION_TOOL ufw default allow outgoing + printf "%b\n" "${YELLOW}Allowing Outcoming Packets by Default(UFW)${RC}" + "$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/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/1-compile-setup.sh b/tabs/system-setup/1-compile-setup.sh index a9d21890d..94ccf7da1 100755 --- a/tabs/system-setup/1-compile-setup.sh +++ b/tabs/system-setup/1-compile-setup.sh @@ -6,39 +6,39 @@ 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 - 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 - echo "Multilib is already enabled." + 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/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 diff --git a/tabs/system-setup/3-global-theme.sh b/tabs/system-setup/3-global-theme.sh index c3e360da5..471441518 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 - apt-get) - $ESCALATION_TOOL apt-get update - $ESCALATION_TOOL apt-get install -y qt6ct kvantum + case "$PACKAGER" in + 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" @@ -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 f804aa5b8..75804ca03 100644 --- a/tabs/system-setup/4-remove-snaps.sh +++ b/tabs/system-setup/4-remove-snaps.sh @@ -3,24 +3,24 @@ . ../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 + "$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" + printf "%b\n" "${RED}Removing snapd not implemented for this package manager${RC}" ;; esac } 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..7e22f2624 --- /dev/null +++ b/tabs/system-setup/5-samba-ssh-setup.sh @@ -0,0 +1,205 @@ +#!/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 + case "$PACKAGER" in + "apt-get") + install_package openssh-server + SSH_SERVICE="ssh" + ;; + "pacman") + install_package openssh + SSH_SERVICE="sshd" + ;; + *) + install_package openssh-server + SSH_SERVICE="sshd" + ;; + esac + + # 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 in $SAMBA_CONFIG.${RC}" + 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 + else + printf "%b\n" "${YELLOW}No existing Samba configuration found. Setting up a new one...${RC}" + + # Prompt user for shared directory path + printf "Enter the path for the Samba share (default: /srv/samba/share): " + read -r 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 + printf "Enter Samba username: " + read -r SAMBA_USER + + # Loop until the passwords match + while true; do + printf "Enter Samba password: " + stty -echo + read -r SAMBA_PASSWORD + stty echo + printf "Confirm Samba password: " + stty -echo + read SAMBA_PASSWORD_CONFIRM + stty echo + printf "\n" + 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" <> /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/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/fedora/rpm-fusion-setup.sh b/tabs/system-setup/fedora/rpm-fusion-setup.sh index 52396d5df..d8b0e2ace 100644 --- a/tabs/system-setup/fedora/rpm-fusion-setup.sh +++ b/tabs/system-setup/fedora/rpm-fusion-setup.sh @@ -5,22 +5,23 @@ # 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..." - $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" "${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 + 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 } checkEnv +checkEscalationTool installRPMFusion 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/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/system-update.sh b/tabs/system-setup/system-update.sh index e6b32af6d..6bcaf99ae 100755 --- a/tabs/system-setup/system-update.sh +++ b/tabs/system-setup/system-update.sh @@ -3,13 +3,15 @@ . ../common-script.sh fastUpdate() { - case ${PACKAGER} in + 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 + "$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 +20,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 + 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 +64,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}" @@ -91,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 } @@ -100,4 +113,4 @@ checkAURHelper checkEscalationTool fastUpdate updateSystem -updateFlatpaks \ No newline at end of file +updateFlatpaks diff --git a/tabs/system-setup/tab_data.toml b/tabs/system-setup/tab_data.toml index e72cb4c59..7d7c41b8d 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]] @@ -26,32 +29,68 @@ name = "Fedora" [[data.preconditions]] matches = true data = "command_exists" -values = ["dnf"] +values = ["dnf"] + +[[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 = "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/" 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" + [[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" +name = "SSH-Samba Setup" +script = "5-samba-ssh-setup.sh" + +[[data]] +name = "Docker Setup" +script = "6-docker-setup.sh" + [[data]] name = "Grub Theme Setup" -script = "7-grub-theme.sh" \ No newline at end of file +script = "7-grub-theme.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 diff --git a/tabs/utils/auto-login.sh b/tabs/utils/auto-login.sh new file mode 100644 index 000000000..aa73211c5 --- /dev/null +++ b/tabs/utils/auto-login.sh @@ -0,0 +1,178 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to list common session options +list_sessions() { + 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 + 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) + printf "Enter custom session name (e.g., mysession.desktop): " + read -r session ;; + *) + printf "Invalid option selected.\n" + exit 1 ;; + esac +} + +# Function to configure LightDM +configure_lightdm() { + printf "Configuring LightDM for autologin...\n" + + printf "Enter username for LightDM autologin: " + read -r user + + $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" + + printf "LightDM has been configured for autologin.\n" +} + +# Function to remove LightDM autologin +remove_lightdm_autologin() { + printf "Removing LightDM autologin configuration...\n" + $ESCALATION_TOOL rm -f /etc/lightdm/lightdm.conf.d/50-autologin.conf + printf "LightDM autologin configuration has been removed.\n" +} + +# Function to configure GDM +configure_gdm() { + printf "Configuring GDM for autologin...\n" + + printf "Enter username for GDM autologin: " + read -r user + + $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" + + printf "GDM has been configured for autologin.\n" +} + +# Function to remove GDM autologin +remove_gdm_autologin() { + 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 + printf "GDM autologin configuration has been removed.\n" +} + +# Function to configure SDDM +configure_sddm() { + printf "Configuring SDDM for autologin...\n" + + printf "Enter username for SDDM autologin: " + read -r user + list_sessions # Show session options + + $ESCALATION_TOOL "printf '[Autologin]' > /etc/sddm.conf" + $ESCALATION_TOOL "printf 'User=$user' >> /etc/sddm.conf" + $ESCALATION_TOOL "printf 'Session=$session' >> /etc/sddm.conf" + + printf "SDDM has been configured for autologin.\n" +} + +# Function to remove SDDM autologin +remove_sddm_autologin() { + printf "Removing SDDM autologin configuration...\n" + $ESCALATION_TOOL sed -i '/\[Autologin\]/,+2d' /etc/sddm.conf + printf "SDDM autologin configuration has been removed.\n" +} + +# Function to configure LXDM +configure_lxdm() { + printf "Configuring LXDM for autologin...\n" + + 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 + + printf "LXDM has been configured for autologin.\n" +} + +# Function to remove LXDM autologin +remove_lxdm_autologin() { + 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 + printf "LXDM autologin configuration has been removed.\n" +} + +# Function to configure or remove autologin based on user choice +configure_or_remove_autologin() { + 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 + 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 + 1) configure_lightdm ;; + 2) configure_gdm ;; + 3) configure_sddm ;; + 4) configure_lxdm ;; + *) printf "Invalid option selected.\n" ;; + esac + elif [ "$action_choice" = "2" ]; then + 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 + 1) remove_lightdm_autologin ;; + 2) remove_gdm_autologin ;; + 3) remove_sddm_autologin ;; + 4) remove_lxdm_autologin ;; + *) printf "Invalid option selected.\n" ;; + esac + else + printf "Invalid choice. Exiting...\n" + exit 1 + fi + + 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 508d3708a..ba8c8c9f0 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 @@ -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}" @@ -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,10 +66,10 @@ 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 - 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 @@ -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 @@ -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 @@ -147,5 +147,6 @@ remove_device() { # Initialize checkEnv +checkEscalationTool setupBluetooth main_menu diff --git a/tabs/utils/create-bootable-usb.sh b/tabs/utils/create-bootable-usb.sh new file mode 100644 index 000000000..e96c73a93 --- /dev/null +++ b/tabs/utils/create-bootable-usb.sh @@ -0,0 +1,194 @@ +#!/bin/sh -e + +. ../common-script.sh + +# Function to display usage instructions +usage() { + printf "%b\n" "${RED} Usage: $0 ${RC}" + 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}" + printf "\n" + $ESCALATION_TOOL lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL + printf "\n" +} + +# 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 + printf "\n" # New line after every 6 versions + fi + + COUNTER=$((COUNTER + 1)) + done + 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}" +} + +# 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}" + 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) + 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 + 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}" + 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 + + 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 + printf "Enter the USB device (e.g., /dev/sdX): " + read -r 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/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/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/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" ;; 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 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}" 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}" diff --git a/tabs/utils/monitor-control/set_brightness.sh b/tabs/utils/monitor-control/set_brightness.sh new file mode 100644 index 000000000..ab97b70a0 --- /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 + + printf "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 + 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}" + printf "Press [Enter] to continue..." + read dummy + 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 + 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 + 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}") + + 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}" + 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/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}" diff --git a/tabs/utils/monitor-control/set_resolutions.sh b/tabs/utils/monitor-control/set_resolutions.sh index 1a6c6fa71..85d7e0cb5 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 @@ -39,11 +41,11 @@ 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 - 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" diff --git a/tabs/utils/monitor-control/utility_functions.sh b/tabs/utils/monitor-control/utility_functions.sh index 48b4c8da9..5bccd94da 100755 --- a/tabs/utils/monitor-control/utility_functions.sh +++ b/tabs/utils/monitor-control/utility_functions.sh @@ -4,77 +4,79 @@ # 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 + case "$PACKAGER" in pacman) - $ESCALATION_TOOL "${PACKAGER}" -S --noconfirm xorg-xrandr + "$ESCALATION_TOOL" "$PACKAGER" -S --noconfirm xorg-xrandr ;; - apt-get) - $ESCALATION_TOOL "${PACKAGER}" install -y x11-xserver-utils + apt-get|nala) + "$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 - 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 +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" 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 } # 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 @@ -83,4 +85,5 @@ confirm_action() { } checkEnv -setup_xrandr \ No newline at end of file +checkEscalationTool +setup_xrandr diff --git a/tabs/utils/numlock.sh b/tabs/utils/numlock.sh index 2b23c3f16..cbae21f35 100755 --- a/tabs/utils/numlock.sh +++ b/tabs/utils/numlock.sh @@ -8,8 +8,8 @@ # Create a script to toggle numlock create_file() { - echo "Creating script..." - $ESCALATION_TOOL tee "/usr/local/bin/numlock" >/dev/null <<'EOF' + printf "Creating script...\n" + "$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' + printf "Creating service...\n" + "$ESCALATION_TOOL" tee "/etc/systemd/system/numlock.service" >/dev/null <<'EOF' [Unit] Description=numlock @@ -51,14 +51,14 @@ 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 - echo "Numlock will be enabled on boot" + "$ESCALATION_TOOL" systemctl enable numlock.service --quiet + printf "Numlock will be enabled on boot\n" else - $ESCALATION_TOOL systemctl disable numlock.service --quiet - echo "Numlock will not be enabled on boot" - + "$ESCALATION_TOOL" systemctl disable numlock.service --quiet + printf "Numlock will not be enabled on boot\n" fi } +checkEnv checkEscalationTool numlockSetup diff --git a/tabs/utils/ollama.sh b/tabs/utils/ollama.sh index 969d62a3b..f93cc7416 100644 --- a/tabs/utils/ollama.sh +++ b/tabs/utils/ollama.sh @@ -6,13 +6,12 @@ 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 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 } @@ -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/power-profile.sh b/tabs/utils/power-profile.sh new file mode 100644 index 000000000..3cc1823fc --- /dev/null +++ b/tabs/utils/power-profile.sh @@ -0,0 +1,100 @@ +#!/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}" + printf "%b" "Enter your choice [1/2]: " + read -r 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/service-control.sh b/tabs/utils/service-control.sh index 96aba4fcd..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..." - $ESCALATION_TOOL systemctl list-units --type=service --all --no-legend | awk '{print $1}' | sed 's/\.service//' | more + 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..." - $ESCALATION_TOOL systemctl list-unit-files --type=service --state=enabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more + 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..." - $ESCALATION_TOOL systemctl list-unit-files --type=service --state=disabled --no-legend | awk '{print $1}' | sed 's/\.service//' | more + 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:" - $ESCALATION_TOOL systemctl list-units --type=service --state=running --no-pager | head -n -6 | awk 'NR>1 {print $1}' | more + 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!" + if "$ESCALATION_TOOL" systemctl list-units --type=service --all --no-legend | grep -q "$SERVICE_NAME.service"; then + 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" + 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." + 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 } # 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..." + printf "Stopping and disabling the service...\n" $ESCALATION_TOOL systemctl stop "$SERVICE_NAME" $ESCALATION_TOOL systemctl disable "$SERVICE_NAME" - echo "Removing the service file..." + printf "Removing the service file...\n" $ESCALATION_TOOL rm -f "$SERVICE_FILE" $ESCALATION_TOOL systemctl daemon-reload - - echo "Service $SERVICE_NAME has been removed." + 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." + 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." + 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." + 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." + 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 @@ -227,30 +225,30 @@ 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 - echo "Service $SERVICE_NAME has been created and is ready to be started." + 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 } 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/tab_data.toml b/tabs/utils/tab_data.toml index bf05a1b36..d09496ff5 100644 --- a/tabs/utils/tab_data.toml +++ b/tabs/utils/tab_data.toml @@ -2,24 +2,49 @@ 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 = "Crypto tool" +script = "encrypt_decrypt_tool.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]] +name = "Auto Login" +script = "auto-login.sh" + +[[data]] +name = "Bootable USB Creator" +script = "create-bootable-usb.sh" + +[[data]] +name = "Auto Power Profiling" +script = "power-profile.sh" + +[[data]] +name = "Timeshift Backup" +script = "timeshift.sh" + [[data]] name = "Monitor Control" @@ -35,41 +60,79 @@ 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 + +[[data.entries]] +name = "Set Brightness" +script = "monitor-control/set_brightness.sh" +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/timeshift.sh b/tabs/utils/timeshift.sh new file mode 100644 index 000000000..ec69081f2 --- /dev/null +++ b/tabs/utils/timeshift.sh @@ -0,0 +1,160 @@ +#!/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 + printf "%b\n" "${GREEN}Timeshift is already installed.${RC}" + fi +} + +# Function to display the menu +display_menu() { + clear + printf "%b\n" "${CYAN}Timeshift CLI Automation${RC}" + 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}" +} + +# Function to list snapshots +list_snapshots() { + printf "%b\n" "${CYAN}Listing snapshots...${RC}" + $ESCALATION_TOOL timeshift --list-snapshots +} + +# Function to list devices +list_devices() { + printf "%b\n" "${CYAN}Listing available devices...${RC}" + $ESCALATION_TOOL timeshift --list-devices +} + +# Function to create a new snapshot +create_snapshot() { + printf "%b\n" "${CYAN}Enter a comment for the snapshot (optional): ${RC}" + read -r COMMENT + 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 + printf "%b\n" "${CYAN}Creating snapshot with no comment or tag...${RC}" + $ESCALATION_TOOL timeshift --create + elif [ -z "$TAG" ]; then + printf "%b\n" "${CYAN}Creating snapshot with no tag...${RC}" + $ESCALATION_TOOL timeshift --create --comments "$COMMENT" + else + printf "%b\n" "${CYAN}Creating snapshot with tag: $TAG...${RC}" + $ESCALATION_TOOL timeshift --create --comments "$COMMENT" --tags "$TAG" + fi + + if [ $? -eq 0 ]; then + printf "%b\n" "${GREEN}Snapshot created successfully.${RC}" + else + printf "%b\n" "${RED}Snapshot creation failed.${RC}" + fi +} + +# Function to restore a snapshot +restore_snapshot() { + list_snapshots + + printf "%b\n" "${CYAN}Enter the snapshot name you want to restore: ${RC}" + read -r SNAPSHOT + printf "%b\n" "${CYAN}Enter the target device (e.g., /dev/sda1): ${RC}" + read -r TARGET_DEVICE + 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\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 + + if [ $? -eq 0 ]; then + printf "%b\n" "${GREEN}Snapshot restored successfully.${RC}" + else + printf "%b\n" "${RED}Snapshot restore failed.${RC}" + fi +} + +# Function to delete a snapshot +delete_snapshot() { + list_snapshots + + printf "%b\n" "${CYAN}Enter the snapshot name you want to delete: ${RC}" + read -r SNAPSHOT + + printf "%b\n" "${YELLOW}Deleting snapshot $SNAPSHOT...${RC}" + $ESCALATION_TOOL timeshift --delete --snapshot "$SNAPSHOT" --yes + + if [ $? -eq 0 ]; then + printf "%b\n" "${GREEN}Snapshot deleted successfully.${RC}" + else + printf "%b\n" "${RED}Snapshot deletion failed.${RC}" + fi +} + +# Function to delete all snapshots +delete_all_snapshots() { + printf "%b\n" "${RED}WARNING: This will delete all snapshots!${RC}" + printf "%b\n" "${CYAN}Are you sure? (yes/no): ${RC}" + read -r CONFIRMATION + + if [ "$CONFIRMATION" = "yes" ]; then + 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}" + 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 + 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 +checkEscalationTool +install_timeshift +main_menu 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 diff --git a/tabs/utils/wifi-control.sh b/tabs/utils/wifi-control.sh old mode 100644 new mode 100755 index 036e2a28c..71abcce51 --- 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 @@ -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}" @@ -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 @@ -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 + printf "Press any key to return to the main menu...\n" + read -r dummy } # Function to turn WiFi on @@ -85,8 +85,8 @@ 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 + printf "Press any key to return to the main menu...\n" + read -r dummy } # Function to turn WiFi off @@ -98,8 +98,8 @@ 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 + printf "Press any key to return to the main menu...\n" + 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 + printf "Press any key to return to the main menu...\n" + 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 - echo "0. Exit to main menu" - echo -n "$prompt_msg" + done < "$temp_file" + + printf "0. Exit to main menu\n" + printf "%s" "$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 - echo + printf "Enter password for SSID %s: " "$ssid" + read password + printf "\n" 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 + + printf "Press any key to return to the selection menu...\n" + 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 @@ -186,5 +174,6 @@ remove_network() { # Initialize checkEnv +checkEscalationTool setupNetworkManager -main_menu +main_menu \ No newline at end of file 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..ad77c36f2 100644 --- a/tui/src/floating_text.rs +++ b/tui/src/floating_text.rs @@ -8,21 +8,29 @@ use ratatui::{ layout::Rect, style::{Style, Stylize}, text::Line, - widgets::{Block, Borders, List}, + widgets::{Block, Borders, Clear, 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) @@ -91,6 +107,9 @@ impl FloatContent for FloatingText { .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 27474ea99..9d10e4dac 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| { [ @@ -114,47 +114,56 @@ 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(Shortcut::new(vec!["h", "Left"], "Focus tab list")); hints.push(get_list_item_shortcut(state)); } else { 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")); + 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, } } + Focus::TabList => ShortcutList { 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"), ], }, + Focus::FloatingWindow(ref float) => float.get_shortcut_list(), } .draw(frame, area); diff --git a/tui/src/state.rs b/tui/src/state.rs index 1d11ce80f..d5d943a71 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, @@ -26,13 +26,14 @@ 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 /// 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,46 @@ 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; + } + + // 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) { @@ -208,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() => @@ -234,6 +317,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() { @@ -243,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(), _ => {} @@ -262,7 +345,7 @@ impl AppState { ); } - /// 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 { @@ -291,6 +374,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); @@ -353,11 +453,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);