emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] trunk r115350: * lisp/emacs-lisp/debug.el (debugger-toggle


From: Stefan Monnier
Subject: [Emacs-diffs] trunk r115350: * lisp/emacs-lisp/debug.el (debugger-toggle-locals): New command.
Date: Mon, 02 Dec 2013 14:45:31 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 115350
revision-id: address@hidden
parent: address@hidden
author: Helmut Eller <address@hidden>
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Mon 2013-12-02 09:45:22 -0500
message:
  * lisp/emacs-lisp/debug.el (debugger-toggle-locals): New command.
  (debugger-mode-map): Bind it.
  (debugger--backtrace-base): New function.
  (debugger-eval-expression): Use it.
  (debugger-frame-number): Skip local vars when present.
  (debugger--locals-visible-p, debugger--insert-locals)
  (debugger--show-locals, debugger--hide-locals): New functions.
  * src/eval.c (Fbacktrace__locals): New function.
  (syms_of_eval): Defsubr it.
modified:
  etc/NEWS                       news-20100311060928-aoit31wvzf25yr1z-1
  lisp/ChangeLog                 changelog-20091113204419-o5vbwnq5f7feedwu-1432
  lisp/emacs-lisp/debug.el       debug.el-20091113204419-o5vbwnq5f7feedwu-398
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/eval.c                     eval.c-20091113204419-o5vbwnq5f7feedwu-237
=== modified file 'etc/NEWS'
--- a/etc/NEWS  2013-11-29 18:36:31 +0000
+++ b/etc/NEWS  2013-12-02 14:45:22 +0000
@@ -247,6 +247,8 @@
 
 * Changes in Specialized Modes and Packages in Emacs 24.4
 
+** The backtrace debugger can display local vars with `v'.
+
 ** prolog-use-smie has been removed, along with the non-SMIE indentation code.
 
 ** SMIE indentation can be customized via `smie-config'.

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2013-12-02 13:52:23 +0000
+++ b/lisp/ChangeLog    2013-12-02 14:45:22 +0000
@@ -1,3 +1,13 @@
+2013-12-02  Helmut Eller  <address@hidden>
+
+       * emacs-lisp/debug.el (debugger-toggle-locals): New command.
+       (debugger-mode-map): Bind it.
+       (debugger--backtrace-base): New function.
+       (debugger-eval-expression): Use it.
+       (debugger-frame-number): Skip local vars when present.
+       (debugger--locals-visible-p, debugger--insert-locals)
+       (debugger--show-locals, debugger--hide-locals): New functions.
+
 2013-12-02  Michael Albinus  <address@hidden>
 
        * net/tramp-sh.el (tramp-remote-process-environment): Do not set

=== modified file 'lisp/emacs-lisp/debug.el'
--- a/lisp/emacs-lisp/debug.el  2013-11-30 09:25:31 +0000
+++ b/lisp/emacs-lisp/debug.el  2013-12-02 14:45:22 +0000
@@ -494,9 +494,13 @@
       (forward-line 1)
       (while (progn
               (forward-char 2)
-              (if (= (following-char) ?\()
-                  (forward-sexp 1)
-                (forward-sexp 2))
+              (cond ((debugger--locals-visible-p)
+                     (goto-char (next-single-char-property-change
+                                 (point) 'locals-visible)))
+                    ((= (following-char) ?\()
+                     (forward-sexp 1))
+                    (t
+                     (forward-sexp 2)))
               (forward-line 1)
               (<= (point) opoint))
        (if (looking-at " *;;;")
@@ -541,6 +545,14 @@
         (progn ,@body)
       (setq debugger-outer-match-data (match-data)))))
 
+(defun debugger--backtrace-base ()
+  "Return the function name that marks the top of the backtrace.
+See `backtrace-frame'."
+  (cond ((eq 'debug--implement-debug-on-entry
+            (cadr (backtrace-frame 1 'debug)))
+        'debug--implement-debug-on-entry)
+       (t 'debug)))
+
 (defun debugger-eval-expression (exp &optional nframe)
   "Eval an expression, in an environment like that outside the debugger.
 The environment used is the one when entering the activation frame at point."
@@ -549,15 +561,70 @@
   (let ((nframe (or nframe
                     (condition-case nil (1+ (debugger-frame-number 'skip-base))
                       (error 0)))) ;; If on first line.
-         (base (if (eq 'debug--implement-debug-on-entry
-                      (cadr (backtrace-frame 1 'debug)))
-                  'debug--implement-debug-on-entry 'debug)))
+       (base (debugger--backtrace-base)))
     (debugger-env-macro
       (let ((val (backtrace-eval exp nframe base)))
         (prog1
             (prin1 val t)
           (let ((str (eval-expression-print-format val)))
             (if str (princ str t))))))))
+
+(defun debugger--locals-visible-p ()
+  "Are the local variables of the current stack frame visible?"
+  (save-excursion
+    (move-to-column 2)
+    (get-text-property (point) 'locals-visible)))
+
+(defun debugger--insert-locals (locals)
+  "Insert the local variables LOCALS at point."
+  (cond ((null locals)
+        (insert "\n    [no locals]"))
+       (t
+        (let ((print-escape-newlines t))
+          (dolist (s+v locals)
+            (let ((symbol (car s+v))
+                  (value (cdr s+v)))
+              (insert "\n    ")
+              (prin1 symbol (current-buffer))
+              (insert " = ")
+              (prin1 value (current-buffer))))))))
+
+(defun debugger--show-locals ()
+  "For the frame at point, insert locals and add text properties."
+  (let* ((nframe (1+ (debugger-frame-number 'skip-base)))
+        (base (debugger--backtrace-base))
+        (locals (backtrace--locals nframe base))
+        (inhibit-read-only t))
+    (save-excursion
+      (let ((start (progn
+                    (move-to-column 2)
+                    (point))))
+       (end-of-line)
+       (debugger--insert-locals locals)
+       (add-text-properties start (point) '(locals-visible t))))))
+
+(defun debugger--hide-locals ()
+  "Delete local variables and remove the text property."
+  (let* ((col (current-column))
+        (end (progn
+               (move-to-column 2)
+               (next-single-char-property-change (point) 'locals-visible)))
+        (start (previous-single-char-property-change end 'locals-visible))
+        (inhibit-read-only t))
+    (remove-text-properties start end '(locals-visible))
+    (goto-char start)
+    (end-of-line)
+    (delete-region (point) end)
+    (move-to-column col)))
+
+(defun debugger-toggle-locals ()
+  "Show or hide local variables of the current stack frame."
+  (interactive)
+  (cond ((debugger--locals-visible-p)
+        (debugger--hide-locals))
+       (t
+        (debugger--show-locals))))
+
 
 (defvar debugger-mode-map
   (let ((map (make-keymap))
@@ -575,6 +642,7 @@
     (define-key map "h" 'describe-mode)
     (define-key map "q" 'top-level)
     (define-key map "e" 'debugger-eval-expression)
+    (define-key map "v" 'debugger-toggle-locals) ;"v" is for "v"ariables.
     (define-key map " " 'next-line)
     (define-key map "R" 'debugger-record-expression)
     (define-key map "\C-m" 'debug-help-follow)

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-12-02 13:35:53 +0000
+++ b/src/ChangeLog     2013-12-02 14:45:22 +0000
@@ -1,3 +1,8 @@
+2013-12-02  Helmut Eller  <address@hidden>
+
+       * eval.c (Fbacktrace__locals): New function.
+       (syms_of_eval): Defsubr it.
+
 2013-12-02  Dmitry Antipov  <address@hidden>
 
        * font.h (FONT_WIDTH, FONT_HEIGHT, FONT_BASE, FONT_DESCENT):

=== modified file 'src/eval.c'
--- a/src/eval.c        2013-11-05 16:29:58 +0000
+++ b/src/eval.c        2013-12-02 14:45:22 +0000
@@ -3576,6 +3576,73 @@
      from the debugger.  */
   return unbind_to (count, eval_sub (exp));
 }
+
+DEFUN ("backtrace--locals", Fbacktrace__locals, Sbacktrace__locals, 1, 2, NULL,
+       doc: /* Return names and values of local variables of a stack frame.
+NFRAMES and BASE specify the activation frame to use, as in `backtrace-frame'. 
 */)
+  (Lisp_Object nframes, Lisp_Object base)
+{
+  union specbinding *frame = get_backtrace_frame (nframes, base);
+  union specbinding *prevframe
+    = get_backtrace_frame (make_number (XFASTINT (nframes) - 1), base);
+  ptrdiff_t distance = specpdl_ptr - frame;
+  Lisp_Object result = Qnil;
+  eassert (distance >= 0);
+
+  if (!backtrace_p (prevframe))
+    error ("Activation frame not found!");
+  if (!backtrace_p (frame))
+    error ("Activation frame not found!");
+
+  /* The specpdl entries normally contain the symbol being bound along with its
+     `old_value', so it can be restored.  The new value to which it is bound is
+     available in one of two places: either in the current value of the
+     variable (if it hasn't been rebount yet) or in the `old_value' slot of the
+     next specpdl entry for it.
+     `backtrace_eval_unrewind' happens to swap the role of `old_value'
+     and "new value", so we abuse it here, to fetch the new value.
+     It's ugly (we'd rather not modify global data) and a bit inefficient,
+     but it does the job for now.  */
+  backtrace_eval_unrewind (distance);
+
+  /* Grab values.  */
+  {
+    union specbinding *tmp = prevframe;
+    for (; tmp > frame; tmp--)
+      {
+       switch (tmp->kind)
+         {
+         case SPECPDL_LET:
+         case SPECPDL_LET_DEFAULT:
+         case SPECPDL_LET_LOCAL:
+           {
+             Lisp_Object sym = specpdl_symbol (tmp);
+             Lisp_Object val = specpdl_old_value (tmp);
+             if (EQ (sym, Qinternal_interpreter_environment))
+               {
+                 Lisp_Object env = val;
+                 for (; CONSP (env); env = XCDR (env))
+                   {
+                     Lisp_Object binding = XCAR (env);
+                     if (CONSP (binding))
+                       result = Fcons (Fcons (XCAR (binding),
+                                              XCDR (binding)),
+                                       result);
+                   }
+               }
+             else
+               result = Fcons (Fcons (sym, val), result);
+           }
+         }
+      }
+  }
+
+  /* Restore values from specpdl to original place.  */
+  backtrace_eval_unrewind (-distance);
+
+  return result;
+}
+
 
 void
 mark_specpdl (void)
@@ -3824,6 +3891,7 @@
   defsubr (&Sbacktrace);
   defsubr (&Sbacktrace_frame);
   defsubr (&Sbacktrace_eval);
+  defsubr (&Sbacktrace__locals);
   defsubr (&Sspecial_variable_p);
   defsubr (&Sfunctionp);
 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]