zsh-workers
 help / color / mirror / code / Atom feed
* Function for examining structure of calls in debug output
@ 2014-08-26 16:40 Peter Stephenson
  2014-08-26 17:10 ` PATCH: evaluation depth in prompts Peter Stephenson
  2014-08-30 19:38 ` Function for examining structure of calls in debug output Bart Schaefer
  0 siblings, 2 replies; 9+ messages in thread
From: Peter Stephenson @ 2014-08-26 16:40 UTC (permalink / raw)
  To: Zsh Hackers' List

In case this is useful to anyone, the function below is a very simple
(and easy to confuse) way of examining the structure of shell debug
output such as what you get from ^X? in completion.  For example (except
I keep changing my mind on the format) from some _complete_debug output:

_complete_debug:16
   _complete_debug:17 -> _main_complete
     _main_complete:25 -> (eval)
     _main_complete:82 -> _setup
     _main_complete:178 -> _oldlist
     _main_complete:178 -> _oldlist
     _main_complete:178 -> _expand
       _expand:81 -> (eval)
       _expand:89 -> (eval)
       _expand:106 -> (eval)
     _main_complete:178 -> _expand
     _main_complete:178 -> _user_expand
       _user_expand:39 -> (eval)
       _user_expand:48 -> _percent
     _main_complete:178 -> _user_expand
     _main_complete:178 -> _complete
       _complete:100 -> (eval)
       _complete:117 -> _normal
         _normal:38 -> _set_command
         _normal:40 -> _dispatch
           _dispatch:63 -> (eval)
             (eval):1 -> _mh
               _mh:44 -> _wanted
                 _wanted:7 -> _tags
                 _wanted:9 -> _tags
                 _wanted:10 -> _all_labels
                   _all_labels:37 -> _description
                     _description:18 -> _setup
                   _all_labels:39 -> _path_files
                     _path_files:17 -> _have_glob_qual
                     _path_files:201 -> _have_glob_qual
                     _path_files:202 -> _have_glob_qual
                     _path_files:725 -> _list_files
                 _wanted:10 -> _dispatch
                   _dispatch:64 -> _complete
                     _complete:144 -> _main_complete
                       _main_complete:380 -> _complete_debug


You'll notice it's already confused because the return from _dispatch
goes to _complete instead of _normal, since there are no further
non-trivial commands in _normal, and searching back up the stack for the
return function would mean there was no hope of it grokking recursive
structures.  I'm not sure how much effort I can be bothered to put into
this.  A better solution might be for a prompt escape that tracks the
nesting level (which is trivial apart from picking a new letter).


xtrace_trace() {
  # 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.
  #
  # 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="+%N:%i> ".  Adapt as appropriate.
  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
  local -a match mbegin mend funcs

  while read line; do
    [[ $line = ${~prompt_match} ]] || continue
    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}
  done <${1:-/dev/stdin}
}


-- 
Peter Stephenson <p.stephenson@samsung.com>  Principal Software Engineer
Tel: +44 (0)1223 434724                Samsung Cambridge Solution Centre
St John's House, St John's Innovation Park, Cowley Road,
Cambridge, CB4 0DS, UK


^ permalink raw reply	[flat|nested] 9+ messages in thread

* PATCH: evaluation depth in prompts
  2014-08-26 16:40 Function for examining structure of calls in debug output Peter Stephenson
@ 2014-08-26 17:10 ` Peter Stephenson
  2014-08-29 16:16   ` Peter Stephenson
  2014-08-30 20:35   ` Bart Schaefer
  2014-08-30 19:38 ` Function for examining structure of calls in debug output Bart Schaefer
  1 sibling, 2 replies; 9+ messages in thread
From: Peter Stephenson @ 2014-08-26 17:10 UTC (permalink / raw)
  To: Zsh Hackers' List

On Tue, 26 Aug 2014 17:40:29 +0100
Peter Stephenson <p.stephenson@samsung.com> 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).

I won't commit this until the release now.  Probably Thursday is my next
chance for that while leaving enough time for people to moan.

diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 0ed52b5..183a93a 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -108,6 +108,12 @@ the full path;
 ifzman(see em(Dynamic) and em(Static named directories) in zmanref(zshexpn))\
 ifnzman(noderef(Filename Expansion)).
 )
+item(tt(%e))(
+Evaluation depth of the current sourced file, shell function, or tt(eval).
+This is incremented or decremented every time the value of tt(%N) is
+set or reverted to a previous value, respectively.  This is most useful
+for debugging as part of tt($PS4).
+)
 xitem(tt(%h))
 item(tt(%!))(
 Current history event number.
diff --git a/Src/prompt.c b/Src/prompt.c
index 328ae3c..4762535 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -786,6 +786,19 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 		if(bv->Rstring)
 		    stradd(bv->Rstring);
 		break;
+	    case 'e':
+	    {
+		int depth = 0;
+		Funcstack fsptr = funcstack;
+		while (fsptr) {
+		    depth++;
+		    fsptr = fsptr->prev;
+		}
+		addbufspc(DIGBUFSIZE);
+		sprintf(bv->bp, "%d", depth);
+		bv->bp += strlen(bv->bp);
+		break;
+	    }
 	    case 'I':
 		if (funcstack && funcstack->tp != FS_SOURCE &&
 		    !IN_EVAL_TRAP()) {


pws


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-08-26 17:10 ` PATCH: evaluation depth in prompts Peter Stephenson
@ 2014-08-29 16:16   ` Peter Stephenson
  2014-09-01 21:02     ` Bart Schaefer
  2014-08-30 20:35   ` Bart Schaefer
  1 sibling, 1 reply; 9+ messages in thread
From: Peter Stephenson @ 2014-08-29 16:16 UTC (permalink / raw)
  To: Zsh Hackers' List

On Tue, 26 Aug 2014 18:10:55 +0100
Peter Stephenson <p.stephenson@samsung.com> wrote:
> On Tue, 26 Aug 2014 17:40:29 +0100
> Peter Stephenson <p.stephenson@samsung.com> 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}


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Function for examining structure of calls in debug output
  2014-08-26 16:40 Function for examining structure of calls in debug output Peter Stephenson
  2014-08-26 17:10 ` PATCH: evaluation depth in prompts Peter Stephenson
@ 2014-08-30 19:38 ` Bart Schaefer
  1 sibling, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2014-08-30 19:38 UTC (permalink / raw)
  To: Zsh Hackers' List

Hi, back from a few days on the road ...

On Aug 26,  5:40pm, Peter Stephenson wrote:
}
} You'll notice it's already confused because the return from _dispatch
} goes to _complete instead of _normal, since there are no further
} non-trivial commands in _normal, and searching back up the stack for the
} return function would mean there was no hope of it grokking recursive
} structures.  I'm not sure how much effort I can be bothered to put into
} this.  A better solution might be for a prompt escape that tracks the
} nesting level (which is trivial apart from picking a new letter).

I see you already implemented the latter idea.  An alternate / additional
idea would be to have xtrace output a "return N" expression any time a
function returns, whenever there is no explicit return statement in the
source.  The line number could be that of the closing curly brace, or
perhaps some flag value such as -1.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-08-26 17:10 ` PATCH: evaluation depth in prompts Peter Stephenson
  2014-08-29 16:16   ` Peter Stephenson
@ 2014-08-30 20:35   ` Bart Schaefer
  1 sibling, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2014-08-30 20:35 UTC (permalink / raw)
  To: Zsh Hackers' List

On Aug 26,  6:10pm, Peter Stephenson wrote:
} Subject: PATCH: evaluation depth in prompts
}
} On Tue, 26 Aug 2014 17:40:29 +0100
} Peter Stephenson <p.stephenson@samsung.com> 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).

Nifty, but it should also be added as %N(e.deep.shallow).


diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 183a93a..17af5b0 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -305,6 +305,7 @@ least var(n) elements relative to the root directory, hence tt(/) is
 counted as 0 elements.)
 sitem(tt(D))(True if the month is equal to var(n) (January = 0).)
 sitem(tt(d))(True if the day of the month is equal to var(n).)
+sitem(tt(e))(True if the evaluation depth is at least var(n).)
 sitem(tt(g))(True if the effective gid of the current process is var(n).)
 sitem(tt(j))(True if the number of jobs is at least var(n).)
 sitem(tt(L))(True if the tt(SHLVL) parameter is at least var(n).)
diff --git a/Src/prompt.c b/Src/prompt.c
index 4762535..9ed6c54 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -372,6 +372,17 @@ putpromptchar(int doprint, int endchar, unsigned int *txtchangep)
 		    if (t0 >= arg)
 			test = 1;
 		    break;
+		case 'e':
+		    {
+			Funcstack fsptr = funcstack;
+			test = arg;
+			while (fsptr && test > 0) {
+			    test--;
+			    fsptr = fsptr->prev;
+			}
+			test = !test;
+		    }
+		    break;
 		case 'L':
 		    if (shlvl >= arg)
 			test = 1;


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-08-29 16:16   ` Peter Stephenson
@ 2014-09-01 21:02     ` Bart Schaefer
  2014-09-02  8:38       ` Peter Stephenson
  2014-09-02 23:53       ` Oliver Kiddle
  0 siblings, 2 replies; 9+ messages in thread
From: Bart Schaefer @ 2014-09-01 21:02 UTC (permalink / raw)
  To: Zsh Hackers' List

On Aug 29,  5:16pm, Peter Stephenson wrote:
}
} In case anyone's still following, here's the original script updated.
} This now gives reliable tracing of who's calling whom

Here's a related idea/suggestion which adds indentation to the output
of _complete_debug.  There's no convenient way to produce ${(%):-%e}
spaces for arbitrary depths without turning on promptsubst, so this
generates a bunch of %N(e. .) expressions and glues them together.
If completion goes more than 20 function calls deep there's probably
something wrong anyway.

I couldn't decide whether to put the indentation after the leading "+"
or before it.  This has it before.

(This is another one I won't commit without positive feedback.)

diff --git a/Completion/Base/Widget/_complete_debug b/Completion/Base/Widget/_complete_debug
index eff0f8e..6c0d9a3 100644
--- a/Completion/Base/Widget/_complete_debug
+++ b/Completion/Base/Widget/_complete_debug
@@ -12,6 +12,8 @@ integer debug_fd=-1
     exec {debug_fd}>&2 2>| $tmp
   fi
 
+  local -a debug_indent; debug_indent=( '%'{3..20}'(e. .)' )
+  local PROMTP4 PS4="${(j::)debug_indent}+%N:%i> "
   setopt xtrace
   : $ZSH_NAME $ZSH_VERSION
   ${1:-_main_complete}


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-09-01 21:02     ` Bart Schaefer
@ 2014-09-02  8:38       ` Peter Stephenson
  2014-09-02 23:53       ` Oliver Kiddle
  1 sibling, 0 replies; 9+ messages in thread
From: Peter Stephenson @ 2014-09-02  8:38 UTC (permalink / raw)
  To: Zsh Hackers' List

On Mon, 01 Sep 2014 14:02:02 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Aug 29,  5:16pm, Peter Stephenson wrote:
> }
> } In case anyone's still following, here's the original script updated.
> } This now gives reliable tracing of who's calling whom
> 
> Here's a related idea/suggestion which adds indentation to the output
> of _complete_debug.  There's no convenient way to produce ${(%):-%e}
> spaces for arbitrary depths without turning on promptsubst, so this
> generates a bunch of %N(e. .) expressions and glues them together.
> If completion goes more than 20 function calls deep there's probably
> something wrong anyway.

Seems reasonable --- it doesn't remove any of the existing information.
A visual cue for calls should make it a lot clearer.

> I couldn't decide whether to put the indentation after the leading "+"
> or before it.  This has it before.

That makes it easier to strip the spaces if you happen to prefer it
like that.

pws


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-09-01 21:02     ` Bart Schaefer
  2014-09-02  8:38       ` Peter Stephenson
@ 2014-09-02 23:53       ` Oliver Kiddle
  2014-09-03  1:38         ` Bart Schaefer
  1 sibling, 1 reply; 9+ messages in thread
From: Oliver Kiddle @ 2014-09-02 23:53 UTC (permalink / raw)
  To: Zsh Hackers' List

Bart wrote:

> Here's a related idea/suggestion which adds indentation to the output
> of _complete_debug.  There's no convenient way to produce ${(%):-%e}

Seems a useful idea and at worst, horizontally scrolling get used when
viewing the output.

> If completion goes more than 20 function calls deep there's probably
> something wrong anyway.

Or if it does, then it doesn't especially matter that indentation simply
stops at this limit: it's arguably a feature rather than a limitation.

> I couldn't decide whether to put the indentation after the leading "+"
> or before it.  This has it before.

When viewing _complete_debug output, I nearly always use the less
feature to filter lines using &pattern, often using a pattern such as
\+_expand to filter by a particular function. With that in mind,
indentation before is more helpful.

> +  local -a debug_indent; debug_indent=( '%'{3..20}'(e. .)' )
> +  local PROMTP4 PS4="${(j::)debug_indent}+%N:%i> "

Note the typo for PROMPT4.

Oliver


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: PATCH: evaluation depth in prompts
  2014-09-02 23:53       ` Oliver Kiddle
@ 2014-09-03  1:38         ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2014-09-03  1:38 UTC (permalink / raw)
  To: Zsh Hackers' List

On Sep 3,  1:53am, Oliver Kiddle wrote:
}
} > +  local -a debug_indent; debug_indent=( '%'{3..20}'(e. .)' )
} > +  local PROMTP4 PS4="${(j::)debug_indent}+%N:%i> "
} 
} Note the typo for PROMPT4.

Thanks for noticing that.  I'm not sure PROMPT4 needs to be declared
there anyway, but given the alter ego I  it might be a good idea.


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2014-09-03  1:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-26 16:40 Function for examining structure of calls in debug output Peter Stephenson
2014-08-26 17:10 ` PATCH: evaluation depth in prompts Peter Stephenson
2014-08-29 16:16   ` Peter Stephenson
2014-09-01 21:02     ` Bart Schaefer
2014-09-02  8:38       ` Peter Stephenson
2014-09-02 23:53       ` Oliver Kiddle
2014-09-03  1:38         ` Bart Schaefer
2014-08-30 20:35   ` Bart Schaefer
2014-08-30 19:38 ` Function for examining structure of calls in debug output Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).