bash-git-prompt
bash-git-prompt copied to clipboard
RFE: highlight directory component of git root
It would be great if when inside a git repository, instead of just printing the current directory, it also highlights the part of the path corresponding to the repository's root directory. For example,
14:46 $ cd tmp ✔ /tmp/tmp 14:46 $ git init myrepo Initialized empty Git repository in /tmp/myrepo/.git/ ✔ /tmp 14:47 $ cd myrepo/ ✔ /tmp/myrepo [master|✔] 14:47 $ mkdir subdir ✔ /tmp/myrepo [master|✔] 14:47 $ cd subdir/ ✔ /tmp/myrepo/subdir [master|✔] 14:47 $
(Notice the bolding). That way, we can quickly know (1) which repository we're in, and (2) how deep we are (useful when typing relative paths).
Should be possible to generate with a custom theme.
If you look at my custom theme from issue #161 you should be able to change the truncated pwd function with something that uses
#Get name of git root
current=$(basename $(git rev-parse --show-toplevel))
#Use sed to highlight first occurrence of git root:
echo $(PWD) |sed "s/${current}/$(tput bold)${current}$(tput sgr0)/g1"
A little test theme that does what you want. It might be slow - if there is a way to determine if we are inside a repo we should't do that check again here for instance, but it might be a way forward.
override_git_prompt_colors() {
GIT_PROMPT_THEME_NAME="Custom"
#Overrides the prompt_callback function used by bash-git-prompt
function prompt_callback {
local repo=$(git rev-parse --show-toplevel 2> /dev/null)
if [[ -n "$repo" ]]; then
#Get name of git root
local current=$(basename $repo)
#Use sed to highlight first occurrence of git root:
echo -n ${PWD} |sed "s/${current}/$(tput bold)${current}$(tput sgr0)$(tput setaf 3)/1"
else
echo -n ${PWD}
fi
}
Time12a="\$(date +%H:%M)"
GIT_PROMPT_START_USER="_LAST_COMMAND_INDICATOR_ ${Yellow}"
GIT_PROMPT_START_ROOT="${GIT_PROMPT_START_USER}"
GIT_PROMPT_END_USER="\n${White}${Time12a}${ResetColor} $ "
GIT_PROMPT_END_ROOT="\n${White}${Time12a}${ResetColor} # "
}
reload_git_prompt_colors "Custom"
@ogr3 Awesome, that works great, thanks!
But nice idea anyway, I'll integrate this into the default theme
Here is a tweaked prompt_callback
which will work also in the case where the repo name appears twice in the path (e.g. for a path like /code/myrepo/myrepo/subdir
would highlight the first myrepo
, even if the real git root was the second one), and also in the case where the current directory was arrived through a symbolic link:
function prompt_callback {
# Get the real path to the repo's root
local repo_realpath=$(git rev-parse --show-toplevel 2> /dev/null)
# Are we even in a repo?
if [[ -n "$repo_realpath" ]]; then
# OK, get the real path to the current dir
local cur_realpath=$(realpath .)
# Get the name of the repo
local repo_name=$(basename $repo_realpath)
# Calculate the paths before and after the repo name
local diff=$((${#cur_realpath} - ${#repo_realpath}))
local head=${PWD:0:$((${#PWD} - $diff - ${#repo_name}))}
if [ $diff -gt 0 ]; then
local tail=${PWD:$((-$diff))}
fi
# Print the full path
echo -n "$head$(tput setaf 2)$repo_name$(tput setaf 3)$tail$(tput setaf 0)"
else
echo -n "\w$(tput setaf 0)"
fi
}
This is meant to work with my custom theme only (hence the hardcoded tput
s), but hopefully you get the idea.
@jlebon this doesn't work when there is a symlink between git root and current path. For example root is ~/repo
and we are at ~/repo/.build/release
which is a symlink to ~/repo/.build/x86_64-apple-macosx/release
prompt_dir() {
# From gitstatus plugin
local repo_realpath="$VCS_STATUS_WORKDIR"
if [[ -n "$repo_realpath" ]]; then
local candidate="$PWD"
while [[ ! -d "$candidate/.git" && "$candidate" != "/" ]]; do
candidate="$(dirname "$candidate")"
done
if [[ "$(realpath "$candidate")" != "$repo_realpath" ]]; then
# PWD contains symlink and repository root is not inside PWD
prompt_segment blue $CURRENT_FG '%~'
return
fi
local repo_name="$(basename "$candidate")"
local diff=$((${#PWD} - ${#candidate}))
local head=${PWD:0:$((${#PWD} - $diff - ${#repo_name}))}
if [ $diff -gt 0 ]; then
local tail=${PWD:$((-$diff))}
fi
local formatted_path="$head%B$repo_name%b$tail"
# If $HOME is git dir, we want to keep the username bold instead of replacing with tilde,
# so matching exactly $HOME is never needed here
prompt_segment blue $CURRENT_FG "${formatted_path/#$HOME\//~/}"
else
prompt_segment blue $CURRENT_FG '%~'
fi
}
If you have any improvement ideas, please let me know