2012-10-29 3 views
22

Ho una richiesta zsh I po 'come: valuta il tempo corrente in precmd e display che sul lato destro del messaggio:zsh: richiesta di aggiornamento del tempo corrente quando un comando viene avviato

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

Tuttavia , questo non è esattamente quello che voglio: come potete vedere qui sotto, questa volta è in realtà il tempo il comando precedente è uscito, non il tempo è stato avviato il comando:

[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] 

c'è un gancio in zsh a eseguire un comando solo prima dello la shell avvia un nuovo comando in modo da poter aggiornare il timestamp del prompt, quindi? (Ho visto Constantly updated clock in zsh prompt?, ma io non ne ho bisogno costantemente aggiornamento, appena aggiornato quando ho colpito entrare.)

(Il ^_^ è basato sul codice di ritorno del comando precedente. Essa mostra ;_; in rosso quando c'è un diverso da zero stato di uscita.)

+0

Condividere il codice per il prompt felice/triste? – slashdottir

+1

@slashdottir Sicuro. L'ho modificato in Unicode, ma il concetto si applica ancora. 'smiley locale ="% (?,% B% F {243} ☆% f% b,% B% F {1} ☃% f% b) "', quindi interpolato nella variabile PS1 con '$ {smiley } '. – cbowns

risposta

14

ho avuto una lotta per fare questo:

visualizza la data sul lato destro quando è stato eseguito il comando. Non sovrascrive il comando mostrato. Attenzione: potrebbe sovrascrivere il RPROMPT corrente.

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 

} 

Fonti:

+0

Questo è fantastico! – cbowns

+0

Questa è una soluzione davvero fantastica, ma si strozza quando cerco di aggiungere colori al mix. Sembra che il punto in cui aggiungere il color setter sia nella riga 'echo', ma se il colore è impostato dopo i caratteri di escape, ottengo in anticipo caratteri'% {%} 'extra. E in qualche modo, non importa dove cerco di reimpostare la combinazione di colori, ottengo anche quei caratteri sul finale finale. – Kevin

+0

Raccomando un paio di miglioramenti: 1) Aggiungi la stringa data davanti alla stringa del tempo ... '% Y-% m-% d% H:% M:% S', e 2) Usa un avanzamento riga davanti di 'RDATE' ... cioè' RDATE = "\ n \ 033 [$ {right_start} C $ {DATE}" ' –

7

zsh eseguirà la funzione preexec appena prima di eseguire una linea. Sarebbe semplice per avere quel uscita l'ora corrente, una versione semplice sarebbe solo:

preexec() { date } 

Modifica di un prompt esistente sarebbe molto più impegnativo.

+0

Sì, sembra difficile, ma 'preexec()' è un buon inizio. Grazie! – cbowns

+0

'zle reset-prompt' ridisegna il prompt zsh per te. –

4

È possibile utilizzare ANSI escape sequences di scrivere oltre la linea precedente, in questo modo:

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

Questo è infatti possibile senza ricorrere a strani hack. Ho questo nel mio .zshrc

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

TMOUT=1 

TRAPALRM() { 
    zle reset-prompt 
} 

La funzione TRAPALRM viene chiamata ogni secondi TMOUT (in questo caso 1), e qui si esegue un aggiornamento rapido, e lo fa fino a quando un comando avvia l'esecuzione (e non interferisce con ciò che scrivi sul prompt prima di premere invio). So che non ne hai bisogno continuamente aggiornato ma continua a svolgere il lavoro senza bisogno di una linea per se stesso!

Fonte: http://www.zsh.org/mla/users/2007/msg00944.html (E 'dal 2007!)

+0

Suggerirei di potenziarlo con un hack anche da lì: http://stackoverflow.com/a/30456173/1091116 – d33tah

+0

Inoltre, notare che questo potrebbe rendere più fastidioso il copia-incolla. – d33tah

+0

Questo è bello e semplice, ma l'impostazione di TMOUT su 1 provoca il caos nelle sessioni SSH. Se non eseguo un comando entro 1 secondo dall'accesso, vengo espulso. –

2

è possibile rimappare la chiave Return per ripristinare il prompt prima di accettare la linea:

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

Ah, una soluzione interessante. Grazie! – cbowns

5

costruzione off @ Vitaut-bajaryn fresco stile ZSH di answer:

Penso Superamento della funzione accetta-line è probabilmente la soluzione zsh più idiomatica:

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

Questo non funziona quando faccio qualcosa di simile a '' C-r somestring RET'', cioè eseguo una linea direttamente dalla ricerca inversa senza spostare il cursore o modificarlo. –

Problemi correlati