Files
dao_hades/dotfiles/dao.sh/local/bin/prompt.sh
2025-11-12 01:11:54 +00:00

280 lines
6.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ---
# @file_name: prompt.sh
# @description: a bash prompt
# @date: 2025-11-12
# @version: 1.0.1
# @usage: . prompt.sh
#
# @author: Jamie Albert
# @author_contact: <mailto:jamie.albert@flatmail.me
# @license: GNU Affero General Public License v3.0 (Included in LICENSE)
# Copyright (C) 2025, Jamie Albert
# ---
# ---
# Script Exports
# ---
declare -x PASSWORD_STORE_DIR=~/dao/storage/pass
# declare -x BW_SESSION; BW_SESSION=$(pass show bw/session)
# ---
# Script globals
# ---
declare -g _cached_uh=""
declare -g _uh_cache_key=""
declare -g _cached_pyenv_version=""
declare -g _pyenv_cache_key=""
declare -g _cached_readonly=""
declare -g _readonly_cache_key=""
# ---
# Shell options configuration
# ---
shopt -s histappend
shopt -s cmdhist
shopt -s histreedit
shopt -s histverify
shopt -s interactive_comments
shopt -s checkwinsize
shopt -s globstar
shopt -s nocaseglob
shopt -s dirspell
shopt -s cdspell
shopt -u autocd
if [[ $- =~ "i" ]]; then
bind "set completion-ignore-case on"
bind "set show-all-if-ambiguous on"
bind "set mark-symlinked-directories on"
fi
# ---
# * Symbols
# ---
_prompt_symbol=""
_git_symbol="git:"
_pyenv_symbol="pyenv:"
_readonly_symbol="ro:"
_screen_symbol="scr:"
# ---
# * Colours
# ---
_prompt_success_colour="142"
_prompt_fail_colour="203"
_prompt_user_colour="109"
_prompt_sudo_colour="208"
_prompt_at_colour="249"
_prompt_hostname_colour="132"
_prompt_info_colour="172"
_prompt_input_colour="254"
_prompt_dir_colour="249"
_git_module_colour="66"
_pyenv_module_colour="66"
_readonly_module_colour="196"
_screen_module_colour="33"
# ---
# * Miscellaneous
# ---
_prompt_hostname="ssh"
_prompt_separator=" "
_prompt_wrapper="[]"
# ---
# // * Nerd Symbols
# // OBSOLETE 2025-11-07
# ---
# _git_symbol="󰘦"
# _pyenv_symbol="󰌠"
# _readonly_symbol="󰍁"
# _screen_symbol="󰐅"
# _prompt_symbol="󰥭"
# ---
# * Aliases
# ---
alias count='find . -type f | wc -l'
alias cdd='cd /home/jamie/dao'
alias dnf='sudo dnf'
alias hist='history|grep'
alias ll="ls -laFh"
alias la='ls -A'
alias li='la | grep -i'
alias lh='ll -d .*'
alias mkdir='mkdir -p'
alias nano='nano -W'
alias qq='exit'
alias sc='sudo systemctl'
alias xclipc='xclip -sel c'
# ---
# * Environment settings
# ---
declare -g HISTTIMEFORMAT='%F %T '
declare -g PROMPT_DIRTRIM="2"
[[ -z "$LC_CTYPE" && -z "$LC_ALL" ]] && declare -g LC_CTYPE="${LANG%%:*}"
[[ -z "$HISTFILE" ]] && declare -g HISTFILE="$HOME/.bash_history"
declare -x HISTCONTROL=ignorespace
declare -x HISTFILESIZE=10000
declare -x HISTSIZE=${HISTFILESIZE}
# ---
# * colour function
# ---
_prompt_colour() {
[[ ${1} != "-" ]] && echo -ne "\[\033[38;5;${1}m\]" || echo -ne "\[\033[0m\]"
}
# ---
# * Generate prompt segments
# ---
_prompt_generate() {
declare _separator="" _text="${1%%|*}" _colour="${1##*|}"
[[ ${_prompt_seg} -gt 1 ]] && _separator="${_prompt_separator}"
_prompt_information+="${_separator}$(_prompt_colour "${_colour}")${_text}\[\e[0m\]"
((_prompt_seg++))
}
# ---
# * Screen
# ---
_screen_pre() {
[[ ${TERM} == "screen"* ]] && _prompt_generate "${_screen_symbol}|${_screen_module_colour}"
}
# ---
# * Git
# ---
_git_post() {
[[ -z "$_git_dir" ]] && _git_dir="$(git rev-parse --git-dir 2>/dev/null)"
[[ -n "$_git_dir" ]] || return
local _unsafe_ref
_unsafe_ref=$(git symbolic-ref -q HEAD 2>/dev/null) || return
local _clean_ref="${_unsafe_ref##refs/heads/}"
_clean_ref="${_clean_ref//[^a-zA-Z0-9\/]/-}"
local _status=""
[[ -n "$(git status --porcelain 2>/dev/null)" ]] && _status="*"
[[ -n "$(git ls-files --others --exclude-standard 2>/dev/null)" ]] && _status="${_status}+"
[[ -n ${_clean_ref} ]] && _prompt_generate "${_git_symbol} ${_clean_ref}${_status}|${_git_module_colour}"
}
# ---
# * Pyenv
# ---
_pyenv_post() {
[[ -n ${VIRTUAL_ENV} ]] || return
[[ "$VIRTUAL_ENV" != "$_pyenv_cache_key" ]] && {
_cached_pyenv_version="${PYTHON_VERSION}"
[[ -z ${_cached_pyenv_version} ]] && _cached_pyenv_version="$(python3 --version 2>/dev/null)"
_cached_pyenv_version="${_cached_pyenv_version#Python }"
_pyenv_cache_key="$VIRTUAL_ENV"
}
[[ -n ${_cached_pyenv_version} ]] && _prompt_generate "${_prompt_wrapper:0:1}${_pyenv_symbol} ${_cached_pyenv_version}${_prompt_wrapper:1:1}|${_pyenv_module_colour}"
}
# ---
# * Readonly
# ---
_readonly_post() {
[[ "$PWD" != "$_readonly_cache_key" ]] && {
_cached_readonly=""
[[ ! -w "$(pwd)" ]] && _cached_readonly="readonly"
_readonly_cache_key="$PWD"
}
[[ -n "$_cached_readonly" ]] && _prompt_generate "${_prompt_wrapper:0:1}${_readonly_symbol}${_prompt_wrapper:1:1}|${_readonly_module_colour}"
}
# ---
# * Build the main prompt
# ---
_prompt_build() {
declare _last_status="$?" _gen_uh _cache_key="${PWD}"
declare -gi _prompt_seg=1
[[ "$_cache_key" != "$_last_cache_key" ]] && {
unset _git_dir _cached_pyenv_version
_last_cache_key="$_cache_key"
}
# ---
# ! Insert *pre* functions here
# ---
# START
_screen_pre
# END
# ---
# * User and hostname
# ---
declare _user_colour="${_prompt_user_colour}"
sudo -nv 2>/dev/null && _user_colour="${_prompt_sudo_colour}"
_gen_uh="${_cached_uh}"
_uh_cache_key="${_prompt_hostname}:${SSH_CLIENT:-}:$(sudo -n -v 2>/dev/null && echo 'sudo' || echo 'nosudo')"
[[ "$_uh_cache_key" != "$_last_uh_key" ]] && {
_gen_uh="$(_prompt_colour "${_user_colour}")${USER}"
if [[ ${_prompt_hostname} == "all" ]] || [[ ${_prompt_hostname} == "ssh" && -n ${SSH_CLIENT} ]]; then
_gen_uh+="$(_prompt_colour "${_prompt_at_colour}")@$(_prompt_colour "${_prompt_hostname_colour}")${HOSTNAME}"
fi
_gen_uh+="\[\033[0m\]"
_cached_uh="$_gen_uh"
_last_uh_key="$_uh_cache_key"
}
_prompt_generate "${_gen_uh}|${_prompt_info_colour}"
# ---
# * Current directory
# ---
declare _current_dir="${PWD}"
_current_dir="${_current_dir/#$HOME/\~}"
_prompt_generate "$(_prompt_colour "${_prompt_info_colour}")${_prompt_wrapper:0:1}$(_prompt_colour "${_prompt_dir_colour}")${_current_dir}$(_prompt_colour "${_prompt_info_colour}")${_prompt_wrapper:1:1}\[\033[0m\]|${_prompt_info_colour}"
# ---
# * Error status
# ---
[[ ${_last_status} -ne 0 ]] && _prompt_generate "${_prompt_wrapper:0:1}${_last_status}${_prompt_wrapper:1:1}|${_prompt_fail_colour}"
# ---
# ! Insert *post* functions here
# ---
# START
_git_post
_pyenv_post
_readonly_post
# END
# ---
# *Final prompt symbol
# ---
_prompt_status_colour=${_prompt_success_colour}
[[ ${_last_status} -ne 0 ]] && _prompt_status_colour=${_prompt_fail_colour}
_prompt_information+="$(_prompt_colour "${_prompt_status_colour}")\n${_prompt_symbol}\[\e[0m\]"
PS1="${_prompt_information} "
unset _prompt_information _prompt_seg
}
# ---
# * Initialize prompt
# ---
_prompt_init() {
case "$PROMPT_COMMAND" in
*"_prompt_build"*) ;;
"") PROMPT_COMMAND="_prompt_build" ;;
*) PROMPT_COMMAND="_prompt_build;${PROMPT_COMMAND}" ;;
esac
}
# ---
# * Initialize when sourced
# ---
[[ ${BASH_SOURCE[0]} != "${0}" ]] && _prompt_init