Existe um gancho postexec / predisplay para o ZSH?

3

Eu sei que o zsh tem um gancho preexec que dispara antes que o comando seja executado, mas existe um que é acionado após o comando ter sido iniciado, mas antes que a saída seja exibida na tela? Eu pergunto porque quero exibir algo com base em se houve / será o resultado real.

Por exemplo: cd dir não produz nada, ls dir produz material

Nesse exemplo, quero exibir: Output:\n antes da exibição do diretório ls, mas não quando cd é executado, pois ele não possui uma exibição. Eu quero que pareça:

~ $: cd dir
~/dir $: ls .
Output:
total 464
drwxr-xr-x+  55 eddie  staff   1.8K May  2 11:07 .
drwxr-xr-x    6 root   admin   204B Apr 22 13:48 ..
~/dir $

Eu não quero apenas envolver cd e ls. Esses foram exemplos. Eu quero que seja para o comando every .

    
por Eddie Monge Jr 02.05.2013 / 20:15

1 resposta

3

Não pode haver nenhum predisplay como o shell não está envolvido quando comandos emitem algo para o terminal ou qualquer outro arquivo.

O gancho teria que estar nos comandos executados na primeira chamada de sistema de escrita feita por qualquer processo ou encadeamento iniciado pela linha de comando para um descritor de arquivo aberto para o dispositivo tty. Ou você teria que redirecionar o stdout e o stderr do comando com algum mecanismo IPC (provavelmente teria que ser um par pseudo-tty para minimizar o impacto no comportamento do comando) e inserir o Output: quando algo estiver recebido¹. De qualquer forma, isso seria bastante complicado e bastante intrusivo.

Agora, não é algo que eu faria, mas você poderia tentar algo como:

preexec() {
  printf '%-*s' $COLUMNS "Output:"
  read -sdR $'pos_before?\e[6n'
}

precmd() {
  read -sdR $'pos_after?\e[6n'
  [[ $pos_after != $pos_before ]] || printf '\r'
}
set +o promptsp

Ou seja, antes de executar uma saída de comando Output: e mover o cursor para a borda direita da tela (para que a próxima coisa escrita, se houver, esteja no início da próxima linha) e registre a posição atual do cursor em $pos_before .

E antes do próximo prompt, consulte novamente a posição do cursor e, se ele não foi movido, mova o cursor de volta para o início da linha para que o próximo prompt substitua o Output: . Desabilitamos promptsp , pois isso interfere nisso.

¹Esta abordagem baseada em pty poderia ser implementada com expect , por exemplo:

#! /usr/bin/expect -f

set x 0
set timeout -1
stty raw -echo
log_user 0
spawn -noecho zsh

# tell zsh to send a special sequence before the prompt (precmd)
# and a different one before each command (preexec)
send {precmd() printf ""; preexec() printf "";set +o promptsp}
send "\r"

# wait for the second prompt
expect ""

# set our x flag when the preexec string has been output and reset
# it upon precmd. write "Output:" if some character is received while
# the flag is up.
expect {
  -re "^" {
    set x 1; exp_continue
  }
  -re "^" {
    set x 0; exp_continue
  }
  -re "^.\[^\]*" {
    if {$x} {send_user "Output:\n"; set x 0}
    send_user -- "$expect_out(buffer)"
    exp_continue
  }

  -i $user_spawn_id -re .+ {
   send -- $expect_out(buffer); exp_continue
  }
}
    
por 16.12.2017 / 00:18

Tags