Zdefiniowałem monit bash (używając PROMPT_FUNCTION) w następujący sposób:
function get_hg_prompt_prefix() {
local APPLIED_COLOR=$1; shift
local UNAPPLIED_COLOR=$1; shift
local ALERT_COLOUR=$1; shift
local TEXTCOLOR=$1; shift
local mercurial_prompt_line="{{patches|join(:)|pre_applied(${APPLIED_COLOR})|post_applied(${TEXTCOLOR})|pre_unapplied(${UNAPPLIED_COLOR})|post_unapplied(${TEXTCOLOR})}\n\r}"
local mercurial_status_prompt="{ ${ALERT_COLOUR}{status}${TEXTCOLOR}}"
echo "$(hg prompt "${mercurial_prompt_line}" 2>/dev/null)$(hg prompt "${mercurial_status_prompt}" 2>/dev/null)"
}
function set_prompt() {
bright='\[[01m\]'
colors_reset='\[[00m\]'
HOSTCOLOR=${colors_reset}='\[[34m\]'
USERCOLOR=${colors_reset}='\[[01m\]'
TEXTCOLOR=${colors_reset}='\[[32m\]'
APPLIED_COLOR=${colors_reset}='\[[32m\]'
UNAPPLIED_COLOR=${colors_reset}='\[[37m\]'
ALERT_COLOUR=${colors_reset}='\[[31m\]'
hg_status="$(get_hg_prompt_prefix $APPLIED_COLOR $UNAPPLIED_COLOR $ALERT_COLOUR $TEXTCOLOR)"
ps1_prefix="${hg_status}$colors_reset($bright$(basename $VIRTUAL_ENV)$colors_reset) "
PROMPTEND='$'
PS1="${ps1_prefix}${USERCOLOR}\u${colors_reset}${TEXTCOLOR}@${colors_reset}${HOSTCOLOR}\h${colors_reset}${TEXTCOLOR} (\W) ${PROMPTEND}${colors_reset} "
}
PROMPT_COMMAND=set_prompt
Ogólnie rzecz biorąc, daje mi to wieloliniowy monit, który wyświetla niektóre informacje o stanie hg, a także mój obecny virtualenv, wyglądający (bez koloru) w następujący sposób:
buggy-wins.patch
! (saas) user@computer (~) $
Problem polega na tym, że jest to niepoprawne w obliczaniu długości pytania (myślę!) I powoduje dziwne problemy z zawijaniem terminali i umieszczaniem kursora. Na przykład w 80-znakowym terminalu oto monit, który widzę (** - otoczony znak to położenie kursora):
~) $ **a**nis) crose@chris-rose (~
W terminalach wystarczająco szerokich, aby wyświetlić monit, zawijanie linii następuje znacznie wcześniej niż powinno; oto jak najwięcej tekstu, jaki mogę zmieścić w pierwszym wierszu monitu w oknie terminala o szerokości 108 znaków (ponownie ** oznacza moją lokalizację kursora):
**(**advanis) crose@chris-rose (~) $ sdkfjlskdjflksdjff
Gdy linia się zawija, zastępuje monit. Drugi wiersz danych wejściowych biegnie jednak do krawędzi terminala, a następnie jest poprawnie zawijany.
Widać więc, że coś jest nie tak z szerokością monitu. Jak sprawić, aby bash określił długość łańcucha PS1 nie według kodów specjalnych ANSI, ale na podstawie rzeczywistej wyświetlanej długości pytania?