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
  }
}

관련 정보