Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: PATCH: evaluation depth in prompts
On Tue, 26 Aug 2014 18:10:55 +0100
Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> On Tue, 26 Aug 2014 17:40:29 +0100
> Peter Stephenson <p.stephenson@xxxxxxxxxxx> wrote:
> > A better solution might be for a prompt escape that tracks the
> > nesting level (which is trivial apart from picking a new letter).
>
> %e for evaluation depth (%E is taken but %e isn't).
In case anyone's still following, here's the original script updated.
This now gives reliable tracing of who's calling whom, even for
functions calling themselves recursively, which I think was pretty much
impossible to automate reliably before by means of prompt tracing ---
you could hack it up or alternatively use debug traps and the functrace
stuff.
pws
# Trivial function to trace the strcture of zsh function calls
# with xtrace output using a PS4 containing %N and %i (see prompt_match
# below).
#
# Input is stderr from a shell with xtrace active and a suitable PS4.
# The completion system's ^X? binding can produce such output.
#
# For shells with %e (added in 5.0.7(?)): using PS4="+%e:%N:%i> "
# allows better tracing by outputting the execution depth of the
# construct being executed.
#
# If that's not available, the default PS4="+%N:%i> " is assumed. In
# this case, because we can't be sure a change in execution is a new
# call or a return to a previous function, we always assume the latter
# where the names match. This is the normal case but may be wrong for
# certain recursive structures.
emulate -L zsh
setopt extendedglob
# Match lines for PS4="+%e:%N:%i> ". Adapt as appropriate.
# With %e for evaluation depth.
local eprompt_match="+(#b)([0-9]##):([^>]##):([0-9]##)> *"
integer edepth_match=1
integer efunc_match=2
integer elineno_match=3
# Match lines for PS4="+%N:%i> ". Adapt as appropriate.
# No evaluation depth.
local prompt_match="+(#b)([^>]##):([0-9]##)> *"
# Function name in $match[1]
integer func_match=1
# Line number in $match[2]
integer lineno_match=2
# Padding to indent a line
local pad=" "
local line func indent last_line
integer lineno depth last_depth=-1 diff
local -a match mbegin mend funcs
while read line; do
if [[ $line = ${~eprompt_match} ]]; then
depth=$match[$edepth_match]
func=$match[$efunc_match]
lineno=$match[$elineno_match]
if (( last_depth == -1 )); then
print -r -- ${func}:${lineno}
elif (( depth < last_depth )); then
(( diff = last_depth - depth ))
while (( diff-- )); do
indent=${indent%%$pad}
done
elif (( depth > last_depth )); then
(( diff = depth - last_depth ))
while (( diff-- )); do
indent+=$pad
done
print -r -- "$indent$last_line -> $func"
fi
last_depth=$depth
last_line=${func}:${lineno}
elif [[ $line = ${~prompt_match} ]]; then
depth=$match[$depth_match]
func=$match[$func_match]
lineno=$match[$lineno_match]
if (( ${#funcs} == 0 )); then
print -r -- ${func}:${lineno}
funcs+=($func)
elif [[ $func != ${funcs[-1]} ]]; then
if [[ $func = ${funcs[-2]} ]]; then
funcs=(${funcs[1,-2]})
indent=${indent%%$pad}
else
indent+=$pad
print -r -- "$indent$last_line -> $func"
funcs+=($func)
fi
fi
last_line=${func}:${lineno}
fi
done <${1:-/dev/stdin}
Messages sorted by:
Reverse Date,
Date,
Thread,
Author