Son aktivite 22 hours ago

Revizyon 20fdf970a5e86d0871b9712f09c9374dec4bfc49

README.md Ham

Bash Script Installer for Zsh

The "Bash Script Installer" simplifies the setup of Zsh.

Zsh

Ubuntu

bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD/zsh_ubuntu.sh)"

MacOS

bash -c "$(curl -fsSL https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD/zsh_macos.sh)"
zsh_macos.sh Ham
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# CONFIG
20# =============================
21CONFIG_FILES=(
22 ".alias|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/alias"
23 ".func|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/func"
24 ".pathrc|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/pathrc"
25 ".sourcerc|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/sourcerc"
26 ".vimrc|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/vimrc"
27 ".zshrc|https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/zshrc"
28)
29
30# =============================
31# REQUIREMENTS
32# =============================
33check_requirements() {
34 if [[ $EUID -eq 0 ]]; then
35 err "Do not run as root on macOS"
36 exit 1
37 fi
38}
39
40# =============================
41# INSTALLATION FUNCTIONS
42# =============================
43configure_git() {
44 log "Configuring Git..."
45 read -p "Git name (leave empty to skip): " name
46 read -p "Git email (leave empty to skip): " email
47
48 if [[ -n "$name" ]]; then
49 git config --global user.name "$name"
50 fi
51 if [[ -n "$email" ]]; then
52 git config --global user.email "$email"
53 fi
54 ok "Git configured"
55}
56
57install_oh_my_zsh() {
58 if [[ -d "$HOME/.oh-my-zsh" ]]; then
59 ok "Oh My Zsh already installed"
60 return
61 fi
62
63 log "Installing Oh My Zsh..."
64 RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
65 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
66 ok "Oh My Zsh installed"
67}
68
69install_plugins() {
70 log "Installing plugins..."
71 local dir="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins"
72 [[ -d "$dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
73 [[ -d "$dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
74 ok "Plugins installed"
75}
76
77install_theme() {
78 log "Installing Spaceship theme..."
79 local themes="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes"
80 local dir="$themes/spaceship-prompt"
81 [[ -d "$dir" ]] || git clone https://github.com/spaceship-prompt/spaceship-prompt.git "$dir" --depth=1
82 ln -sf "$dir/spaceship.zsh-theme" "$themes/spaceship.zsh-theme"
83 ok "Theme installed"
84}
85
86clean_macos_aliases() {
87 local alias_file="$HOME/.alias"
88 if [[ -f "$alias_file" ]]; then
89 log "Patching .alias for macOS..."
90 sed -i '' '/# System update & cleanup/,/sudo apt-get clean/d' "$alias_file"
91 sed -i '' '/# xclip shortcuts/,/xclip -selection clipboard/d' "$alias_file"
92 sed -i '' '/./,$!d' "$alias_file"
93 ok "macOS incompatibilities removed from .alias"
94 fi
95}
96
97clean_func_file() {
98 local func_file="$HOME/.func"
99 if [[ -f "$func_file" ]]; then
100 log "Patching .func to remove 'open' function (WSL/Explorer specific)..."
101
102 # Deletes from the comment line containing 'Function: open' down to the closing brace }
103 # This preserves the native macOS 'open' command.
104 sed -i '' '/# Function: open/,/^}/d' "$func_file"
105
106 # Trim leading blank lines that might remain at the top
107 sed -i '' '/./,$!d' "$func_file"
108
109 ok "'open' function removed from .func"
110 fi
111}
112
113download_configs() {
114 log "Downloading custom config files..."
115 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
116 mkdir -p "$backup"
117
118 for entry in "${CONFIG_FILES[@]}"; do
119 local f="${entry%%|*}"
120 local url="${entry##*|}"
121
122 if [[ -f "$HOME/$f" ]]; then
123 cp "$HOME/$f" "$backup/"
124 fi
125 log "Fetching $f ..."
126 curl -fsSL "$url" -o "$HOME/$f" || warn "Failed to download $f"
127 done
128
129 # Run cleanup patches
130 clean_macos_aliases
131 clean_func_file
132
133 ok "Configs downloaded (Backup at $backup)"
134}
135
136update_zshrc() {
137 local zshrc="$HOME/.zshrc"
138 log "Updating .zshrc..."
139
140 if [[ ! -f "$zshrc" ]]; then
141 warn ".zshrc not found, creating new one..."
142 touch "$zshrc"
143 fi
144
145 grep -q 'ZSH_THEME="spaceship"' "$zshrc" || sed -i '' 's/ZSH_THEME=".*"/ZSH_THEME="spaceship"/' "$zshrc"
146 grep -q 'zsh-autosuggestions' "$zshrc" || sed -i '' 's/plugins=(/plugins=(zsh-autosuggestions /' "$zshrc"
147 grep -q 'zsh-syntax-highlighting' "$zshrc" || sed -i '' 's/plugins=(/plugins=(zsh-syntax-highlighting /' "$zshrc"
148 ok ".zshrc updated with plugins and theme"
149}
150
151switch_shell() {
152 log "Starting Zsh session..."
153 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
154 echo "----------------------------------------"
155 zsh -l
156 echo "----------------------------------------"
157 ok "Returned from Zsh session"
158}
159
160# =============================
161# INTERACTIVE MENU
162# =============================
163show_menu() {
164 echo "==========================================="
165 echo "macOS Zsh Setup - Choose what to do"
166 echo "==========================================="
167 echo " 0) Run ALL steps (1-7)"
168 echo " 1) Configure Git"
169 echo " 2) Install Oh My Zsh"
170 echo " 3) Install plugins (autosuggestions, syntax highlighting)"
171 echo " 4) Install Spaceship theme"
172 echo " 5) Download custom configs (~/.alias, .func, .vimrc, etc.)"
173 echo " 6) Update ~/.zshrc for plugins & theme"
174 echo " 7) Switch to Zsh (Temporary Sub-shell)"
175 echo " 8) Quit"
176 echo "==========================================="
177}
178
179run_choices() {
180 local input
181 read -p "Select: " input
182 input="${input//,/ }"
183
184 local -a to_run=()
185 local -a to_exclude=()
186
187 for item in $input; do
188 if [[ "$item" == !* ]]; then
189 to_exclude+=("${item:1}")
190 elif [[ "$item" == "0" ]]; then
191 to_run+=(1 2 3 4 5 6 7)
192 else
193 to_run+=("$item")
194 fi
195 done
196
197 if [[ ${#to_run[@]} -gt 0 ]]; then
198 for choice in "${to_run[@]}"; do
199 local skip=false
200
201 # Array empty-check for older Bash versions (Fixes 'unbound variable' error)
202 if [[ ${#to_exclude[@]} -gt 0 ]]; then
203 for ex in "${to_exclude[@]}"; do
204 if [[ "$choice" == "$ex" ]]; then
205 skip=true; break
206 fi
207 done
208 fi
209
210 $skip && continue
211
212 case "$choice" in
213 1) configure_git ;;
214 2) install_oh_my_zsh ;;
215 3) install_plugins ;;
216 4) install_theme ;;
217 5) download_configs ;;
218 6) update_zshrc ;;
219 7) switch_shell ;;
220 8) exit 0 ;;
221 *) warn "Skipping invalid option: $choice" ;;
222 esac
223 echo
224 done
225 fi
226}
227
228# =============================
229# MAIN
230# =============================
231main() {
232 check_requirements
233 while true; do
234 show_menu
235 run_choices
236 read -p "Do you want to run more options? (y/n): " again
237 [[ "$again" =~ ^[Yy]$ ]] || break
238 done
239 ok "macOS configuration complete!"
240}
241
242main "$@"
zsh_ubuntu.sh Ham
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# FLAGS & CONFIG
20# =============================
21SKIP_PACKAGES=false
22SKIP_GIT_CONFIG=false
23SKIP_SHELL_CHANGE=false
24CUSTOM_CONFIG=false
25SKIP_XCLIP=false
26INSTALL_HOMEBREW=false
27
28declare -A CONFIG_FILES=(
29 [".alias"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/alias"
30 [".func"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/func"
31 [".pathrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/pathrc"
32 [".sourcerc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/sourcerc"
33 [".vimrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/vimrc"
34 [".zshrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/zshrc"
35)
36
37# =============================
38# OS DETECTION
39# =============================
40detect_os() {
41 if [ -f /etc/os-release ]; then
42 . /etc/os-release
43 echo "$ID"
44 else
45 echo "unknown"
46 fi
47}
48
49# =============================
50# REQUIREMENTS
51# =============================
52check_requirements() {
53 if [[ $EUID -eq 0 ]]; then
54 err "Do not run as root"
55 exit 1
56 fi
57 if ! command -v sudo >/dev/null; then
58 err "sudo required"
59 exit 1
60 fi
61}
62
63# =============================
64# INSTALLATION FUNCTIONS
65# =============================
66update_system() {
67 $SKIP_PACKAGES && return
68 log "Updating system..."
69 sudo apt-get update -y
70 sudo apt-get upgrade -y
71 ok "System updated"
72}
73
74install_packages() {
75 $SKIP_PACKAGES && return
76 log "Installing core packages..."
77 sudo apt-get install -y \
78 zsh git vim curl wget unzip zip build-essential xz-utils
79 ok "Packages installed"
80}
81
82set_timezone() {
83 log "Setting timezone to Asia/Singapore..."
84 sudo timedatectl set-timezone Asia/Singapore
85 ok "Timezone set to Asia/Singapore"
86}
87
88install_xclip() {
89 local os
90 os=$(detect_os)
91 [[ "$os" != "ubuntu" && "$os" != "debian" ]] && return 0
92 $SKIP_XCLIP && return 0
93 command -v xclip >/dev/null && ok "xclip already installed" && return 0
94
95 read -r -p "Install xclip? (y/N): " r
96 case "$r" in
97 [Yy]) sudo apt-get install -y xclip; ok "xclip installed" ;;
98 *) log "Skipping xclip installation" ;;
99 esac
100}
101
102configure_git() {
103 $SKIP_GIT_CONFIG && return
104 log "Configuring Git..."
105 read -p "Git name (leave empty to skip): " name
106 read -p "Git email (leave empty to skip): " email
107 [[ -n "$name" ]] && git config --global user.name "$name"
108 [[ -n "$email" ]] && git config --global user.email "$email"
109 ok "Git configured"
110}
111
112install_homebrew() {
113 ! $INSTALL_HOMEBREW && return
114 command -v brew >/dev/null && ok "Homebrew already installed" && return
115 log "Installing Homebrew..."
116 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
117 ok "Homebrew installed"
118}
119
120configure_shell() {
121 $SKIP_SHELL_CHANGE && return
122 log "Changing default shell to zsh..."
123 local zsh_path
124 zsh_path=$(command -v zsh)
125 grep -qx "$zsh_path" /etc/shells || echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
126 sudo chsh -s "$zsh_path" "$USER"
127 ok "Shell changed (requires logout/login to take effect)"
128}
129
130install_oh_my_zsh() {
131 [[ -d "$HOME/.oh-my-zsh" ]] && ok "Oh My Zsh already installed" && return
132 log "Installing Oh My Zsh..."
133 RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
134 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
135 ok "Oh My Zsh installed"
136}
137
138install_plugins() {
139 log "Installing plugins..."
140 local dir="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins"
141 [[ -d "$dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
142 [[ -d "$dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
143 ok "Plugins installed"
144}
145
146install_theme() {
147 log "Installing Spaceship theme..."
148 local themes="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes"
149 local dir="$themes/spaceship-prompt"
150 [[ -d "$dir" ]] || git clone https://github.com/spaceship-prompt/spaceship-prompt.git "$dir" --depth=1
151 ln -sf "$dir/spaceship.zsh-theme" "$themes/spaceship.zsh-theme"
152 ok "Theme installed"
153}
154
155download_configs() {
156 log "Downloading custom config files..."
157 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
158 mkdir -p "$backup"
159 for f in "${!CONFIG_FILES[@]}"; do
160 if [[ -f "$HOME/$f" ]]; then
161 cp "$HOME/$f" "$backup/"
162 fi
163 log "Fetching $f ..."
164 curl -fsSL "${CONFIG_FILES[$f]}" -o "$HOME/$f" || warn "Failed to download $f"
165
166 # --- Logic to remove the open function from .func ---
167 if [[ "$f" == ".func" ]]; then
168 # Removes the block starting with open() { and ending with }
169 sed -i '/^open[[:space:]]*()[[:space:]]*{/,/^}/d' "$HOME/$f"
170 ok "Stripped 'open' function from .func to prevent system conflicts"
171 fi
172 done
173 ok "Configs downloaded (Backup at $backup)"
174}
175
176update_zshrc() {
177 local zshrc="$HOME/.zshrc"
178 log "Updating .zshrc..."
179
180 if [[ ! -f "$zshrc" ]]; then
181 warn ".zshrc not found, creating new one..."
182 touch "$zshrc"
183 fi
184
185 grep -q 'ZSH_THEME="spaceship"' "$zshrc" || sed -i 's/ZSH_THEME=".*"/ZSH_THEME="spaceship"/' "$zshrc"
186 grep -q 'zsh-autosuggestions' "$zshrc" || sed -i 's/plugins=(/plugins=(zsh-autosuggestions /' "$zshrc"
187 grep -q 'zsh-syntax-highlighting' "$zshrc" || sed -i 's/plugins=(/plugins=(zsh-syntax-highlighting /' "$zshrc"
188 ok ".zshrc updated with plugins and theme"
189}
190
191switch_shell() {
192 $SKIP_SHELL_CHANGE && return
193 log "Starting Zsh session..."
194 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
195 echo "----------------------------------------"
196 zsh -l
197 echo "----------------------------------------"
198 ok "Returned from Zsh session"
199}
200
201# =============================
202# INTERACTIVE MENU
203# =============================
204show_menu() {
205 echo "==========================================="
206 echo "Zsh Installer - Choose what to do"
207 echo "==========================================="
208 echo " 0) Run ALL steps (1-13)"
209 echo " 1) Update system packages"
210 echo " 2) Install core packages (zsh, git, vim, etc.)"
211 echo " 3) Set Timezone (Asia/Singapore)"
212 echo " 4) Install xclip"
213 echo " 5) Configure Git"
214 echo " 6) Install Homebrew"
215 echo " 7) Configure shell (chsh - sets default shell)"
216 echo " 8) Install Oh My Zsh"
217 echo " 9) Install plugins (autosuggestions, syntax highlighting)"
218 echo "10) Install Spaceship theme"
219 echo "11) Download custom configs (~/.alias, .vimrc, etc.)"
220 echo "12) Update ~/.zshrc for plugins & theme"
221 echo "13) Switch to Zsh (Temporary Sub-shell)"
222 echo "14) Quit"
223 echo "==========================================="
224}
225
226run_choices() {
227 local input
228 read -p "Select: " input
229 input="${input//,/ }"
230
231 local -a to_run=()
232 local -a to_exclude=()
233
234 for item in $input; do
235 if [[ "$item" == !* ]]; then
236 to_exclude+=("${item:1}")
237 elif [[ "$item" == "0" ]]; then
238 to_run+=(1 2 3 4 5 6 7 8 9 10 11 12 13)
239 else
240 to_run+=("$item")
241 fi
242 done
243
244 for choice in "${to_run[@]}"; do
245 local skip=false
246 for ex in "${to_exclude[@]}"; do
247 if [[ "$choice" == "$ex" ]]; then
248 skip=true
249 break
250 fi
251 done
252
253 $skip && continue
254
255 case "$choice" in
256 1) update_system ;;
257 2) install_packages ;;
258 3) set_timezone ;;
259 4) install_xclip ;;
260 5) configure_git ;;
261 6) install_homebrew ;;
262 7) configure_shell ;;
263 8) install_oh_my_zsh ;;
264 9) install_plugins ;;
265 10) install_theme ;;
266 11) download_configs ;;
267 12) update_zshrc ;;
268 13) switch_shell ;;
269 14) log "Exiting..."; exit 0 ;;
270 *) warn "Skipping invalid option: $choice" ;;
271 esac
272 echo
273 done
274}
275
276# =============================
277# MAIN
278# =============================
279main() {
280 check_requirements
281 while true; do
282 show_menu
283 run_choices
284 read -p "Do you want to run more options? (y/n): " again
285 [[ "$again" =~ ^[Yy]$ ]] || break
286 done
287 ok "Zsh installation/configuration complete!"
288}
289
290main "$@"
zsh_wsl.sh Ham
1#!/bin/bash
2set -euo pipefail
3
4# =============================
5# COLORS & LOGGING
6# =============================
7RED='\033[0;31m'
8GREEN='\033[0;32m'
9YELLOW='\033[1;33m'
10BLUE='\033[0;34m'
11NC='\033[0m'
12
13log() { echo -e "${BLUE}[INFO]${NC} $*"; }
14ok() { echo -e "${GREEN}[OK]${NC} $*"; }
15warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
16err() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
17
18# =============================
19# FLAGS & CONFIG
20# =============================
21SKIP_PACKAGES=false
22SKIP_GIT_CONFIG=false
23SKIP_SHELL_CHANGE=false
24CUSTOM_CONFIG=false
25SKIP_XCLIP=false
26INSTALL_HOMEBREW=false
27
28declare -A CONFIG_FILES=(
29 [".alias"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/alias"
30 [".func"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/func"
31 [".pathrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/pathrc"
32 [".sourcerc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/sourcerc"
33 [".vimrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/vimrc"
34 [".zshrc"]="https://gist.githubusercontent.com/weehongkoh/72bdb76beacacf2ca3dd39a72395b9ee/raw/zshrc"
35)
36
37# =============================
38# OS DETECTION
39# =============================
40detect_os() {
41 if [ -f /etc/os-release ]; then
42 . /etc/os-release
43 echo "$ID"
44 else
45 echo "unknown"
46 fi
47}
48
49# =============================
50# REQUIREMENTS
51# =============================
52check_requirements() {
53 # Fixed to prevent silent failure with 'set -e'
54 if [[ $EUID -eq 0 ]]; then
55 err "Do not run as root"
56 exit 1
57 fi
58 if ! command -v sudo >/dev/null; then
59 err "sudo required"
60 exit 1
61 fi
62}
63
64# =============================
65# INSTALLATION FUNCTIONS
66# =============================
67update_system() {
68 $SKIP_PACKAGES && return
69 log "Updating system..."
70 sudo apt-get update -y
71 sudo apt-get upgrade -y
72 ok "System updated"
73}
74
75install_packages() {
76 $SKIP_PACKAGES && return
77 log "Installing core packages..."
78 sudo apt-get install -y \
79 zsh git vim curl wget unzip zip build-essential xz-utils
80 ok "Packages installed"
81}
82
83set_timezone() {
84 log "Setting timezone to Asia/Singapore..."
85 sudo timedatectl set-timezone Asia/Singapore
86 ok "Timezone set to Asia/Singapore"
87}
88
89install_xclip() {
90 local os
91 os=$(detect_os)
92 [[ "$os" != "ubuntu" && "$os" != "debian" ]] && return 0
93 $SKIP_XCLIP && return 0
94 command -v xclip >/dev/null && ok "xclip already installed" && return 0
95
96 read -r -p "Install xclip? (y/N): " r
97 case "$r" in
98 [Yy]) sudo apt-get install -y xclip; ok "xclip installed" ;;
99 *) log "Skipping xclip installation" ;;
100 esac
101}
102
103configure_git() {
104 $SKIP_GIT_CONFIG && return
105 log "Configuring Git..."
106 read -p "Git name (leave empty to skip): " name
107 read -p "Git email (leave empty to skip): " email
108 [[ -n "$name" ]] && git config --global user.name "$name"
109 [[ -n "$email" ]] && git config --global user.email "$email"
110 ok "Git configured"
111}
112
113install_homebrew() {
114 ! $INSTALL_HOMEBREW && return
115 command -v brew >/dev/null && ok "Homebrew already installed" && return
116 log "Installing Homebrew..."
117 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
118 ok "Homebrew installed"
119}
120
121configure_shell() {
122 $SKIP_SHELL_CHANGE && return
123 log "Changing default shell to zsh..."
124 local zsh_path
125 zsh_path=$(command -v zsh)
126 grep -qx "$zsh_path" /etc/shells || echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
127 sudo chsh -s "$zsh_path" "$USER"
128 ok "Shell changed (requires logout/login to take effect)"
129}
130
131install_oh_my_zsh() {
132 [[ -d "$HOME/.oh-my-zsh" ]] && ok "Oh My Zsh already installed" && return
133 log "Installing Oh My Zsh..."
134 # Keep zshrc ensures we don't blow away configs if they exist
135 RUNZSH=no CHSH=no KEEP_ZSHRC=yes \
136 sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
137 ok "Oh My Zsh installed"
138}
139
140install_plugins() {
141 log "Installing plugins..."
142 local dir="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins"
143 [[ -d "$dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
144 [[ -d "$dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
145 ok "Plugins installed"
146}
147
148install_theme() {
149 log "Installing Spaceship theme..."
150 local themes="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes"
151 local dir="$themes/spaceship-prompt"
152 [[ -d "$dir" ]] || git clone https://github.com/spaceship-prompt/spaceship-prompt.git "$dir" --depth=1
153 ln -sf "$dir/spaceship.zsh-theme" "$themes/spaceship.zsh-theme"
154 ok "Theme installed"
155}
156
157download_configs() {
158 log "Downloading custom config files..."
159 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
160 mkdir -p "$backup"
161 for f in "${!CONFIG_FILES[@]}"; do
162 if [[ -f "$HOME/$f" ]]; then
163 cp "$HOME/$f" "$backup/"
164 fi
165 log "Fetching $f ..."
166 curl -fsSL "${CONFIG_FILES[$f]}" -o "$HOME/$f" || warn "Failed to download $f"
167 done
168 ok "Configs downloaded (Backup at $backup)"
169}
170
171update_zshrc() {
172 local zshrc="$HOME/.zshrc"
173 log "Updating .zshrc..."
174
175 # Create zshrc if missing to prevent errors
176 if [[ ! -f "$zshrc" ]]; then
177 warn ".zshrc not found, creating new one..."
178 touch "$zshrc"
179 fi
180
181 # Use || true to prevent 'set -e' from exiting if grep finds nothing
182 grep -q 'ZSH_THEME="spaceship"' "$zshrc" || sed -i 's/ZSH_THEME=".*"/ZSH_THEME="spaceship"/' "$zshrc"
183 grep -q 'zsh-autosuggestions' "$zshrc" || sed -i 's/plugins=(/plugins=(zsh-autosuggestions /' "$zshrc"
184 grep -q 'zsh-syntax-highlighting' "$zshrc" || sed -i 's/plugins=(/plugins=(zsh-syntax-highlighting /' "$zshrc"
185 ok ".zshrc updated with plugins and theme"
186}
187
188switch_shell() {
189 $SKIP_SHELL_CHANGE && return
190
191 log "Starting Zsh session..."
192 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
193 echo "----------------------------------------"
194
195 # Run zsh as a subprocess, not exec
196 zsh -l
197
198 echo "----------------------------------------"
199 ok "Returned from Zsh session"
200}
201
202# =============================
203# INTERACTIVE MENU
204# =============================
205show_menu() {
206 echo "==========================================="
207 echo "Zsh Installer - Choose what to do"
208 echo "==========================================="
209 echo " 0) Run ALL steps (1-13)"
210 echo " 1) Update system packages"
211 echo " 2) Install core packages (zsh, git, vim, etc.)"
212 echo " 3) Set Timezone (Asia/Singapore)"
213 echo " 4) Install xclip"
214 echo " 5) Configure Git"
215 echo " 6) Install Homebrew"
216 echo " 7) Configure shell (chsh - sets default shell)"
217 echo " 8) Install Oh My Zsh"
218 echo " 9) Install plugins (autosuggestions, syntax highlighting)"
219 echo "10) Install Spaceship theme"
220 echo "11) Download custom configs (~/.alias, .vimrc, etc.)"
221 echo "12) Update ~/.zshrc for plugins & theme"
222 echo "13) Switch to Zsh (Temporary Sub-shell)"
223 echo "14) Quit"
224 echo "==========================================="
225 echo "Inputs: '0' (All), '2 3 7' (Specific), '0 !4 !6' (All except 4 and 6)"
226}
227
228run_choices() {
229 local input
230 read -p "Select: " input
231 input="${input//,/ }" # replace commas with spaces
232
233 local -a to_run=()
234 local -a to_exclude=()
235
236 # Parse positive selections and negative exclusions
237 for item in $input; do
238 if [[ "$item" == !* ]]; then
239 to_exclude+=("${item:1}") # Strip the '!' character
240 elif [[ "$item" == "0" ]]; then
241 to_run+=(1 2 3 4 5 6 7 8 9 10 11 12 13)
242 else
243 to_run+=("$item")
244 fi
245 done
246
247 # Loop through intended runs and apply exclusions
248 for choice in "${to_run[@]}"; do
249
250 local skip=false
251 for ex in "${to_exclude[@]}"; do
252 if [[ "$choice" == "$ex" ]]; then
253 skip=true
254 break
255 fi
256 done
257
258 $skip && continue
259
260 case "$choice" in
261 1) update_system ;;
262 2) install_packages ;;
263 3) set_timezone ;;
264 4) install_xclip ;;
265 5) configure_git ;;
266 6) install_homebrew ;;
267 7) configure_shell ;;
268 8) install_oh_my_zsh ;;
269 9) install_plugins ;;
270 10) install_theme ;;
271 11) download_configs ;;
272 12) update_zshrc ;;
273 13) switch_shell ;;
274 14) log "Exiting..."; exit 0 ;;
275 *) warn "Skipping invalid option: $choice" ;;
276 esac
277 echo
278 done
279}
280
281# =============================
282# MAIN
283# =============================
284main() {
285 check_requirements
286 while true; do
287 show_menu
288 run_choices
289 read -p "Do you want to run more options? (y/n): " again
290 [[ "$again" =~ ^[Yy]$ ]] || break
291 done
292 ok "Zsh installation/configuration complete!"
293}
294
295main "$@"