Mercurial > index.cgi > dotfiles
diff .shared/bash_prompt @ 265:df0b24d4fabd
Think I'm ready to check this all in now; shared dotfiles that can be "sent"
through an SSH connection to be used and cleaned up when finished.
author | Steve Huston <huston@srhuston.net> |
---|---|
date | Wed, 24 Apr 2024 16:15:40 -0400 |
parents | .bash_prompt@c15ff56617a9 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.shared/bash_prompt Wed Apr 24 16:15:40 2024 -0400 @@ -0,0 +1,163 @@ +#!/bin/bash +# +# DESCRIPTION: +# +# Set the bash prompt according to: +# * the branch/status of the current Git or Mercurial repository +# * the return value of the previous command +# +# USAGE: +# +# 1. Save this file as ~/.bash_prompt +# 2. Add the following line to the end of your ~/.bashrc or ~/.bash_profile: +# . ~/.bash_prompt +# +# LINEAGE: +# +# https://gist.github.com/2959821 +# https://gist.github.com/31967 +# https://gist.github.com/2394150 +# Overhauled by Steve Huston 2024/03/28 to reduce delays and adapt to my personal style + +# The various escape codes that we can use to color our prompt. + RED="\[\e[0;31m\]" + YELLOW="\[\e[1;33m\]" + GREEN="\[\e[0;32m\]" + BLUE="\[\e[1;34m\]" + LIGHT_BLUE="\[\e[1;36m\]" + LIGHT_RED="\[\e[1;31m\]" +LIGHT_GREEN="\[\e[1;32m\]" + WHITE="\[\e[1;37m\]" + LIGHT_GRAY="\[\e[0;37m\]" + COLOR_NONE="\[\e[0m\]" + +# Determine if this is a Git repo and get the branch/state information. +function set_git_branch { + # Capture the output of the "git status" command. + git_status="$(git status 2> /dev/null)" + + # Short circuit if this isn't a git repo + if [ -z "$git_status" ]; then + return 1 + fi + + # Set color based on clean/staged/dirty. + # Some versions of git say tree, some say directory + green_pattern="working (tree|directory) clean" + if [[ ${git_status} =~ ${green_pattern} ]]; then + state="${GREEN}" + elif [[ ${git_status} =~ "Changes to be committed" ]]; then + state="${YELLOW}" + else + state="${LIGHT_RED}" + fi + + # Set arrow icon based on status against remote. + remote_pattern="Your branch is ([^${IFS}]*)" + if [[ ${git_status} =~ ${remote_pattern} ]]; then + if [[ ${BASH_REMATCH[1]} == "ahead" ]]; then + remote="↑" + elif [[ ${BASH_REMATCH[1]} == "up" ]]; then + remote="" + else + remote="↓" + fi + else + remote="" + fi + diverge_pattern="Your branch and (.*) have diverged" + if [[ ${git_status} =~ ${diverge_pattern} ]]; then + remote="↕" + fi + + # Get the name of the branch. + branch_pattern="^(#\s+)?On branch ([^${IFS}]*)" + if [[ ${git_status} =~ ${branch_pattern} ]]; then + branch=${BASH_REMATCH[2]} + else + branch="?" + fi + + # Set the final branch string. + BRANCH=" ${state}(git:${branch})${remote}${COLOR_NONE}" + return 0 +} + +# Determine if this is a Mercurial repo, and get the branch/state accordingly. +function set_mercurial_branch { + # I keep my dotfiles in a mercurial repo rooted in $HOME, so if that's + # what's detected just abort as other processes warn me about dirty repos + # and otherwise I would "always" be considered to be in a hg repo + root=$(hg root 2>/dev/null) + [[ -z "$root" || "$root" == "$HOME" ]] && return 1 + + # Get all the details + hg_summary=$(hg summary) + + # Get the name of the branch. + branch_pattern="branch: ([^${IFS}]*)" + [[ ${hg_summary} =~ ${branch_pattern} ]] && branch=${BASH_REMATCH[1]} || branch="?" + + # Set color based on clean/staged/dirty. + # This doesn't make a distinction between untracked files and uncommitted + # changes, anything that isn't right is dirty and red. If the working + # directory is not at the tip that's a caution. + state_pattern="commit: \(clean\)" + update_pattern="update: \(current\)" + if [[ ! ${hg_summary} =~ ${state_pattern} ]]; then + state="${LIGHT_RED}" + elif [[ ! ${hg_summary} =~ ${update_pattern} ]]; then + state="${YELLOW}" + else + state="${GREEN}" + fi + + # I still have to incorporate this part, or decide not to + #bookmarks=$(hg summary | grep "^bookmarks" | sed -e "s/^bookmarks: //" -e "s/ /,/") + #if [ -n "${bookmarks}" ]; then + # bookmarks="/${bookmarks}" + #fi + + # Set the final branch string. + BRANCH=" ${state}(hg:${branch}$bookmarks)${COLOR_NONE}" +} + +# Return the prompt symbol to use, colorized based on the return value of the +# previous command. +function set_prompt_symbol () { + if test $1 -eq 0 ; then + PROMPT_SYMBOL="\\$" + else + PROMPT_SYMBOL="${LIGHT_RED}\\\$${COLOR_NONE}" + fi +} + +# Set the full bash prompt. +function set_bash_prompt () { + # Set the PROMPT_SYMBOL variable. We do this first so we don't lose the + # return value of the last command. + set_prompt_symbol $? + + # Set the BRANCH variable. + set_git_branch || set_mercurial_branch || BRANCH='' + + # Only change the terminal title bar if it's really an xterm - don't want it + # set on screen window names, that's annoying. + [[ $TERM =~ (xterm|rxvt) ]] && echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/\~}\007" + + # If we're root, we'd like to call attention to that. + case $EUID in + 0) + U="${LIGHT_RED}\u@" + ;; + *) + U="\u@${LIGHT_GREEN}" + ;; + esac + + # Set the bash prompt variable. + export PS1="${debian_chroot:+($debian_chroot)}${U}\h${COLOR_NONE}:${LIGHT_BLUE}\w${COLOR_NONE}${BRANCH}${PROMPT_SYMBOL} " +} + +# Tell bash to execute this function just before displaying its prompt. +PROMPT_COMMAND="set_bash_prompt ; history -a"