comparison .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
comparison
equal deleted inserted replaced
264:bb69763716a7 265:df0b24d4fabd
1 #!/bin/bash
2 #
3 # DESCRIPTION:
4 #
5 # Set the bash prompt according to:
6 # * the branch/status of the current Git or Mercurial repository
7 # * the return value of the previous command
8 #
9 # USAGE:
10 #
11 # 1. Save this file as ~/.bash_prompt
12 # 2. Add the following line to the end of your ~/.bashrc or ~/.bash_profile:
13 # . ~/.bash_prompt
14 #
15 # LINEAGE:
16 #
17 # https://gist.github.com/2959821
18 # https://gist.github.com/31967
19 # https://gist.github.com/2394150
20 # Overhauled by Steve Huston 2024/03/28 to reduce delays and adapt to my personal style
21
22 # The various escape codes that we can use to color our prompt.
23 RED="\[\e[0;31m\]"
24 YELLOW="\[\e[1;33m\]"
25 GREEN="\[\e[0;32m\]"
26 BLUE="\[\e[1;34m\]"
27 LIGHT_BLUE="\[\e[1;36m\]"
28 LIGHT_RED="\[\e[1;31m\]"
29 LIGHT_GREEN="\[\e[1;32m\]"
30 WHITE="\[\e[1;37m\]"
31 LIGHT_GRAY="\[\e[0;37m\]"
32 COLOR_NONE="\[\e[0m\]"
33
34 # Determine if this is a Git repo and get the branch/state information.
35 function set_git_branch {
36 # Capture the output of the "git status" command.
37 git_status="$(git status 2> /dev/null)"
38
39 # Short circuit if this isn't a git repo
40 if [ -z "$git_status" ]; then
41 return 1
42 fi
43
44 # Set color based on clean/staged/dirty.
45 # Some versions of git say tree, some say directory
46 green_pattern="working (tree|directory) clean"
47 if [[ ${git_status} =~ ${green_pattern} ]]; then
48 state="${GREEN}"
49 elif [[ ${git_status} =~ "Changes to be committed" ]]; then
50 state="${YELLOW}"
51 else
52 state="${LIGHT_RED}"
53 fi
54
55 # Set arrow icon based on status against remote.
56 remote_pattern="Your branch is ([^${IFS}]*)"
57 if [[ ${git_status} =~ ${remote_pattern} ]]; then
58 if [[ ${BASH_REMATCH[1]} == "ahead" ]]; then
59 remote="↑"
60 elif [[ ${BASH_REMATCH[1]} == "up" ]]; then
61 remote=""
62 else
63 remote="↓"
64 fi
65 else
66 remote=""
67 fi
68 diverge_pattern="Your branch and (.*) have diverged"
69 if [[ ${git_status} =~ ${diverge_pattern} ]]; then
70 remote="↕"
71 fi
72
73 # Get the name of the branch.
74 branch_pattern="^(#\s+)?On branch ([^${IFS}]*)"
75 if [[ ${git_status} =~ ${branch_pattern} ]]; then
76 branch=${BASH_REMATCH[2]}
77 else
78 branch="?"
79 fi
80
81 # Set the final branch string.
82 BRANCH=" ${state}(git:${branch})${remote}${COLOR_NONE}"
83 return 0
84 }
85
86 # Determine if this is a Mercurial repo, and get the branch/state accordingly.
87 function set_mercurial_branch {
88 # I keep my dotfiles in a mercurial repo rooted in $HOME, so if that's
89 # what's detected just abort as other processes warn me about dirty repos
90 # and otherwise I would "always" be considered to be in a hg repo
91 root=$(hg root 2>/dev/null)
92 [[ -z "$root" || "$root" == "$HOME" ]] && return 1
93
94 # Get all the details
95 hg_summary=$(hg summary)
96
97 # Get the name of the branch.
98 branch_pattern="branch: ([^${IFS}]*)"
99 [[ ${hg_summary} =~ ${branch_pattern} ]] && branch=${BASH_REMATCH[1]} || branch="?"
100
101 # Set color based on clean/staged/dirty.
102 # This doesn't make a distinction between untracked files and uncommitted
103 # changes, anything that isn't right is dirty and red. If the working
104 # directory is not at the tip that's a caution.
105 state_pattern="commit: \(clean\)"
106 update_pattern="update: \(current\)"
107 if [[ ! ${hg_summary} =~ ${state_pattern} ]]; then
108 state="${LIGHT_RED}"
109 elif [[ ! ${hg_summary} =~ ${update_pattern} ]]; then
110 state="${YELLOW}"
111 else
112 state="${GREEN}"
113 fi
114
115 # I still have to incorporate this part, or decide not to
116 #bookmarks=$(hg summary | grep "^bookmarks" | sed -e "s/^bookmarks: //" -e "s/ /,/")
117 #if [ -n "${bookmarks}" ]; then
118 # bookmarks="/${bookmarks}"
119 #fi
120
121 # Set the final branch string.
122 BRANCH=" ${state}(hg:${branch}$bookmarks)${COLOR_NONE}"
123 }
124
125 # Return the prompt symbol to use, colorized based on the return value of the
126 # previous command.
127 function set_prompt_symbol () {
128 if test $1 -eq 0 ; then
129 PROMPT_SYMBOL="\\$"
130 else
131 PROMPT_SYMBOL="${LIGHT_RED}\\\$${COLOR_NONE}"
132 fi
133 }
134
135 # Set the full bash prompt.
136 function set_bash_prompt () {
137 # Set the PROMPT_SYMBOL variable. We do this first so we don't lose the
138 # return value of the last command.
139 set_prompt_symbol $?
140
141 # Set the BRANCH variable.
142 set_git_branch || set_mercurial_branch || BRANCH=''
143
144 # Only change the terminal title bar if it's really an xterm - don't want it
145 # set on screen window names, that's annoying.
146 [[ $TERM =~ (xterm|rxvt) ]] && echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/\~}\007"
147
148 # If we're root, we'd like to call attention to that.
149 case $EUID in
150 0)
151 U="${LIGHT_RED}\u@"
152 ;;
153 *)
154 U="\u@${LIGHT_GREEN}"
155 ;;
156 esac
157
158 # Set the bash prompt variable.
159 export PS1="${debian_chroot:+($debian_chroot)}${U}\h${COLOR_NONE}:${LIGHT_BLUE}\w${COLOR_NONE}${BRANCH}${PROMPT_SYMBOL} "
160 }
161
162 # Tell bash to execute this function just before displaying its prompt.
163 PROMPT_COMMAND="set_bash_prompt ; history -a"