Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: TRAPDEBUG vs zsh -x

On Wed, Apr 20, 2022 at 4:55 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> You could play around with variations on this hack:

This was actually kind of fun, except for the part where I was baffled
for an hour by sysread apparently being buggy.

I installed https://gitlab.com/saalen/highlight

Aside:  Anyone want to supply a zsh language file and completion
script for that?  The "sh" language file is OK but not perfect for

The attached file creates a function "hlxt" plus a precmd helper which
arrange to write xtrace output through "highlight" and play it back
just before printing the next prompt.  It uses a coproc for this.
That means it won't work in a shell script, which is why I've named
the file "v1" while I play with it some more.

To use it, source the file and type "hlxt on".  To stop, "hlxt off".

Important caveats:

Capturing the trace output has to redirect stderr, which means error
output from the commands you run is also passed through it.  To avoid
that, add 2>&$stderr to the command line.

This can only handle as much trace output as will fit in the OS pipe
buffers on the input and output of the coprocess.  More than that will
cause it to hang because the output buffer is not consumed until
precmd runs.  Solving for the script problem might solve this too.

autoload add-zsh-hook
zmodload zsh/system || exit 1

typeset -g hlxtout hlxtin stderr oPS4="$PS4"
coproc highlight -S sh -O xterm256
exec {hlxtout}<&p
exec {hlxtin}>&p
exec {stderr}>&2

# We don't want the commands that are managing highlighting to appear
# in the trace output, so create them "sticky" with xtrace disabled
emulate zsh +x -c '
  hlxt_precmd() {
    local xtrace xt xc=0
    # Unfortunately this has to use a one-second timeout because
    # "highlight" does not always write quickly enough.
    # Manual says combining sysread -o with a param is valid, but
    # that does not work; neither output nor parameter is written.
    # while sysread -t 1 -i $hlxtout -c xc -o $stderr xtrace
    while sysread -t 1 -i $hlxtout -c xc xtrace
      [[ -n $xtrace ]] && print -n -u $stderr -r -- "${xt::=$xtrace}"
    # Need to handle error?  (( $? < 4 && xc )) && [[ -n $xtrace ]]
    [[ -z $xt || $xt == *$'"'\\n'"' ]] || echo
  hlxt() {
    setopt localoptions localtraps
    case $1 in
      add-zsh-hook precmd hlxt_precmd || exit 1
      exec 2>&$hlxtin
      # Bypass local scope restore of xtrace
      trap "setopt xtrace" EXIT
      exec 2>&$stderr
      add-zsh-hook -d precmd hlxt_precmd
      trap "unsetopt xtrace" EXIT
      # Flush leftovers
      local stderr
      hlxt_precmd {stderr}>&/dev/null
    (*) add-zsh-hook -L

Messages sorted by: Reverse Date, Date, Thread, Author