comparison .bash_prompt @ 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
children 09e37b590785
comparison
equal deleted inserted replaced
253:282804a3a32b 256:d868be3816bf
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 if [[ ${git_status} =~ "working tree clean" ]]; then
46 state="${GREEN}"
47 elif [[ ${git_status} =~ "Changes to be committed" ]]; then
48 state="${YELLOW}"
49 else
50 state="${LIGHT_RED}"
51 fi
52
53 # Set arrow icon based on status against remote.
54 remote_pattern="Your branch is (.*) of"
55 if [[ ${git_status} =~ ${remote_pattern} ]]; then
56 if [[ ${BASH_REMATCH[1]} == "ahead" ]]; then
57 remote="↑"
58 else
59 remote="↓"
60 fi
61 else
62 remote=""
63 fi
64 diverge_pattern="Your branch and (.*) have diverged"
65 if [[ ${git_status} =~ ${diverge_pattern} ]]; then
66 remote="↕"
67 fi
68
69 # Get the name of the branch.
70 branch_pattern="^(#\s+)?On branch ([^${IFS}]*)"
71 if [[ ${git_status} =~ ${branch_pattern} ]]; then
72 branch=${BASH_REMATCH[2]}
73 else
74 branch="?"
75 fi
76
77 # Set the final branch string.
78 BRANCH=" ${state}(git:${branch})${remote}${COLOR_NONE}"
79 return 0
80 }
81
82 # Determine if this is a Mercurial repo, and get the branch/state accordingly.
83 function set_mercurial_branch {
84 # See if this is a repo we care about - the one rooted in $HOME is for my
85 # dotfiles, so if that's what's detected just abort as other processes warn
86 # me about dirty repos and otherwise I would "always" be considered to be in
87 # a hg repo
88 root=$(hg root 2>/dev/null)
89
90 [[ -z "$root" || "$root" == "$HOME" ]] && return 1
91
92 # Get all the details
93 hg_summary=$(hg summary)
94
95 # Get the name of the branch.
96 branch_pattern="branch: ([^${IFS}]*)"
97 [[ ${hg_summary} =~ ${branch_pattern} ]] && branch=${BASH_REMATCH[1]} || branch="?"
98
99 # Set color based on clean/staged/dirty.
100 # This doesn't make a distinction between untracked files and uncommitted
101 # changes, anything that isn't right is dirty and red. If the working
102 # directory is not at the tip that's a caution.
103 state_pattern="commit: \(clean\)"
104 update_pattern="update: \(current\)"
105 if [[ ! ${hg_summary} =~ ${state_pattern} ]]; then
106 state="${LIGHT_RED}"
107 elif [[ ! ${hg_summary} =~ ${update_pattern} ]]; then
108 state="${YELLOW}"
109 else
110 state="${GREEN}"
111 fi
112
113 #bookmarks=$(hg summary | grep "^bookmarks" | sed -e "s/^bookmarks: //" -e "s/ /,/")
114 #if [ -n "${bookmarks}" ]; then
115 # bookmarks="/${bookmarks}"
116 #fi
117
118 # Maybe a better way using 'hg sum' for everything... that outputs:
119 # branch: [branch name]
120 # commit: [(clean) or number added/deleted/modified]
121 # update: [(current) or changesets to update]
122 # .... if I can get the root from that, that's everything needed. If not it
123 # still shrinks the number of calls to two from four.
124
125 # Set the final branch string.
126 BRANCH=" ${state}(hg:${branch}$bookmarks)${COLOR_NONE}"
127 }
128
129 # Return the prompt symbol to use, colorized based on the return value of the
130 # previous command.
131 function set_prompt_symbol () {
132 if test $1 -eq 0 ; then
133 PROMPT_SYMBOL="\\$"
134 else
135 PROMPT_SYMBOL="${LIGHT_RED}\\$${COLOR_NONE}"
136 fi
137 }
138
139 # Set the full bash prompt.
140 function set_bash_prompt () {
141 # Set the PROMPT_SYMBOL variable. We do this first so we don't lose the
142 # return value of the last command.
143 set_prompt_symbol $?
144
145 # Set the BRANCH variable.
146 set_git_branch || set_mercurial_branch || BRANCH=''
147
148 [[ $TERM =~ (xterm|rxvt) ]] && echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD/$HOME/~}\007"
149
150 # Set the bash prompt variable.
151 # This part isn't going to work with the way it's going currently because of
152 # how they're evaluated. I need to think about how to do it the way it was,
153 # on the other hand that means if I'm in a repo when I 'su' then it'll
154 # always have the repo information printed there which isn't right either.
155 # Maybe I need to source my .bashrc when I 'su'...
156 case $EUID in
157 0)
158 U="\u@${LIGHT_RED}"
159 ;;
160 *)
161 U="${LIGHT_GREEN}"
162 ;;
163 esac
164 export PS1="${debian_chroot:+($debian_chroot)}${U}\h${COLOR_NONE}:${LIGHT_BLUE}\w${COLOR_NONE}${BRANCH}${PROMPT_SYMBOL} "
165 }
166
167 # Tell bash to execute this function just before displaying its prompt.
168 PROMPT_COMMAND="history -a ; set_bash_prompt"