From a8920ad9b7cf901faa9a36a1b8f94ab201d0469a Mon Sep 17 00:00:00 2001 From: John Mertz Date: Fri, 16 Aug 2024 22:26:07 -0600 Subject: [PATCH] Freshen up that prompt! Emulate a Powerline setup. Includes: * Change custom foreground colours to background colours * Add 8 different separators, selected randomly based on terminal ID * Prettier and more sensible Git repo sigils * Cleaned and condensed code --- bash/prompt.sh | 246 ++++++++++++++++++++++++------------------------- 1 file changed, 119 insertions(+), 127 deletions(-) diff --git a/bash/prompt.sh b/bash/prompt.sh index 8e34a17f3..46288428b 100755 --- a/bash/prompt.sh +++ b/bash/prompt.sh @@ -1,14 +1,45 @@ # vim: ft=sh # Explain prompt -ARG=$1 -if [[ $ARG == 'h' || $ARG == '-h' || $ARG == 'help' || $ARG == '--help' || $ARG == '?' ]]; then - ARG="-h" -elif [[ $ARG != '' ]]; then - echo "Invalid argument: $ARG" - exit 0 +if [[ $1 && $1 != 'h' && $1 != '-h' && $1 != 'help' && $1 != '--help' && $1 != '?' ]]; then + echo "Invalid argument: $1" + exit fi +# Declare the S name (as used by `setterm`) and B for POSIX background colour +# Reference them later like: ${COLOURS["BLACK","S"]} or ${COLOURS["CYAN","B"]} +declare -A COLOURS='( + [0,S]="default" + [0,B]="\[\e[0m\]" + [1,S]="red" + [1,B]="\[\e[1;30;41m\]" + [2,S]="green" + [2,B]="\[\e[1;30;42m\]" + [3,S]="yellow" + [3,B]="\[\e[1;30;43m\]" + [4,S]="blue" + [4,B]="\[\e[1;30;44m\]" + [5,S]="magenta" + [5,B]="\[\e[1;30;45m\]" + [6,S]="cyan" + [6,B]="\[\e[1;30;46m\]" + [7,S]="white" + [7,B]="\[\e[1;30;47m\]" +)' + +# Assign colour to each module +P="7" # prompt default, white +T="3" # time, yellow +E="7" # venv, white +C="0" # chroot, default +U="2" # user +R="1" # root user +H="1" # host (overwritten for distrobox and ssh) +B="4" # distrobox +S="5" # ssh +D="6" # dir +G="7" # git + # If directory was just changed to the root of a git repository, print onefetch if [ -n "$DIRCHANGED" ]; then source ${HOME}/.dotfiles/bash/plenv-path.sh @@ -22,166 +53,127 @@ if [ -n "$DIRCHANGED" ]; then unset DIRCHANGED fi -# Default colours -# 0 default, 1 red 2 green 3 yellow 4 blue 5 magenta 6 cyan 7 white (grey) -PC="0" # prompt default -TC="3" # time -EC="7" # venv -CC="1" # chroot -UC="2" # user -RC="1" # root user -HC="4" # host -SC="1" # ssh host -DC="6" # dir -GC="5" # git +# Choose a pseudo random separator character -# Declare the SET name (as used by `setterm`) and PS string for colour options -# Reference them later like: ${COLOURS["5","SET"]} or ${COLOURS["2","PS"]} -declare -A COLOURS='( - [0,SET]="default" - [0,PS]="\[\033[0;0m\]" - [1,SET]="red" - [1,PS]="\[\033[0;31m\]" - [2,SET]="green" - [2,PS]="\[\033[0;32m\]" - [3,SET]="yellow" - [3,PS]="\[\033[0;33m\]" - [4,SET]="blue" - [4,PS]="\[\033[0;34m\]" - [5,SET]="magenta" - [5,PS]="\[\033[0;35m\]" - [6,SET]="cyan" - [6,PS]="\[\033[0;36m\]" - [7,SET]="white" - [7,PS]="\[\033[0;37m\]" -)' +# Local connections can just use ALACRITTY_WINDOW_ID +if [[ -n $ALACRITTY_WINDOW_ID ]]; then + # The last 4 bits are always 0, so drop them + SEP=$(($ALACRITTY_WINDOW_ID >> 4)) + (( SEP &= 7 )) +# SSH connections can use PID stored in SSH_CONNECTION +else + # Seems to always be even, so drop 1 bit + SEP=$(( $(echo $SSH_CONNECTION | cut -d ' ' -f 2) >> 1 )) +fi +# Just use the new last 4 bits to get a pseudo random number from 0-7 +(( SEP &= 7 )) + +# Select the separator character (some wide characters look better with a trailing space) +# See https://github.com/ryanoasis/powerline-extra-symbols +case "$SEP" in + 0) SEP="" ;; + 1) SEP=" " ;; + 2) SEP=" " ;; + 3) SEP=" " ;; + 4) SEP=" " ;; + 5) SEP="" ;; + 6) SEP=" " ;; + 7) SEP="" ;; +esac # Get current git branch function parse_git_branch() { - BRANCH=$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/') - if [ ! "${BRANCH}" == "" ] - then - STAT=$(parse_git_dirty) - echo "${COLOURS[\"$GC\",\"PS\"]}(${BRANCH}${STAT})${COLOURS[\"0\",\"PS\"]}" - else - echo "" - fi + BRANCH=$(git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/') + [ ! "${BRANCH}" == "" ] && echo "\[\e[1;31;4${G}m\]$(parse_git_dirty)${COLOURS["$G","B"]}${BRANCH}" || echo "" } # Get git status function parse_git_dirty { - status=$(git status 2>&1 | tee) - dirty=$(echo -n "${status}" 2> /dev/null | grep "modified:" &> /dev/null; echo "$?") - untracked=$(echo -n "${status}" 2> /dev/null | grep "Untracked files" &> /dev/null; echo "$?") - ahead=$(echo -n "${status}" 2> /dev/null | grep "Your branch is ahead of" &> /dev/null; echo "$?") - newfile=$(echo -n "${status}" 2> /dev/null | grep "new file:" &> /dev/null; echo "$?") - renamed=$(echo -n "${status}" 2> /dev/null | grep "renamed:" &> /dev/null; echo "$?") - deleted=$(echo -n "${status}" 2> /dev/null | grep "deleted:" &> /dev/null; echo "$?") + status=$(git status 2>/dev/null) + modified=$(echo -n "${status}" | grep "modified:" &> /dev/null; echo "$?") + untracked=$(echo -n "${status}" | grep "Untracked files" &> /dev/null; echo "$?") + ahead=$(echo -n "${status}" | grep "Your branch is ahead of" &> /dev/null; echo "$?") + newfile=$(echo -n "${status}" | grep "new file:" &> /dev/null; echo "$?") + renamed=$(echo -n "${status}" | grep "renamed:" &> /dev/null; echo "$?") + deleted=$(echo -n "${status}" | grep "deleted:" &> /dev/null; echo "$?") bits='' - if [ "${renamed}" == "0" ]; then - bits=">${bits}" - fi - if [ "${ahead}" == "0" ]; then - bits="*${bits}" - fi - if [ "${newfile}" == "0" ]; then - bits="+${bits}" - fi - if [ "${untracked}" == "0" ]; then - bits="?${bits}" - fi - if [ "${deleted}" == "0" ]; then - bits="x${bits}" - fi - if [ "${dirty}" == "0" ]; then - bits="!${bits}" - fi - if [ "${bits}" != "" ]; then - echo " ${bits}" - else - echo "" - fi + [ "${modified}" == "0" ] && bits="${bits} " + [ "${newfile}" == "0" ] && bits="${bits} " + [ "${deleted}" == "0" ] && bits="${bits} " + [ "${renamed}" == "0" ] && bits="${bits} " + [ "${untracked}" == "0" ] && bits="${bits}🯄 " + [ "${ahead}" == "0" ] && bits="${bits} " + [ "${bits}" != "" ] && echo "${bits}" || echo "" } -# Comment - allow for command history to be copied directly to bash script -PS1="${COLOURS["$PC","PS"]}# " +# Opening # so that PS1 gets interpretted as a comment if pasted into a terminal or script +PS1="${COLOURS["$P","B"]}#" + +# Track the last Background colour so that it can be used for the next separator +LASTB=$P + +# Sigil to indicate host, distrobox or ssh. Store HC so that host matches connection type if [ -f "/run/.containerenv" ]; then - # Sigil to indicate host, distrobox or ssh - PS1="${PS1}${COLOURS["0","PS"]}⧉ " + H=$B + [[ $1 ]] && setterm --foreground ${COLOURS[$H,"S"]} && echo "distrobox" && setterm --foreground default + PS1="${PS1}\[\e[0;3${LASTB};4${H}m\]"${SEP}"${COLOURS["$H","B"]}📦" elif [[ -z $SSH_CLIENT ]]; then - PS1="${PS1}${COLOURS["1","PS"]}⌂ " + [[ $1 ]] && setterm --foreground ${COLOURS[$H,"S"]} && echo "host session" && setterm --foreground default + PS1="${PS1}\[\e[0;3${LASTB};4${H}m\]"${SEP}"${COLOURS["$H","B"]}🏠" else - PS1="${PS1}${COLOURS["1","PS"]}🖧 " + H=$S + [[ $1 ]] && setterm --foreground ${COLOURS[$H,"S"]} && echo "ssh connection" && setterm --foreground default + PS1="${PS1}\[\e[0;3${LASTB};4${H}m\]"${SEP}"${COLOURS["$H","B"]}🖧 " fi +LASTB=$H # Time -PS1="${PS1}${COLOURS["$TC","PS"]}\\t " -if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$TC","SET"]}; echo "time"; setterm --foreground default -fi +[[ $1 ]] && setterm --foreground ${COLOURS["$T","S"]} && echo "time" && setterm --foreground default +PS1="${PS1}\[\e[0;3${LASTB};4${T}m\]"${SEP} +PS1="${PS1}${COLOURS["$T","B"]}\\t" +LASTB=$T # Python venv if [ "$VIRTUAL_ENV" ]; then VENV="${VIRTUAL_ENV##*/}" VENV=$(echo "$VENV" | sed -r 's/.*/[\0]/') - PS1="${PS1}${COLOURS["$EC","PS"]}${VENV} " - if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$EC","SET"]}; echo "venv"; setterm --foreground default - fi + [[ $1 ]] && setterm --foreground ${COLOURS["$E","S"]} && echo "venv" && setterm --foreground default + PS1=${PS1}\[\e[0;3${LASTB};4${E}m\]${SEP}${COLOURS["$E","B"]}${VENV} + LASTB=$E fi # Debian Chroot if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then - PS1="${PS1}${COLOURS["$CC","PS"]}<$(cat /etc/debian_chroot)>" - if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$CC","SET"]}; echo "debian chroot"; setterm --foreground default - fi + [[ $1 ]] && setterm --foreground ${COLOURS["$C","S"]} && echo "debian chroot" && setterm --foreground default + PS1="${PS1}\[\e[0;3${LASTB};4${C}m\]${SEP}"${COLOURS["$C","B"]}"<$(cat /etc/debian_chroot)>" + LASTB=$C fi # User -if [[ $(whoami) == 'root' ]]; then - UC=$RC -fi -PS1="${PS1}${COLOURS["$UC","PS"]}\\u" -if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$UC","SET"]}; echo "user"; setterm --foreground default -fi - -# @ -PS1="${PS1}${COLOURS["$PC","PS"]}@" +[[ $(whoami) == 'root' ]] && U=$R +[[ $1 ]] && setterm --foreground ${COLOURS["$U","S"]} && echo "user" && setterm --foreground default +PS1="${PS1}\[\e[0;3${LASTB};4${U}m\]"${SEP}"${COLOURS["$U","B"]}\\u\[\e[0;30;4${U}m\]@" +LASTB=$U # Host -if [[ $SSH_TTY != '' ]]; then - HC="${SC}" # Host colour - if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$HC","SET"]}; echo "host"; setterm --foreground default - fi -else - if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$HC","SET"]}; echo "host (ssh)"; setterm --foreground default - fi -fi -PS1="${PS1}${COLOURS["$HC","PS"]}\\h" - -# : -PS1="${PS1}${COLOURS["$PC","PS"]}:" +[[ $1 ]] && setterm --foreground ${COLOURS["$H","S"]} && echo "hostname" $([[ -z $SSH_TTY ]] || echo " (ssh)") && setterm --foreground default +PS1="${PS1}\[\e[0;3${LASTB};4${H}m\]"${SEP}"${COLOURS["$H","B"]}\\h\[\e[0;30;4${H}m\]:" +LASTB=$H # Dir -PS1="${PS1}${COLOURS["$DC","PS"]}\\w " -if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$DC","SET"]}; echo "directory"; setterm --foreground default -fi +[[ $1 ]] && setterm --foreground ${COLOURS["$D","S"]} && echo "directory" && setterm --foreground default +PS1="${PS1}\[\e[0;3${LASTB};4${D}m\]"${SEP}"${COLOURS["$D","B"]}\\w" +LASTB=$D # Git GIT=$(parse_git_branch) if [[ $GIT != '' ]]; then - PS1="${PS1}${COLOURS["$GC","PS"]}${GIT}" - if [[ $ARG == '-h' ]]; then - setterm --foreground ${COLOURS["$GC","SET"]}; echo "git branch status"; setterm --foreground default - fi + [[ $1 ]] && setterm --foreground ${COLOURS["$G","S"]} && echo "git branch status" && setterm --foreground default + PS1="$PS1\[\e[0;3${LASTB};4${G}m\]"${SEP}${GIT} + LASTB=$G fi # \n - start input on new line, again to support copy-paste into bash script -PS1="${PS1}${COLOURS["$PC","PS"]}\\n" +PS1="${PS1}\[\e[0;3${LASTB};1m\]"${SEP}"\[\e[0m\]\n" export PS1