ZSHにはpostexec/predisplayフックがありますか?

ZSHにはpostexec/predisplayフックがありますか?

zshには、コマンドが実行される前に実行される事前実行フックがあることを知っていますが、コマンドの開始後に出力が画面に表示される前に実行されるフックはありますか?実際の出力があるかどうかに応じて何かを表示したいので、この質問をします。

例:
cd dir何も出力せずに
ls dir何かを出力します。

Output:\nこの例では、lsディレクトリが表示される前に表示したいが表示されないcdため、実行時には表示しません。私はそれが次のように見えるようにしたいです:

~ $: 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 $

私はCDとLSを詰めたくありません。これらはすべて例です。私はそれを願っていますすべて注文する。

答え1

できません時事フックは、コマンドが端末や他のファイルに何かを出力するときにシェルがまったく関係しないためです。

フックは、コマンドラインから開始されたプロセスまたはスレッドがttyデバイスで開かれたファイル記述子に対して最初の書き込みシステムコールを実行したときに実行されるコマンドに存在する必要があります。あるいは、いくつかのIPCメカニズムを使用してコマンドのstdoutとstderr(コマンドの動作への影響を最小限に抑えるための擬似ttyペア)をリダイレクトし、何かが受信されたときにそれらを挿入するOutput:必要があります。それにもかかわらず、これは非常に複雑で侵害的な可能性があります。

私がすることはありませんが、次のように試してみることができます。

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

つまり、コマンド出力を実行する前に、Output:カーソルを画面の右端に移動し(したがって、次の内容は次の行の先頭に書き込まれます)、現在のカーソル位置をに書き込みます$pos_before

次のプロンプトの前にカーソル位置を再度照会し、移動しなかった場合は、次のプロンプトがその位置を上書きするようにカーソルを行の先頭に戻しますOutput:promptspこれを妨げるので無効にします。


¹このptyベースのアプローチは、次のexpectように実装できます。

#! /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 "\1\1"; preexec() printf "\2\2";set +o promptsp}
send "\r"

# wait for the second prompt
expect "\1\1"

# 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 "^\2\2" {
    set x 1; exp_continue
  }
  -re "^\1\1" {
    set x 0; exp_continue
  }
  -re "^.\[^\1\2\]*" {
    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
  }
}

関連情報