dotfiles/.config/zsh/functions/prompt_tastytea_setup
tastytea b252ce4ec5
Tweak path algorithm in Zsh prompt
Reduce allowed element width to increase probability of unshortened last
element.
2022-04-27 15:01:59 +02:00

168 lines
6.2 KiB
Plaintext

# tastytea prompt theme
prompt_tastytea_help() {
cat <<'EOF'
Minimal + vcs_info on the left, PWD on the right (shortened to 1/3 screen).
This prompt is colour-scheme-able. You can invoke it thus:
prompt tastytea [user [root [remote [vcs [path [highlight [inactive]]]]]]]
Set DEFAULT_USER to only show non-default users in prompt. You need to set up
vcs_info before enabling the prompt.
EOF
if [[ ! -v ASYNC_VERSION ]]; then
print "Load https://github.com/mafredri/zsh-async" \
"for asynchronous VCS info support."
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 prompt_tastytea_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]} - ${#short_dir[-1]} ) / ${#short_dir} ))
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}
}
# Needs <https://github.com/mafredri/zsh-async>
function prompt_tastytea_vcs_async() {
# From https://vincent.bernat.ch/en/blog/2019-zsh-async-vcs-info
function prompt_tastytea_vcs_async_start() {
async_start_worker prompt_tastytea_vcs_info
async_register_callback prompt_tastytea_vcs_info \
prompt_tastytea_vcs_info_done
}
function prompt_tastytea_vcs_info_job() {
cd -q ${1}
vcs_info
print "${vcs_info_msg_0_}"
}
function prompt_tastytea_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
prompt_tastytea_vcs_async_start
return
fi
fi
vcs_info_msg_0_="${stdout}"
(( ${more} )) || zle reset-prompt
}
function prompt_tastytea_vcs_chpwd() {
# Change colour of old value
vcs_info_msg_0_="${vcs_info_msg_0_//\%F\{${prompt_tastytea_colours[vcs]}/%F{${prompt_tastytea_colours[inactive]}}"
vcs_info_msg_0_="${vcs_info_msg_0_//\%F\{${prompt_tastytea_colours[highlight]}/%F{${prompt_tastytea_colours[inactive]}}"
}
function prompt_tastytea_vcs_precmd() {
async_flush_jobs prompt_tastytea_vcs_info
async_job prompt_tastytea_vcs_info prompt_tastytea_vcs_info_job $PWD
}
prompt_tastytea_vcs_async_start
add-zsh-hook precmd prompt_tastytea_vcs_precmd
add-zsh-hook chpwd prompt_tastytea_vcs_chpwd
}
function prompt_tastytea_vcs() {
autoload -U vcs_info add-zsh-hook
zmodload zsh/zutil
zstyle ':vcs_info:*' formats "%F{${prompt_tastytea_colours[vcs]}}(%b)%u%c%f "
zstyle ':vcs_info:*' actionformats "%F{${prompt_tastytea_colours[vcs]}}(%b|%F{${prompt_tastytea_colours[highlight]}}%a%F{${prompt_tastytea_colours[vcs]}})%u%c%f "
zstyle ':vcs_info:*' stagedstr "%F{${prompt_tastytea_colours[highlight]}}●"
zstyle ':vcs_info:*' unstagedstr "%F{${prompt_tastytea_colours[highlight]}}○"
# Use asynchronous VCS prompt if zsh-async is available
if [[ -v ASYNC_VERSION ]]; then
[[ ${ASYNC_INIT_DONE} -eq 0 ]] && async_init
prompt_tastytea_vcs_async
else
add-zsh-hook precmd vcs_info
fi
}
function prompt_tastytea_setup() {
if [[ ${ZSH_VERSION[1]} -lt 5 ]]; then
print -u2 "This theme needs Zsh >= 5"
return 1
fi
# Needs to be global for async functions
typeset -gA prompt_tastytea_colours
prompt_tastytea_colours[user]="${1:-207}" # bright pink
prompt_tastytea_colours[root]="${2:-196}" # bright red
prompt_tastytea_colours[remote]="${3:-226}" # bright yellow
prompt_tastytea_colours[vcs]="${4:-97}" # dark pink
prompt_tastytea_colours[path]="${5:-61}" # dark violet
prompt_tastytea_colours[highlight]="${6:-201}" # pink
prompt_tastytea_colours[inactive]="${7:-237}" # grey
prompt_tastytea_colours[prompt]=${prompt_tastytea_colours[user]}
if [[ -v SSH_CONNECTION ]]; then
prompt_tastytea_colours[prompt]=${prompt_tastytea_colours[remote]}
fi
if [[ ${EUID} -eq 0 ]]; then
prompt_tastytea_colours[prompt]=${prompt_tastytea_colours[root]}
fi
# Show username if it is not the default user
local showuser=""
if [[ "${USERNAME}" != "${DEFAULT_USER}" ]] && [[ -n "${USERNAME}" ]]; then
showuser="%B%F{${prompt_tastytea_colours[prompt]}}%n%f%b "
fi
prompt_tastytea_vcs
prompt_opts=(cr percent sp subst)
PS1="${showuser}"'${vcs_info_msg_0_}'"%B%F{${prompt_tastytea_colours[prompt]}}%#%f%b "
RPS1="%F{${prompt_tastytea_colours[path]}}%(?..[%B%F{${prompt_tastytea_colours[highlight]}}%?%b%F{${prompt_tastytea_colours[path]}}] )"'$(prompt_tastytea_shrunkpwd)'"%f"
PS2='%F{${prompt_tastytea_colours[prompt]}}%_>%f '
PS3='%F{${prompt_tastytea_colours[prompt]}}?#%f '
PS4='%F{${prompt_tastytea_colours[prompt]}}+%N:%i>%f '
prompt_cleanup 'prompt_tastytea_cleanup'
}
function prompt_tastytea_cleanup() {
if [[ -v ASYNC_VERSION ]]; then
async_stop_worker prompt_tastytea_vcs_info
fi
}
prompt_tastytea_setup "$@"
# Local Variables:
# mode: shell-script
# End: