最終更新 2 weeks ago

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

修正履歴 d1baab13efcc70a2b69b7250d71363c08fb52fc7

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)"

WSL

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

MacOS

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

Configuration

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

Prompt theme

Run the installer theme option and select either Spaceship or Starship. Starship uses the Catppuccin Powerline preset from the managed config at ~/.config/starship.toml. A Nerd Font is required for the Powerline symbols.

alias Raw
1# =============================================================================
2# OS-SPECIFIC ALIASES
3# =============================================================================
4if [[ "$OSTYPE" == "linux-gnu"* ]] && command -v apt-get >/dev/null 2>&1; then
5 # Linux Only System update & cleanup
6 alias uu='sudo apt-get update && \
7 sudo apt-get upgrade -y && \
8 sudo apt-get full-upgrade -y && \
9 sudo apt-get autoremove -y && \
10 sudo apt-get autoclean -y && \
11 sudo apt-get clean'
12elif [[ "$OSTYPE" == "darwin"* ]]; then
13 # macOS Only
14 alias flushdns='sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder'
15fi
16
17# =============================================================================
18# UNIVERSAL GIT ALIASES (Fixed: Removed broken "$@" from aliases)
19# =============================================================================
20alias gph='git push'
21alias gco='git checkout'
22alias gbh='git branch'
23alias gmt='git commit'
24alias gpl='git pull'
25alias grb='git rebase'
26alias grt='git reset'
27alias gst='git status'
28alias grmrf='git checkout -- . && git clean -fd'
config.sh Raw
1#!/bin/bash
2set -euo pipefail
3
4# Configuration
5GIST_RAW_BASE="https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
6CONFIG_FILES=(
7 ".alias"
8 ".func"
9 ".pathrc"
10 ".sourcerc"
11 ".vimrc"
12 ".zshrc"
13 ".config/starship.toml"
14)
15
16echo "Starting configuration download..."
17
18for f in "${CONFIG_FILES[@]}"; do
19 # Remove the leading dot for the URL path
20 remote_name="${f#.}"
21 [[ "$f" == ".config/starship.toml" ]] && remote_name="starship.toml"
22 url="$GIST_RAW_BASE/$remote_name"
23 target="$HOME/$f"
24
25 echo "Downloading $f..."
26 mkdir -p "$(dirname "$target")"
27
28 # Use -f to fail silently on server errors, -s for silent, -L to follow redirects
29 if curl -fsSL "$url" -o "$target"; then
30 echo "Successfully updated $target"
31 else
32 echo "Error: Failed to download $f from $url" >&2
33 fi
34done
35
36echo "Done! All configuration files have been replaced."
37
func Raw
1# =============================================================================
2# CUSTOM FUNCTIONS
3# =============================================================================
4
5# -----------------------------------------------------------------------------
6# Function: clip (Cross-platform clipboard)
7# -----------------------------------------------------------------------------
8clip() {
9 local cmd
10 local args=()
11
12 if command -v pbcopy >/dev/null 2>&1; then
13 cmd="pbcopy" # macOS
14 elif grep -qi "microsoft" /proc/version 2>/dev/null && command -v clip.exe >/dev/null 2>&1; then
15 cmd="clip.exe" # WSL
16 elif [ "$XDG_SESSION_TYPE" = "wayland" ] && command -v wl-copy >/dev/null 2>&1; then
17 cmd="wl-copy" # Linux Wayland
18 elif command -v xclip >/dev/null 2>&1; then
19 cmd="xclip" # Linux X11 (Fallback 1)
20 args=("-selection" "clipboard")
21 elif command -v xsel >/dev/null 2>&1; then
22 cmd="xsel" # Linux X11 (Fallback 2)
23 args=("--clipboard" "--input")
24 else
25 printf "Error: No supported clipboard utility found.\n" >&2
26 return 1
27 fi
28
29 if [ $# -gt 0 ]; then
30 if [ -f "$1" ]; then
31 "$cmd" "${args[@]}" < "$1"
32 echo "Copied contents of '$1' to clipboard."
33 else
34 printf "Error: File '%s' not found.\n" "$1" >&2
35 return 1
36 fi
37 else
38 "$cmd" "${args[@]}"
39 fi
40}
41
42# -----------------------------------------------------------------------------
43# Function: open_file (Cross-platform file/directory opener)
44# -----------------------------------------------------------------------------
45open_file() {
46 local target="${1:-.}"
47
48 if [[ "$OSTYPE" == "darwin"* ]]; then
49 command open "$target"
50 elif grep -qi "microsoft" /proc/version 2>/dev/null; then
51 if command -v wslpath >/dev/null 2>&1 && command -v explorer.exe >/dev/null 2>&1; then
52 explorer.exe "$(wslpath -w "$target")"
53 else
54 printf "Error: 'wslpath' or 'explorer.exe' not found.\n" >&2
55 return 1
56 fi
57 elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
58 if command -v xdg-open >/dev/null 2>&1; then
59 xdg-open "$target"
60 else
61 printf "Error: 'xdg-open' not found.\n" >&2
62 return 1
63 fi
64 fi
65}
66alias open='open_file'
67
68# -----------------------------------------------------------------------------
69# Function: clear_history (Supports shell and Claude)
70# -----------------------------------------------------------------------------
71# -----------------------------------------------------------------------------
72# Function: clear_history (Supports shell and Claude)
73# -----------------------------------------------------------------------------
74clear_history() {
75 case "$1" in
76 claude)
77 if [ -d "$HOME/.claude/projects" ]; then
78 # Use 'yes' to skip prompts and -f to ignore non-existent files
79 yes | rm -rf "$HOME/.claude/projects"/*
80 echo "Claude project history/cache cleared."
81 fi
82 ;;
83
84 *)
85 # 1. Truncate the file
86 : > "$HISTFILE"
87
88 # 2. Clear RAM by briefly setting history size to 0
89 local old_histsize=$HISTSIZE
90 HISTSIZE=0
91 HISTSIZE=$old_histsize
92
93 echo "Shell history cleared."
94 ;;
95 esac
96}
97
98# -----------------------------------------------------------------------------
99# Function: claude (Includes --yolo and clear shortcuts)
100# -----------------------------------------------------------------------------
101claude() {
102 # Shortcut for clearing cache
103 if [[ "$1" == "clear" ]]; then
104 clear_history claude
105 return 0
106 fi
107
108 # Check if binary exists
109 if ! whence -p claude >/dev/null 2>&1; then
110 printf "Error: 'claude' CLI is not installed or not in your PATH.\n" >&2
111 return 1
112 fi
113
114 # Handle --yolo mode
115 if [[ "$1" == "--yolo" ]]; then
116 shift
117 command claude --dangerously-skip-permissions "$@"
118 return $?
119 fi
120
121 command claude "$@"
122}
123
124# -----------------------------------------------------------------------------
125# Function: create (Efficiently create file + parent dirs)
126# -----------------------------------------------------------------------------
127create() {
128 if ! command -v install >/dev/null 2>&1; then
129 printf "Error: 'install' coreutil is not available.\n" >&2
130 return 1
131 fi
132
133 if [ $# -eq 0 ]; then
134 printf "Usage: create <file> [file ...]\n" >&2
135 return 2
136 fi
137
138 for p in "$@"; do
139 # Expand tilde manually if shell doesn't
140 [[ "$p" == "~/"* ]] && p="${HOME}/${p#\~/}"
141
142 if [ -z "$p" ] || [ "$p" = "/" ]; then
143 printf "create: refusing to operate on '%s'\n" "$p" >&2
144 continue
145 fi
146
147 if [ -e "$p" ]; then
148 printf "create: '%s' already exists. Skipping.\n" "$p" >&2
149 continue
150 fi
151
152 if install -D /dev/null "$p"; then
153 echo "Created '$p'"
154 fi
155 done
156}
157
158# -----------------------------------------------------------------------------
159# Function: check_port
160# -----------------------------------------------------------------------------
161check_port() {
162 local PORT=$1
163 if [ -z "$PORT" ]; then
164 printf "Usage: check_port <port_number>\n" >&2
165 return 1
166 fi
167
168 if [[ "$OSTYPE" == "darwin"* ]]; then
169 lsof -i :"$PORT" || echo "Port $PORT is FREE"
170 else
171 sudo ss -tulnp | grep ":$PORT " || echo "Port $PORT is FREE"
172 fi
173}
174
175# -----------------------------------------------------------------------------
176# Function: append_path (Adds to session PATH if exists)
177# -----------------------------------------------------------------------------
178append_path() {
179 local dir="$1"
180 if [ -d "$dir" ]; then
181 case ":$PATH:" in
182 *":$dir:"*) ;;
183 *) PATH="$PATH:$dir" ;;
184 esac
185 elif [ "${SUPPRESS_WARNINGS:-0}" -ne 1 ]; then
186 echo "Warning: $dir does not exist." >&2
187 fi
188}
189
190# -----------------------------------------------------------------------------
191# Function: add_path_to_config (Fixed awk/sed injection)
192# -----------------------------------------------------------------------------
193add_path_to_config() {
194 local new_path="$1"
195 local config_file="$HOME/.bashrc"
196 [[ "$SHELL" == *"zsh"* ]] && config_file="$HOME/.zshrc"
197
198 if [ -z "$new_path" ]; then
199 printf "Usage: add_path_to_config <directory>\n" >&2
200 return 1
201 fi
202
203 new_path="${new_path/#\~/$HOME}"
204
205 if [ ! -d "$new_path" ]; then
206 printf "Warning: '%s' does not exist. Add anyway? (y/N) " "$new_path"
207 read -r REPLY
208 [[ ! $REPLY =~ ^[Yy]$ ]] && return 1
209 fi
210
211 # Check if already exists in file
212 if grep -Fq "append_path \"$new_path\"" "$config_file"; then
213 printf "Notice: Already in %s.\n" "$config_file"
214 return 0
215 fi
216
217 # Robust Injection: Use sed to insert before export PATH or just append
218 if grep -q "^export PATH" "$config_file"; then
219 sed -i.bak "/^export PATH/i append_path \"$new_path\"" "$config_file"
220 else
221 echo "append_path \"$new_path\"" >> "$config_file"
222 echo "export PATH" >> "$config_file"
223 fi
224
225 printf "✅ Success: Added to %s\n" "$config_file"
226 append_path "$new_path" && export PATH
227}
pathrc Raw
1# =============================================================================
2# ENVIRONMENT & PATH CONFIGURATION
3# =============================================================================
4
5# 1. Source functions first
6if [[ -f "$HOME/.func" && -r "$HOME/.func" ]]; then
7 source "$HOME/.func"
8fi
9
10# 2. Define Root Variables
11export DOTNET_ROOT="$HOME/.dotnet"
12
13# 3. PATH INITIALIZATION
14# -----------------------------------------------------------------------------
15append_path "$HOME/.local/bin"
16append_path "$DOTNET_ROOT"
17append_path "$DOTNET_ROOT/tools"
18append_path "$HOME/.opencode/bin"
19append_path "$HOME/Flutter/bin"
20
21# macOS specific paths
22if [[ "$OSTYPE" == "darwin"* ]]; then
23 append_path "/Applications/Espanso.app/Contents/MacOS"
24fi
25
26# Finalize PATH
27export PATH
sourcerc Raw
1# =============================================================================
2# FILE: ~/.sourcerc
3# Description: Initializes third-party package managers and external tools.
4# =============================================================================
5
6# =============================================================================
7# GENERAL ENV
8# =============================================================================
9if [[ -f "$HOME/.local/bin/env" && -r "$HOME/.local/bin/env" ]]; then
10 source "$HOME/.local/bin/env"
11fi
12
13# =============================================================================
14# CLAUDE CODE / AI GATEWAY
15# =============================================================================
16export ANTHROPIC_BASE_URL="https://gateway.ai.cloudflare.com/v1/9a71825e3842e918e0dff9ad84f50484/claude-code-gateway/anthropic"
17
18# =============================================================================
19# SDKMAN (Java/Kotlin/Scala Version Manager)
20# =============================================================================
21export SDKMAN_DIR="$HOME/.sdkman"
22if [[ -f "$SDKMAN_DIR/bin/sdkman-init.sh" && -r "$SDKMAN_DIR/bin/sdkman-init.sh" ]]; then
23 source "$SDKMAN_DIR/bin/sdkman-init.sh"
24fi
25
26# =============================================================================
27# NVM (Node Version Manager)
28# =============================================================================
29export NVM_DIR="$HOME/.nvm"
30if [[ -f "$NVM_DIR/nvm.sh" && -r "$NVM_DIR/nvm.sh" ]]; then
31 source "$NVM_DIR/nvm.sh"
32fi
33if [[ -f "$NVM_DIR/bash_completion" && -r "$NVM_DIR/bash_completion" ]]; then
34 source "$NVM_DIR/bash_completion"
35fi
36
37# =============================================================================
38# GOOGLE CLOUD SDK
39# =============================================================================
40if [[ -f "$HOME/google-cloud-sdk/path.zsh.inc" ]]; then
41 source "$HOME/google-cloud-sdk/path.zsh.inc"
42fi
43
44if [[ -f "$HOME/google-cloud-sdk/completion.zsh.inc" ]]; then
45 source "$HOME/google-cloud-sdk/completion.zsh.inc"
46fi
starship.toml Raw
1"$schema" = 'https://starship.rs/config-schema.json'
2
3format = """
4[](red)\
5$os\
6$username\
7[](bg:peach fg:red)\
8$directory\
9[](bg:yellow fg:peach)\
10$git_branch\
11$git_status\
12[](fg:yellow bg:green)\
13$c\
14$rust\
15$golang\
16$nodejs\
17$bun\
18$php\
19$java\
20$kotlin\
21$haskell\
22$python\
23[](fg:green bg:sapphire)\
24$conda\
25[](fg:sapphire bg:lavender)\
26$time\
27[ ](fg:lavender)\
28$cmd_duration\
29$line_break\
30$character"""
31
32palette = 'catppuccin_mocha'
33
34[os]
35disabled = false
36style = "bg:red fg:crust"
37
38[os.symbols]
39Windows = ""
40Ubuntu = "󰕈"
41SUSE = ""
42Raspbian = "󰐿"
43Mint = "󰣭"
44Macos = "󰀵"
45Manjaro = ""
46Linux = "󰌽"
47Gentoo = "󰣨"
48Fedora = "󰣛"
49Alpine = ""
50Amazon = ""
51Android = ""
52AOSC = ""
53Arch = "󰣇"
54Artix = "󰣇"
55CentOS = ""
56Debian = "󰣚"
57Redhat = "󱄛"
58RedHatEnterprise = "󱄛"
59
60[username]
61show_always = true
62style_user = "bg:red fg:crust"
63style_root = "bg:red fg:crust"
64format = '[ $user]($style)'
65
66[directory]
67style = "bg:peach fg:crust"
68format = "[ $path ]($style)"
69truncation_length = 3
70truncation_symbol = "…/"
71
72[directory.substitutions]
73"Documents" = "󰈙 "
74"Downloads" = " "
75"Music" = "󰝚 "
76"Pictures" = " "
77"Developer" = "󰲋 "
78
79[git_branch]
80symbol = ""
81style = "bg:yellow"
82format = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)'
83
84[git_status]
85style = "bg:yellow"
86format = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)'
87
88[nodejs]
89symbol = ""
90style = "bg:green"
91format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
92
93[bun]
94symbol = ""
95style = "bg:green"
96format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
97
98[c]
99symbol = " "
100style = "bg:green"
101format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
102
103[rust]
104symbol = ""
105style = "bg:green"
106format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
107
108[golang]
109symbol = ""
110style = "bg:green"
111format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
112
113[php]
114symbol = ""
115style = "bg:green"
116format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
117
118[java]
119symbol = " "
120style = "bg:green"
121format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
122
123[kotlin]
124symbol = ""
125style = "bg:green"
126format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
127
128[haskell]
129symbol = ""
130style = "bg:green"
131format = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'
132
133[python]
134symbol = ""
135style = "bg:green"
136format = '[[ $symbol( $version)(\(#$virtualenv\)) ](fg:crust bg:green)]($style)'
137
138[docker_context]
139symbol = ""
140style = "bg:sapphire"
141format = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)'
142
143[conda]
144symbol = "  "
145style = "fg:crust bg:sapphire"
146format = '[$symbol$environment ]($style)'
147ignore_base = false
148
149[time]
150disabled = false
151time_format = "%R"
152style = "bg:lavender"
153format = '[[  $time ](fg:crust bg:lavender)]($style)'
154
155[line_break]
156disabled = false
157
158[character]
159disabled = false
160success_symbol = '[❯](bold fg:green)'
161error_symbol = '[❯](bold fg:red)'
162vimcmd_symbol = '[❮](bold fg:green)'
163vimcmd_replace_one_symbol = '[❮](bold fg:lavender)'
164vimcmd_replace_symbol = '[❮](bold fg:lavender)'
165vimcmd_visual_symbol = '[❮](bold fg:yellow)'
166
167[cmd_duration]
168show_milliseconds = true
169format = " in $duration "
170style = "bg:lavender"
171disabled = false
172show_notifications = true
173min_time_to_notify = 45000
174
175[palettes.catppuccin_mocha]
176rosewater = "#f5e0dc"
177flamingo = "#f2cdcd"
178pink = "#f5c2e7"
179mauve = "#cba6f7"
180red = "#f38ba8"
181maroon = "#eba0ac"
182peach = "#fab387"
183yellow = "#f9e2af"
184green = "#a6e3a1"
185teal = "#94e2d5"
186sky = "#89dceb"
187sapphire = "#74c7ec"
188blue = "#89b4fa"
189lavender = "#b4befe"
190text = "#cdd6f4"
191subtext1 = "#bac2de"
192subtext0 = "#a6adc8"
193overlay2 = "#9399b2"
194overlay1 = "#7f849c"
195overlay0 = "#6c7086"
196surface2 = "#585b70"
197surface1 = "#45475a"
198surface0 = "#313244"
199base = "#1e1e2e"
200mantle = "#181825"
201crust = "#11111b"
202
203[palettes.catppuccin_frappe]
204rosewater = "#f2d5cf"
205flamingo = "#eebebe"
206pink = "#f4b8e4"
207mauve = "#ca9ee6"
208red = "#e78284"
209maroon = "#ea999c"
210peach = "#ef9f76"
211yellow = "#e5c890"
212green = "#a6d189"
213teal = "#81c8be"
214sky = "#99d1db"
215sapphire = "#85c1dc"
216blue = "#8caaee"
217lavender = "#babbf1"
218text = "#c6d0f5"
219subtext1 = "#b5bfe2"
220subtext0 = "#a5adce"
221overlay2 = "#949cbb"
222overlay1 = "#838ba7"
223overlay0 = "#737994"
224surface2 = "#626880"
225surface1 = "#51576d"
226surface0 = "#414559"
227base = "#303446"
228mantle = "#292c3c"
229crust = "#232634"
230
231[palettes.catppuccin_latte]
232rosewater = "#dc8a78"
233flamingo = "#dd7878"
234pink = "#ea76cb"
235mauve = "#8839ef"
236red = "#d20f39"
237maroon = "#e64553"
238peach = "#fe640b"
239yellow = "#df8e1d"
240green = "#40a02b"
241teal = "#179299"
242sky = "#04a5e5"
243sapphire = "#209fb5"
244blue = "#1e66f5"
245lavender = "#7287fd"
246text = "#4c4f69"
247subtext1 = "#5c5f77"
248subtext0 = "#6c6f85"
249overlay2 = "#7c7f93"
250overlay1 = "#8c8fa1"
251overlay0 = "#9ca0b0"
252surface2 = "#acb0be"
253surface1 = "#bcc0cc"
254surface0 = "#ccd0da"
255base = "#eff1f5"
256mantle = "#e6e9ef"
257crust = "#dce0e8"
258
259[palettes.catppuccin_macchiato]
260rosewater = "#f4dbd6"
261flamingo = "#f0c6c6"
262pink = "#f5bde6"
263mauve = "#c6a0f6"
264red = "#ed8796"
265maroon = "#ee99a0"
266peach = "#f5a97f"
267yellow = "#eed49f"
268green = "#a6da95"
269teal = "#8bd5ca"
270sky = "#91d7e3"
271sapphire = "#7dc4e4"
272blue = "#8aadf4"
273lavender = "#b7bdf8"
274text = "#cad3f5"
275subtext1 = "#b8c0e0"
276subtext0 = "#a5adcb"
277overlay2 = "#939ab7"
278overlay1 = "#8087a2"
279overlay0 = "#6e738d"
280surface2 = "#5b6078"
281surface1 = "#494d64"
282surface0 = "#363a4f"
283base = "#24273a"
284mantle = "#1e2030"
285crust = "#181926"
286
vimrc Raw
1" Enable line numbers
2set number
3
4" Enable relative line numbers
5set relativenumber
6
7" Enable syntax highlighting
8syntax on
9
10" Set colorscheme
11colorscheme slate
12
13" Enable file type detection and plugins
14filetype plugin indent on
15
16" Set the tab width to 4 spaces
17set tabstop=4
18set shiftwidth=4
19set expandtab
20
21" Enable auto-indentation
22set autoindent
23set smartindent
24
25" Highlight current line
26set cursorline
27
28" Show matching parentheses
29set showmatch
30
31" Enable line wrapping
32set wrap
33
34" Enable mouse support
35set mouse=a
36
37" Enable clipboard access
38set clipboard=unnamedplus
39
40" Disable swap file
41set noswapfile
42
43" Enable incremental search
44set incsearch
45
46" Ignore case in search
47set ignorecase
48
49" Override ignorecase if search contains capital letters
50set smartcase
51
52" Display line and column number of the cursor position
53set ruler
54
55" Set the status line at the bottom
56set laststatus=2
57
58" Show command in bottom bar
59set showcmd
60
61" Set command height
62set cmdheight=2
63
64" Set history lines
65set history=1000
66
67" Disable backup file
68set nobackup
69
70" Enable persistent undo
71set undofile
72
73" Set maximum number of undo levels
74set undolevels=1000
75
76" Set undo directory
77if has("persistent_undo")
78 silent !mkdir ~/.vim/undodir > /dev/null 2>&1
79 set undodir=~/.vim/undodir
80endif
81
82" Set search highlighting
83set hlsearch
84
85" Enable visual bell
86set visualbell
87
88" Set default file encoding
89set encoding=utf-8
90
91" Set the leader key to space
92let mapleader = " "
93
94" Map <Leader>w to save the file
95nnoremap <Leader>w :w<CR>
96
97" Map <Leader>q to quit
98nnoremap <Leader>q :q<CR>
99
100" Map <Leader>x to save and quit
101nnoremap <Leader>x :wq<CR>
102
103" Enable folding
104set foldmethod=syntax
105set foldlevelstart=99
106
107" Enable line wrapping at 80 characters
108set textwidth=80
109set colorcolumn=80
110
111" Add some basic key mappings
112" Map jj to escape insert mode
113inoremap jj <Esc>
114
115" Map <Leader>n to toggle line numbers
116nnoremap <Leader>n :set number!<CR>
117
118" Map <Leader>r to toggle relative line numbers
119nnoremap <Leader>r :set relativenumber!<CR>
120
121" Configure plugins (if you use a plugin manager like vim-plug)
122" Example with vim-plug:
123" call plug#begin('~/.vim/plugged')
124" Plug 'tpope/vim-sensible'
125" Plug 'preservim/nerdtree'
126" Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
127" Plug 'airblade/vim-gitgutter'
128" call plug#end()
129
130" NERDTree key mappings
131" nnoremap <C-n> :NERDTreeToggle<CR>
132
133" Enable automatic hard wrapping at textwidth (80 chars)
134set formatoptions+=t " Auto-wrap text using textwidth
135set formatoptions+=c " Auto-wrap comments using textwidth
136set formatoptions+=r " Continue comments when pressing Enter
137set formatoptions+=o " Continue comments when using 'o' or 'O'
138set formatoptions+=q " Allow formatting of comments with 'gq'
139set formatoptions+=n " Recognize numbered lists
140set formatoptions+=l " Don't break lines that were already long
141
142" Enable syntax highlighting
143syntax on
144
145" Increase memory limit for complex syntax parsing (Prevents E363)
146set maxmempattern=20000
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# =============================
21GIST_RAW_BASE="https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
22
23CONFIG_FILES=(
24 ".alias"
25 ".func"
26 ".pathrc"
27 ".sourcerc"
28 ".vimrc"
29 ".zshrc"
30 ".config/starship.toml"
31)
32
33# =============================
34# REQUIREMENTS
35# =============================
36check_requirements() {
37 if [[ $EUID -eq 0 ]]; then
38 err "Do not run as root on macOS"
39 exit 1
40 fi
41}
42
43# =============================
44# INSTALLATION FUNCTIONS
45# =============================
46install_plugins() {
47 log "Installing manual Zsh plugins..."
48 local dir="$HOME/.zsh"
49 mkdir -p "$dir"
50
51 [[ -d "$dir/zsh-autosuggestions" ]] || \
52 git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
53
54 [[ -d "$dir/zsh-syntax-highlighting" ]] || \
55 git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
56
57 ok "Plugins installed directly to $dir"
58}
59
60install_starship() {
61 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
62 ok "Starship already installed"
63 elif command -v brew >/dev/null 2>&1; then
64 log "Installing Starship with Homebrew..."
65 brew install starship
66 ok "Starship installed"
67 else
68 log "Installing Starship..."
69 mkdir -p "$HOME/.local/bin"
70 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
71 ok "Starship installed"
72 fi
73}
74
75download_configs() {
76 log "Downloading custom config files..."
77 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
78 mkdir -p "$backup"
79
80 for f in "${CONFIG_FILES[@]}"; do
81 # Strip the leading dot for the download URL
82 local remote_file="${f#.}"
83 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
84 local url="$GIST_RAW_BASE/$remote_file"
85 local target="$HOME/$f"
86 local tmp="${target}.tmp.$$"
87
88 mkdir -p "$(dirname "$target")"
89
90 if [[ -f "$target" ]]; then
91 cp "$target" "$backup/"
92 fi
93
94 log "Fetching $remote_file -> $f ..."
95 if curl -fsSL "$url" -o "$tmp"; then
96 mv "$tmp" "$target"
97 else
98 rm -f "$tmp"
99 warn "Failed to download $remote_file"
100 fi
101 done
102
103 ok "Configs downloaded (Backup at $backup)"
104}
105
106configure_zshrc() {
107 local zshrc="$HOME/.zshrc"
108 log "Configuring .zshrc for plugins and Starship..."
109
110 touch "$zshrc"
111
112 # CRITICAL FIX: Purge old corrupted multi-line/plaintext starship lines
113 if [[ -f "$zshrc" ]]; then
114 sed -i '' '/starship init zsh/d' "$zshrc" 2>/dev/null || true
115 sed -i '' '/firing,/d' "$zshrc" 2>/dev/null || true
116 fi
117
118 # Ensure local binary path is explicitly loaded first
119 if ! grep -q '\.local/bin' "$zshrc"; then
120 # macOS sed requires an empty string argument with -i
121 sed -i '' '1i\
122export PATH="$HOME/.local/bin:$PATH"
123' "$zshrc" 2>/dev/null || echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$zshrc"
124 fi
125
126 # Cleanly inject one-line safe evaluator
127 if ! grep -q 'starship init zsh' "$zshrc"; then
128 echo -e '\n# Initialize Starship' >> "$zshrc"
129 echo 'if command -v starship >/dev/null 2>&1; then eval "$(starship init zsh)"; else eval "$($HOME/.local/bin/starship init zsh)"; fi' >> "$zshrc"
130 fi
131
132 # Add autosuggestions if not present
133 if ! grep -q 'zsh-autosuggestions.zsh' "$zshrc"; then
134 echo -e '\n# Load Plugins' >> "$zshrc"
135 echo 'source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh' >> "$zshrc"
136 fi
137
138 # Add syntax highlighting if not present (MUST be last)
139 if ! grep -q 'zsh-syntax-highlighting.zsh' "$zshrc"; then
140 echo 'source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh' >> "$zshrc"
141 fi
142
143 ok ".zshrc configured cleanly for zero-framework setup!"
144 ok "Load order is preserved: .sourcerc -> .func -> .pathrc -> .alias"
145}
146
147switch_shell() {
148 log "Starting Zsh session..."
149 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
150 echo "----------------------------------------"
151 zsh -l
152 echo "----------------------------------------"
153 ok "Returned from Zsh session"
154}
155
156# =============================
157# INTERACTIVE MENU
158# =============================
159show_menu() {
160 echo "==========================================="
161 echo "macOS Minimal Zsh Setup - Choose what to do"
162 echo "==========================================="
163 echo " 0) Run ALL steps (1-5)"
164 echo " 1) Install manual Zsh plugins (autosuggestions, syntax highlighting)"
165 echo " 2) Install Starship prompt"
166 echo " 3) Download custom configs (~/.alias, .func, .vimrc, etc.)"
167 echo " 4) Configure ~/.zshrc (Inject Starship & Plugins)"
168 echo " 5) Switch to Zsh (Temporary Sub-shell)"
169 echo " 6) 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)
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
195 if [[ ${#to_exclude[@]} -gt 0 ]]; then
196 for ex in "${to_exclude[@]}"; do
197 if [[ "$choice" == "$ex" ]]; then
198 skip=true
199 break
200 fi
201 done
202 fi
203
204 $skip && continue
205
206 case "$choice" in
207 1) install_plugins ;;
208 2) install_starship ;;
209 3) download_configs ;;
210 4) configure_zshrc ;;
211 5) switch_shell ;;
212 6) exit 0 ;;
213 *) warn "Skipping invalid option: $choice" ;;
214 esac
215 echo
216 done
217 fi
218}
219
220# =============================
221# MAIN
222# =============================
223main() {
224 check_requirements
225 while true; do
226 show_menu
227 run_choices
228 read -p "Do you want to run more options? (y/n): " again
229 [[ "$again" =~ ^[Yy]$ ]] || break
230 done
231 ok "macOS minimal Zsh configuration complete!"
232}
233
234main "$@"
235
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_SHELL_CHANGE=false
23INSTALL_HOMEBREW=false
24
25GIST_RAW_BASE="https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
26CONFIG_FILES=(
27 ".alias"
28 ".func"
29 ".pathrc"
30 ".sourcerc"
31 ".vimrc"
32 ".zshrc"
33 ".config/starship.toml"
34)
35
36# =============================
37# OS DETECTION
38# =============================
39detect_os() {
40 if [[ "$OSTYPE" == "darwin"* ]]; then
41 echo "macos"
42 elif [ -f /etc/os-release ]; then
43 . /etc/os-release
44 echo "$ID"
45 else
46 echo "unknown"
47 fi
48}
49
50# =============================
51# REQUIREMENTS
52# =============================
53check_requirements() {
54 if [[ $EUID -eq 0 ]]; then
55 err "Do not run as root. The script will request sudo when necessary."
56 exit 1
57 fi
58 if [[ "$(detect_os)" != "macos" ]] && ! command -v sudo >/dev/null 2>&1; then
59 err "sudo required on Linux"
60 exit 1
61 fi
62}
63
64# =============================
65# INSTALLATION FUNCTIONS
66# =============================
67update_system() {
68 $SKIP_PACKAGES && return
69 log "Updating system..."
70 local os=$(detect_os)
71
72 case "$os" in
73 macos) brew update ;;
74 ubuntu|debian) sudo apt-get update -y && sudo apt-get upgrade -y ;;
75 fedora) sudo dnf upgrade -y ;;
76 arch) sudo pacman -Syu --noconfirm ;;
77 *) warn "Auto-update not supported for OS: $os" ;;
78 esac
79 ok "System updated"
80}
81
82install_packages() {
83 $SKIP_PACKAGES && return
84 log "Installing core packages..."
85 local os=$(detect_os)
86
87 case "$os" in
88 macos) brew install zsh git vim curl wget unzip xz ;;
89 ubuntu|debian) sudo apt-get install -y zsh git vim curl wget unzip zip build-essential xz-utils ;;
90 fedora) sudo dnf install -y zsh git vim curl wget unzip zip @development-tools xz ;;
91 arch) sudo pacman -S --noconfirm zsh git vim curl wget unzip zip base-devel xz ;;
92 *) warn "Auto-install not supported for OS: $os. Please install zsh, git, vim, curl manually." ;;
93 esac
94 ok "Packages installed"
95}
96
97set_timezone() {
98 log "Setting timezone to Asia/Singapore..."
99 local os=$(detect_os)
100 if [[ "$os" == "macos" ]]; then
101 sudo systemsetup -settimezone Asia/Singapore >/dev/null
102 else
103 sudo timedatectl set-timezone Asia/Singapore
104 fi
105 ok "Timezone set to Asia/Singapore"
106}
107
108install_homebrew() {
109 ! $INSTALL_HOMEBREW && return
110 command -v brew >/dev/null 2>&1 && ok "Homebrew already installed" && return
111 log "Installing Homebrew..."
112 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
113 ok "Homebrew installed"
114}
115
116configure_shell() {
117 $SKIP_SHELL_CHANGE && return
118 log "Changing default shell to zsh..."
119 local zsh_path
120 zsh_path="$(command -v zsh)"
121
122 if ! grep -qx "$zsh_path" /etc/shells; then
123 echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
124 fi
125 chsh -s "$zsh_path"
126 ok "Shell changed (requires logout/login to take effect)"
127}
128
129install_plugins() {
130 log "Installing manual Zsh plugins..."
131 local dir="$HOME/.zsh"
132 mkdir -p "$dir"
133
134 [[ -d "$dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
135 [[ -d "$dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
136
137 ok "Plugins installed directly to $dir"
138}
139
140install_starship() {
141 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
142 ok "Starship already installed"
143 else
144 log "Installing Starship prompt..."
145 if command -v brew >/dev/null 2>&1; then
146 brew install starship
147 else
148 mkdir -p "$HOME/.local/bin"
149 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
150 fi
151 ok "Starship installed"
152 fi
153}
154
155download_configs() {
156 log "Downloading custom config files from OpenGist..."
157 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
158 mkdir -p "$backup"
159
160 for f in "${CONFIG_FILES[@]}"; do
161 local remote_file="${f#.}"
162 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
163 local url="$GIST_RAW_BASE/$remote_file"
164 local target="$HOME/$f"
165 local tmp="${target}.tmp.$$"
166
167 mkdir -p "$(dirname "$target")"
168
169 if [[ -f "$target" ]]; then
170 cp "$target" "$backup/"
171 fi
172
173 log "Fetching $remote_file -> $f ..."
174 if curl -fsSL "$url" -o "$tmp"; then
175 mv "$tmp" "$target"
176 else
177 rm -f "$tmp"
178 warn "Failed to download $remote_file"
179 fi
180 done
181
182 ok "Configs downloaded (Backup at $backup)"
183}
184
185configure_zshrc() {
186 local zshrc="$HOME/.zshrc"
187 log "Configuring .zshrc for plugins and Starship..."
188
189 touch "$zshrc"
190
191 # CRITICAL FIX: Purge old corrupted multi-line/plaintext starship lines that broke preexec
192 if [[ -f "$zshrc" ]]; then
193 sed -i '/starship init zsh/d' "$zshrc" 2>/dev/null || true
194 sed -i '/firing,/d' "$zshrc" 2>/dev/null || true
195 fi
196
197 # Ensure local binary path is explicitly loaded first
198 if ! grep -q '\.local/bin' "$zshrc"; then
199 sed -i '1i\export PATH="$HOME/.local/bin:$PATH"' "$zshrc" 2>/dev/null || echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$zshrc"
200 fi
201
202 # Cleanly inject one-line safe evaluator
203 if ! grep -q 'starship init zsh' "$zshrc"; then
204 echo -e '\n# Initialize Starship' >> "$zshrc"
205 echo 'if command -v starship >/dev/null 2>&1; then eval "$(starship init zsh)"; else eval "$($HOME/.local/bin/starship init zsh)"; fi' >> "$zshrc"
206 fi
207
208 # Add autosuggestions if not present
209 if ! grep -q 'zsh-autosuggestions.zsh' "$zshrc"; then
210 echo -e '\n# Load Plugins' >> "$zshrc"
211 echo 'source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh' >> "$zshrc"
212 fi
213
214 # Add syntax highlighting if not present (MUST be last line)
215 if ! grep -q 'zsh-syntax-highlighting.zsh' "$zshrc"; then
216 echo 'source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh' >> "$zshrc"
217 fi
218
219 ok ".zshrc configured cleanly for zero-framework setup!"
220}
221
222switch_shell() {
223 log "Starting Zsh session..."
224 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
225 echo "----------------------------------------"
226 zsh -l
227 echo "----------------------------------------"
228 ok "Returned from Zsh session"
229}
230
231# =============================
232# INTERACTIVE MENU
233# =============================
234show_menu() {
235 echo "==========================================="
236 echo "Minimal Zsh Installer - Choose what to do"
237 echo "==========================================="
238 echo " 0) Run ALL steps (1-10)"
239 echo " 1) Update system packages"
240 echo " 2) Install core packages (zsh, git, vim, etc.)"
241 echo " 3) Set Timezone (Asia/Singapore)"
242 echo " 4) Install Homebrew"
243 echo " 5) Configure shell (chsh - sets default shell)"
244 echo " 6) Install manual Zsh plugins (Autosuggestions, Syntax Highlighting)"
245 echo " 7) Install Starship prompt"
246 echo " 8) Download custom configs (from OpenGist)"
247 echo " 9) Configure ~/.zshrc (Inject Starship & Plugins)"
248 echo "10) Switch to Zsh (Temporary Sub-shell)"
249 echo "11) Quit"
250 echo "==========================================="
251}
252
253run_choices() {
254 local input
255 read -p "Select: " input
256 input="${input//,/ }"
257
258 local -a to_run=()
259 local -a to_exclude=()
260
261 for item in $input; do
262 if [[ "$item" == !* ]]; then
263 to_exclude+=("${item:1}")
264 elif [[ "$item" == "0" ]]; then
265 to_run+=(1 2 3 4 5 6 7 8 9 10)
266 else
267 to_run+=("$item")
268 fi
269 done
270
271 for choice in "${to_run[@]}"; do
272 local skip=false
273
274 for ex in "${to_exclude[@]}"; do
275 if [[ "$choice" == "$ex" ]]; then
276 skip=true
277 break
278 fi
279 done
280
281 $skip && continue
282
283 case "$choice" in
284 1) update_system ;;
285 2) install_packages ;;
286 3) set_timezone ;;
287 4) install_homebrew ;;
288 5) configure_shell ;;
289 6) install_plugins ;;
290 7) install_starship ;;
291 8) download_configs ;;
292 9) configure_zshrc ;;
293 10) switch_shell ;;
294 11) log "Exiting..."; exit 0 ;;
295 *) warn "Skipping invalid option: $choice" ;;
296 esac
297 echo
298 done
299}
300
301# =============================
302# MAIN
303# =============================
304main() {
305 check_requirements
306 while true; do
307 show_menu
308 run_choices
309 read -p "Do you want to run more options? (y/n): " again
310 [[ "$again" =~ ^[Yy]$ ]] || break
311 done
312 ok "Zsh installation/configuration complete!"
313}
314
315main "$@"
316
zsh_wsl.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_SHELL_CHANGE=false
23INSTALL_HOMEBREW=false
24
25GIST_RAW_BASE="https://opengist.rmrf.online/weehong/f0d940c3c1214bf5b7996195199fdc09/raw/HEAD"
26CONFIG_FILES=(
27 ".alias"
28 ".func"
29 ".pathrc"
30 ".sourcerc"
31 ".vimrc"
32 ".zshrc"
33 ".config/starship.toml"
34)
35
36# =============================
37# PLATFORM DETECTION
38# =============================
39detect_os() {
40 if [ -f /etc/os-release ]; then
41 . /etc/os-release
42 echo "$ID"
43 else
44 echo "unknown"
45 fi
46}
47
48is_wsl() {
49 grep -qi "microsoft" /proc/version 2>/dev/null
50}
51
52# =============================
53# REQUIREMENTS
54# =============================
55check_requirements() {
56 if [[ $EUID -eq 0 ]]; then
57 err "Do not run as root. The script will request sudo when necessary."
58 exit 1
59 fi
60 if ! command -v sudo >/dev/null 2>&1; then
61 err "sudo required"
62 exit 1
63 fi
64 if ! is_wsl; then
65 err "This installer is intended for WSL"
66 exit 1
67 fi
68}
69
70# =============================
71# INSTALLATION FUNCTIONS
72# =============================
73update_system() {
74 $SKIP_PACKAGES && return
75 log "Updating system..."
76 local os=$(detect_os)
77
78 case "$os" in
79 ubuntu|debian) sudo apt-get update -y && sudo apt-get upgrade -y ;;
80 fedora) sudo dnf upgrade -y ;;
81 arch) sudo pacman -Syu --noconfirm ;;
82 *) warn "Auto-update not supported for OS: $os" ;;
83 esac
84 ok "System updated"
85}
86
87install_packages() {
88 $SKIP_PACKAGES && return
89 log "Installing core packages..."
90 local os=$(detect_os)
91
92 case "$os" in
93 ubuntu|debian) sudo apt-get install -y zsh git vim curl wget unzip zip build-essential xz-utils ;;
94 fedora) sudo dnf install -y zsh git vim curl wget unzip zip @development-tools xz ;;
95 arch) sudo pacman -S --noconfirm zsh git vim curl wget unzip zip base-devel xz ;;
96 *) warn "Auto-install not supported for OS: $os. Please install zsh, git, vim, curl manually." ;;
97 esac
98 ok "Packages installed"
99}
100
101set_timezone() {
102 log "Checking timezone configuration..."
103 if command -v timedatectl >/dev/null 2>&1 && timedatectl status >/dev/null 2>&1; then
104 sudo timedatectl set-timezone Asia/Singapore
105 ok "Timezone set to Asia/Singapore"
106 return
107 fi
108
109 warn "Skipping timezone change: timedatectl is not available in this WSL environment"
110}
111
112install_homebrew() {
113 ! $INSTALL_HOMEBREW && return
114 command -v brew >/dev/null 2>&1 && 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
126 if ! grep -qx "$zsh_path" /etc/shells; then
127 echo "$zsh_path" | sudo tee -a /etc/shells >/dev/null
128 fi
129 chsh -s "$zsh_path"
130 ok "Shell changed (open a new WSL session for it to take effect)"
131}
132
133install_plugins() {
134 log "Installing manual Zsh plugins..."
135 local dir="$HOME/.zsh"
136 mkdir -p "$dir"
137
138 [[ -d "$dir/zsh-autosuggestions" ]] || git clone https://github.com/zsh-users/zsh-autosuggestions "$dir/zsh-autosuggestions"
139 [[ -d "$dir/zsh-syntax-highlighting" ]] || git clone https://github.com/zsh-users/zsh-syntax-highlighting "$dir/zsh-syntax-highlighting"
140
141 ok "Plugins installed directly to $dir"
142}
143
144install_starship() {
145 if command -v starship >/dev/null 2>&1 || [[ -f "$HOME/.local/bin/starship" ]]; then
146 ok "Starship already installed"
147 else
148 log "Installing Starship prompt..."
149 if command -v brew >/dev/null 2>&1; then
150 brew install starship
151 else
152 mkdir -p "$HOME/.local/bin"
153 curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b "$HOME/.local/bin"
154 fi
155 ok "Starship installed"
156 fi
157}
158
159download_configs() {
160 log "Downloading custom config files from OpenGist..."
161 local backup="$HOME/.config_backup_$(date +%Y%m%d_%H%M%S)"
162 mkdir -p "$backup"
163
164 for f in "${CONFIG_FILES[@]}"; do
165 local remote_file="${f#.}"
166 [[ "$f" == ".config/starship.toml" ]] && remote_file="starship.toml"
167 local url="$GIST_RAW_BASE/$remote_file"
168 local target="$HOME/$f"
169 local tmp="${target}.tmp.$$"
170
171 mkdir -p "$(dirname "$target")"
172
173 if [[ -f "$target" ]]; then
174 cp "$target" "$backup/"
175 fi
176
177 log "Fetching $remote_file -> $f ..."
178 if curl -fsSL "$url" -o "$tmp"; then
179 mv "$tmp" "$target"
180 else
181 rm -f "$tmp"
182 warn "Failed to download $remote_file"
183 fi
184 done
185
186 ok "Configs downloaded (Backup at $backup)"
187}
188
189configure_zshrc() {
190 local zshrc="$HOME/.zshrc"
191 log "Configuring .zshrc for plugins and Starship..."
192
193 touch "$zshrc"
194
195 # CRITICAL FIX: Purge old corrupted multi-line/plaintext starship lines
196 if [[ -f "$zshrc" ]]; then
197 sed -i '/starship init zsh/d' "$zshrc" 2>/dev/null || true
198 sed -i '/firing,/d' "$zshrc" 2>/dev/null || true
199 fi
200
201 # Ensure local binary path is explicitly loaded first
202 if ! grep -q '\.local/bin' "$zshrc"; then
203 sed -i '1i\export PATH="$HOME/.local/bin:$PATH"' "$zshrc" 2>/dev/null || echo 'export PATH="$HOME/.local/bin:$PATH"' >> "$zshrc"
204 fi
205
206 # Cleanly inject one-line safe evaluator
207 if ! grep -q 'starship init zsh' "$zshrc"; then
208 echo -e '\n# Initialize Starship' >> "$zshrc"
209 echo 'if command -v starship >/dev/null 2>&1; then eval "$(starship init zsh)"; else eval "$($HOME/.local/bin/starship init zsh)"; fi' >> "$zshrc"
210 fi
211
212 # Add autosuggestions if not present
213 if ! grep -q 'zsh-autosuggestions.zsh' "$zshrc"; then
214 echo -e '\n# Load Plugins' >> "$zshrc"
215 echo 'source ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh' >> "$zshrc"
216 fi
217
218 # Add syntax highlighting if not present (MUST be last)
219 if ! grep -q 'zsh-syntax-highlighting.zsh' "$zshrc"; then
220 echo 'source ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh' >> "$zshrc"
221 fi
222
223 ok ".zshrc configured cleanly for zero-framework setup!"
224}
225
226switch_shell() {
227 log "Starting Zsh session..."
228 echo -e "${YELLOW}Type 'exit' to return to this installer menu.${NC}"
229 echo "----------------------------------------"
230 zsh -l
231 echo "----------------------------------------"
232 ok "Returned from Zsh session"
233}
234
235# =============================
236# INTERACTIVE MENU
237# =============================
238show_menu() {
239 echo "==========================================="
240 echo "WSL Minimal Zsh Installer - Choose what to do"
241 echo "==========================================="
242 echo " 0) Run ALL steps (1-10)"
243 echo " 1) Update system packages"
244 echo " 2) Install core packages (zsh, git, vim, etc.)"
245 echo " 3) Set Timezone (best effort)"
246 echo " 4) Install Homebrew"
247 echo " 5) Configure shell (chsh - sets default shell)"
248 echo " 6) Install manual Zsh plugins (Autosuggestions, Syntax Highlighting)"
249 echo " 7) Install Starship prompt"
250 echo " 8) Download custom configs (from OpenGist)"
251 echo " 9) Configure ~/.zshrc (Inject Starship & Plugins)"
252 echo "10) Switch to Zsh (Temporary Sub-shell)"
253 echo "11) Quit"
254 echo "==========================================="
255}
256
257run_choices() {
258 local input
259 read -p "Select: " input
260 input="${input//,/ }"
261
262 local -a to_run=()
263 local -a to_exclude=()
264
265 for item in $input; do
266 if [[ "$item" == !* ]]; then
267 to_exclude+=("${item:1}")
268 elif [[ "$item" == "0" ]]; then
269 to_run+=(1 2 3 4 5 6 7 8 9 10)
270 else
271 to_run+=("$item")
272 fi
273 done
274
275 for choice in "${to_run[@]}"; do
276 local skip=false
277
278 for ex in "${to_exclude[@]}"; do
279 if [[ "$choice" == "$ex" ]]; then
280 skip=true
281 break
282 fi
283 done
284
285 $skip && continue
286
287 case "$choice" in
288 1) update_system ;;
289 2) install_packages ;;
290 3) set_timezone ;;
291 4) install_homebrew ;;
292 5) configure_shell ;;
293 6) install_plugins ;;
294 7) install_starship ;;
295 8) download_configs ;;
296 9) configure_zshrc ;;
297 10) switch_shell ;;
298 11) log "Exiting..."; exit 0 ;;
299 *) warn "Skipping invalid option: $choice" ;;
300 esac
301 echo
302 done
303}
304
305# =============================
306# MAIN
307# =============================
308main() {
309 check_requirements
310 while true; do
311 show_menu
312 run_choices
313 read -p "Do you want to run more options? (y/n): " again
314 [[ "$again" =~ ^[Yy]$ ]] || break
315 done
316 ok "WSL Zsh installation/configuration complete!"
317}
318
319main "$@"
320
zshrc Raw
1# =============================================================================
2# 1. HELPER FUNCTIONS & PATH
3# =============================================================================
4source_if_readable() {
5 local file="$1"
6 if [[ -f "$file" && -r "$file" ]]; then
7 source "$file"
8 fi
9}
10
11# Ensure local bin is in PATH early (catches manual Starship installations)
12export PATH="$HOME/.local/bin:$PATH"
13
14# =============================================================================
15# 2. THIRD-PARTY INITIALIZATION & CUSTOM CONFIGS
16# =============================================================================
17# Load external initializers (SDKMAN, NVM, etc.)
18source_if_readable "$HOME/.sourcerc"
19
20# Custom Functions (must load before Path Management)
21source_if_readable "$HOME/.func"
22
23# Path Management (Relies on append_path from .func)
24source_if_readable "$HOME/.pathrc"
25
26# Aliases (Loaded late so they override system defaults)
27source_if_readable "$HOME/.alias"
28
29# =============================================================================
30# 3. STARSHIP PROMPT
31# =============================================================================
32if [[ -z "${STARSHIP_CONFIG:-}" && -f "$HOME/.config/starship.toml" ]]; then
33 export STARSHIP_CONFIG="$HOME/.config/starship.toml"
34fi
35
36# Cleanly initialize Starship checking both system and local paths
37if command -v starship >/dev/null 2>&1; then
38 eval "$(starship init zsh)"
39elif [[ -f "$HOME/.local/bin/starship" ]]; then
40 eval "$($HOME/.local/bin/starship init zsh)"
41fi
42
43# =============================================================================
44# 4. PLUGINS (Loaded directly from ~/.zsh)
45# =============================================================================
46# Autosuggestions
47source_if_readable "$HOME/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh"
48
49# Syntax Highlighting (CRITICAL: Must be the absolute last thing loaded)
50source_if_readable "$HOME/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh"