dotfiles/.config/zsh/themes/prompt.zsh

134 lines
4.6 KiB
Bash

# Zsh prompt theme, needs Zsh >= 5.0.0. Asynchronous prompt if zsh-async is
# detected. Requires 256 colours.
function() # Keep local variables in here
{
# Make theme variables global for later use
typeset -gA zsh_theme_colours
zsh_theme_colours[prompt]="207" # bright pink
zsh_theme_colours[vcs]="97" # dark pink
zsh_theme_colours[highlight]="201" # pink
zsh_theme_colours[minor]="61" # dark violet
zsh_theme_colours[inactive]="236" # grey
# This will use potentially user defined colours
[[ -n "${SSH_CONNECTION}" ]] && zsh_theme_colours[prompt]="11" # bright yellow
[[ ${EUID} -eq 0 ]] && zsh_theme_colours[prompt]="9" # bright red
# Show username if it is not the default user
local showuser=""
if [[ "${USERNAME}" != "${DEFAULT_USER}" ]] && [[ -n "${USERNAME}" ]]; then
showuser="%n "
fi
autoload -Uz vcs_info
zmodload zsh/zutil
zstyle ':vcs_info:*' enable git svn hg # vcs_info_printsys
zstyle ':vcs_info:*' formats "%F{${zsh_theme_colours[vcs]}}(%b)%u%c%f "
zstyle ':vcs_info:*' actionformats "%F{${zsh_theme_colours[vcs]}}(%b|%F{${zsh_theme_colours[highlight]}}%a%F{${zsh_theme_colours[vcs]}})%u%c%f "
zstyle ':vcs_info:*' stagedstr "%F{${zsh_theme_colours[highlight]}}●%f"
zstyle ':vcs_info:*' unstagedstr "%F{${zsh_theme_colours[highlight]}}○%f"
zstyle ':vcs_info:*' check-for-changes true
# Needs mafredri/zsh-async, async_init must be called before using
function _async_vcs_prompt()
{
# From https://vincent.bernat.ch/en/blog/2019-zsh-async-vcs-info
function _my_vcs_async_start()
{
async_start_worker vcs_info
async_register_callback vcs_info _my_vcs_info_done
}
function _my_vcs_info()
{
cd -q ${1}
vcs_info
print "${vcs_info_msg_0_}"
}
function _my_vcs_info_done()
{
local job=${1}
local return_code=${2}
local stdout=${3}
local more=${6}
if [[ ${job} == '[async]' ]]; then
if [[ ${return_code} -eq 2 ]]; then
# Need to restart the worker
_my_vcs_async_start
return
fi
fi
vcs_info_msg_0_="${stdout}"
(( ${more} )) || zle reset-prompt
}
function _my_vcs_chpwd()
{
# Change colour of old value
vcs_info_msg_0_="${vcs_info_msg_0_//\%F\{${zsh_theme_colours[vcs]}/%F{${zsh_theme_colours[inactive]}}"
vcs_info_msg_0_="${vcs_info_msg_0_//\%F\{${zsh_theme_colours[highlight]}/%F{${zsh_theme_colours[inactive]}}"
}
function _my_vcs_precmd()
{
async_flush_jobs vcs_info
async_job vcs_info _my_vcs_info $PWD
}
_my_vcs_async_start
autoload -Uz add-zsh-hook
add-zsh-hook precmd _my_vcs_precmd
add-zsh-hook chpwd _my_vcs_chpwd
}
# Use asynchronous VCS prompt if zsh-async is available
if [[ -v ASYNC_VERSION ]]; then
[[ ${ASYNC_INIT_DONE} -eq 0 ]] && async_init
_async_vcs_prompt
else
add-zsh-hook precmd vcs_info
fi
# Reduce directory elements to first letter until directory path is reasonably
# short. Never shrink first element. Don't shrink relatively short elements. Try
# to not shrink last element.
function _shrunkpwd()
{
local dir=${(D)PWD}
local -i max_width=$(( ${COLUMNS} / 3 ))
if [[ ${#dir} -le ${max_width} ]]; then
print -n ${dir}
return
fi
# Maybe shorten all elements but the first and last
local -a short_dir=(${(s:/:)dir})
local -i allowed_element_width=$(( ${max_width} / ${#short_dir} - 1 ))
for index in {2..$(( ${#short_dir} - 1 ))}; do
if [[ ${#short_dir[index]} -gt ${allowed_element_width} ]]; then
[[ ${#${(j:/:)short_dir}} -le ${max_width} ]] && break
short_dir[index]=${short_dir[index][1]}
fi
done
# If the last element is too long, replace the mid-section with …
if [[ ${#short_dir[-1]} -gt ${allowed_element_width} ]]; then
local -i current_width=${#${(j:/:)short_dir}}
if [[ ${current_width} -gt ${max_width} ]]; then
local -i half_length=$(( ( ${max_width} - ( ${current_width} - ${#short_dir[-1]} ) ) / 2 - 1 ))
short_dir[-1]=${short_dir[-1][1,${half_length}]}"…"${short_dir[-1][$(( ${half_length} * -1 )),-1]}
fi
fi
local out=${(j:/:)short_dir}
[[ ${out[1]} != '~' ]] && out[1]="/${out[1]}"
print -n ${out}
}
setopt PROMPT_SUBST
PROMPT="%B%F{${zsh_theme_colours[prompt]}}${showuser}%b"'${vcs_info_msg_0_}'"%B%F{${zsh_theme_colours[prompt]}}%#%f%b "
RPROMPT="%F{${zsh_theme_colours[minor]}}%(?..[%B%F{${zsh_theme_colours[highlight]}}%?%b%F{${zsh_theme_colours[minor]}}] )"'$(_shrunkpwd)'"%f"
}