2012-10-29 12 views
22

mam zsh szybka raczej jak: ocenia aktualny czas w precmd i wyświetlaczy, które po prawej stronie wiersza:zsh: szybka zmiana z obecnym czasie, gdy polecenie jest uruchamiany

[Floatie:~] ^_^ 
cbowns%      [9:28:31 on 2012-10-29] 

jednak nie jest to dokładnie czego chcę: jak widać poniżej, tym razem jest rzeczywiście czas poprzednie polecenie wyszedł, a nie razem polecenie zostało rozpoczętych

[Floatie:~] ^_^ 
cbowns% date       [9:28:26 on 2012-10-29] 
Mon Oct 29 09:28:31 PDT 2012 
[Floatie:~] ^_^ 
cbowns% date       [9:28:31 on 2012-10-29] 
Mon Oct 29 09:28:37 PDT 2012 
[Floatie:~] ^_^ 
cbowns%        [9:28:37 on 2012-10-29] 

Czy istnieje hak w zsh do uruchomić komendę po prostu przed powłoka uruchamia nowe polecenie, więc mogę zaktualizować datownik, a następnie? (Widziałem Constantly updated clock in zsh prompt?, ale nie muszę go stale aktualizowane, po prostu aktualizowana kiedy nacisnąć enter.)

(The ^_^ jest oparta na kodzie powrotnej poprzedniego polecenia użytkownika. To pokazuje ;_; na czerwono, gdy istnieje niezerowe status wyjścia.)

+0

Udostępnij kod dla szczęśliwej/smutny wierszu? – slashdottir

+1

@slashdottir Pewnie. Zmieniłem go na jakiś kod Unicode, ale koncepcja nadal obowiązuje. 'local smiley ="% (?,% B% F {243} ☆% f% b,% B% F {1} ☃% f% b) "', to jest interpolowane do var PS1 z '$ {smiley } '. – cbowns

Odpowiedz

14

miałem walkę, aby w ten sposób:

Wyświetla datę po prawej stronie, gdy polecenie zostało wykonane. Nie zastępuje wyświetlonego polecenia. Ostrzeżenie: może zastąpić bieżący RPROMPT.

strlen() { 
    FOO=$1 
    local zero='%([BSUbfksu]|([FB]|){*})' 
    LEN=${#${(S%%)FOO//$~zero/}} 
    echo $LEN 
} 

# show right prompt with date ONLY when command is executed 
preexec() { 
    DATE=$(date +"[%H:%M:%S]") 
    local len_right=$(strlen "$DATE") 
    len_right=$(($len_right+1)) 
    local right_start=$(($COLUMNS - $len_right)) 

    local len_cmd=$(strlen "[email protected]") 
    local len_prompt=$(strlen "$PROMPT") 
    local len_left=$(($len_cmd+$len_prompt)) 

    RDATE="\033[${right_start}C ${DATE}" 

    if [ $len_left -lt $right_start ]; then 
     # command does not overwrite right prompt 
     # ok to move up one line 
     echo -e "\033[1A${RDATE}" 
    else 
     echo -e "${RDATE}" 
    fi 

} 

Źródła:

+0

To jest fantastyczne! – cbowns

+0

To naprawdę niesamowite rozwiązanie, ale dławi go mocno, gdy próbuję dodać kolory do miksu. Wygląda na to, że miejsce do dodania setera kolorów znajduje się w linii 'echo', ale jeśli kolor zostanie ustawiony po znakach escape, otrzymam wcześniej dodatkowe znaki'% {%} '. I w jakiś sposób, bez względu na to, gdzie próbuję zresetować schemat kolorów, otrzymuję te znaki także na końcu końcowym. – Kevin

+0

Polecam kilka ulepszeń: 1) Dodaj ciąg daty przed ciągiem czasu ... '% Y-% m-% d% H:% M:% S' i 2) Użyj podajnika z przodu 'RDATE' ... tj.' RDATE = "\ n \ 033 [$ {right_start} C $ {DATE}" ' –

7

zsh uruchomi funkcję preexec tuż przed wykonaniem linii. Byłoby proste mieć, że wyświetlamy aktualny czas, prosta wersja byłaby tylko:

preexec() { date } 

Modyfikacja istniejącego wiersza byłoby znacznie trudniejsze.

+0

Tak, to wygląda na trudne, ale 'preexec()' to dobry początek. Dzięki! – cbowns

+0

'zle reset-prompt' ponownie rysuje monit zsh dla ciebie. –

4

Można użyć ANSI escape sequences nadpisać poprzednią linię, jak to:

preexec() { 
    DATE=`date +"%H:%M:%S on %Y-%m-%d"` 
    C=$(($COLUMNS-24)) 
    echo -e "\033[1A\033[${C}C ${DATE} " 
} 
24

To jest w rzeczywistości możliwe bez uciekania się do dziwnych sztuczek. Mam to w moim .zshrc

RPROMPT='[%D{%L:%M:%S %p}]' 

TMOUT=1 

TRAPALRM() { 
    zle reset-prompt 
} 

Funkcja TRAPALRM jest wywoływana co TMOUT sekund (w tym przypadku 1), tutaj wykonuje ona szybkiego odświeżenia, i robi tak aż zacznie wykonanie polecenia (i to nie ingeruje w nic, co wpisujesz w monicie przed naciśnięciem klawisza Enter). Wiem, że nie potrzebujesz go ciągle odświeżonego, ale wciąż wykonuje swoją pracę bez potrzeby posiadania linii dla siebie!

Źródło: http://www.zsh.org/mla/users/2007/msg00944.html (Jest to od 2007 roku!)

+0

Proponuję ulepszyć to także z hackem: http://stackoverflow.com/a/30456173/1091116 – d33tah

+0

Należy również pamiętać, że może to powodować irytujące wklejanie kopii. – d33tah

+0

To jest ładne i proste, ale ustawienie TMOUT na 1 sieje spustoszenie w sesjach SSH. Jeśli nie uruchomię polecenia w ciągu 1 sekundy od zalogowania, zostaniesz wyrzucony. –

2

Można zmiany klawisza Return zresetować wiersz przed zaakceptowaniem linię:

reset-prompt-and-accept-line() { 
    zle reset-prompt 
    zle accept-line 
} 

zle -N reset-prompt-and-accept-line 

bindkey '^m' reset-prompt-and-accept-line 
+0

Ach, interesujące rozwiązanie. Dziękuję Ci! – cbowns

5

budynku off @ Vitaut-bajaryn chłodny styl ZSH za answer:

myślę nadrzędnych funkcji accept-liniowy jest prawdopodobnie najbardziej idiomatyczne rozwiązanie zsh:

function _reset-prompt-and-accept-line { 
    zle reset-prompt 
    zle .accept-line  # Note the . meaning the built-in accept-line. 
} 
zle -N accept-line _reset-prompt-and-accept-line 
+0

To nie działa, gdy robię coś takiego, jak "C-r somestring RET", tzn. Uruchamiam linię bezpośrednio z wyszukiwania wstecznego bez przesuwania kursora lub modyfikowania go. –

Powiązane problemy