mirror of
https://github.com/itme-brain/bash.git
synced 2026-03-23 17:59:44 -04:00
optimize: eliminate git spawns, use utf codes for icons
This commit is contained in:
parent
0088c9646a
commit
b286fe447b
1 changed files with 142 additions and 118 deletions
248
prompt
248
prompt
|
|
@ -1,139 +1,163 @@
|
||||||
# Detect graphical environment for icons
|
# Detect graphical environment once at source time
|
||||||
_has_graphics() {
|
if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then
|
||||||
[ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]
|
_gfx=1
|
||||||
}
|
_py_sym=$'\ue73c'
|
||||||
|
_js_sym=$'\ue781'
|
||||||
|
_nix_sym=$'\ue843'
|
||||||
|
_proj_sym=$'\ueb45 '
|
||||||
|
_branch_sym=$'\uf418'
|
||||||
|
else
|
||||||
|
_gfx=""
|
||||||
|
_py_sym="py"
|
||||||
|
_js_sym="js"
|
||||||
|
_nix_sym="nix"
|
||||||
|
_proj_sym="../"
|
||||||
|
_branch_sym=""
|
||||||
|
fi
|
||||||
|
|
||||||
check_ssh() {
|
# Pre-compute colored icons
|
||||||
|
_python_icon="\[\033[01;33m\]$_py_sym\[\033[00m\]"
|
||||||
|
_node_icon="\[\033[01;93m\]$_js_sym\[\033[00m\]"
|
||||||
|
_nix_icon="\[\033[01;34m\]$_nix_sym\[\033[00m\]"
|
||||||
|
|
||||||
|
# SSH check once at source time
|
||||||
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
|
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
|
||||||
ssh_PS1="\n\[\033[01;37m\]\u@\h:\[\033[00m\]\n"
|
_ssh_PS1="\n\[\033[01;37m\]\u@\h:\[\033[00m\]\n"
|
||||||
|
else
|
||||||
|
_ssh_PS1=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Static prompt parts
|
||||||
|
_green_arrow="\[\033[01;32m\]>> "
|
||||||
|
_white_text="\[\033[00m\]"
|
||||||
|
|
||||||
|
# Cache: dir -> "git_root|superproject|" or "-" for non-git
|
||||||
|
declare -A _dir_cache
|
||||||
|
|
||||||
|
# Find git root by walking up (no git spawn)
|
||||||
|
_find_git_root() {
|
||||||
|
local dir="$PWD"
|
||||||
|
while [ -n "$dir" ]; do
|
||||||
|
if [ -e "$dir/.git" ]; then
|
||||||
|
_git_root="$dir"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
dir="${dir%/*}"
|
||||||
|
done
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# Git-related functions (only if git available)
|
# Find superproject by walking up from git root
|
||||||
if command -v git &>/dev/null; then
|
_find_superproject() {
|
||||||
|
local dir="${_git_root%/*}"
|
||||||
check_venv() {
|
_superproject=""
|
||||||
add_icon() {
|
while [ -n "$dir" ]; do
|
||||||
local icon=$1
|
if [ -e "$dir/.git" ]; then
|
||||||
if [[ ! $venv_icons =~ $icon ]]; then
|
_superproject="$dir"
|
||||||
venv_icons+="$icon "
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_icon() {
|
|
||||||
local icon=$1
|
|
||||||
venv_icons=${venv_icons//$icon/}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _has_graphics; then
|
|
||||||
py=""
|
|
||||||
js=""
|
|
||||||
nix=""
|
|
||||||
else
|
|
||||||
py="py"
|
|
||||||
js="js"
|
|
||||||
nix="nix"
|
|
||||||
fi
|
|
||||||
|
|
||||||
python_icon="\[\033[01;33m\]$py\[\033[00m\]"
|
|
||||||
node_icon="\[\033[01;93m\]$js\[\033[00m\]"
|
|
||||||
nix_icon="\[\033[01;34m\]$nix\[\033[00m\]"
|
|
||||||
|
|
||||||
if [ -n "$IN_NIX_SHELL" ]; then
|
|
||||||
add_icon "$nix_icon"
|
|
||||||
else
|
|
||||||
remove_icon "$nix_icon"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$VIRTUAL_ENV" ]; then
|
|
||||||
add_icon "$python_icon"
|
|
||||||
else
|
|
||||||
remove_icon "$python_icon"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -d "${git_root}/node_modules" ]; then
|
|
||||||
add_icon "$node_icon"
|
|
||||||
else
|
|
||||||
remove_icon "$node_icon"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
set_git_dir() {
|
|
||||||
if _has_graphics; then
|
|
||||||
project_icon=" "
|
|
||||||
else
|
|
||||||
project_icon="../"
|
|
||||||
fi
|
|
||||||
|
|
||||||
local superproject_root=$(git rev-parse --show-superproject-working-tree 2>/dev/null)
|
|
||||||
if [[ -n "$superproject_root" ]]; then
|
|
||||||
local submodule_name=$(basename "$git_root")
|
|
||||||
working_dir="\[\033[01;34m\]$project_icon${superproject_root##*/}/$submodule_name$git_curr_dir\[\033[00m\]"
|
|
||||||
elif [ "$git_curr_dir" == "." ]; then
|
|
||||||
working_dir="\[\033[01;34m\]$project_icon$git_root_dir\[\033[00m\]"
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
working_dir="\[\033[01;34m\]$project_icon$git_root_dir$git_curr_dir\[\033[00m\]"
|
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
dir="${dir%/*}"
|
||||||
|
done
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
relative_path() {
|
# Read branch from .git/HEAD (no git spawn)
|
||||||
local absolute_target=$(readlink -f "$1")
|
_read_branch() {
|
||||||
local absolute_base=$(readlink -f "$2")
|
local git_dir="$_git_root/.git"
|
||||||
echo "${absolute_target#$absolute_base}"
|
local head_file
|
||||||
}
|
|
||||||
|
|
||||||
check_project() {
|
# Submodule: .git is a file with "gitdir: <path>"
|
||||||
git_root=$(git rev-parse --show-toplevel 2>/dev/null)
|
if [ -f "$git_dir" ]; then
|
||||||
|
read -r _ head_file < "$git_dir"
|
||||||
if [ -n "$git_root" ]; then
|
head_file="$head_file/HEAD"
|
||||||
git_branch=$(git branch --show-current 2>/dev/null)
|
|
||||||
|
|
||||||
if [ -z "$git_branch" ]; then
|
|
||||||
git_branch=$(git describe --tags --exact-match 2>/dev/null)
|
|
||||||
git_branch=${git_branch:-$(git rev-parse --short HEAD 2>/dev/null)}
|
|
||||||
fi
|
|
||||||
|
|
||||||
git_curr_dir=$(relative_path "." "$git_root")
|
|
||||||
git_root_dir=$(basename "$git_root")
|
|
||||||
|
|
||||||
if _has_graphics; then
|
|
||||||
git_branch_PS1="\[\033[01;31m\]$git_branch :\[\033[00m\]"
|
|
||||||
else
|
else
|
||||||
git_branch_PS1="\[\033[01;31m\]$git_branch:\[\033[00m\]"
|
head_file="$git_dir/HEAD"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
set_git_dir
|
[ -f "$head_file" ] || return 1
|
||||||
check_venv
|
|
||||||
|
|
||||||
return 0
|
local head
|
||||||
|
read -r head < "$head_file"
|
||||||
|
|
||||||
|
if [[ "$head" == "ref: refs/heads/"* ]]; then
|
||||||
|
_git_branch="${head#ref: refs/heads/}"
|
||||||
|
else
|
||||||
|
# Detached HEAD - short hash
|
||||||
|
_git_branch="${head:0:7}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
fi # end git check
|
# Build venv icons (must run every prompt - env can change)
|
||||||
|
_build_venv_icons() {
|
||||||
|
venv_icons=""
|
||||||
|
[ -n "$IN_NIX_SHELL" ] && venv_icons+="$_nix_icon "
|
||||||
|
[ -n "$VIRTUAL_ENV" ] && venv_icons+="$_python_icon "
|
||||||
|
[ -d "$_git_root/node_modules" ] && venv_icons+="$_node_icon "
|
||||||
|
}
|
||||||
|
|
||||||
set_prompt() {
|
# Main prompt logic
|
||||||
local green_arrow="\[\033[01;32m\]>> "
|
_set_prompt() {
|
||||||
local white_text="\[\033[00m\]"
|
local cached="${_dir_cache[$PWD]}"
|
||||||
local working_dir="\[\033[01;34m\]\w\[\033[00m\]"
|
|
||||||
|
|
||||||
local ssh_PS1
|
# Check cache
|
||||||
|
if [ -z "$cached" ]; then
|
||||||
|
if _find_git_root; then
|
||||||
|
_find_superproject
|
||||||
|
_dir_cache[$PWD]="$_git_root|$_superproject|"
|
||||||
|
else
|
||||||
|
_dir_cache[$PWD]="-"
|
||||||
|
cached="-"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
check_ssh
|
# Non-git directory
|
||||||
|
if [ "$cached" = "-" ] || [ "${_dir_cache[$PWD]}" = "-" ]; then
|
||||||
|
venv_icons=""
|
||||||
|
[ -n "$IN_NIX_SHELL" ] && venv_icons+="$_nix_icon "
|
||||||
|
[ -n "$VIRTUAL_ENV" ] && venv_icons+="$_python_icon "
|
||||||
|
PS1="$_ssh_PS1\n\[\033[01;34m\]\w\[\033[00m\]\n$venv_icons$_green_arrow$_white_text"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
if command -v git &>/dev/null; then
|
# Parse cache
|
||||||
local venv_icons
|
[ -z "$cached" ] && cached="${_dir_cache[$PWD]}"
|
||||||
|
IFS='|' read -r _git_root _superproject _ <<< "$cached"
|
||||||
|
|
||||||
|
# Get branch (can change without cd)
|
||||||
|
_read_branch
|
||||||
|
|
||||||
|
# Build paths using bash string ops (no readlink spawn)
|
||||||
|
local git_curr_dir="${PWD#$_git_root}"
|
||||||
|
local git_root_dir="${_git_root##*/}"
|
||||||
|
|
||||||
|
# Build working_dir
|
||||||
|
local working_dir
|
||||||
|
if [ -n "$_superproject" ]; then
|
||||||
|
local super_name="${_superproject##*/}"
|
||||||
|
working_dir="\[\033[01;34m\]$_proj_sym$super_name/$git_root_dir$git_curr_dir\[\033[00m\]"
|
||||||
|
elif [ -z "$git_curr_dir" ]; then
|
||||||
|
working_dir="\[\033[01;34m\]$_proj_sym$git_root_dir\[\033[00m\]"
|
||||||
|
else
|
||||||
|
working_dir="\[\033[01;34m\]$_proj_sym$git_root_dir$git_curr_dir\[\033[00m\]"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build branch PS1
|
||||||
local git_branch_PS1
|
local git_branch_PS1
|
||||||
|
if [ -n "$_gfx" ]; then
|
||||||
check_project
|
git_branch_PS1="\[\033[01;31m\]$_git_branch $_branch_sym:\[\033[00m\]"
|
||||||
|
|
||||||
PS1="$ssh_PS1\n$working_dir\n$venv_icons$green_arrow$git_branch_PS1$white_text"
|
|
||||||
else
|
else
|
||||||
PS1="$ssh_PS1\n$working_dir\n$green_arrow$white_text"
|
git_branch_PS1="\[\033[01;31m\]$_git_branch:\[\033[00m\]"
|
||||||
fi
|
fi
|
||||||
return 0
|
|
||||||
|
# Build venv icons
|
||||||
|
_build_venv_icons
|
||||||
|
|
||||||
|
PS1="$_ssh_PS1\n$working_dir\n$venv_icons$_green_arrow$git_branch_PS1$_white_text"
|
||||||
}
|
}
|
||||||
|
|
||||||
PROMPT_COMMAND="set_prompt"
|
# Invalidate cache (call after git clone, init, etc)
|
||||||
|
_prompt_cache_invalidate() {
|
||||||
|
unset "_dir_cache[$PWD]"
|
||||||
|
}
|
||||||
|
|
||||||
|
PROMPT_COMMAND="_set_prompt"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue