view .bash_prompt @ 264:bb69763716a7

Buncha changes for floyd thanks to RHEL8
author Steve Huston <huston@princeton.edu>
date Thu, 18 Apr 2024 13:37:00 -0400
parents c15ff56617a9
children
line wrap: on
line source

#!/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 {
  # See if this is a repo we care about - the one rooted in $HOME is for my
  # dotfiles, 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

  #bookmarks=$(hg summary | grep "^bookmarks" | sed -e "s/^bookmarks: //" -e "s/ /,/")
  #if [ -n "${bookmarks}" ]; then
  #  bookmarks="/${bookmarks}"
  #fi

  # Maybe a better way using 'hg sum' for everything... that outputs:
  # branch: [branch name]
  # commit: [(clean) or number added/deleted/modified]
  # update: [(current) or changesets to update]
  # .... if I can get the root from that, that's everything needed.  If not it
  # still shrinks the number of calls to two from four.

  # 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=''

  [[ $TERM =~ (xterm|rxvt) ]] && echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/\~}\007"

  # Set the bash prompt variable.
  # This part isn't going to work with the way it's going currently because of
  # how they're evaluated.  I need to think about how to do it the way it was,
  # on the other hand that means if I'm in a repo when I 'su' then it'll
  # always have the repo information printed there which isn't right either.
  # Maybe I need to source my .bashrc when I 'su'...
  case $EUID in
    0)
      U="\u@${LIGHT_RED}"
      ;;
    *)
      U="${LIGHT_GREEN}"
      ;;
  esac
  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"