diff --git a/bin/omakub-sub/menu.sh b/bin/omakub-sub/menu.sh index c573c7c05..611f40411 100644 --- a/bin/omakub-sub/menu.sh +++ b/bin/omakub-sub/menu.sh @@ -1,7 +1,7 @@ #!/bin/bash if [ $# -eq 0 ]; then - SUB=$(gum choose "Theme" "Font" "Update" "Install" "Uninstall" "Manual" "Quit" --height 10 --header "" | tr '[:upper:]' '[:lower:]') + SUB=$(gum choose "Theme" "Font" "Shell" "Update" "Install" "Uninstall" "Manual" "Quit" --height 11 --header "" | tr '[:upper:]' '[:lower:]') else SUB=$1 fi diff --git a/bin/omakub-sub/shell-switch.sh b/bin/omakub-sub/shell-switch.sh new file mode 100644 index 000000000..01bf98f76 --- /dev/null +++ b/bin/omakub-sub/shell-switch.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +target_shell=$1 +current_shell=$(basename "$SHELL") +timestamp=$(date +%Y%m%d_%H%M%S) +backup_dir="$HOME/.omakub-shell-backups/$timestamp" + +# ============================================ +# Confirmation +# ============================================ +echo "" +gum style --border double --padding "1 2" --border-foreground 212 \ + "SHELL SWITCH" \ + "" \ + "From: $current_shell" \ + "To: $target_shell" \ + "" \ + "This will:" \ + " - Backup current config" \ + " - Install fresh $target_shell config" \ + " - Change default login shell" \ + "" \ + "Note: You'll need to manually copy" \ + "your customizations to the new shell." + +echo "" +if ! gum confirm "Proceed?"; then + echo "Cancelled." + sleep 1 + return 0 +fi + +echo "" +gum style --foreground 214 "Administrator privileges required." +echo "" + +# ============================================ +# Backup +# ============================================ +echo "Creating backup..." +mkdir -p "$backup_dir" + +case $current_shell in + bash) + [ -f ~/.bashrc ] && cp ~/.bashrc "$backup_dir/" + [ -f ~/.inputrc ] && cp ~/.inputrc "$backup_dir/" + ;; + zsh) + [ -f ~/.zshrc ] && cp ~/.zshrc "$backup_dir/" + ;; +esac +echo "Backup saved: $backup_dir" + +# ============================================ +# Extract customizations +# ============================================ +echo "Extracting customizations..." +customizations="$backup_dir/customizations.sh" + +case $current_shell in + bash) + if [ -f ~/.bashrc ]; then + # Extract lines after the Omakub source line and EDITOR settings + sed -n '/^# Add your customizations/,$p' ~/.bashrc > "$customizations" 2>/dev/null + # If that didn't work, try extracting after SUDO_EDITOR + if [ ! -s "$customizations" ]; then + sed -n '/^export SUDO_EDITOR/,$p' ~/.bashrc | tail -n +2 > "$customizations" 2>/dev/null + fi + fi + ;; + zsh) + if [ -f ~/.zshrc ]; then + sed -n '/^# Add your customizations/,$p' ~/.zshrc > "$customizations" 2>/dev/null + if [ ! -s "$customizations" ]; then + sed -n '/^export SUDO_EDITOR/,$p' ~/.zshrc | tail -n +2 > "$customizations" 2>/dev/null + fi + fi + ;; +esac + +if [ -s "$customizations" ]; then + lines=$(wc -l < "$customizations") + echo "Found $lines lines to migrate" +else + rm -f "$customizations" + echo "No customizations found" +fi + +# ============================================ +# Install target shell +# ============================================ +case $target_shell in + zsh) + if ! command -v zsh &> /dev/null; then + echo "Installing Zsh..." + sudo apt install -y zsh + if ! command -v zsh &> /dev/null; then + gum style --foreground 196 "Installation failed!" + return 1 + fi + echo "Zsh installed" + fi + + zsh_path=$(which zsh) + grep -q "$zsh_path" /etc/shells || echo "$zsh_path" | sudo tee -a /etc/shells > /dev/null + + echo "Configuring Zsh..." + cp $OMAKUB_PATH/configs/zshrc ~/.zshrc + + echo "Setting default shell..." + sudo chsh -s "$zsh_path" $USER + echo "Default shell: Zsh" + ;; + + bash) + bash_path=$(which bash) + + echo "Configuring Bash..." + cp $OMAKUB_PATH/configs/bashrc ~/.bashrc + cp $OMAKUB_PATH/configs/inputrc ~/.inputrc + + echo "Setting default shell..." + sudo chsh -s "$bash_path" $USER + echo "Default shell: Bash" + ;; +esac + +# Record choice +echo "$target_shell" > ~/.local/share/omakub/.shell-choice + +# ============================================ +# Complete +# ============================================ +echo "" +gum style --border double --padding "1 2" --border-foreground 82 \ + "SWITCH COMPLETE" \ + "" \ + "Changed: $current_shell -> $target_shell" \ + "Backup: $backup_dir" + +if [ -f "$customizations" ]; then + echo "" + gum style --foreground 214 \ + "Your customizations were saved to:" \ + " $customizations" \ + "" \ + "Review and copy them to your new" \ + "shell config (~/.${target_shell}rc)." \ + "Some commands may need adjustment" \ + "for the new shell (e.g., init bash -> init zsh)." +fi + +echo "" +gum style \ + "To activate:" \ + " - Log out and back in, OR" \ + " - Run: exec $target_shell" + +echo "" +if gum confirm "Start $target_shell now?"; then + exec $target_shell +fi diff --git a/bin/omakub-sub/shell.sh b/bin/omakub-sub/shell.sh new file mode 100644 index 000000000..c57ff6199 --- /dev/null +++ b/bin/omakub-sub/shell.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +current_shell=$(basename "$SHELL") + +echo "" +gum style --foreground 212 --bold "Shell Management" +echo "" +echo "Current shell: $current_shell" +echo "" + +CHOICE=$(gum choose "Switch to Bash" "Switch to Zsh" "Shell Info" "<< Back" --header "") + +case "$CHOICE" in + "Switch to Bash") + if [[ "$current_shell" == "bash" ]]; then + gum style --foreground 208 "Already using Bash!" + sleep 2 + else + source $OMAKUB_PATH/bin/omakub-sub/shell-switch.sh bash + fi + ;; + + "Switch to Zsh") + if [[ "$current_shell" == "zsh" ]]; then + gum style --foreground 208 "Already using Zsh!" + sleep 2 + else + source $OMAKUB_PATH/bin/omakub-sub/shell-switch.sh zsh + fi + ;; + + "Shell Info") + echo "" + echo "Current shell: $current_shell" + echo "Default shell: $(getent passwd $USER | cut -d: -f7)" + echo "" + echo "Bash: $(bash --version | head -1)" + if command -v zsh &> /dev/null; then + echo "Zsh: $(zsh --version)" + else + echo "Zsh: Not installed" + fi + echo "" + echo "Shell choice file: ~/.local/share/omakub/.shell-choice" + if [ -f ~/.local/share/omakub/.shell-choice ]; then + echo "Recorded choice: $(cat ~/.local/share/omakub/.shell-choice)" + fi + echo "" + echo "Config location:" + case "$current_shell" in + bash) echo " ~/.bashrc" ;; + zsh) echo " ~/.zshrc" ;; + esac + echo "" + read -p "Press Enter to continue..." + ;; + + *) + # Back to menu + ;; +esac + +clear +source $OMAKUB_PATH/bin/omakub diff --git a/configs/zshrc b/configs/zshrc new file mode 100644 index 000000000..0d1340e4e --- /dev/null +++ b/configs/zshrc @@ -0,0 +1,7 @@ +source ~/.local/share/omakub/defaults/zsh/rc + +# Editor used by CLI +export EDITOR="nvim" +export SUDO_EDITOR="$EDITOR" + +# Add your customizations below this line diff --git a/defaults/bash/rc b/defaults/bash/rc index 99a8f5a9f..b2022fe4f 100644 --- a/defaults/bash/rc +++ b/defaults/bash/rc @@ -1,5 +1,15 @@ +# ============================================ +# OMAKUB BASH RC - Main Loader +# ============================================ + +# Bash-specific settings first source ~/.local/share/omakub/defaults/bash/shell -source ~/.local/share/omakub/defaults/bash/aliases -source ~/.local/share/omakub/defaults/bash/functions + +# Shared configs (bash/zsh compatible) +source ~/.local/share/omakub/defaults/shared/environment.sh +source ~/.local/share/omakub/defaults/shared/aliases.sh +source ~/.local/share/omakub/defaults/shared/functions.sh + +# Bash-specific configs source ~/.local/share/omakub/defaults/bash/prompt source ~/.local/share/omakub/defaults/bash/init diff --git a/defaults/bash/shell b/defaults/bash/shell index b27935758..7cd3b1cfb 100644 --- a/defaults/bash/shell +++ b/defaults/bash/shell @@ -1,14 +1,11 @@ -# History control +# ============================================ +# OMAKUB BASH-SPECIFIC SHELL SETTINGS +# ============================================ + +# Bash-specific options shopt -s histappend HISTCONTROL=ignoreboth -HISTSIZE=32768 -HISTFILESIZE="${HISTSIZE}" +set +h # Disable hashing for dynamic PATH -# Autocompletion +# Bash completion source /usr/share/bash-completion/bash_completion - -# Set complete path -export PATH="./bin:$HOME/.local/bin:$HOME/.local/share/omakub/bin:$PATH" -set +h - -export OMAKUB_PATH="$HOME/.local/share/omakub" diff --git a/defaults/bash/aliases b/defaults/shared/aliases.sh similarity index 78% rename from defaults/bash/aliases rename to defaults/shared/aliases.sh index bfa1a6945..66575883e 100644 --- a/defaults/bash/aliases +++ b/defaults/shared/aliases.sh @@ -1,3 +1,8 @@ +# ============================================ +# OMAKUB SHARED ALIASES +# Compatible with: bash, zsh +# ============================================ + # File system alias ls='eza -lh --group-directories-first --icons=auto' alias lsa='ls -a' @@ -13,7 +18,6 @@ alias ...='cd ../..' alias ....='cd ../../..' # Tools -n() { if [ "$#" -eq 0 ]; then nvim .; else nvim "$@"; fi; } alias g='git' alias d='docker' alias r='rails' diff --git a/defaults/shared/environment.sh b/defaults/shared/environment.sh new file mode 100644 index 000000000..ae681d21f --- /dev/null +++ b/defaults/shared/environment.sh @@ -0,0 +1,14 @@ +# ============================================ +# OMAKUB SHARED ENVIRONMENT +# Compatible with: bash, zsh +# ============================================ + +# History +export HISTSIZE=32768 +export HISTFILESIZE="${HISTSIZE}" + +# Path setup +export PATH="./bin:$HOME/.local/bin:$HOME/.local/share/omakub/bin:$PATH" + +# Omakub +export OMAKUB_PATH="$HOME/.local/share/omakub" diff --git a/defaults/bash/functions b/defaults/shared/functions.sh similarity index 86% rename from defaults/bash/functions rename to defaults/shared/functions.sh index a3bf5ee2b..f9a5c67a7 100644 --- a/defaults/bash/functions +++ b/defaults/shared/functions.sh @@ -1,3 +1,17 @@ +# ============================================ +# OMAKUB SHARED FUNCTIONS +# Compatible with: bash, zsh +# ============================================ + +# Neovim launcher +n() { + if [ "$#" -eq 0 ]; then + nvim . + else + nvim "$@" + fi +} + # Compression compress() { tar -czf "${1%/}.tar.gz" "${1%/}"; } alias decompress="tar -xzf" @@ -112,21 +126,26 @@ app2folder-remove() { if [[ "$CURRENT_APPS" == *"$DESKTOP_FILE"* ]]; then local RAW_LIST=$(echo "$CURRENT_APPS" | tr -d "[]'") - IFS=',' read -ra APPS_ARRAY <<< "$RAW_LIST" - # Filter out the app to be removed - local NEW_APPS=() - for app in "${APPS_ARRAY[@]}"; do + # Split by comma - compatible with both bash and zsh + local NEW_APPS="" + local OLDIFS="$IFS" + IFS=',' + for app in $RAW_LIST; do + IFS="$OLDIFS" app=$(echo "$app" | xargs) # trim spaces if [[ "$app" != "$DESKTOP_FILE" && -n "$app" ]]; then - NEW_APPS+=("'$app'") + if [[ -n "$NEW_APPS" ]]; then + NEW_APPS="$NEW_APPS,'$app'" + else + NEW_APPS="'$app'" + fi fi + IFS=',' done + IFS="$OLDIFS" - # Join list again - local NEW_LIST=$(IFS=, ; echo "${NEW_APPS[*]}") - - gsettings set "$SCHEMA" apps "[$NEW_LIST]" + gsettings set "$SCHEMA" apps "[$NEW_APPS]" fi } diff --git a/defaults/zsh/completions.zsh b/defaults/zsh/completions.zsh new file mode 100644 index 000000000..81da02985 --- /dev/null +++ b/defaults/zsh/completions.zsh @@ -0,0 +1,37 @@ +# ============================================ +# OMAKUB ZSH COMPLETIONS & KEY BINDINGS +# ============================================ + +autoload -Uz compinit && compinit + +# ------------------------------------------ +# Key Bindings (equivalent to bash inputrc) +# ------------------------------------------ + +# Arrow keys search history matching current input (like bash inputrc) +autoload -Uz up-line-or-beginning-search down-line-or-beginning-search +zle -N up-line-or-beginning-search +zle -N down-line-or-beginning-search +bindkey "^[[A" up-line-or-beginning-search # Up arrow +bindkey "^[[B" down-line-or-beginning-search # Down arrow + +# ------------------------------------------ +# Completion Settings +# ------------------------------------------ + +# Case-insensitive completion +zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' + +# Menu selection +zstyle ':completion:*' menu select + +# Colored completions +zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" + +# Group completions +zstyle ':completion:*:descriptions' format '%F{yellow}-- %d --%f' +zstyle ':completion:*:warnings' format '%F{red}-- no matches --%f' + +# Cache completions for faster loading +zstyle ':completion:*' use-cache on +zstyle ':completion:*' cache-path ~/.zsh/cache diff --git a/defaults/zsh/init b/defaults/zsh/init new file mode 100644 index 000000000..1bb5ae8e2 --- /dev/null +++ b/defaults/zsh/init @@ -0,0 +1,28 @@ +# ============================================ +# OMAKUB ZSH TOOL INITIALIZATION +# ============================================ + +# mise (version manager) +# Note: mise's activation script uses $+functions[...] syntax which is +# incompatible with KSH_ARRAYS. Temporarily disable it during activation. +if command -v mise &> /dev/null; then + setopt NO_KSH_ARRAYS + eval "$(mise activate zsh)" + setopt KSH_ARRAYS +fi + +# zoxide (smart cd) +if command -v zoxide &> /dev/null; then + eval "$(zoxide init zsh)" +fi + +# fzf (fuzzy finder) +if command -v fzf &> /dev/null; then + # Try different possible locations for fzf zsh files + if [[ -f /usr/share/doc/fzf/examples/key-bindings.zsh ]]; then + source /usr/share/doc/fzf/examples/key-bindings.zsh + fi + if [[ -f /usr/share/doc/fzf/examples/completion.zsh ]]; then + source /usr/share/doc/fzf/examples/completion.zsh + fi +fi diff --git a/defaults/zsh/prompt b/defaults/zsh/prompt new file mode 100644 index 000000000..e6917767b --- /dev/null +++ b/defaults/zsh/prompt @@ -0,0 +1,12 @@ +# ============================================ +# OMAKUB ZSH PROMPT +# ============================================ + +# Minimal prompt matching Omakub aesthetic (Nerd Font arrow icon) +# Using the actual unicode character to avoid escape issues +PROMPT=$'%F{white}\uf0a9%f ' + +# Working directory in terminal title +precmd() { + print -Pn "\e]0;%~\a" +} diff --git a/defaults/zsh/rc b/defaults/zsh/rc new file mode 100644 index 000000000..f83fcb5ed --- /dev/null +++ b/defaults/zsh/rc @@ -0,0 +1,16 @@ +# ============================================ +# OMAKUB ZSH RC - Main Loader +# ============================================ + +# Zsh-specific settings first +source ~/.local/share/omakub/defaults/zsh/shell + +# Shared configs (bash/zsh compatible) +source ~/.local/share/omakub/defaults/shared/environment.sh +source ~/.local/share/omakub/defaults/shared/aliases.sh +source ~/.local/share/omakub/defaults/shared/functions.sh + +# Zsh-specific configs +source ~/.local/share/omakub/defaults/zsh/prompt +source ~/.local/share/omakub/defaults/zsh/init +source ~/.local/share/omakub/defaults/zsh/completions.zsh diff --git a/defaults/zsh/shell b/defaults/zsh/shell new file mode 100644 index 000000000..dd93b2999 --- /dev/null +++ b/defaults/zsh/shell @@ -0,0 +1,21 @@ +# ============================================ +# OMAKUB ZSH-SPECIFIC SHELL SETTINGS +# ============================================ + +# Zsh options for bash compatibility +setopt NO_CASE_GLOB # Case-insensitive globbing +setopt NULL_GLOB # No error on failed glob +setopt KSH_ARRAYS # 0-indexed arrays like bash +setopt SH_WORD_SPLIT # Word splitting like bash +setopt NO_NOMATCH # Pass failed globs as literal + +# Zsh-specific enhancements +setopt AUTO_CD # cd by typing directory name +setopt CORRECT # Command correction +setopt APPEND_HISTORY # Append to history +setopt HIST_IGNORE_DUPS # No duplicate history entries +setopt HIST_IGNORE_SPACE # Ignore commands starting with space +setopt SHARE_HISTORY # Share history between sessions + +# History file location +HISTFILE=~/.zsh_history diff --git a/install/first-run-choices.sh b/install/first-run-choices.sh index 4d92f8824..efece931e 100644 --- a/install/first-run-choices.sh +++ b/install/first-run-choices.sh @@ -1,5 +1,9 @@ #!/bin/bash +# Shell selection +AVAILABLE_SHELLS=("Bash (default)" "Zsh") +export OMAKUB_SHELL=$(gum choose "${AVAILABLE_SHELLS[@]}" --header "Select your preferred shell") + # Only ask for default desktop app choices when running Gnome if [[ "$XDG_CURRENT_DESKTOP" == *"GNOME"* ]]; then OPTIONAL_APPS=("1password" "Spotify" "Zoom" "Dropbox") diff --git a/install/terminal/a-shell.sh b/install/terminal/a-shell.sh index c5f11920c..fe34b4ff3 100644 --- a/install/terminal/a-shell.sh +++ b/install/terminal/a-shell.sh @@ -1,12 +1,74 @@ #!/bin/bash -# Configure the bash shell using Omakub defaults -[ -f ~/.bashrc ] && mv ~/.bashrc ~/.bashrc.bak -cp ~/.local/share/omakub/configs/bashrc ~/.bashrc +# ============================================ +# OMAKUB SHELL SETUP +# Supports: Bash, Zsh +# ============================================ -# Load the PATH for use later in the installers -source ~/.local/share/omakub/defaults/bash/shell +# Normalize shell selection +case "$OMAKUB_SHELL" in + Zsh|zsh|"Zsh") selected_shell="zsh" ;; + *) selected_shell="bash" ;; +esac -[ -f ~/.inputrc ] && mv ~/.inputrc ~/.inputrc.bak -# Configure the inputrc using Omakub defaults -cp ~/.local/share/omakub/configs/inputrc ~/.inputrc +echo "Setting up shell: $selected_shell" + +# ============================================ +# ZSH SETUP +# ============================================ +if [[ "$selected_shell" == "zsh" ]]; then + + # Install zsh if needed + if ! command -v zsh &> /dev/null; then + echo "Installing Zsh..." + sudo apt install -y zsh + + if ! command -v zsh &> /dev/null; then + echo "Zsh installation failed. Falling back to Bash." + selected_shell="bash" + fi + fi + + if [[ "$selected_shell" == "zsh" ]]; then + # Register in /etc/shells if needed + zsh_path=$(which zsh) + if ! grep -q "$zsh_path" /etc/shells; then + echo "$zsh_path" | sudo tee -a /etc/shells > /dev/null + fi + + # Backup existing zsh configs + [ -f ~/.zshrc ] && mv ~/.zshrc ~/.zshrc.pre-omakub.bak + [ -f ~/.zshenv ] && mv ~/.zshenv ~/.zshenv.pre-omakub.bak + + # Install Omakub zsh config + cp ~/.local/share/omakub/configs/zshrc ~/.zshrc + + # Set as default shell + sudo chsh -s "$zsh_path" $USER + + # Load environment for remaining installers + source ~/.local/share/omakub/defaults/shared/environment.sh + fi +fi + +# ============================================ +# BASH SETUP (default or fallback) +# ============================================ +if [[ "$selected_shell" == "bash" ]]; then + + # Backup existing bash configs + [ -f ~/.bashrc ] && mv ~/.bashrc ~/.bashrc.bak + [ -f ~/.inputrc ] && mv ~/.inputrc ~/.inputrc.bak + + # Install Omakub bash config + cp ~/.local/share/omakub/configs/bashrc ~/.bashrc + cp ~/.local/share/omakub/configs/inputrc ~/.inputrc + + # Load environment for remaining installers + source ~/.local/share/omakub/defaults/shared/environment.sh +fi + +# ============================================ +# RECORD SHELL CHOICE +# ============================================ +echo "$selected_shell" > ~/.local/share/omakub/.shell-choice