Последняя активность 1788255366

# shell-prompt.zsh # Powerline-style prompt untuk Zsh di macOS Tahoe. # Diadaptasi dari konfigurasi synth-shell Bash.

dartokloning's Avatar dartokloning ревизий этого фрагмента 1788255366. К ревизии

1 file changed, 28 insertions, 5 deletions

shell-prompt.zsh

@@ -1,6 +1,7 @@
1 1 # shell-prompt.zsh
2 2 # Powerline-style prompt untuk Zsh di macOS Tahoe.
3 3 # Diadaptasi dari konfigurasi synth-shell Bash.
4 + # Membutuhkan Nerd Font agar icon dapat tampil dengan benar.
4 5
5 6 [[ -o interactive ]] || return
6 7
@@ -12,6 +13,14 @@ SSP_SEPARATOR_CHAR=$'\uE0B0'
12 13 SSP_SEGMENT_PADDING=' '
13 14 SSP_MAX_PWD_CHAR=25
14 15
16 + # Nerd Font icons.
17 + SSP_ICON_USER=$'\uf007'
18 + SSP_ICON_FOLDER=$'\uf07b'
19 + SSP_ICON_CALENDAR=$'\uf073'
20 + SSP_ICON_CLOCK=$'\uf017'
21 + SSP_ICON_APPLE=$'\uf179'
22 + SSP_ICON_LINUX=$'\uf17c'
23 +
15 24 SSP_GIT_SYNCED=''
16 25 SSP_GIT_AHEAD=' ▲'
17 26 SSP_GIT_BEHIND=' ▼'
@@ -226,17 +235,31 @@ _ssp_short_pwd() {
226 235 fi
227 236 }
228 237
238 + _ssp_os_icon() {
239 + case "$(uname -s 2>/dev/null)" in
240 + Darwin)
241 + printf '%s' "$SSP_ICON_APPLE"
242 + ;;
243 + Linux)
244 + printf '%s' "$SSP_ICON_LINUX"
245 + ;;
246 + *)
247 + printf '%s' "$SSP_ICON_LINUX"
248 + ;;
249 + esac
250 + }
251 +
229 252 _ssp_segment_text() {
230 253 case "$1" in
231 - USER) printf '%s' "$USER" ;;
232 - HOST) hostname -s 2>/dev/null || printf '%s' "$HOST" ;;
233 - PWD) _ssp_short_pwd ;;
254 + USER) printf '%s %s' "$SSP_ICON_USER" "$USER" ;;
255 + HOST) printf '%s %s' "$(_ssp_os_icon)" "$(hostname -s 2>/dev/null || printf '%s' "$HOST")" ;;
256 + PWD) printf '%s %s' "$SSP_ICON_FOLDER" "$(_ssp_short_pwd)" ;;
234 257 GIT) _ssp_git_branch ;;
235 258 PYENV) _ssp_pyenv ;;
236 259 TF) _ssp_terraform ;;
237 260 KUBE) _ssp_kube ;;
238 - DATE) _ssp_indonesian_date ;;
239 - CLOCK) date +%H:%M:%S ;;
261 + DATE) printf '%s %s' "$SSP_ICON_CALENDAR" "$(_ssp_indonesian_date)" ;;
262 + CLOCK) printf '%s %s' "$SSP_ICON_CLOCK" "$(date +%H:%M:%S)" ;;
240 263 esac
241 264 }
242 265

dartokloning's Avatar dartokloning ревизий этого фрагмента 1788244670. К ревизии

1 file changed, 12 insertions, 5 deletions

shell-prompt.zsh

@@ -258,10 +258,15 @@ _ssp_print_segment() {
258 258
259 259 _ssp_build_prompt() {
260 260 local -a active
261 - local element text i current next next_bg prompt=''
261 + active=()
262 +
263 + local element text i current next next_bg
264 + local built_prompt=''
262 265
263 266 for element in "${SSP_FORMAT[@]}"; do
264 - text=$(_ssp_segment_text "$element")
267 + # Segment opsional seperti Git/Terraform/Kubernetes boleh tidak tersedia.
268 + # Status non-zero dari segment tidak boleh menghentikan seluruh prompt builder.
269 + text=$(_ssp_segment_text "$element" 2>/dev/null) || text=''
265 270 [[ -n "$text" ]] && active+=("$element:$text")
266 271 done
267 272
@@ -277,18 +282,20 @@ _ssp_build_prompt() {
277 282 else
278 283 next_bg='none'
279 284 fi
280 - prompt+=$(_ssp_print_segment "$element" "$text" "$next_bg")
285 +
286 + built_prompt+=$(_ssp_print_segment "$element" "$text" "$next_bg") || true
281 287 done
282 288
283 289 local input_code reset
284 290 input_code=$(_ssp_ansi "$(_ssp_fg_code "${SSP_COLOR_FG[INPUT]}");$(_ssp_bg_code "${SSP_COLOR_BG[INPUT]}");$(_ssp_effect_code "${SSP_COLOR_EFFECT[INPUT]}")")
285 291 reset=$(_ssp_ansi '0')
286 292
287 - # Dua baris seperti prompt Debian: ╭ segments ... lalu ╰>$
288 - PROMPT=$'\n╭'"${prompt}"$'\n╰>'"${input_code}"'$ '"${reset}"
293 + # Tetapkan eksplisit sebagai parameter global Zsh.
294 + typeset -g PROMPT=$'\n╭'"${built_prompt}"$'\n╰>'"${input_code}"'$ '"${reset}"
289 295
290 296 # Judul terminal.
291 297 print -Pn "\e]0;${USER}@$(hostname -s): ${PWD}\a"
298 + return 0
292 299 }
293 300
294 301 # Hook native Zsh, menggantikan PROMPT_COMMAND milik Bash.

dartokloning's Avatar dartokloning ревизий этого фрагмента 1788241808. К ревизии

1 file changed, 299 insertions

shell-prompt.zsh(файл создан)

@@ -0,0 +1,299 @@
1 + # shell-prompt.zsh
2 + # Powerline-style prompt untuk Zsh di macOS Tahoe.
3 + # Diadaptasi dari konfigurasi synth-shell Bash.
4 +
5 + [[ -o interactive ]] || return
6 +
7 + # -----------------------------------------------------------------------------
8 + # Konfigurasi tampilan
9 + # -----------------------------------------------------------------------------
10 + SSP_FORMAT=(USER HOST PWD GIT PYENV TF KUBE DATE CLOCK)
11 + SSP_SEPARATOR_CHAR=$'\uE0B0'
12 + SSP_SEGMENT_PADDING=' '
13 + SSP_MAX_PWD_CHAR=25
14 +
15 + SSP_GIT_SYNCED=''
16 + SSP_GIT_AHEAD=' ▲'
17 + SSP_GIT_BEHIND=' ▼'
18 + SSP_GIT_DIVERGED=' ◆'
19 + SSP_GIT_DIRTY=' ◔'
20 + SSP_GIT_DIRTY_AHEAD=' ◔ △'
21 + SSP_GIT_DIRTY_BEHIND=' ◔ ▽'
22 + SSP_GIT_DIRTY_DIVERGED=' ◔ ◇'
23 + SSP_GIT_STASH='🗎'
24 + SSP_GIT_UPDATE_PERIOD_MINUTES=15
25 +
26 + # color-name -> ANSI foreground/background base codes.
27 + _ssp_8bit_code() {
28 + case "$1" in
29 + default|none) echo 9 ;;
30 + black) echo 0 ;;
31 + red) echo 1 ;;
32 + green) echo 2 ;;
33 + yellow) echo 3 ;;
34 + blue) echo 4 ;;
35 + magenta|purple|pink) echo 5 ;;
36 + cyan) echo 6 ;;
37 + light-gray) echo 7 ;;
38 + dark-gray) echo 60 ;;
39 + light-red) echo 61 ;;
40 + light-green) echo 62 ;;
41 + light-yellow) echo 63 ;;
42 + light-blue) echo 64 ;;
43 + light-magenta|light-purple) echo 65 ;;
44 + light-cyan) echo 66 ;;
45 + white) echo 67 ;;
46 + *) echo 0 ;;
47 + esac
48 + }
49 +
50 + _ssp_fg_code() {
51 + local color="$1"
52 + if [[ "$color" == <-> ]] && (( color >= 0 && color < 256 )); then
53 + printf '38;5;%s' "$color"
54 + else
55 + local bit=$(_ssp_8bit_code "$color")
56 + (( bit == 9 )) && printf '39' || printf '%d' $((bit + 30))
57 + fi
58 + }
59 +
60 + _ssp_bg_code() {
61 + local color="$1"
62 + if [[ "$color" == <-> ]] && (( color >= 0 && color < 256 )); then
63 + printf '48;5;%s' "$color"
64 + else
65 + local bit=$(_ssp_8bit_code "$color")
66 + (( bit == 9 )) && printf '49' || printf '%d' $((bit + 40))
67 + fi
68 + }
69 +
70 + _ssp_effect_code() {
71 + case "$1" in
72 + bold|bright) echo 1 ;;
73 + dim) echo 2 ;;
74 + underline) echo 4 ;;
75 + blink) echo 5 ;;
76 + reverse) echo 7 ;;
77 + hidden) echo 8 ;;
78 + strikeout) echo 9 ;;
79 + *) echo 0 ;;
80 + esac
81 + }
82 +
83 + _ssp_ansi() {
84 + printf '%%{\033[%sm%%}' "$1"
85 + }
86 +
87 + # -----------------------------------------------------------------------------
88 + # Warna tiap segment: foreground background effect
89 + # -----------------------------------------------------------------------------
90 + typeset -gA SSP_COLOR_FG SSP_COLOR_BG SSP_COLOR_EFFECT
91 + SSP_COLOR_FG[USER]='black'; SSP_COLOR_BG[USER]='green'; SSP_COLOR_EFFECT[USER]='bold'
92 + SSP_COLOR_FG[HOST]='white'; SSP_COLOR_BG[HOST]='light-blue'; SSP_COLOR_EFFECT[HOST]='bold'
93 + SSP_COLOR_FG[PWD]='dark-gray'; SSP_COLOR_BG[PWD]='white'; SSP_COLOR_EFFECT[PWD]='bold'
94 + SSP_COLOR_FG[GIT]='light-gray'; SSP_COLOR_BG[GIT]='dark-gray'; SSP_COLOR_EFFECT[GIT]='bold'
95 + SSP_COLOR_FG[PYENV]='white'; SSP_COLOR_BG[PYENV]='blue'; SSP_COLOR_EFFECT[PYENV]='bold'
96 + SSP_COLOR_FG[KUBE]='white'; SSP_COLOR_BG[KUBE]='purple'; SSP_COLOR_EFFECT[KUBE]='bold'
97 + SSP_COLOR_FG[TF]='purple'; SSP_COLOR_BG[TF]='light-purple'; SSP_COLOR_EFFECT[TF]='bold'
98 + SSP_COLOR_FG[DATE]='white'; SSP_COLOR_BG[DATE]='light-purple'; SSP_COLOR_EFFECT[DATE]='bold'
99 + SSP_COLOR_FG[CLOCK]='white'; SSP_COLOR_BG[CLOCK]='black'; SSP_COLOR_EFFECT[CLOCK]='bold'
100 + SSP_COLOR_FG[INPUT]='45'; SSP_COLOR_BG[INPUT]='none'; SSP_COLOR_EFFECT[INPUT]='bold'
101 +
102 + _ssp_git_branch() {
103 + command -v git >/dev/null 2>&1 || return
104 + git rev-parse --is-inside-work-tree >/dev/null 2>&1 || return
105 +
106 + local branch
107 + branch=$(git symbolic-ref --quiet --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null) || return
108 +
109 + # Periodic fetch. macOS memakai stat -f, bukan GNU stat -c.
110 + if (( SSP_GIT_UPDATE_PERIOD_MINUTES >= 0 )); then
111 + local gitdir fetch_head last_update now elapsed
112 + gitdir=$(git rev-parse --git-dir 2>/dev/null)
113 + [[ "$gitdir" != /* ]] && gitdir="$PWD/$gitdir"
114 + fetch_head="$gitdir/FETCH_HEAD"
115 + if [[ -f "$fetch_head" ]]; then
116 + last_update=$(stat -f '%m' "$fetch_head" 2>/dev/null)
117 + now=$(date +%s)
118 + if [[ -n "$last_update" ]]; then
119 + elapsed=$(( (now - last_update) / 60 ))
120 + if (( elapsed >= SSP_GIT_UPDATE_PERIOD_MINUTES )); then
121 + (git fetch --recurse-submodules >/dev/null 2>&1 &!)
122 + fi
123 + fi
124 + fi
125 + fi
126 +
127 + local porcelain tracking dirty=false ahead=false behind=false symbol=''
128 + porcelain=$(git status --porcelain 2>/dev/null)
129 + [[ -n "$porcelain" ]] && dirty=true
130 + tracking=$(git status --porcelain -uno -b 2>/dev/null)
131 + [[ "$tracking" == *ahead* ]] && ahead=true
132 + [[ "$tracking" == *behind* ]] && behind=true
133 +
134 + if $dirty && $ahead && $behind; then
135 + symbol=$SSP_GIT_DIRTY_DIVERGED
136 + elif $dirty && $ahead; then
137 + symbol=$SSP_GIT_DIRTY_AHEAD
138 + elif $dirty && $behind; then
139 + symbol=$SSP_GIT_DIRTY_BEHIND
140 + elif $dirty; then
141 + symbol=$SSP_GIT_DIRTY
142 + elif $ahead && $behind; then
143 + symbol=$SSP_GIT_DIVERGED
144 + elif $ahead; then
145 + symbol=$SSP_GIT_AHEAD
146 + elif $behind; then
147 + symbol=$SSP_GIT_BEHIND
148 + else
149 + symbol=$SSP_GIT_SYNCED
150 + fi
151 +
152 + local stash_count stash='' tags tag=''
153 + stash_count=$(git stash list 2>/dev/null | wc -l | tr -d ' ')
154 + (( stash_count > 0 )) && stash=" ${stash_count}${SSP_GIT_STASH}"
155 + tags=$(git tag --points-at HEAD 2>/dev/null | paste -sd ',' -)
156 + [[ -n "$tags" ]] && tag=" $tags"
157 +
158 + printf '%s%s%s%s' "$branch" "$symbol" "$stash" "$tag"
159 + }
160 +
161 + _ssp_terraform() {
162 + command -v terraform >/dev/null 2>&1 || return
163 + [[ -d .terraform ]] || return
164 + terraform workspace show 2>/dev/null | tr -d '\n'
165 + }
166 +
167 + _ssp_pyenv() {
168 + if [[ -n "${CONDA_DEFAULT_ENV:-}" ]]; then
169 + printf '%s' "$CONDA_DEFAULT_ENV"
170 + elif [[ -n "${VIRTUAL_ENV:-}" ]]; then
171 + basename "$VIRTUAL_ENV"
172 + fi
173 + }
174 +
175 + _ssp_kube() {
176 + command -v kubectl >/dev/null 2>&1 || return
177 + local ctx cluster
178 + ctx=$(kubectl config current-context 2>/dev/null) || return
179 + [[ -n "$ctx" ]] || return
180 + cluster=$(kubectl config view -o "jsonpath={.contexts[?(@.name==\"$ctx\")].context.cluster}" 2>/dev/null)
181 + [[ -n "$cluster" ]] && printf '%s' "$cluster" || printf '%s' "$ctx"
182 + }
183 +
184 + _ssp_indonesian_date() {
185 + local day month hari bulan
186 + day=$(LC_ALL=C date +%A)
187 + month=$(LC_ALL=C date +%B)
188 +
189 + case "$day" in
190 + Monday) hari='Senin' ;;
191 + Tuesday) hari='Selasa' ;;
192 + Wednesday) hari='Rabu' ;;
193 + Thursday) hari='Kamis' ;;
194 + Friday) hari="Jum'at" ;;
195 + Saturday) hari='Sabtu' ;;
196 + Sunday) hari='Ahad' ;;
197 + *) hari="$day" ;;
198 + esac
199 +
200 + case "$month" in
201 + January) bulan='Januari' ;;
202 + February) bulan='Februari' ;;
203 + March) bulan='Maret' ;;
204 + April) bulan='April' ;;
205 + May) bulan='Mei' ;;
206 + June) bulan='Juni' ;;
207 + July) bulan='Juli' ;;
208 + August) bulan='Agustus' ;;
209 + September) bulan='September' ;;
210 + October) bulan='Oktober' ;;
211 + November) bulan='November' ;;
212 + December) bulan='Desember' ;;
213 + *) bulan="$month" ;;
214 + esac
215 +
216 + printf '%s, %s %s %s' "$hari" "$(date +%d)" "$bulan" "$(date +%Y)"
217 + }
218 +
219 + _ssp_short_pwd() {
220 + local p="$PWD"
221 + p=${p/#$HOME/~}
222 + if (( ${#p} > SSP_MAX_PWD_CHAR )); then
223 + printf '…%s' "${p: -$((SSP_MAX_PWD_CHAR - 1))}"
224 + else
225 + printf '%s' "$p"
226 + fi
227 + }
228 +
229 + _ssp_segment_text() {
230 + case "$1" in
231 + USER) printf '%s' "$USER" ;;
232 + HOST) hostname -s 2>/dev/null || printf '%s' "$HOST" ;;
233 + PWD) _ssp_short_pwd ;;
234 + GIT) _ssp_git_branch ;;
235 + PYENV) _ssp_pyenv ;;
236 + TF) _ssp_terraform ;;
237 + KUBE) _ssp_kube ;;
238 + DATE) _ssp_indonesian_date ;;
239 + CLOCK) date +%H:%M:%S ;;
240 + esac
241 + }
242 +
243 + _ssp_print_segment() {
244 + local element="$1" text="$2" next_bg="$3"
245 + local fg=${SSP_COLOR_FG[$element]}
246 + local bg=${SSP_COLOR_BG[$element]}
247 + local effect=${SSP_COLOR_EFFECT[$element]}
248 + local text_code sep_code reset
249 +
250 + text_code=$(_ssp_ansi "$(_ssp_fg_code "$fg");$(_ssp_bg_code "$bg");$(_ssp_effect_code "$effect")")
251 + sep_code=$(_ssp_ansi "$(_ssp_fg_code "$bg");$(_ssp_bg_code "$next_bg")")
252 + reset=$(_ssp_ansi '0')
253 +
254 + printf '%s%s%s%s%s%s%s' \
255 + "$text_code" "$SSP_SEGMENT_PADDING" "$text" "$SSP_SEGMENT_PADDING" \
256 + "$sep_code" "$SSP_SEPARATOR_CHAR" "$reset"
257 + }
258 +
259 + _ssp_build_prompt() {
260 + local -a active
261 + local element text i current next next_bg prompt=''
262 +
263 + for element in "${SSP_FORMAT[@]}"; do
264 + text=$(_ssp_segment_text "$element")
265 + [[ -n "$text" ]] && active+=("$element:$text")
266 + done
267 +
268 + for (( i=1; i<=${#active[@]}; i++ )); do
269 + current=${active[$i]}
270 + element=${current%%:*}
271 + text=${current#*:}
272 +
273 + if (( i < ${#active[@]} )); then
274 + next=${active[$((i+1))]}
275 + next=${next%%:*}
276 + next_bg=${SSP_COLOR_BG[$next]}
277 + else
278 + next_bg='none'
279 + fi
280 + prompt+=$(_ssp_print_segment "$element" "$text" "$next_bg")
281 + done
282 +
283 + local input_code reset
284 + input_code=$(_ssp_ansi "$(_ssp_fg_code "${SSP_COLOR_FG[INPUT]}");$(_ssp_bg_code "${SSP_COLOR_BG[INPUT]}");$(_ssp_effect_code "${SSP_COLOR_EFFECT[INPUT]}")")
285 + reset=$(_ssp_ansi '0')
286 +
287 + # Dua baris seperti prompt Debian: ╭ segments ... lalu ╰>$
288 + PROMPT=$'\n╭'"${prompt}"$'\n╰>'"${input_code}"'$ '"${reset}"
289 +
290 + # Judul terminal.
291 + print -Pn "\e]0;${USER}@$(hostname -s): ${PWD}\a"
292 + }
293 +
294 + # Hook native Zsh, menggantikan PROMPT_COMMAND milik Bash.
295 + autoload -Uz add-zsh-hook
296 + add-zsh-hook precmd _ssp_build_prompt
297 +
298 + # Bangun prompt pertama kali saat file di-source.
299 + _ssp_build_prompt
Новее Позже