Gilles zidentyfikował twój główny problem, ale chciałem spróbować wyjaśnić go inaczej.
Bash interpretuje specjalne znaki zachęty tylko przed rozwinięciem jakichkolwiek zmiennych w znaku zachęty. Oznacza to, że użycie \e
w zmiennej rozwiniętej z monitu nie działa, nawet jeśli działa bezpośrednio w PS1
.
Na przykład działa to zgodnie z oczekiwaniami i daje czerwony tekst:
PS1='\e[1;31m this is in red '
Ale tak nie jest, po prostu umieszcza literał \e
w znaku zachęty:
RED='\e[1;31m'
PS1="$RED not in red "
Jeśli chcesz przechowywać $'...'
znaki zmiany koloru w zmiennych, możesz użyć ANSI-C quoting ( ), aby wstawić dosłowny znak zmiany znaczenia w zmiennej.
Aby to zrobić, można zmienić definicję GREEN
, RED
i NONE
, więc ich wartość jest rzeczywista sekwencja ucieczki.
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
Jeśli to zrobisz, Twoje pierwsze PS1
z pojedynczymi cudzysłowami powinny działać:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
Będziesz miał jednak drugi problem.
Spróbuj uruchomić to, a następnie naciśnij Up Arrow, a następnie Home, a kursor nie wróci do początku linii.
Aby to naprawić, zmień, PS1
aby uwzględnić sekwencje specjalne koloru \[
i \]
wokół nich, np
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
Nie można get_exit_status
tutaj prawidłowo używać , ponieważ jego dane wyjściowe zawierają zarówno znaki drukujące (kod wyjścia), jak i znaki niedrukowalne (kody kolorów) i nie ma możliwości prawidłowego oznaczenia go w monicie. Umieszczenie \[...\]
oznaczałoby go jako całkowicie niedrukowalny, co jest nieprawidłowe. Będziesz musiał zmienić funkcję, aby drukowała tylko odpowiedni kod koloru, a następnie otoczyła go \[...\]
w wierszu polecenia.
\[
jest\1
i\[
jest\2
. Te, które odpowiadają jakiejś linii readlineRL_PROMPT_{START,END}_IGNORE
, która prosi ją o zignorowanie bajtów podczas liczenia długości pytania na ekranie. Zobacz lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html .\]
to\2
? Czy masz na myśli to, dlaczego jest to potrzebne${exitStatus}
? Chodzi mi o to, że${exitStatus}
nie zawiera znaki inne niż drukowanie, więc bash powinien być w stanie prawidłowo określić ile znaków porusza się monit bez\[
i\]
w\[${exitStatus}\]
.\e
i\033
(i\[
/\]
,\u
i\h
) od pytania, po prostu robi to przed rozwinięciem zmiennych. TakPS1='\e[1;31m red'
działa,red='\e[1;31m'; PS1='$red red'
nie.Po uruchomieniu
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
ThePS1
zmienna jest ustawiona${RED}\h $(get_path) ${exitStatus}${NONE}
, gdzie tylko\h
jest szybka sekwencja ucieczki. Po rozwinięciu (generowaniu${RED}darkstar $(get_path) ${exitStatus}${NONE}
) sekwencji podpowiedzi powłoka wykonuje zwykłe rozszerzenia, takie jak rozszerzenia zmienne. Wyświetlany jest monit, który wygląda\e[1;31mdarkstar PATH 0\e[m
. Nic po drodze nie rozszerza\e
sekwencji na rzeczywiste znaki ucieczki.Po uruchomieniu
PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
ThePS1
zmienna jest ustawiona\e[1;31m\h PATH 0\e[m
. ZmienneRED
,exitStatus
iNONE
są rozszerzone w czasie zadania. Następnie natychmiastowe wiersz zawiera trzy sekwencje sterująca (\e
,\h
i\e
ponownie). Na tym etapie nie ma zmiennych powłoki.Aby zobaczyć kolory, potrzebujesz zmiennych kolorów, które zawierają rzeczywiste znaki specjalne. Możesz to zrobić w ten sposób:
$'…'
rozszerza sekwencje odwrotne odwrotne i niektóre sekwencje odwrotnych liter, takie jak\n
, ale bez uwzględnienia\e
. Wprowadziłem trzy inne zmiany w pytaniu:\[…\]
pobliżu nie drukowanych sekwencji, takich jak polecenia zmieniające kolory. W przeciwnym razie ekran skończy się zniekształcony, ponieważ bash nie może określić szerokości monitu.\w
jest wbudowaną sekwencją zmiany znaczenia do wydrukowania bieżącego katalogu.$?
w monicie, jeśli nie maszPROMPT_COMMAND
w ogóle .źródło
PS1
jest źle, ale wskazówka, z której należy$'...'
skorzystaćRED
iGREEN
powinna sprawić, że będzie działać przy użyciu dogbanePS1
.Próbować:
źródło
Oto podejście, które wybrałem, pozwala uniknąć użycia
PROMPT_COMMAND
.Zatem moje
$PS1
jest następujące:źródło
$?
może mieć, jest liczba całkowita, naprawdę powinieneś jej użyćprintf '%b' "$GREEN"
. Unikaj także używania nazw funkcji z prefiksem__
lub,_
ponieważ są one używane przez bash-uzupełnianie.Proszę bardzo - This Works For Me (TM) w Ubuntu i innych Linuxach (Linuxen?).
Powodem wprowadzenia wykrywania kodu wyjścia
$PS1
jest to, że jeden host ma$PROMPT_COMMAND
ustawiony tylko do odczytu przed odczytaniem .bashrc.źródło
Ponieważ
PROMPT_COMMAND
łatwiej jest zdefiniować funkcję i użyć jej:źródło