Używasz zmiennych do przechowywania kodów kolorów terminali dla PS1?

33

W moim przypadku .bashrcużywam kodów kolorów terminala ANSI do kolorowania różnych bitów. To wygląda tak:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

gdzie virtual_envi git_branchsą funkcjami bash, które wypisują rzeczy na standardowe wyjście.

Teraz, aby ułatwić czytanie i modyfikację, chciałbym przechowywać kody kolorów w zmiennych i odwoływać się do nich, zamiast osadzać je bezpośrednio w PS1. Mam więc kilka takich zmiennych:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Chciałbym móc napisać coś takiego:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Ale to nie działa - kody kolorów wyświetlają się w monicie, jakby uciekły. Kolory działają poprawnie, jeśli zamiast nich używam podwójnych cudzysłowów PS1, ale wówczas monit zmienia się tylko wtedy, gdy to robię source ~/.bashrc.

Próbowałem innych rzeczy Widziałem ludzi zrobić - używając printfprzy użyciu apostrofów dla kolorów, strzelaj \[i \]we PS1zamiast zmiennej barwy, ale nic nie wydaje się do pracy.

Jak mogę używać zmiennych dla kodów kolorów?

Ismail Badawi
źródło
Czy możesz dać nam swój .bashrc?
cuonglm
@cuonglm Wszystkie twoje .bashrc należą do nas? Pokażę się.
CivFan

Odpowiedzi:

20

Rozwiązaniem jest skłonienie powłoki do zastąpienia zmiennych kolorów podczas definiowania monitu, ale nie funkcji. Aby to zrobić, użyj podwójnych cudzysłowów, tak jak pierwotnie próbowałeś, ale unikaj poleceń, aby nie były oceniane, dopóki nie zostanie narysowany monit.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Zwróć uwagę na \przed $()każdym poleceniem.

Jeśli to powtórzymy, zobaczymy:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Jak widać zmienne kolorów zostały podstawione, ale nie polecenia.

Patrick
źródło
1
Nie wydaje się to działać, jeśli $ (git_branch) również próbuje drukować za pomocą $ {ŻÓŁTY} itp. Tylko w tej sekcji nadal będziesz mieć wszystkie [] znaki.
WB Reed
7

Problem polega na tym, że twoja zmienna GREENzawiera dosłowny ciąg znaków składający się z „odwrotnego nawiasu ukośnego zero trzy trzy trzy” i tak dalej. Nie zawiera na przykład znaku zmiany znaczenia ASCII wymaganego do zmiany koloru terminala.

Można umieścić znaki sterujące w GREEN(a YELLOW, a RESET) ręcznie, ale o wiele lepszym rozwiązaniem jest użycie tputw pierwszej kolejności, tak aby nie trzeba ciężko kodem cokolwiek i będzie obsługiwać dowolny typ terminala.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

Powodem, dla którego pojawia się na świecie po umieszczeniu „odwrotnego ukośnika zero trzy trzy” itd.… Bezpośrednio, PS1jest to, że interpretacja niektórych sekwencji odwrotnego ukośnika jest cechą monitowania basha (zobacz sekcję PROMPTING w instrukcji. Podstawienie to następuje przed rozwinięciem parametru, polecenie podstawianie, interpretacja arytmetyczna i usuwanie cytatów, więc nie jest stosowane do wyników wszystkich innych operacji.

Celada
źródło
5
Robiąc to w ten sposób, musisz owinąć zmienne kolorów \[\]wewnątrz $PS1. Na przykład: PS1='\u@\h:\w\[${YELLOW}\]'. Jeśli tego nie zrobisz, a skończy się na długim poleceniu, które zawinie do następnego wiersza, napotkasz różnego rodzaju problemy. Powłoka używa \[\]do określenia, które znaki nie są drukowalne, więc nie uwzględnia ich w obliczeniach długości pytania. Potrzebuje tego, aby mógł poprawnie narysować linię, gdy przekroczy szerokość terminala.
Patrick
Dzięki nie wiedziałem o tym tput. Na razie skorzystam z odpowiedzi Patricka, ale wrócę do niej, kiedy będę miał szansę.
Ismail Badawi
2

Zmień sposób wypełniania $ ZIELONY, $ ŻÓŁTY i $ RESET:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '
Cyrus
źródło
1
To w rzeczywistości robi dokładnie to samo, co odpowiedź Celady. Ale Celada jest bardziej przenośny na wypadek, gdyby terminal używał różnych kodów ucieczki do ustawiania kolorów. Będzie to miało również ten sam problem z poleceniem wielu linii.
Patrick
2
Na \[…\]potrzeby bitowe pozostać w wierszu poleceń nie można nadziać ją w zmiennej. Usunąłeś go całkowicie, co spowoduje problemy z wyświetlaniem (kursor nie znajduje się w pozycji, w której oczekuje bash).
Gilles „SO- przestań być zły”
Oprócz problemów @Patrick, echo -e nie jest przenośne.
helpermethod
1
Brak możliwości przenoszenia oferuje więcej funkcji - tput setafnie pozwala wybierać z „jasnego” zestawu kolorów, takich jak jasnobłękitny. Odpowiedź @ Cyrusa tak jest.
CivFan