summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/backtrace.el
diff options
context:
space:
mode:
authorGemini Lasswell <gazally@runbox.com>2018-07-17 11:47:43 -0700
committerGemini Lasswell <gazally@runbox.com>2018-08-03 08:54:08 -0700
commitca98377280005344fb07c816997b9bc2a737056a (patch)
tree11172830e890866a63a154dad9e68850b8cf5064 /lisp/emacs-lisp/backtrace.el
parent1459ad2c670e7633f426d7a5a7f05fab23195b32 (diff)
downloademacs-ca98377280005344fb07c816997b9bc2a737056a.tar.gz
emacs-ca98377280005344fb07c816997b9bc2a737056a.tar.bz2
emacs-ca98377280005344fb07c816997b9bc2a737056a.zip
Add new commands to Edebug backtraces
Add commands to go to source if available, and to show and hide Edebug's instrumentation. Make Edebug pop to backtraces instead of displaying them, which makes Edebug consistant with the behavior of ERT and the Lisp Debugger. * doc/lispref/edebug.texi (Edebug Misc): Document when and how you can jump to source code from an Edebug backtrace. Document 'edebug-backtrace-show-instrumentation' and 'edebug-backtrace-hide-instrumentation'. * lisp/emacs-lisp/backtrace.el (backtrace-frame): Add comments to describe the fields. (backtrace-goto-source-functions): New abnormal hook. (backtrace-mode-map): Add keybinding and menu item for backtrace-goto-source. (backtrace--flags-width): New constant. (backtrace-update-flags): Use it. (backtrace-goto-source): New command. (backtrace--print-flags): Print the :source-available flag. * lisp/emacs-lisp/edebug.el (edebug-backtrace-frames) (edebug-instrumented-backtrace-frames): New variables. (edebug-backtrace, edebug--backtrace-frames): Remove functions. (edebug-pop-to-backtrace, edebug--backtrace-goto-source) (edebug--add-source-info): New functions. (edebug-mode-map, edebug-mode-menus): Replace 'edebug-backtrace' with 'edebug-pop-to-backtrace'. (edebug--strip-instrumentation): New function. (edebug--unwrap-and-add-info): Remove. (edebug-unwrap-frame, edebug-add-source-info): New functions. (edebug-backtrace-show-instrumentation) (edebug-backtrace-hide-instrumentation): New commands. * test/lisp/emacs-lisp/edebug-tests.el (edebug-tests-check-keymap): Verify keybindings in backtrace-mode-map used by new test. Update with binding for 'edebug-pop-to-backtrace'. (edebug-tests-backtrace-goto-source): New test. * test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el (edebug-test-code-range): Add a new stop point.
Diffstat (limited to 'lisp/emacs-lisp/backtrace.el')
-rw-r--r--lisp/emacs-lisp/backtrace.el52
1 files changed, 48 insertions, 4 deletions
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el
index b6ca2890764..5169c305035 100644
--- a/lisp/emacs-lisp/backtrace.el
+++ b/lisp/emacs-lisp/backtrace.el
@@ -66,7 +66,14 @@ abbreviate the forms it prints."
(cl-defstruct
(backtrace-frame
(:constructor backtrace-make-frame))
- evald fun args flags locals buffer pos)
+ evald ; Non-nil if argument evaluation is complete.
+ fun ; The function called/to call in this frame.
+ args ; Either evaluated or unevaluated arguments to the function.
+ flags ; A plist, possible properties are :debug-on-exit and :source-available.
+ locals ; An alist containing variable names and values.
+ buffer ; If non-nil, the buffer in use by eval-buffer or eval-region.
+ pos ; The position in the buffer.
+ )
(cl-defun backtrace-get-frames
(&optional base &key (constructor #'backtrace-make-frame))
@@ -181,6 +188,15 @@ This is commonly used to recompute `backtrace-frames'.")
(defvar-local backtrace-print-function #'cl-prin1
"Function used to print values in the current Backtrace buffer.")
+(defvar-local backtrace-goto-source-functions nil
+ "Abnormal hook used to jump to the source code for the current frame.
+Each hook function is called with no argument, and should return
+non-nil if it is able to switch to the buffer containing the
+source code. Execution of the hook will stop if one of the
+functions returns non-nil. When adding a function to this hook,
+you should also set the :source-available flag for the backtrace
+frames where the source code location is known.")
+
(defvar backtrace-mode-map
(let ((map (copy-keymap special-mode-map)))
(set-keymap-parent map button-buffer-map)
@@ -188,6 +204,7 @@ This is commonly used to recompute `backtrace-frames'.")
(define-key map "p" 'backtrace-backward-frame)
(define-key map "v" 'backtrace-toggle-locals)
(define-key map "#" 'backtrace-toggle-print-circle)
+ (define-key map "s" 'backtrace-goto-source)
(define-key map "\C-m" 'backtrace-help-follow-symbol)
(define-key map "+" 'backtrace-pretty-print)
(define-key map "-" 'backtrace-collapse)
@@ -212,6 +229,12 @@ This is commonly used to recompute `backtrace-frames'.")
:help "Use line breaks and indentation to make a form more readable"]
["Collapse to Single Line" backtrace-collapse]
"--"
+ ["Go to Source" backtrace-goto-source
+ :active (and (backtrace-get-index)
+ (plist-get (backtrace-frame-flags
+ (nth (backtrace-get-index) backtrace-frames))
+ :source-available))
+ :help "Show the source code for the current frame"]
["Help for Symbol" backtrace-help-follow-symbol
:help "Show help for symbol at point"]
["Describe Backtrace Mode" describe-mode
@@ -219,6 +242,9 @@ This is commonly used to recompute `backtrace-frames'.")
map)
"Local keymap for `backtrace-mode' buffers.")
+(defconst backtrace--flags-width 2
+ "Width in characters of the flags for a backtrace frame.")
+
;;; Navigation and Text Properties
;; This mode uses the following text properties:
@@ -580,6 +606,20 @@ content of the sexp."
'(backtrace-section backtrace-index backtrace-view
backtrace-form))))
+(defun backtrace-goto-source ()
+ "If its location is known, jump to the source code for the frame at point."
+ (interactive)
+ (let* ((index (or (backtrace-get-index) (user-error "Not in a stack frame")))
+ (frame (nth index backtrace-frames))
+ (source-available (plist-get (backtrace-frame-flags frame)
+ :source-available)))
+ (unless (and source-available
+ (catch 'done
+ (dolist (func backtrace-goto-source-functions)
+ (when (funcall func)
+ (throw 'done t)))))
+ (user-error "Source code location not known"))))
+
(defun backtrace-help-follow-symbol (&optional pos)
"Follow cross-reference at POS, defaulting to point.
For the cross-reference format, see `help-make-xrefs'."
@@ -681,8 +721,12 @@ property for use by navigation."
(defun backtrace--print-flags (frame view)
"Print the flags of a backtrace FRAME if enabled in VIEW."
(let ((beg (point))
- (flag (plist-get (backtrace-frame-flags frame) :debug-on-exit)))
- (insert (if (and (plist-get view :show-flags) flag) "* " " "))
+ (flag (plist-get (backtrace-frame-flags frame) :debug-on-exit))
+ (source (plist-get (backtrace-frame-flags frame) :source-available)))
+ (when (plist-get view :show-flags)
+ (when source (insert ">"))
+ (when flag (insert "*")))
+ (insert (make-string (- backtrace--flags-width (- (point) beg)) ?\s))
(put-text-property beg (point) 'backtrace-section 'func)))
(defun backtrace--print-func-and-args (frame _view)
@@ -770,7 +814,7 @@ Fall back to `prin1' if there is an error."
(let ((props (backtrace-get-text-properties begin))
(inhibit-read-only t)
(standard-output (current-buffer)))
- (delete-char 2)
+ (delete-char backtrace--flags-width)
(backtrace--print-flags (nth (backtrace-get-index) backtrace-frames)
view)
(add-text-properties begin (point) props))))))