Escape non-printing characters in a function for a Bash prompt
The readline library accepts \001
and \002
(ASCII SOH and STX) as non-printable text delimiters. These also work in any application that uses readline.
From lib/readline/display.c:243
in bash source code:
243 /* Current implementation:
244 \001 (^A) start non-visible characters
245 \002 (^B) end non-visible characters
246 all characters except \001 and \002 (following a \001) are copied to
247 the returned string; all characters except those between \001 and
248 \002 are assumed to be `visible'. */
The bash-specific \[
and \]
are in fact translated to \001
and \002
at y.tab.c:7640
.
Note: If you use bash's printf
or echo -e
, and if your text has \001
or \002
immediately before a number, you'll hit a bash bug that causes it to eat one digit too many when processing octal escapes – that is, \00142
will be interpreted as octal 014 (followed by ASCII "2"), instead of the correct octal 01 (followed by ASCII "42"). For this reason, use hexadecimal versions \x01
and \x02
instead.
Here's a nice complete answer. I had to do a lot more digging to figure out where the \001 etc. had to go. Hope this helps.
# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)
PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'
alias branchname="git branch 2>/dev/null | grep '*' | sed 's/* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/'"
GIT_STATUS='$(branchname)'
PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "
The way I have it set up here, the git branch parentheses only appear if you're in a git branch, otherwise it's blank.