jak sformatować ścieżkę w wierszu polecenia zsh?

23

Chciałbym mieć czytelną kolorową ścieżkę. Na przykład, zamiast po prostu użyć% ~ do powrotu ~/path/to/foo, chciałbym sformatować go, ~$RED/$NOCOLORpath$RED/$NOCOLORto$RED/$NOCOLORfooaby podświetlić separatory ścieżek.

Czy mogę zdefiniować zawartość PROMPT, aby wyrażenie ścieżki było ponownie oceniane na każdym ekranie? Coś takiego ${${(%):-%~}//\//_some_format_expression/}oczywiście nie działa.

A może powinienem to jeszcze zhakować i wymusić resetowanie wartości PROMPT za każdym razem, gdy zmieniamy katalog?

Wszelkie rozwiązania osiągające cel formatowania ścieżki byłyby mile widziane.

Dzięki :)

Nicolas Dumazet
źródło
jeśli nadal istniejesz, możesz zaznaczyć na to najlepszą odpowiedź :)
Dan Rosenstark

Odpowiedzi:

37

zsh

Spróbuj tego:

setopt PROMPT_SUBST
PROMPT='%{$(pwd|grep --color=always /)%${#PWD}G%} %(!.%F{red}.%F{cyan})%n%f@%F{yellow}%m%f%(!.%F{red}.)%#%f '

Oto podział pytania:

  • PROMPT_SUBST włącza podstawianie poleceń w wierszu poleceń (oraz interpretację parametrów i interpretację arytmetyczną)
  • %{...%} - sekwencja ucieczki
  • $(pwd|grep --color=always /)- wydrukuj bieżący katalog i podświetl /- kolor będzie zależeć od zmiennej środowiskowej $ GREP_COLORS (lub jej wartości domyślnej) - domyślnie pogrubiona czerwień
  • %${#PWD}G- użyj długości w znakach nazwy bieżącego katalogu jako wartości usterki. To sprawia, że ​​powłoka bierze to pod uwagę długość poprzedzającej sekwencji znaków (po „ %{”) zamiast rzeczywistej długości ciągu zawierającego sekwencje specjalne ANSI. Dzięki temu powłoka nie jest mylona co do pozycji kursora względem końca monitu.
    - - - - - - - to koniec części, która odpowiada na twoje pytanie - - - - - - -
  • %(!.%F{red}.%F{cyan}) - jeśli jest to uprzywilejowana powłoka (root), ustaw kolor pierwszego planu na czerwony, w przeciwnym razie cyjan
  • %n - wypisuje nazwę użytkownika
  • %f - przywróć domyślny kolor pierwszego planu
  • @ - dosłowny znak
  • %F{yellow} - uczynić kolor pierwszego planu żółtym
  • %m - wypisz nazwę hosta
  • %f - przywróć domyślny kolor pierwszego planu
  • %(!.%F{red}.) - jeśli jest to uprzywilejowana powłoka (root), ustaw kolor pierwszego planu na czerwony
  • %#- wypisuje a #dla uprzywilejowanej powłoki lub %dla nieuprzywilejowanej powłoki
  • %f - przywróć domyślny kolor pierwszego planu

Kładę nacisk na ścieżkę na pierwszym miejscu, ponieważ pytanie dotyczy ścieżki.

alternatywny tekst

Oto wersja dla zsh, która zmienia kolor ukośnika w zależności od tego, czy jesteś rootem (uprzywilejowanym) poprzez manipulowanie $GREP_COLORSzmienną:

setopt PROMPT_SUBST
PROMPT='%{$(pwd|([[ $EUID == 0 ]] && GREP_COLORS="mt=01;31" grep --color=always /|| GREP_COLORS="mt=01;34" grep --color=always /))%${#PWD}G%} %(!.%F{red}.%F{cyan})%n%f@%F{yellow}%m%f%(!.%F{red}.)%#%f '

Grzmotnąć

Możesz zrobić podobny monit w Bash. W tym przykładzie umieściłem nazwę użytkownika i hosta na pierwszym miejscu, a kolor ukośników również zmienia się, gdy UID ma wartość 0. Ostrzeżenie: to zastępuje $PS1zmienną zachęty Basha . Nie powinno to stanowić problemu, chyba że robisz coś specjalnego lub nie spodziewasz się, że zachowanie zmieni się, gdy ustawisz tę zmienną bezpośrednio, a to nastąpi. Ponadto wykorzystuje zmienną o nazwie „ usercolor”, która może kolidować z czymś innym, chociaż cała ta rzecz mogłaby zostać umieszczona w funkcji, a zmienna deklarowana jako lokalna.

PROMPT_COMMAND='usercolor="\[\033[0;36m\]";[[ $EUID == 0 ]] && usercolor="\[\033[1;31m\]";PS1="$(pwd)";PS1="$usercolor\u\[\033[0m\]@\[\033[0;33m\]\h\[\033[0m\]:${PS1//\//$usercolor/\[\033[0m\]}$usercolor\\$\[\033[0m\] "'

alternatywny tekst

Skorzystałem z faktu, że Bash nie ma funkcji „glitch” zsh, aby użyć podstawiania rozszerzenia parametru do warunkowego pokolorowania ukośników (zamiast używania grep).

Wstrzymano do odwołania.
źródło
nazywaj mnie głupim, ale jedyną złą częścią, jaką miałem, było użycie podwójnych cudzysłowów zamiast pojedynczych cudzysłowów w definicji PROMPT. Dzięki :)
Nicolas Dumazet,
@NicDumZ, zabawne, spędziłem wczoraj około 20 minut na tym problemie gdzie indziej :)
Dan Rosenstark
1
to jest masowo (naukowy i) fajny. Dzięki ...
Dan Rosenstark
Masz pomysł, jak to zrobić w Bash lub dlaczego nie działa w Bash? Dla mnie z Bash po prostu zacina się w pierwszym katalogu, w którym uruchamiam terminal, i nie aktualizuje się, kiedy się poruszam. Właśnie wziąłem $ (pwd | grep --color = always /) i włożyłem to do mojego PS1 i dostałem dziwne zachowanie. Edytuj: OH! Nie widziałem sekcji Bash lol.
Ibrahim,
Właściwie próbuję użyć twojej sztuczki PS1 dla Basha w mojej bardziej złożonej zachęcie i to nie działa, moje PWD znów się zacina. Ale Twój fragment działa bez zmian. Jaki jest cel PROMPT_COMMAND? Oto, co mam: PS1="$(pwd)"; PS1="${debian_chroot:+($debian_chroot)}\[$bldgrn\]\u@$(fgcolor $hostnamecolor)\h$(resetcolor)\[$txtrst\]:\[$bldblu\]${PS1//\//$txtred/$bldblu}\[\e[00m\]$bldred\$(parse_git_branch)\[$txtrst\] \[$undcyn\]\T \d\[$txtrst\] 95\$ "kolory zdefiniowane w github.com/ibrahima/dotfiles/blob/master/.bashrc.d/prompt.sh
Ibrahim
4

Po krótkim obejściu mogę podać rozwiązanie zastępujące chpwd:

doprompt() {
  local my_path=${(%):-%~}
  PROMPT="${yourstuff}${my_path//\//${PR_BOLD_RED}/${reset_color}}${otherstuff}"
}
doprompt

chpwd() {
  doprompt
  # unrelated: set window title
  [[ -t 1 ]] || return;
  print -Pn "\e]2;%n@%m: %~\a";
}
  • Czy istnieje sposób na ulepszenie tego kodu, aby pozbyć się tymczasowego my_path var? Nie mogę bezpośrednio zastąpić / inside% ~ ...
  • Każde rozwiązanie wykorzystujące składnię dynamiczną w celu uniknięcia wywoływania przy każdej zmianie katalogu dopromptjest prawdopodobnie czystsze.
Nicolas Dumazet
źródło
4

Czyste rozwiązanie Zsh:

PROMPT='%n@%m: %{$PR_BOLD_RED%}${${(%):-%~}//\//${PR_BOLD_RED}/%f}%f '
  • ${(%):-%~} jest bieżącą ścieżką.
  • ${xxxxx//\//${PR_BOLD_RED}/%f} zastępuje każdy / w xxxxx pogrubioną czerwoną czcionką
  • i oczywiście PROMPT_SUBST musi być włączony.

W testach używałem podwójnych cudzysłowów, co nie pozwala na podstawienie. Wszystko działa dobrze z pojedynczymi cudzysłowami.

Nicolas Dumazet
źródło
Musisz $PR_BOLD_REDzdefiniować gdzie indziej. Muszę użyć, w PROMPT='%n@%m: %{%B%F{red}%}${${(%):-%~}//\//%B%F{red\}/%b%f}%b%f 'tym bardzo dziwnego ucieczki zamykającego nawiasu klamrowego (tylko) po drugim „czerwonym”.
Wstrzymano do odwołania.
tak, używam nazw Aarona Toponce'a pthree.org/wp-content/uploads/2009/03/zsh_prompt, które uznałem za przydatne. Poza tym nie muszę niczego uciekać, działa zgodnie z przeznaczeniem.
Nicolas Dumazet
0

Oto moja próba (na podstawie NicDumZ):

setopt PROMPT_SUBST
# red, green, yellow, blue, magenta, cyan, white, black
# B (bold), K(background color), F(foreground color)

function doprompt {
# this is just the directory (%d could be %~ -- I prefer full path always)
PROMPT='%F{yellow}${${(%):-%d}//\//%F{magenta\}%B/%b%F{yellow\}}%f'
}

function chpwd() {
    doprompt
}

Różnica polega na tym, że używam kolorowej ścieżki, więc po powrocie koloru ukośnik muszę wrócić do pierwotnego koloru ścieżki. W moim przypadku ścieżka jest zwykle żółta, a ukośnik zmienia kolor na purpurowy, a następnie wraca do żółtego. Wolę też używać sekwencji% F% f, ponieważ wydają mi się one bardziej czytelne.

dwuwargowy
źródło