Subject: Re: bug#24514: 24.5; [WIP][PATCH] Lispy backtraces

From: Vasilij Schneidermann <[email-masked]>
Date: Fri, 30 Sep 2016 12:29:56 +0200

> How about debugger-stack-frame-as-list?

Thanks, sounds good to me.

> Two minor nits to make this patch perfect:
> 
>   . Add the variable to cus-start.el, so that it will be a defcustom
>   . Add a NEWS entry and mention the variable in the ELisp manual

I've done these and changed the commit message to comply better with the
changelog style.  Let me know if there's still something off.
>From 62d47f75adc8d319b6fc35bb79bcf316d16bec00 Mon Sep 17 00:00:00 2001
From: Vasilij Schneidermann <[email-masked]>
Date: Thu, 22 Sep 2016 23:01:21 +0200
Subject: [PATCH] Add new 'debugger-stack-frame-as-list' option

Allow displaying all lines in `backtrace' as lists.
* doc/lispref/debugging.texi: Document the new variable
* src/eval.c: New variable
* lisp/emacs-lisp/debug.el: Adjust backtrace processing for new variable
* lisp/emacs-lisp/edebug.el: Adjust backtrace processing for new
variable
---
 doc/lispref/debugging.texi | 29 +++++++++++++++++++++++++++++
 etc/NEWS                   |  5 +++++
 lisp/cus-start.el          |  1 +
 lisp/emacs-lisp/debug.el   |  4 +++-
 lisp/emacs-lisp/edebug.el  |  4 +++-
 src/eval.c                 | 12 ++++++++++--
 6 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi
index 98c4705..15eea8a 100644
--- a/doc/lispref/debugging.texi
+++ b/doc/lispref/debugging.texi
@@ -623,6 +623,35 @@ forms are elided.
 @end smallexample
 @end deffn
 
+@defvar debugger-stack-frame-as-list
+If this variable is non-@code{nil}, every line of the backtrace is
+displayed as a list.  This aims to improve backtrace readability at
+the cost of special forms no longer being visually different from
+regular function calls.
+
+The above example would look as follows:
+@smallexample
+@group
+----------- Buffer: backtrace-output ------------
+  (backtrace)
+  (list ...computing arguments...)
+@end group
+  (progn ...)
+  (eval (progn (1+ var) (list (quote testing) (backtrace))))
+  (setq ...)
+  (save-excursion ...)
+  (let ...)
+  (with-output-to-temp-buffer ...)
+  (eval (with-output-to-temp-buffer ...))
+  (eval-last-sexp-1 nil)
+@group
+  (eval-last-sexp nil)
+  (call-interactively eval-last-sexp)
+----------- Buffer: backtrace-output ------------
+@end group
+@end smallexample
+@end defvar
+
 @defvar debug-on-next-call
 @cindex @code{eval}, and debugging
 @cindex @code{apply}, and debugging
diff --git a/etc/NEWS b/etc/NEWS
index a72be53..a88d9ec 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -179,6 +179,11 @@ questions, with a handy way to display help texts.
 +++
 ** 'switch-to-buffer-preserve-window-point' now defaults to t.
 
++++
+** The new variable 'debugger-stack-frame-as-list' allows displaying
+all call stack frames in 'backtrace' as lists.  Both debug.el and
+edebug.el have been updated accordingly.
+
 
 * Editing Changes in Emacs 25.2
 
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index c830ed8..c6d0ae4 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -246,6 +246,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
 	     (debug-ignored-errors debug (repeat (choice symbol regexp)))
 	     (debug-on-quit debug boolean)
 	     (debug-on-signal debug boolean)
+             (debugger-stack-frame-as-list debugger boolean)
 	     ;; fileio.c
 	     (delete-by-moving-to-trash auto-save boolean "23.1")
 	     (auto-save-visited-file-name auto-save boolean)
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index 22a3f39..7d27380 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -279,7 +279,9 @@ That buffer should be current already."
   (goto-char (point-min))
   (delete-region (point)
 		 (progn
-		   (search-forward "\n  debug(")
+		   (search-forward (if debugger-stack-frame-as-list
+                                       "\n  (debug "
+                                     "\n  debug("))
 		   (forward-line (if (eq (car args) 'debug)
                                      ;; Remove debug--implement-debug-on-entry
                                      ;; and the advice's `apply' frame.
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index c283c16..0c2a8ad 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -3797,7 +3797,9 @@ Otherwise call `debug' normally."
 	  (forward-line 1)
 	  (delete-region last-ok-point (point)))
 
-	 ((looking-at "^  edebug")
+	 ((looking-at (if debugger-stack-frame-as-list
+                          "^  (edebug"
+                        "^  edebug"))
 	  (forward-line 1)
 	  (delete-region last-ok-point (point))
 	  )))
diff --git a/src/eval.c b/src/eval.c
index 72facd5..f07cc83 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3409,13 +3409,17 @@ Output stream used is value of `standard-output'.  */)
       else
 	{
 	  tem = backtrace_function (pdl);
+	  if (debugger_stack_frame_as_list)
+	    write_string ("(");
 	  Fprin1 (tem, Qnil);	/* This can QUIT.  */
-	  write_string ("(");
+	  if (!debugger_stack_frame_as_list)
+	    write_string ("(");
 	  {
 	    ptrdiff_t i;
 	    for (i = 0; i < backtrace_nargs (pdl); i++)
 	      {
-		if (i) write_string (" ");
+		if (i || debugger_stack_frame_as_list)
+		  write_string(" ");
 		Fprin1 (backtrace_args (pdl)[i], Qnil);
 	      }
 	  }
@@ -3838,6 +3842,10 @@ This is nil when the debugger is called under circumstances where it
 might not be safe to continue.  */);
   debugger_may_continue = 1;
 
+  DEFVAR_BOOL ("debugger-stack-frame-as-list", debugger_stack_frame_as_list,
+	       doc: /* Non-nil means display call stack frames as lists. */);
+  debugger_stack_frame_as_list = 0;
+
   DEFVAR_LISP ("debugger", Vdebugger,
 	       doc: /* Function to call to invoke debugger.
 If due to frame exit, args are `exit' and the value being returned;
-- 
2.10.0