changeset 256:d868be3816bf

New prompt settings to test out, works well on the Mac so far.
author Steve Huston <huston@srhuston.net>
date Thu, 28 Mar 2024 19:26:06 -0400
parents 282804a3a32b
children 98c08bf73f5a
files .bash_prompt .bashrc
diffstat 2 files changed, 173 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.bash_prompt	Thu Mar 28 19:26:06 2024 -0400
@@ -0,0 +1,168 @@
+#!/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.
+  if [[ ${git_status} =~ "working tree clean" ]]; 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 (.*) of"
+  if [[ ${git_status} =~ ${remote_pattern} ]]; then
+    if [[ ${BASH_REMATCH[1]} == "ahead" ]]; 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="history -a ; set_bash_prompt"
--- a/.bashrc	Wed Mar 27 18:39:22 2024 -0400
+++ b/.bashrc	Thu Mar 28 19:26:06 2024 -0400
@@ -25,14 +25,9 @@
 #
 # Environment variables
 #
-#[[ "$PS1" ]] && export PS1='${debian_chroot:+($debian_chroot)}\e[01;32m\h\e[00m:\e[01;34m\w\e[00m\$ '
-[[ "$PS1" ]] && {
-  if [ -z "$DARWIN" ] ; then
-    export PS1='${debian_chroot:+($debian_chroot)}\[\e[01;`case $EUID in 0) echo -n 31; ;; *) echo -n 32; ;; esac;`m\]\h\[\e[00m\]:\[\e[01;34m\]\w\[\e[00m\]\$ '
-  else
-    export PS1='${debian_chroot:+($debian_chroot)}\[\e[01;`case $EUID in 0) echo "31\c"; ;; *) echo -n 32; ;; esac;`m\]\h\[\e[00m\]:\[\e[01;34m\]\w\[\e[00m\]\$ '
-  fi
-}
+
+[[ "$PS1" ]] && . $HOME/.bash_prompt
+
 export PAGER=less
 export EDITOR=vim
 export RUBYLIB=$HOME/Installs/rubygems/lib
@@ -44,25 +39,8 @@
   export SCREENRC=$HOME/.screen/$HOST
 fi
 
-# If this is an xterm set the title to user@host:dir
-case $TERM in
-  xterm*|rxvt*)
-    PROMPT_COMMAND='history -a ; echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"'
-    ;;
-  screen.xterm-256color)
-    # Specifically, to hell with this one
-    export TERM=screen-256color
-    # Copied from below because the Mac's bash doesn't grok ;& as a
-    # passthrough
-    PROMPT_COMMAND="history -a"
-    ;;
-  screen*)
-    # But if it's a screen window, leave it alone please
-    PROMPT_COMMAND="history -a"
-    ;;
-  *)
-    ;;
-esac
+# Specifically, to hell with this one
+[[ $TERM =~ screen.xterm-256color ]] && export TERM=screen-256color
 
 # Set some friendly options for history
 # Append to ~/.bash_history, don't overwrite it