Ultima attività 2 weeks ago

Cross-platform Zsh setup scripts and managed dotfiles with Oh My Zsh framework, Starship prompt, aliases, functions, and path configuration.

Revisione 21eb36e14204faa619caca664774ed1f7d7f0ac9

README.md Raw

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 Raw
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_pathrc() {
98 local pathrc_file="$HOME/.pathrc"
99 if [[ -f "$pathrc_file" ]]; then
100 log "Patching .pathrc to remove 'open' function..."
101 # Deletes the function block from name down to the closing brace }
102 sed -i '' '/^open[ (].*/,/^}/d' "$pathrc_file"
103 ok "'open' function removed from .pathrc"
104 fi
105}
106
107download_configs() {
108 log "Downloading custom config files..."
109 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
110 mkdir -p "$backup"
111
112 for entry in "${CONFIG_FILES[@]}"; do
113 local f="${entry%%|*}"
114 local url="${entry##*|}"
115
116 if [[ -f "$HOME/$f" ]]; then
117 cp "$HOME/$f" "$backup/"
118 fi
119 log "Fetching $f ..."
120 curl -fsSL "$url" -o "$HOME/$f" || warn "Failed to download $f"
121 done
122
123 # Apply cleanup patches
124 clean_macos_aliases
125 clean_pathrc
126
127 ok "Configs downloaded (Backup at $backup)"
128}
129
130update_zshrc() {
131 local zshrc="$HOME/.zshrc"
132 log "Updating .zshrc..."
133
134 if [[ ! -f "$zshrc" ]]; then
135 warn ".zshrc not found, creating new one..."
136 touch "$zshrc"
137 fi
138
139 grep -q 'ZSH_THEME="spaceship"' "$zshrc" || sed -i '' 's/ZSH_THEME=".*"/ZSH_THEME="spaceship"/' "$zshrc"
140 grep -q 'zsh-autosuggestions' "$zshrc" || sed -i '' 's/plugins=(/plugins=(zsh-autosuggestions /' "$zshrc"
141 grep -q 'zsh-syntax-highlighting' "$zshrc" || sed -i '' 's/plugins=(/plugins=(zsh-syntax-highlighting /' "$zshrc"
142 ok ".zshrc updated with plugins and theme"
143}
144
145switch_shell() {
146 log "Starting Zsh session..."
147 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
148 echo "----------------------------------------"
149 zsh -l
150 echo "----------------------------------------"
151 ok "Returned from Zsh session"
152}
153
154# =============================
155# INTERACTIVE MENU
156# =============================
157show_menu() {
158 echo "==========================================="
159 echo "macOS Zsh Setup - Choose what to do"
160 echo "==========================================="
161 echo " 0) Run ALL steps (1-7)"
162 echo " 1) Configure Git"
163 echo " 2) Install Oh My Zsh"
164 echo " 3) Install plugins (autosuggestions, syntax highlighting)"
165 echo " 4) Install Spaceship theme"
166 echo " 5) Download custom configs (~/.alias, .vimrc, etc.)"
167 echo " 6) Update ~/.zshrc for plugins & theme"
168 echo " 7) Switch to Zsh (Temporary Sub-shell)"
169 echo " 8) Quit"
170 echo "==========================================="
171}
172
173run_choices() {
174 local input
175 read -p "Select: " input
176 input="${input//,/ }"
177
178 local -a to_run=()
179 local -a to_exclude=()
180
181 for item in $input; do
182 if [[ "$item" == !* ]]; then
183 to_exclude+=("${item:1}")
184 elif [[ "$item" == "0" ]]; then
185 to_run+=(1 2 3 4 5 6 7)
186 else
187 to_run+=("$item")
188 fi
189 done
190
191 if [[ ${#to_run[@]} -gt 0 ]]; then
192 for choice in "${to_run[@]}"; do
193 local skip=false
194 for ex in "${to_exclude[@]}"; do
195 if [[ "$choice" == "$ex" ]]; then
196 skip=true; break
197 fi
198 done
199
200 $skip && continue
201
202 case "$choice" in
203 1) configure_git ;;
204 2) install_oh_my_zsh ;;
205 3) install_plugins ;;
206 4) install_theme ;;
207 5) download_configs ;;
208 6) update_zshrc ;;
209 7) switch_shell ;;
210 8) exit 0 ;;
211 *) warn "Skipping invalid option: $choice" ;;
212 esac
213 echo
214 done
215 fi
216}
217
218# =============================
219# MAIN
220# =============================
221main() {
222 check_requirements
223 while true; do
224 show_menu
225 run_choices
226 read -p "Do you want to run more options? (y/n): " again
227 [[ "$again" =~ ^[Yy]$ ]] || break
228 done
229 ok "macOS configuration complete!"
230}
231
232main "$@"
zsh_ubuntu.sh Raw
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 "$@"