Add collection of cursor line immediately after the previous command completes and use this when calculating the number of lines required to move the screen in order to display only the latest prompt.
188 lines
6.1 KiB
Bash
188 lines
6.1 KiB
Bash
prompt_fresh_help() {
|
|
echo "\
|
|
options:
|
|
-a enable almostontop like behaviour
|
|
-r recompile git-prompt executable"
|
|
}
|
|
|
|
prompt_fresh_setup() {
|
|
# Parse options
|
|
local almostontop=0
|
|
local recompile=0
|
|
while getopts 'ar' opt; do
|
|
case $opt in
|
|
a) local almostontop=1 ;;
|
|
r) local recompile=1 ;;
|
|
*) prompt -h fresh; return 1 ;;
|
|
esac
|
|
done
|
|
|
|
autoload -U add-zsh-hook
|
|
|
|
# Hook to print the first line of the "two line" prompt, this line is not
|
|
# actually part of the prompt so does not get redrawn, this is preferable
|
|
# since sometimes lines before the prompt can disappear.
|
|
add-zsh-hook precmd fresh_line_one
|
|
|
|
if [ $almostontop -eq 1 ]; then
|
|
# Hook to clear the screen then prints the prompt with previous command at
|
|
# the top of the screen.
|
|
add-zsh-hook precmd fresh_almostontop_precmd
|
|
add-zsh-hook preexec fresh_almostontop_preexec
|
|
else
|
|
add-zsh-hook -d preexec fresh_almostontop_preexec
|
|
add-zsh-hook -d precmd fresh_almostontop_precmd
|
|
fi
|
|
|
|
[ $recompile -eq 1 ] && prompt_cleanup
|
|
fresh_compile_git_prompt
|
|
|
|
if [ "$USER" = "root" ]; then
|
|
local user="%{%F{1}%}%n%{%f%}"
|
|
else
|
|
local user="%{%F{35}%}%n%{%f%}"
|
|
fi
|
|
|
|
local userhost=$USER
|
|
if [ "$SSH_CONNECTION" != "" ]; then
|
|
local user="$user@%{%F{244}%}%M%{%f%}"
|
|
local userhost="$userhost@`hostname`"
|
|
fi
|
|
|
|
PS1="«$user» "
|
|
PS2="«${(l:${#userhost}:: :)}» "
|
|
|
|
prompt_opts=(percent sp subst)
|
|
}
|
|
|
|
prompt_cleanup() {
|
|
[ -f ~/.cache/zsh/git-prompt ] && rm ~/.cache/zsh/git-prompt
|
|
}
|
|
|
|
fresh_line_one() {
|
|
# First get the last commands exit code before doing anything
|
|
local exit_code=$?
|
|
|
|
# Construct the time and directory portions of the prompt
|
|
local time_stamp="%{%F{244}%}%D{%H:%M:%S}%{%f%}"
|
|
[[ -n $SANDBOX_HOME ]] && \
|
|
local directory="%{%F{3}%}$SANDBOX_NAME${PWD#$SANDBOX_HOME}%{%f%}" || \
|
|
local directory="%{%F{37}%}%~%{%f%}"
|
|
|
|
# Check we are in a git repository
|
|
local git=`~/.cache/zsh/git-prompt`
|
|
|
|
# If the last command failed, display its error code at the right
|
|
if [[ $exit_code -ne 0 ]]; then
|
|
case $exit_code in
|
|
129) exit_code="SIGHUP" ;; # 128 + 1
|
|
130) exit_code="SIGINT" ;; # 128 + 2
|
|
131) exit_code="SIGQUIT" ;; # 128 + 3
|
|
132) exit_code="SIGILL" ;; # 128 + 4
|
|
133) exit_code="SIGTRAP" ;; # 128 + 5
|
|
134) exit_code="SIGABRT" ;; # 128 + 6
|
|
134) exit_code="SIGIOT" ;; # 128 + 6
|
|
135) exit_code="SIGBUS" ;; # 128 + 7
|
|
136) exit_code="SIGFPE" ;; # 128 + 8
|
|
137) exit_code="SIGKILL" ;; # 128 + 9
|
|
138) exit_code="SIGUSR1" ;; # 128 + 10
|
|
139) exit_code="SIGSEGV" ;; # 128 + 11
|
|
140) exit_code="SIGUSR2" ;; # 128 + 12
|
|
141) exit_code="SIGPIPE" ;; # 128 + 13
|
|
142) exit_code="SIGALRM" ;; # 128 + 14
|
|
143) exit_code="SIGTERM" ;; # 128 + 15
|
|
144) exit_code="SIGSTKFLT" ;; # 128 + 16
|
|
145) exit_code="SIGCHLD" ;; # 128 + 17
|
|
146) exit_code="SIGCONT" ;; # 128 + 18
|
|
147) exit_code="SIGSTOP" ;; # 128 + 19
|
|
148) exit_code="SIGTSTP" ;; # 128 + 20
|
|
149) exit_code="SIGTTIN" ;; # 128 + 21
|
|
150) exit_code="SIGTTOU" ;; # 128 + 22
|
|
151) exit_code="SIGURG" ;; # 128 + 23
|
|
152) exit_code="SIGXCPU" ;; # 128 + 24
|
|
153) exit_code="SIGXFSZ" ;; # 128 + 25
|
|
154) exit_code="SIGVTALRM" ;; # 128 + 26
|
|
155) exit_code="SIGPROF" ;; # 128 + 27
|
|
156) exit_code="SIGWINCH" ;; # 128 + 28
|
|
157) exit_code="SIGIO" ;; # 128 + 29
|
|
158) exit_code="SIGPWR" ;; # 128 + 30
|
|
159) exit_code="SIGSYS" ;; # 128 + 31
|
|
esac
|
|
local result=" %{%B%F{1}%}$exit_code%{%f%b%}"
|
|
fi
|
|
|
|
# Unset vim/tmux navigate flag to handle C-z and multiple vim jobs.
|
|
[[ ! -z "$TMUX" ]] && \
|
|
[[ "`tmux show-window-options`" = *"@vim$TMUX_PANE"* ]] && \
|
|
tmux set-window-option -u @vim$TMUX_PANE
|
|
|
|
# If a virtualenv is enabled, display it's basename
|
|
if [[ ! -z "$VIRTUAL_ENV" ]]; then
|
|
local py=" %{%F{4}%}py%{%f%}%{%F{3}%}$(basename $VIRTUAL_ENV)%{%f%}"
|
|
fi
|
|
|
|
# If docker-machine env is active, display the machines name
|
|
if [[ ! -z "$DOCKER_MACHINE_NAME" ]]; then
|
|
local docker=" %{%F{6}%}$DOCKER_MACHINE_NAME%{%f%}"
|
|
fi
|
|
|
|
# Print the first line of the prompt
|
|
print -P "$time_stamp $directory$git$py$docker$result"
|
|
}
|
|
|
|
# Executed before each prompt.
|
|
fresh_almostontop_precmd() {
|
|
# CSI ESC[6n gets the cursor position in the form ESC[<row>;<column>R
|
|
printf "\033[6n"
|
|
# Discard prefix delimited by [
|
|
read -s -d [
|
|
# Store the <row> delimited by ; in row_before
|
|
read -s -d \; row_before
|
|
# Discard suffix delimted by R otherwise it is output to the tty
|
|
read -s -d R
|
|
}
|
|
|
|
# Executed just after a command has been read and is about to be executed.
|
|
fresh_almostontop_preexec() {
|
|
# CSI ESC[6n gets the cursor position in the form ESC[<row>;<column>R
|
|
printf "\033[6n"
|
|
# Discard prefix delimited by [
|
|
read -s -d [
|
|
# Store the <row> delimited by ; in row
|
|
read -s -d \; row
|
|
# Discard suffix delimted by R otherwise it is output to the tty
|
|
read -s -d R
|
|
# Move the cursor to the bottom of the terminal
|
|
# CSI ESC[<num>B moves the cursor down <num> lines
|
|
let "down = $LINES - $row"
|
|
printf "\033[${down}B"
|
|
# Calculate the number of lines in the prompt
|
|
let "prompt_lines = ($row - $row_before) + 2"
|
|
# Print new lines to push the old command out of view
|
|
let "new = $row - $prompt_lines"
|
|
for (( i = 0; i < $new; i++ )); do
|
|
printf "\n"
|
|
done
|
|
# Move the cursor to the line below the prompt
|
|
# CSI ESC[<num>A moves the cursor up <num> lines
|
|
let "up = $LINES - $prompt_lines"
|
|
printf "\033[${up}A"
|
|
}
|
|
|
|
fresh_compile_git_prompt() {
|
|
# Compile a simple C program which parses the output of `git status
|
|
# --procelain` to greatly decrease the time taken to draw the prompt
|
|
[ ! -d ~/.cache/zsh ] && mkdir -p ~/.cache/zsh
|
|
if [ ! -f ~/.cache/zsh/git-prompt ]; then
|
|
cc -std=gnu99 -O3 -DNDEBUG -Wno-unused-result \
|
|
~/.config/zsh/git-prompt.c -o ~/.cache/zsh/git-prompt
|
|
if [ $? -ne 0 ]; then
|
|
echo "git-prompt was not compiled, is a C99 toolchain installed?"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
prompt_fresh_setup "$@"
|
|
|
|
# vim:ft=zsh
|