-
Notifications
You must be signed in to change notification settings - Fork 7
/
prompt_statusline_setup
585 lines (513 loc) · 17.6 KB
/
prompt_statusline_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
#
# A two-line, responsive theme styled after powerline.
# Originally ported from agnoster, in oh-my-zsh (https://github.com/robbyrussell/oh-my-zsh)
# Async support from sorin's prompt in prezto
#
# Authors:
# Ellis Tsung (github.com/el1t)
#
#
# ==============Colors==============
# Base | Color | Bold | Solarized
# ----------------------------------
# 0 | Black | 8 | Base03
# 1 | Red | 9 | Orange
# 2 | Green | 10 | Base01
# 3 | Yellow | 11 | Base00
# 4 | Blue | 12 | Base0
# 5 | Magenta | 13 | Violet
# 6 | Cyan | 14 | Base1
# 7 | White | 15 | Base3
#
# Load dependencies
pmodload 'helper'
# Global vars/constants
typeset -i _prompt_statusline_length=0
_prompt_statusline_git=''
_prompt_statusline_bg=(7 15 7 '') # foreground, background, middle, current
_prompt_statusline_symbols=( )
_prompt_statusline_left_segments=(status user git-branch directory)
_prompt_statusline_right_segments=(git-status virtualenv clock history machine)
#
# Segment drawing utility
#
prompt_statusline_draw() {
local -a left right start end center diamond standalone no_draw warning
local escape_sequences='%([BSUbfksu]|([FK]|){*})'
zparseopts -D l=left -left=left \
r=right -right=right \
s=start -start=start \
e=end -end=end \
c=center -center=center \
d=diamond -diamond=diamond \
a=standalone -standalone=standalone \
n=no_draw -no-draw=no_draw \
w=warning -warning=warning
# Begin a left segment
if [[ -n $left ]]; then
local bg fg
[[ -n $1 ]] && bg="%K{$1}" || bg='%k'
[[ -n $2 ]] && fg="%F{$2}" || fg='%f'
if [[ -n $_prompt_statusline_bg[4] ]]; then
if [[ $1 != $_prompt_statusline_bg[4] ]]; then
echo -n " $bg%F{$_prompt_statusline_bg[4]}$_prompt_statusline_symbols[4]"
else
echo -n " $bg%F{$_prompt_statusline_bg[2]}$_prompt_statusline_symbols[3]"
fi
(( _prompt_statusline_length += 2 ))
else
echo -n "$bg"
fi
_prompt_statusline_bg[4]=$1
echo -n "$fg "
if [[ -n $3 ]]; then
echo -n $3
(( _prompt_statusline_length += ${#${(S%%)${3}//$~escape_sequences/}} + 2 ))
fi
# Begin a right segment
elif [[ -n $right ]]; then
local bg fg
[[ -n $1 ]] && bg="%K{$1}" || bg='%k'
[[ -n $2 ]] && fg="%F{$2}" || fg='%f'
if [[ -n $_prompt_statusline_bg[4] ]]; then
if [[ $1 != $_prompt_statusline_bg[4] ]]; then
echo -n "%F{$_prompt_statusline_bg[4]}$bg%S$_prompt_statusline_symbols[1]%s$fg "
else
echo -n "%F{$_prompt_statusline_bg[2]}$bg$_prompt_statusline_symbols[2]$fg "
fi
else
echo -n "%F{$1}$_prompt_statusline_symbols[1]$bg$fg "
fi
_prompt_statusline_bg[4]=$1
if [[ -n $3 ]]; then
echo -n "$3 "
fi
# Used to count the length of right prompt segments without drawing segments
elif [[ -n $no_draw ]]; then
if [[ -n $_prompt_statusline_bg[4] ]]; then
(( _prompt_statusline_length += 3 ))
else
(( _prompt_statusline_length += 2 ))
_prompt_statusline_bg[4]=0
fi
if [[ -n $3 ]]; then
(( _prompt_statusline_length += ${#${(S%%)${3}//$~escape_sequences/}} + 1 ))
fi
# Start the right prompt, setting the current bg color
elif [[ -n $start ]]; then
local bg
[[ -n $_prompt_statusline_bg[3] ]] && bg="%K{$_prompt_statusline_bg[3]}" || bg='%k'
echo -n "$bg"
_prompt_statusline_bg[4]=$_prompt_statusline_bg[3]
# End the left prompt, closing any open segments
elif [[ -n $end ]]; then
local bg
[[ -n $_prompt_statusline_bg[3] ]] && bg="%K{$_prompt_statusline_bg[3]}" || bg='%k'
if [[ -n $_prompt_statusline_bg[4] ]]; then
echo -n " %F{$_prompt_statusline_bg[4]}$bg$_prompt_statusline_symbols[4]"
[[ -z $uncalculated ]] && (( _prompt_statusline_length += 2 ))
else
echo -n $_prompt_statusline_bg[3]
fi
echo -n '%f'
# Center a prompt
elif [[ -n $center ]]; then
local length=$(( (COLUMNS - $#3 - 4) / 2 ))
[[ -n $4 ]] && echo -n "%K{$4}"
# Pad spaces
echo -n "${(l:$length:: :)}"
# Output a warning
elif [[ -n $warning ]]; then
print -P "$(prompt_statusline_draw -a 4 7 Statusline)%F{1}%UWarning%u%f: $1" >&2
fi
# Sample output
if [[ -n $diamond ]]; then
local padding_color=$4
[[ -z $4 ]] && padding_color=$_prompt_statusline_bg[2]
echo -n "%F{$1}%K{$padding_color}$_prompt_statusline_symbols[1]%F{$2}%K{$1} $3 %F{$1}%K{$padding_color}$_prompt_statusline_symbols[4]%f%E%k"
# Standalone
elif [[ -n $standalone ]]; then
local bg fg
[[ -n $1 ]] && bg="%K{$1}" || bg="%K{$_prompt_statusline_bg[1]}"
[[ -n $2 ]] && fg="%F{$2}" || fg='%f'
echo -n "$fg$bg $3 %F{$_prompt_statusline_bg[2]}%S$_prompt_statusline_symbols[4]%s%f%k "
fi
}
#
# Segment components
#
prompt_statusline_segments() {
local -a left right no_draw
zparseopts -D r=right -right=right \
l=left -left=left \
n=no_draw -no-calc=no_draw
# Start right prompt
local draw_options
if [[ -n $right ]]; then
draw_options='-r'
elif [[ -n $no_draw ]]; then
draw_options='-n'
elif [[ -n $left ]]; then
draw_options='-l'
fi
while (( # > 0 )); do
case "$1" in
# Status: root/error/background jobs
(status)
local symbols=''
[[ $UID == 0 || $EUID == 0 ]] && symbols+='%F{3}⚡'
(( retval != 0 )) && symbols+='%F{1}✘'
[[ -n $(jobs -l) ]] && symbols+='%F{6}⚙'
if [[ -n $symbols ]]; then
prompt_statusline_draw $draw_options 0 '' $symbols
fi
;;
# User: username
(user)
if [[ -n "$SSH_CLIENT$SSH_TTY" ]]; then
prompt_statusline_draw $draw_options 0 3 $LOGNAME
fi
;;
# Machine: machine name
(machine)
if [[ -n "$SSH_CLIENT$SSH_TTY" ]]; then
prompt_statusline_draw $draw_options 3 0 '@%m'
fi
;;
# Git: branch, dirty status, commits behind/ahead of remote
(git-branch)
if [[ -n $_prompt_statusline_git ]]; then
# If async has finished
if (( _prompt_statusline_precmd_async_pid == 0 )); then
# Declaring this inside the if statement would not be local
local git_output="${(e)git_info[prompt]}"
if [[ -n $git_output ]]; then
prompt_statusline_draw $draw_options $git_info[bg] 7 $git_output
fi
else
# Display placeholder for async, gray color
prompt_statusline_draw $draw_options 14 0 ' ... '
fi
fi
;;
# Git: format action, output other statuses defined in git_info[rprompt]
(git-status)
# If async has finished
if [[ -n $_prompt_statusline_git && $_prompt_statusline_precmd_async_pid -eq 0 ]]; then
if [[ -n $git_info[rprompt] ]]; then
case $git_info[action] in
(apply)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '<A<'
;;
(bisect)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '<B>'
;;
(cherry-pick|cherry-pick-sequence)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '<C<'
;;
(merge)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '>M<'
;;
(rebase|rebase-interactive|rebase-merge)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '>R>'
;;
esac
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' $git_info[rprompt]
fi
fi
;;
# Dir: current working directory, shortens if longer than available space
(directory)
local directory="${${(%):-%~}}"
local hashed_directory="${${directory[2,-1]%%/*}:-$directory[1]}"
prompt_statusline_draw $draw_options 4 7 $hashed_directory
# Replace directory with empty string if at base of hashed directory, else eliminate hashed portion
directory="${${directory:#^?*/*}:+${directory#?*/}}"
if [[ -n $directory ]]; then
# Count spaces available for printing the working directory
# Subtract the extra 3 chars used for the current segment and an extra space in case
local spacing=$(( COLUMNS - _prompt_statusline_length - 3 - 1 ))
local length="$#directory"
if (( length <= spacing )); then
prompt_statusline_draw $draw_options 4 7 $directory
else
# Shorten path as much as necessary
local dir_segment
prompt_statusline_draw $draw_options 4 7
for dir_segment in "${(@s:/:)directory:h}"; do
if (( length > spacing )); then
echo -n "$dir_segment[1]/"
(( length -= $#dir_segment - 1 ))
else
echo -n "$dir_segment/"
fi
done
echo -n "${directory:t}"
fi
fi
;;
(virtualenv)
if [[ -n "$python_info[virtualenv]" ]]; then
if (( _prompt_statusline_precmd_async_pid == 0 )); then
prompt_statusline_draw $draw_options 6 7 "$python_info[virtualenv]"
fi
fi
;;
(clock)
prompt_statusline_draw $draw_options 5 7 "${${(%%):-%t}## }"
;;
(history)
prompt_statusline_draw $draw_options $_prompt_statusline_bg[1] '' '!%F{4}%!'
;;
(*)
prompt_statusline_draw -w "$1 is not a valid segment!"
;;
esac
shift
done
}
# Output runtime of previous task
prompt_statusline_elapsed_time() {
if [[ -n $_prompt_statusline_start_time ]]; then
local -i end_time=$(( SECONDS - _prompt_statusline_start_time ))
if (( end_time >= 10 )); then
local -a output
if (( end_time >= 60 )); then
if (( end_time >= 3600 )); then
output+=("$(( end_time / 3600 ))h")
end_time=$(( end_time % 3600 ))
fi
output+=("$(( end_time / 60 ))m")
end_time=$(( end_time % 60 ))
fi
output+=("${end_time}s")
echo
print -P '$(prompt_statusline_draw -cd 13 7 "$output" $_prompt_statusline_bg[1])'
fi
unset _prompt_statusline_start_time
fi
}
# Draw prompt(s)
prompt_statusline() {
local retval=$?
local -a left right single
zparseopts l=left -left=left \
r=right -right=right \
s=single -single=single
if [[ -n "$left" ]]; then
[[ -z "$single" && -n "$TMUX" ]] && echo -n "%K{$_prompt_statusline_bg[1]}%{${(l:$COLUMNS:: :)}%}%k%{$(echotc LEFT $COLUMNS)%}"
prompt_statusline_segments -n $_prompt_statusline_right_segments
_prompt_statusline_bg[4]=''
prompt_statusline_segments -l $_prompt_statusline_left_segments
prompt_statusline_draw -e
if [[ -n "$single" ]]; then
echo -n '%k'
elif [[ -z "$TMUX" ]]; then
echo -n '%E'
fi
elif [[ -n $right ]]; then
prompt_statusline_draw -s
prompt_statusline_segments -r $_prompt_statusline_right_segments
fi
}
#
# Prezto setup functions
#
prompt_statusline_precmd_async() {
# Get Git repository information.
if (( $+functions[git-info] )); then
git-info
typeset -p git_info >! $_prompt_statusline_precmd_async_data
fi
# Signal completion to parent process.
kill -WINCH $$
}
prompt_statusline_git_info() {
# Append Git status.
if [[ $_prompt_statusline_precmd_async_pid -gt 0 && -s $_prompt_statusline_precmd_async_data ]]; then
alias typeset='typeset -g'
source $_prompt_statusline_precmd_async_data
unalias typeset
# Reset PID.
_prompt_statusline_precmd_async_pid=0
# Display prompt.
zle && zle reset-prompt
fi
}
prompt_statusline_precmd() {
setopt LOCAL_OPTIONS
unsetopt XTRACE KSH_ARRAYS
# Check previous task runtime
prompt_statusline_elapsed_time
# Kill the old process of slow commands if it is still running.
if (( _prompt_statusline_precmd_async_pid > 0 )); then
kill -KILL $_prompt_statusline_precmd_async_pid &> /dev/null
fi
# Split off async task to check git status if in git repo
if $(git rev-parse --is-inside-work-tree 2> /dev/null); then
_prompt_statusline_git=1
# Compute slow commands in the background.
trap prompt_statusline_git_info WINCH
prompt_statusline_precmd_async &!
_prompt_statusline_precmd_async_pid=$!
else
unset _prompt_statusline_git
fi
if (( $+functions[python-info] )); then
python-info
fi
}
prompt_statusline_preexec() {
_prompt_statusline_start_time=$SECONDS
}
prompt_statusline_help() {
print -P \
"This prompt supports solarized light and dark. Solarized light with a white statusbar on two lines is the default style.
You can invoke it thus:
prompt statusline [--color <color>] [--dark] [--font <font>] [--single]
Set this theme with the following in your rc file:
zstyle ':prezto:module:prompt' theme 'statusline' [-c|--color <color>] [-d|--dark] [-f|--font <font>] [-s|--single]
%BOPTIONS%b
-c, --color <color>
Set the statusbar background color. Does not work in single-line mode.
-d, --dark
Apply the dark theme.
-f, --font <font>
Customize the special characters used for dividers. <font> may be powerline, legacy, blocks, or none.
-s, --single
Fit the prompt to one line."
}
prompt_statusline_preview() {
# Prevent changes from affecting default prompt
local +h PROMPT=''
local +h RPROMPT=''
local +h PS2=''
local +h RPS2=''
local +h PS3=''
local +h PS4=''
local +h SPROMPT=''
editor-info 2> /dev/null
if (( # > 0 )); then
prompt_preview_theme statusline "$@"
else
prompt_preview_theme statusline
echo "$FX[none]"
prompt_preview_theme statusline --dark
echo "$FX[none]"
prompt_preview_theme statusline --single
echo "$FX[none]"
prompt_preview_theme statusline --font powerline
fi
}
# %s = undo standout, %u = remove underline, %b = unbold, %f = default foreground, %k = default background
# %S = standout, %U = underline, %B = bold, %F = fg (text) color, %K = bg color, %E = clear to end of line
prompt_statusline_setup() {
setopt LOCAL_OPTIONS
unsetopt XTRACE KSH_ARRAYS SHWORDSPLIT
prompt_opts=(cr percent subst)
typeset -i _prompt_statusline_precmd_async_pid=0
_prompt_statusline_precmd_async_data="${TMPPREFIX}-prompt_statusline_data"
# Load required functions
autoload -Uz add-zsh-hook
# Add hooks
add-zsh-hook preexec prompt_statusline_preexec
add-zsh-hook precmd prompt_statusline_precmd
# Enable prezto editor-info module
zstyle ':prezto:module:prompt' managed 'yes'
# Customize theme
local -a dark color single font
zparseopts d=dark -dark=dark \
c:=color -color:=color \
s=single -single=single \
f:=font -font:=font
if [[ -n $dark ]]; then
_prompt_statusline_bg=(0 8 0)
else
_prompt_statusline_bg=(7 15 7)
fi
# Set single-line prompt
if [[ -n $single ]]; then
if [[ -n $color ]]; then
prompt_statusline_draw -w 'cannot set color (-c) when in single-line mode (-s)'
fi
_prompt_statusline_bg[3]="$_prompt_statusline_bg[2]"
PROMPT="%{$(print $FX[none])%}"'
$(prompt_statusline -sl)'
RPROMPT="%{$terminfo[cuf1]%}"'$(prompt_statusline -sr)'
[[ -n "$TMUX" ]] && RPROMPT+="%{$terminfo[cub1]%}" || RPROMPT+="%{$terminfo[cuf1]%}"
else
if [[ -n $color ]]; then
_prompt_statusline_bg[3]=$color[2]
fi
PROMPT="%{$(print $FX[none])%}"'
$(prompt_statusline -l)
$editor_info[keymap]'
RPROMPT="%{$terminfo[cuu1]$terminfo[cuf1]%}"'$(prompt_statusline -r)'"%{$(echotc DO 1)%}"
fi
if [[ -n $font ]]; then
case "$font[2]" in
(powerline)
_prompt_statusline_symbols=(⮂ ⮃ ⮁ ⮀)
;;
(legacy)
_prompt_statusline_symbols=(◀ '<' '>' ▶︎)
;;
(block*)
_prompt_statusline_symbols=(◼ '|' '|' ◼︎)
;;
(none)
_prompt_statusline_symbols=('' '' '' '')
;;
(*)
prompt_statusline_draw -w "font type not found: $font[2]"
;;
esac
fi
# Virtualenv styling
zstyle ':prezto:module:python:info:virtualenv' format '%v'
# Completion styling
zstyle ':completion:*:corrections' format "$(prompt_statusline_draw -a 2 7 '%d (errors: %e)')"
zstyle ':completion:*:descriptions' format "$(prompt_statusline_draw -a 3 7 '%d')"
zstyle ':completion:*:messages' format ' %F{13} -- %d --%f'
zstyle ':completion:*:warnings' format "$(prompt_statusline_draw -cd 1 $_prompt_statusline_bg[1] 'No matches found')"
zstyle ':completion:*:default' list-prompt '%S%M matches%s'
zstyle ':completion:*' format "$(prompt_statusline_draw -a 3 7 '%d')"
# Editor styling
zstyle ':prezto:module:editor:info:completing' format '%B%F{1}...%f%b'
zstyle ':prezto:module:editor:info:keymap:primary' format \
"%F{4}%K{$_prompt_statusline_bg[1]}❯%K{$_prompt_statusline_bg[2]}%F{$_prompt_statusline_bg[1]}$_prompt_statusline_symbols[4]%f%k"
zstyle ':prezto:module:editor:info:keymap:primary:overwrite' format ' %F{1}♺%f'
zstyle ':prezto:module:editor:info:keymap:alternate' format \
"%F{9}%K{$_prompt_statusline_bg[1]}❯%K{$_prompt_statusline_bg[2]}%F{$_prompt_statusline_bg[1]}$_prompt_statusline_symbols[4]%f%k"
# Git-info styling
zstyle ':prezto:module:git:info' verbose 'yes'
zstyle ':prezto:module:git:info:action' format '%s'
zstyle ':prezto:module:git:info:added' format '%F{2}✚%f'
zstyle ':prezto:module:git:info:ahead' format '%F{3}↑%A%f'
zstyle ':prezto:module:git:info:behind' format '%F{3}↓%B%f'
zstyle ':prezto:module:git:info:branch' format ' %b'
zstyle ':prezto:module:git:info:commit' format '%.7c'
zstyle ':prezto:module:git:info:deleted' format '%F{1}✖%f'
zstyle ':prezto:module:git:info:modified' format '3'
zstyle ':prezto:module:git:info:position' format ':%p'
zstyle ':prezto:module:git:info:renamed' format '%F{9}➜%f'
zstyle ':prezto:module:git:info:stashed' format '%F{6}§%f'
zstyle ':prezto:module:git:info:unmerged' format '%F{3}₥%f'
zstyle ':prezto:module:git:info:untracked' format '1'
zstyle ':prezto:module:git:info:keys' format \
'prompt' '$(coalesce "%b" "%p" "%c")%s' \
'rprompt' '%A%B%S%a%d%r%U' \
'bg' '$(coalesce "%u" "%m" "2")'
# Secondary prompt, printed when the shell needs more information to complete a command
PS2="%F{6}%K{$_prompt_statusline_bg[1]}❯%k%F{$_prompt_statusline_bg[1]}$_prompt_statusline_symbols[4]%f"
RPS2="%k%F{$_prompt_statusline_bg[1]}$_prompt_statusline_symbols[1]%F{6}%K{$_prompt_statusline_bg[1]} %_%E"
# Selection prompt used within a select loop
PS3="$(prompt_statusline_draw -a 7 13 'Select:')"
# Execution trace prompt
# setopt xtrace # disable with unsetopt xtrace
PS4="$(prompt_statusline_draw -a '' 2 '%N%f:%F{4}%i')"
# Spelling prompt used to correct spelling errors
SPROMPT="$(prompt_statusline_draw -a 9 7 'Correction:')change %B%F{1}%R%b%f to %B%F{2}%r%b%f [%Unyae%u]? "
}
prompt_statusline_setup "$@"
# vim: set ft=sh :