dotfiles/zsh/prompt.zsh
Thomas Preisner 88ed6d9d9b zsh: prompt: switch from ZLE_RPROMPT_INDENT=0 to %{ %} for bottom_right_suffix
Apparently ZLE_RPROMPT_INDENT is a bit buggy on several prompts (e.g.
iTerm2, virtual-terminal on linux, etc) since not only the most right
space is removed as intended, but also the cursor is moved on to the
right causing the last character of the prompt to be overwritten.
This causes completion to be rather weird (some characters are
drawn twice and some aren't at all).

Fix: Use %{ .. %} with ${bottom_right_suffix} to tell the terminal the
last symbols have a width of zero -> the most right space will be
overdrawn and thus not shown.
2017-08-02 14:25:59 +02:00

128 lines
3.9 KiB
Bash

# ===== setopts and misc
# only show RPROMPT on the current prompt
setopt transient_rprompt # only show the rprompt on the current prompt
# ===== set the prompt
zshrc_prompt_precmd() {
# regex to remove all zerospace elements. Used to calculate the width of
# the top prompt.
local zero='%([BSUBfksu]|([FB]|){*})'
# linedrawing characters
local top_left_corner="╭"
local top_right_corner="╮"
local bottom_left_corner="╰"
local bottom_right_corner="╯"
local dash="─"
# check $TERM and use non unicode symbols if necessary
if [[ $TERM == "linux" ]]; then
top_left_corner="+"
top_right_corner="+"
bottom_left_corner="+"
bottom_right_corner="+"
dash="-"
fi
# commonly used design elements
local bracket_open="%F{blue}${dash}(%f"
local bracket_close="%F{blue}%)${dash}%f"
local separator="%F{cyan}${dash}%f"
# current directory, truncated if necessary (WIDTH is replaced later)
local directory="%F{magenta}%WIDTH<..<%~%<<%f"
# current time (HH:MM)
local time="%F{yellow}%D{%H:%M}%f"
# username, green for normal users, red for root
local user="%(!.%F{red}.%F{green})%n%f"
# hostname, underlined if running on a remote system through SSH
local host="%F{green}%m%f"
if [[ -n $SSH_CONNECTION ]]; then
host="%U${host}%u"
fi
# exitcode in parentheses if not zero
local exitcode="%(?..[%F{red}%?%f])"
# prompt symbol, $ in cyan for normal users, # in red for root
local symbol="%(!.%F{red}#%f.%F{cyan}>%f)"
# battery percentage, if acpi is available
local battery_pct=
if [[ -d /sys/class/power_supply/BAT*(#qN) ]] && type acpi &> /dev/null; then
battery_pct="$(acpi -b | cut -d, -f2 | sed -e 's/[^0-9]//g')"
# colorize battery percentage or display status
if [[ $(acpi -a | cut -d':' -f2) == " on-line" ]]; then
battery_pct="charging"
elif [[ $battery_pct -le 20 ]]; then
battery_pct="%F{red}${battery_pct}%%%f"
elif [[ $battery_pct -le 65 ]]; then
battery_pct="%F{yellow}${battery_pct}%%%f"
else
battery_pct="%F{green}${battery_pct}%%%f"
fi
fi
# prefix characters in first and second line
local top_prefix="%F{cyan}${top_left_corner}%f"
local bottom_prefix="%F{cyan}${bottom_left_corner}%f"
# suffix characters in first and second line
local top_suffix="%F{cyan}${top_right_corner}%f"
# use %{ .. %} for bottom_right_corner to remove useless space after RPROMPT
local bottom_suffix="%F{cyan}%{${bottom_right_corner}%}%f"
# combine them to create the prompt
local top_left=""
local top_right="${bracket_open}${time}${bracket_close}"
local bottom_left="${bracket_open}${user}%F{green}@%f${host}${bracket_close}${exitcode}${separator}${symbol}"
local bottom_right=
# if $battery_pct is empty, just add a vertical line
if [[ -n $battery_pct ]]; then
bottom_right="${separator}${bracket_open}${battery_pct}${bracket_close}"
else
bottom_right="%F{blue}${dash}%f"
fi
# calculate width of prompt components
local width_top_prefix=${#${(S%%%)top_prefix//$~zero/}}
local width_top_suffix=${#${(S%%%)top_suffix//$~zero/}}
local width_top_left=${#${(S%%%)top_left//$~zero/}}
local width_top_right=${#${(S%%%)top_right//$~zero/}}
# calculate the maximum width of ${top_left}:
# (-4 for brackets, -1 as spacing between top_left and top_right)
local top_left_width_max=$((
COLUMNS - $width_top_prefix
- $width_top_left - 4
- 1
- $width_top_right
- $width_top_suffix
))
# truncated directory if necessary
top_left="${bracket_open}${directory/WIDTH/${top_left_width_max}}${bracket_close}${top_left}"
width_top_left=${#${(S%%)top_left//$~zero/}}
# calculate the width of the top prompt to fill the middle with separators
local width=$((
COLUMNS - width_top_prefix
- width_top_left
- width_top_right
- width_top_suffix
))
local top_separator="%F{cyan}${(pl:${width}::$dash:)}%f"
PROMPT="${top_prefix}${top_left}${top_separator}${top_right}${top_suffix}
${bottom_prefix}${bottom_left} "
RPROMPT="${bottom_right}${bottom_suffix}"
}
precmd_functions+=(zshrc_prompt_precmd)