.dotfiles/bash/prompt.sh

180 lines
6.1 KiB
Bash
Executable File

# vim: ft=sh
# Explain prompt
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
if [ -d "$PWD/.git" ]; then
if [[ "$(which onefetch)" == "" ]]; then
echo "This is a git directory, but you don't have 'onefetch' in your PATH"
else
onefetch
fi
fi
unset DIRCHANGED
fi
# Choose a pseudo random separator character
# 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/')
[ ! "${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>/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=''
[ "${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 ""
}
# 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
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
[[ $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
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
[[ $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]/')
[[ $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
[[ $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
[[ $(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
[[ $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
[[ $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
[[ $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}\[\e[0;3${LASTB};1m\]"${SEP}"\[\e[0m\]\n"
export PS1