dotfiles

🎜 Clone'em, tweak'em, stick'em in your $HOME 🎝
git clone https://git.kevinlegouguec.net/dotfiles
Log | Files | Refs | README

.bash_prompt (4236B)


      1 # Emacs?  -*- shell-script -*- please.
      2 
      3 # Environment variables:
      4 #
      5 # PS1_SHOWHOSTNAME
      6 #       'auto' (default):       Only show hostname over SSH
      7 #       'yes':                  Always show hostname
      8 #       anything else:          Never show hostname
      9 
     10 
     11 __show-hostname ()
     12 {
     13     case ${PS1_SHOWHOSTNAME} in
     14         (''|auto)
     15             test "${SSH_CONNECTION}";;
     16         (yes)
     17             true;;
     18         (*)
     19             false;;
     20     esac
     21 }
     22 
     23 __have-gitprompt ()
     24 {
     25     test -f /usr/lib/git-core/git-sh-prompt
     26 }
     27 
     28 __set-title ()
     29 {
     30     local title=${USER}
     31 
     32     __show-hostname && title+=@${HOSTNAME}
     33 
     34     # Empirically, no need to escape slashes in $HOME: Bash seems to
     35     # parse ${VAR/#PAT/REP} by (1) splitting VAR, PAT & REP (2) *then*
     36     # expanding PAT?
     37     title+=:${PWD/#${HOME}/\~}
     38 
     39     # Cf. console_codes(4):
     40     #
     41     #   ESC ] 2 ; txt ST        Set window title to txt.
     42     #
     43     # ST is a "string terminator", either "ESC \" or "BEL".
     44 
     45     printf $'\E]2;%s\a' "${title}"
     46 }
     47 
     48 # Bash relies on \[ \] to distinguish non-printing characters in prompts.
     49 __start-nonprinting ()
     50 {
     51     test ${BUILDING_PS} && printf '\['
     52 }
     53 
     54 __end-nonprinting ()
     55 {
     56     test ${BUILDING_PS} && printf '\]'
     57 }
     58 
     59 __fontify ()
     60 {
     61     local -r text=$1
     62     shift
     63 
     64     local -Ar codes=(
     65         [bold]=1
     66         [dim]=2
     67         [reverse]=7
     68         [red]=31
     69         [green]=32
     70         [blue]=34
     71     )
     72 
     73     local -a params=()
     74     local c
     75     for c
     76     do
     77         params+=(${codes[${c}]})
     78     done
     79 
     80     local params_seq
     81     IFS=';' eval 'params_seq="${params[*]}"'
     82 
     83     __start-nonprinting
     84     printf $'\E[%sm' "${params_seq}"
     85     __end-nonprinting
     86 
     87     printf %s "${text}"
     88 
     89     __start-nonprinting
     90     printf $'\E[0m'
     91     __end-nonprinting
     92 }
     93 
     94 __current-column ()
     95 {
     96     # Cf. console_codes(4) § ECMA-48 Status Report Commands.
     97 
     98     local position
     99     read -sdR -p$'\E[6n' position
    100 
    101     local -r pattern='\[[0-9]+;([0-9]+)'
    102 
    103     [[ ${position} =~ ${pattern} ]] || {
    104         echo 0
    105         return
    106     }
    107     echo ${BASH_REMATCH[1]}
    108 }
    109 
    110 __signal-no-newline ()
    111 {
    112     local -ir col=$(__current-column)
    113     ((col > 1)) || return
    114 
    115     __fontify ∅ bold red
    116     echo
    117 }
    118 
    119 __write-epilogue ()
    120 {
    121     local -ir rc=$1
    122     local -r rc_hex=$(printf %02x ${rc})
    123 
    124     local -r stamp=$(printf '%(%T)T')
    125 
    126     __fontify '[ ' dim
    127     if ((rc))
    128     then
    129         __fontify '$?:' dim red
    130         __fontify ${rc_hex} bold red
    131     else
    132         __fontify "\$?:${rc_hex}" dim
    133     fi
    134 
    135     __fontify " | ${stamp} ]" dim
    136     echo
    137 }
    138 
    139 __smart-term/set-ps1 ()
    140 {
    141     PS1=$(
    142         BUILDING_PS=t
    143         __fontify '\u' green
    144 
    145         __show-hostname && {
    146             __fontify @ dim
    147             __fontify '\H' bold green
    148         }
    149 
    150         printf ' '
    151 
    152         __fontify '\w' bold blue
    153 
    154         test "${PS1_SHOWGITSTATUS}" && {
    155             printf ' '
    156             __fontify "$(__git_ps1 '(%s)')" red
    157         }
    158 
    159         printf '\\n'
    160 
    161         __fontify '\$' dim
    162         printf ' '
    163     )
    164 }
    165 
    166 __smart-term/refresh ()
    167 {
    168     local -ir rc=$?
    169 
    170     __set-title
    171     __signal-no-newline
    172     __write-epilogue ${rc}
    173     __smart-term/set-ps1
    174 }
    175 
    176 __smart-term/init ()
    177 {
    178     # Prompts.
    179 
    180     __have-gitprompt && {
    181         . /usr/lib/git-core/git-sh-prompt
    182         GIT_PS1_SHOWDIRTYSTATE=t
    183         GIT_PS1_SHOWUPSTREAM=auto
    184 
    185         PS1_SHOWGITSTATUS=t
    186     }
    187 
    188     PROMPT_COMMAND=__smart-term/refresh
    189 
    190     PS2=$(
    191         BUILDING_PS=t
    192         __fontify '… ' dim
    193     )
    194 
    195     # Bindings.
    196 
    197     bind -f ~/.bash_inputrc
    198 
    199     # Unset the TTY's "stop" char, so that readline receives C-s.
    200     tty -s && stty stop ''
    201 }
    202 
    203 __dumb-term/refresh ()
    204 {
    205     local -ir rc=$?
    206     __write-epilogue ${rc}
    207 }
    208 
    209 __dumb-term/init ()
    210 {
    211     PROMPT_COMMAND=__dumb-term/refresh
    212     PS1='\W\$ '
    213 
    214     # I configure 'M-x shell' to use TERM=dumb-emacs-ansi; empirically
    215     # this makes Bash emit this bracketed paste sequence…
    216     #
    217     #     ^[[?2004l^M^J^[[?2004h
    218     #
    219     # … whenever I send a command in a nested shell ('bash' started
    220     # within the original shell, without --noediting).
    221     #
    222     # Until I figure something smarter:
    223     bind 'set enable-bracketed-paste off' 2>/dev/null
    224     # (Silence stderr: 'bind' complains when run with --noediting)
    225 }
    226 
    227 
    228 case "${TERM}"
    229 in
    230     dumb*)  __dumb-term/init ;;
    231     *)      __smart-term/init ;;
    232 esac