diff options
| author | Gemini Lasswell | 2018-07-17 11:47:43 -0700 |
|---|---|---|
| committer | Gemini Lasswell | 2018-08-03 08:54:08 -0700 |
| commit | ca98377280005344fb07c816997b9bc2a737056a (patch) | |
| tree | 11172830e890866a63a154dad9e68850b8cf5064 | |
| parent | 1459ad2c670e7633f426d7a5a7f05fab23195b32 (diff) | |
| download | emacs-ca98377280005344fb07c816997b9bc2a737056a.tar.gz 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.
| -rw-r--r-- | doc/lispref/edebug.texi | 12 | ||||
| -rw-r--r-- | etc/NEWS | 13 | ||||
| -rw-r--r-- | lisp/emacs-lisp/backtrace.el | 52 | ||||
| -rw-r--r-- | lisp/emacs-lisp/edebug.el | 118 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el | 2 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/edebug-tests.el | 18 |
6 files changed, 165 insertions, 50 deletions
diff --git a/doc/lispref/edebug.texi b/doc/lispref/edebug.texi index 0e0a2e8a643..59c9a68c54b 100644 --- a/doc/lispref/edebug.texi +++ b/doc/lispref/edebug.texi | |||
| @@ -442,8 +442,16 @@ Redisplay the most recently known expression result in the echo area | |||
| 442 | Display a backtrace, excluding Edebug's own functions for clarity | 442 | Display a backtrace, excluding Edebug's own functions for clarity |
| 443 | (@code{edebug-backtrace}). | 443 | (@code{edebug-backtrace}). |
| 444 | 444 | ||
| 445 | @xref{Debugging,, Backtraces, elisp}, for the commands which work | 445 | @xref{Debugging,, Backtraces, elisp}, for a description of backtraces |
| 446 | in a backtrace buffer. | 446 | and the commands which work on them. |
| 447 | |||
| 448 | If you would like to see Edebug's functions in the backtrace, | ||
| 449 | use @kbd{M-x edebug-backtrace-show-instrumentation}. To hide them | ||
| 450 | again use @kbd{M-x edebug-backtrace-hide-instrumentation}. | ||
| 451 | |||
| 452 | If a backtrace frame starts with @samp{>} that means that Edebug knows | ||
| 453 | where the source code for the frame is located. Use @kbd{s} to jump | ||
| 454 | to the source code for the current frame. | ||
| 447 | 455 | ||
| 448 | The backtrace buffer is killed automatically when you continue | 456 | The backtrace buffer is killed automatically when you continue |
| 449 | execution. | 457 | execution. |
| @@ -484,11 +484,20 @@ using the new variables 'edebug-behavior-alist', | |||
| 484 | globally or for individual definitions. | 484 | globally or for individual definitions. |
| 485 | 485 | ||
| 486 | +++ | 486 | +++ |
| 487 | *** Edebug's backtrace buffer now uses 'backtrace-mode'. | 487 | *** Edebug's backtrace buffer now uses 'backtrace-mode'. Backtrace |
| 488 | Backtrace mode adds fontification, links and commands for changing the | 488 | mode adds fontification, links and commands for changing the |
| 489 | appearance of backtrace frames. See the node "Backtraces" in the Elisp | 489 | appearance of backtrace frames. See the node "Backtraces" in the Elisp |
| 490 | manual for documentation of the new mode and its commands. | 490 | manual for documentation of the new mode and its commands. |
| 491 | 491 | ||
| 492 | The binding of 'd' in Edebug's keymap is now 'edebug-pop-to-backtrace' | ||
| 493 | which replaces 'edebug-backtrace'. Consequently Edebug's backtrace | ||
| 494 | windows now behave like those of the Lisp Debugger and of ERT, in that | ||
| 495 | when they appear they will be the selected window. | ||
| 496 | |||
| 497 | The new 'backtrace-goto-source' command, bound to 's', works in | ||
| 498 | Edebug's backtraces on backtrace frames whose source code has | ||
| 499 | been instrumented by Edebug. | ||
| 500 | |||
| 492 | ** Enhanced xterm support | 501 | ** Enhanced xterm support |
| 493 | 502 | ||
| 494 | *** New variable 'xterm-set-window-title' controls whether Emacs sets | 503 | *** New variable 'xterm-set-window-title' controls whether Emacs sets |
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." | |||
| 66 | (cl-defstruct | 66 | (cl-defstruct |
| 67 | (backtrace-frame | 67 | (backtrace-frame |
| 68 | (:constructor backtrace-make-frame)) | 68 | (:constructor backtrace-make-frame)) |
| 69 | evald fun args flags locals buffer pos) | 69 | evald ; Non-nil if argument evaluation is complete. |
| 70 | fun ; The function called/to call in this frame. | ||
| 71 | args ; Either evaluated or unevaluated arguments to the function. | ||
| 72 | flags ; A plist, possible properties are :debug-on-exit and :source-available. | ||
| 73 | locals ; An alist containing variable names and values. | ||
| 74 | buffer ; If non-nil, the buffer in use by eval-buffer or eval-region. | ||
| 75 | pos ; The position in the buffer. | ||
| 76 | ) | ||
| 70 | 77 | ||
| 71 | (cl-defun backtrace-get-frames | 78 | (cl-defun backtrace-get-frames |
| 72 | (&optional base &key (constructor #'backtrace-make-frame)) | 79 | (&optional base &key (constructor #'backtrace-make-frame)) |
| @@ -181,6 +188,15 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 181 | (defvar-local backtrace-print-function #'cl-prin1 | 188 | (defvar-local backtrace-print-function #'cl-prin1 |
| 182 | "Function used to print values in the current Backtrace buffer.") | 189 | "Function used to print values in the current Backtrace buffer.") |
| 183 | 190 | ||
| 191 | (defvar-local backtrace-goto-source-functions nil | ||
| 192 | "Abnormal hook used to jump to the source code for the current frame. | ||
| 193 | Each hook function is called with no argument, and should return | ||
| 194 | non-nil if it is able to switch to the buffer containing the | ||
| 195 | source code. Execution of the hook will stop if one of the | ||
| 196 | functions returns non-nil. When adding a function to this hook, | ||
| 197 | you should also set the :source-available flag for the backtrace | ||
| 198 | frames where the source code location is known.") | ||
| 199 | |||
| 184 | (defvar backtrace-mode-map | 200 | (defvar backtrace-mode-map |
| 185 | (let ((map (copy-keymap special-mode-map))) | 201 | (let ((map (copy-keymap special-mode-map))) |
| 186 | (set-keymap-parent map button-buffer-map) | 202 | (set-keymap-parent map button-buffer-map) |
| @@ -188,6 +204,7 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 188 | (define-key map "p" 'backtrace-backward-frame) | 204 | (define-key map "p" 'backtrace-backward-frame) |
| 189 | (define-key map "v" 'backtrace-toggle-locals) | 205 | (define-key map "v" 'backtrace-toggle-locals) |
| 190 | (define-key map "#" 'backtrace-toggle-print-circle) | 206 | (define-key map "#" 'backtrace-toggle-print-circle) |
| 207 | (define-key map "s" 'backtrace-goto-source) | ||
| 191 | (define-key map "\C-m" 'backtrace-help-follow-symbol) | 208 | (define-key map "\C-m" 'backtrace-help-follow-symbol) |
| 192 | (define-key map "+" 'backtrace-pretty-print) | 209 | (define-key map "+" 'backtrace-pretty-print) |
| 193 | (define-key map "-" 'backtrace-collapse) | 210 | (define-key map "-" 'backtrace-collapse) |
| @@ -212,6 +229,12 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 212 | :help "Use line breaks and indentation to make a form more readable"] | 229 | :help "Use line breaks and indentation to make a form more readable"] |
| 213 | ["Collapse to Single Line" backtrace-collapse] | 230 | ["Collapse to Single Line" backtrace-collapse] |
| 214 | "--" | 231 | "--" |
| 232 | ["Go to Source" backtrace-goto-source | ||
| 233 | :active (and (backtrace-get-index) | ||
| 234 | (plist-get (backtrace-frame-flags | ||
| 235 | (nth (backtrace-get-index) backtrace-frames)) | ||
| 236 | :source-available)) | ||
| 237 | :help "Show the source code for the current frame"] | ||
| 215 | ["Help for Symbol" backtrace-help-follow-symbol | 238 | ["Help for Symbol" backtrace-help-follow-symbol |
| 216 | :help "Show help for symbol at point"] | 239 | :help "Show help for symbol at point"] |
| 217 | ["Describe Backtrace Mode" describe-mode | 240 | ["Describe Backtrace Mode" describe-mode |
| @@ -219,6 +242,9 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 219 | map) | 242 | map) |
| 220 | "Local keymap for `backtrace-mode' buffers.") | 243 | "Local keymap for `backtrace-mode' buffers.") |
| 221 | 244 | ||
| 245 | (defconst backtrace--flags-width 2 | ||
| 246 | "Width in characters of the flags for a backtrace frame.") | ||
| 247 | |||
| 222 | ;;; Navigation and Text Properties | 248 | ;;; Navigation and Text Properties |
| 223 | 249 | ||
| 224 | ;; This mode uses the following text properties: | 250 | ;; This mode uses the following text properties: |
| @@ -580,6 +606,20 @@ content of the sexp." | |||
| 580 | '(backtrace-section backtrace-index backtrace-view | 606 | '(backtrace-section backtrace-index backtrace-view |
| 581 | backtrace-form)))) | 607 | backtrace-form)))) |
| 582 | 608 | ||
| 609 | (defun backtrace-goto-source () | ||
| 610 | "If its location is known, jump to the source code for the frame at point." | ||
| 611 | (interactive) | ||
| 612 | (let* ((index (or (backtrace-get-index) (user-error "Not in a stack frame"))) | ||
| 613 | (frame (nth index backtrace-frames)) | ||
| 614 | (source-available (plist-get (backtrace-frame-flags frame) | ||
| 615 | :source-available))) | ||
| 616 | (unless (and source-available | ||
| 617 | (catch 'done | ||
| 618 | (dolist (func backtrace-goto-source-functions) | ||
| 619 | (when (funcall func) | ||
| 620 | (throw 'done t))))) | ||
| 621 | (user-error "Source code location not known")))) | ||
| 622 | |||
| 583 | (defun backtrace-help-follow-symbol (&optional pos) | 623 | (defun backtrace-help-follow-symbol (&optional pos) |
| 584 | "Follow cross-reference at POS, defaulting to point. | 624 | "Follow cross-reference at POS, defaulting to point. |
| 585 | For the cross-reference format, see `help-make-xrefs'." | 625 | For the cross-reference format, see `help-make-xrefs'." |
| @@ -681,8 +721,12 @@ property for use by navigation." | |||
| 681 | (defun backtrace--print-flags (frame view) | 721 | (defun backtrace--print-flags (frame view) |
| 682 | "Print the flags of a backtrace FRAME if enabled in VIEW." | 722 | "Print the flags of a backtrace FRAME if enabled in VIEW." |
| 683 | (let ((beg (point)) | 723 | (let ((beg (point)) |
| 684 | (flag (plist-get (backtrace-frame-flags frame) :debug-on-exit))) | 724 | (flag (plist-get (backtrace-frame-flags frame) :debug-on-exit)) |
| 685 | (insert (if (and (plist-get view :show-flags) flag) "* " " ")) | 725 | (source (plist-get (backtrace-frame-flags frame) :source-available))) |
| 726 | (when (plist-get view :show-flags) | ||
| 727 | (when source (insert ">")) | ||
| 728 | (when flag (insert "*"))) | ||
| 729 | (insert (make-string (- backtrace--flags-width (- (point) beg)) ?\s)) | ||
| 686 | (put-text-property beg (point) 'backtrace-section 'func))) | 730 | (put-text-property beg (point) 'backtrace-section 'func))) |
| 687 | 731 | ||
| 688 | (defun backtrace--print-func-and-args (frame _view) | 732 | (defun backtrace--print-func-and-args (frame _view) |
| @@ -770,7 +814,7 @@ Fall back to `prin1' if there is an error." | |||
| 770 | (let ((props (backtrace-get-text-properties begin)) | 814 | (let ((props (backtrace-get-text-properties begin)) |
| 771 | (inhibit-read-only t) | 815 | (inhibit-read-only t) |
| 772 | (standard-output (current-buffer))) | 816 | (standard-output (current-buffer))) |
| 773 | (delete-char 2) | 817 | (delete-char backtrace--flags-width) |
| 774 | (backtrace--print-flags (nth (backtrace-get-index) backtrace-frames) | 818 | (backtrace--print-flags (nth (backtrace-get-index) backtrace-frames) |
| 775 | view) | 819 | view) |
| 776 | (add-text-properties begin (point) props)))))) | 820 | (add-text-properties begin (point) props)))))) |
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 3bf9cb9a488..fc295485fd4 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el | |||
| @@ -3692,7 +3692,7 @@ be installed in `emacs-lisp-mode-map'.") | |||
| 3692 | 3692 | ||
| 3693 | ;; misc | 3693 | ;; misc |
| 3694 | (define-key map "?" 'edebug-help) | 3694 | (define-key map "?" 'edebug-help) |
| 3695 | (define-key map "d" 'edebug-backtrace) | 3695 | (define-key map "d" 'edebug-pop-to-backtrace) |
| 3696 | 3696 | ||
| 3697 | (define-key map "-" 'negative-argument) | 3697 | (define-key map "-" 'negative-argument) |
| 3698 | 3698 | ||
| @@ -3985,6 +3985,13 @@ Otherwise call `debug' normally." | |||
| 3985 | 3985 | ||
| 3986 | ;;; Backtrace buffer | 3986 | ;;; Backtrace buffer |
| 3987 | 3987 | ||
| 3988 | (defvar-local edebug-backtrace-frames nil | ||
| 3989 | "Stack frames of the current Edebug Backtrace buffer without instrumentation. | ||
| 3990 | This should be a list of `edebug---frame' objects.") | ||
| 3991 | (defvar-local edebug-instrumented-backtrace-frames nil | ||
| 3992 | "Stack frames of the current Edebug Backtrace buffer with instrumentation. | ||
| 3993 | This should be a list of `edebug---frame' objects.") | ||
| 3994 | |||
| 3988 | ;; Data structure for backtrace frames with information | 3995 | ;; Data structure for backtrace frames with information |
| 3989 | ;; from Edebug instrumentation found in the backtrace. | 3996 | ;; from Edebug instrumentation found in the backtrace. |
| 3990 | (cl-defstruct | 3997 | (cl-defstruct |
| @@ -3993,7 +4000,7 @@ Otherwise call `debug' normally." | |||
| 3993 | (:include backtrace-frame)) | 4000 | (:include backtrace-frame)) |
| 3994 | def-name before-index after-index) | 4001 | def-name before-index after-index) |
| 3995 | 4002 | ||
| 3996 | (defun edebug-backtrace () | 4003 | (defun edebug-pop-to-backtrace () |
| 3997 | "Display the current backtrace in a `backtrace-mode' window." | 4004 | "Display the current backtrace in a `backtrace-mode' window." |
| 3998 | (interactive) | 4005 | (interactive) |
| 3999 | (if (or (not edebug-backtrace-buffer) | 4006 | (if (or (not edebug-backtrace-buffer) |
| @@ -4002,31 +4009,33 @@ Otherwise call `debug' normally." | |||
| 4002 | (generate-new-buffer "*Edebug Backtrace*")) | 4009 | (generate-new-buffer "*Edebug Backtrace*")) |
| 4003 | ;; Else, could just display edebug-backtrace-buffer. | 4010 | ;; Else, could just display edebug-backtrace-buffer. |
| 4004 | ) | 4011 | ) |
| 4005 | (with-output-to-temp-buffer (buffer-name edebug-backtrace-buffer) | 4012 | (pop-to-buffer edebug-backtrace-buffer) |
| 4006 | (setq edebug-backtrace-buffer standard-output) | 4013 | (unless (derived-mode-p 'backtrace-mode) |
| 4007 | (with-current-buffer edebug-backtrace-buffer | 4014 | (backtrace-mode) |
| 4008 | (unless (derived-mode-p 'backtrace-mode) | 4015 | (add-hook 'backtrace-goto-source-functions 'edebug--backtrace-goto-source)) |
| 4009 | (backtrace-mode)) | 4016 | (setq edebug-instrumented-backtrace-frames |
| 4010 | (setq backtrace-frames (edebug--backtrace-frames)) | 4017 | (backtrace-get-frames 'edebug-debugger |
| 4011 | (backtrace-print) | 4018 | :constructor #'edebug--make-frame) |
| 4012 | (goto-char (point-min))))) | 4019 | edebug-backtrace-frames (edebug--strip-instrumentation |
| 4013 | 4020 | edebug-instrumented-backtrace-frames) | |
| 4014 | (defun edebug--backtrace-frames () | 4021 | backtrace-frames edebug-backtrace-frames) |
| 4015 | "Return backtrace frames with instrumentation removed. | 4022 | (backtrace-print) |
| 4023 | (goto-char (point-min))) | ||
| 4024 | |||
| 4025 | (defun edebug--strip-instrumentation (frames) | ||
| 4026 | "Return a new list of backtrace frames with instrumentation removed. | ||
| 4016 | Remove frames for Edebug's functions and the lambdas in | 4027 | Remove frames for Edebug's functions and the lambdas in |
| 4017 | `edebug-enter' wrappers." | 4028 | `edebug-enter' wrappers. Fill in the def-name, before-index |
| 4018 | (let* ((frames (backtrace-get-frames 'edebug-debugger | 4029 | and after-index fields in both FRAMES and the returned list |
| 4019 | :constructor #'edebug--make-frame)) | 4030 | of deinstrumented frames, for those frames where the source |
| 4020 | skip-next-lambda def-name before-index after-index | 4031 | code location is known." |
| 4021 | results | 4032 | (let (skip-next-lambda def-name before-index after-index results |
| 4022 | (index (length frames))) | 4033 | (index (length frames))) |
| 4023 | (dolist (frame (reverse frames)) | 4034 | (dolist (frame (reverse frames)) |
| 4024 | (let ((fun (edebug--frame-fun frame)) | 4035 | (let ((new-frame (copy-edebug--frame frame)) |
| 4036 | (fun (edebug--frame-fun frame)) | ||
| 4025 | (args (edebug--frame-args frame))) | 4037 | (args (edebug--frame-args frame))) |
| 4026 | (cl-decf index) | 4038 | (cl-decf index) |
| 4027 | (when (edebug--frame-evald frame) | ||
| 4028 | (setq before-index nil | ||
| 4029 | after-index nil)) | ||
| 4030 | (pcase fun | 4039 | (pcase fun |
| 4031 | ('edebug-enter | 4040 | ('edebug-enter |
| 4032 | (setq skip-next-lambda t | 4041 | (setq skip-next-lambda t |
| @@ -4037,17 +4046,18 @@ Remove frames for Edebug's functions and the lambdas in | |||
| 4037 | (nth 0 args)) | 4046 | (nth 0 args)) |
| 4038 | after-index (nth 1 args))) | 4047 | after-index (nth 1 args))) |
| 4039 | ((pred edebug--symbol-not-prefixed-p) | 4048 | ((pred edebug--symbol-not-prefixed-p) |
| 4040 | (edebug--unwrap-and-add-info frame def-name before-index after-index) | 4049 | (edebug--unwrap-frame new-frame) |
| 4041 | (setf (edebug--frame-def-name frame) (and before-index def-name)) | 4050 | (edebug--add-source-info new-frame def-name before-index after-index) |
| 4042 | (setf (edebug--frame-before-index frame) before-index) | 4051 | (edebug--add-source-info frame def-name before-index after-index) |
| 4043 | (setf (edebug--frame-after-index frame) after-index) | 4052 | (push new-frame results) |
| 4044 | (push frame results) | ||
| 4045 | (setq before-index nil | 4053 | (setq before-index nil |
| 4046 | after-index nil)) | 4054 | after-index nil)) |
| 4047 | (`(,(or 'lambda 'closure) . ,_) | 4055 | (`(,(or 'lambda 'closure) . ,_) |
| 4048 | (unless skip-next-lambda | 4056 | (unless skip-next-lambda |
| 4049 | (edebug--unwrap-and-add-info frame def-name before-index after-index) | 4057 | (edebug--unwrap-frame new-frame) |
| 4050 | (push frame results)) | 4058 | (edebug--add-source-info frame def-name before-index after-index) |
| 4059 | (edebug--add-source-info new-frame def-name before-index after-index) | ||
| 4060 | (push new-frame results)) | ||
| 4051 | (setq before-index nil | 4061 | (setq before-index nil |
| 4052 | after-index nil | 4062 | after-index nil |
| 4053 | skip-next-lambda nil))))) | 4063 | skip-next-lambda nil))))) |
| @@ -4058,14 +4068,9 @@ Remove frames for Edebug's functions and the lambdas in | |||
| 4058 | (and (symbolp sym) | 4068 | (and (symbolp sym) |
| 4059 | (not (string-prefix-p "edebug-" (symbol-name sym))))) | 4069 | (not (string-prefix-p "edebug-" (symbol-name sym))))) |
| 4060 | 4070 | ||
| 4061 | (defun edebug--unwrap-and-add-info (frame def-name before-index after-index) | 4071 | (defun edebug--unwrap-frame (frame) |
| 4062 | "Update FRAME with the additional info needed by an edebug--frame. | 4072 | "Remove Edebug's instrumentation from FRAME. |
| 4063 | Save DEF-NAME, BEFORE-INDEX and AFTER-INDEX in FRAME. Also | 4073 | Strip it from the function and any unevaluated arguments." |
| 4064 | remove Edebug's instrumentation from the function and any | ||
| 4065 | unevaluated arguments in FRAME." | ||
| 4066 | (setf (edebug--frame-def-name frame) (and before-index def-name)) | ||
| 4067 | (setf (edebug--frame-before-index frame) before-index) | ||
| 4068 | (setf (edebug--frame-after-index frame) after-index) | ||
| 4069 | (setf (edebug--frame-fun frame) (edebug-unwrap* (edebug--frame-fun frame))) | 4074 | (setf (edebug--frame-fun frame) (edebug-unwrap* (edebug--frame-fun frame))) |
| 4070 | (unless (edebug--frame-evald frame) | 4075 | (unless (edebug--frame-evald frame) |
| 4071 | (let (results) | 4076 | (let (results) |
| @@ -4073,6 +4078,41 @@ unevaluated arguments in FRAME." | |||
| 4073 | (push (edebug-unwrap* arg) results)) | 4078 | (push (edebug-unwrap* arg) results)) |
| 4074 | (setf (edebug--frame-args frame) (nreverse results))))) | 4079 | (setf (edebug--frame-args frame) (nreverse results))))) |
| 4075 | 4080 | ||
| 4081 | (defun edebug--add-source-info (frame def-name before-index after-index) | ||
| 4082 | "Update FRAME with the additional info needed by an edebug--frame. | ||
| 4083 | Save DEF-NAME, BEFORE-INDEX and AFTER-INDEX in FRAME." | ||
| 4084 | (when (and before-index def-name) | ||
| 4085 | (setf (edebug--frame-flags frame) | ||
| 4086 | (plist-put (copy-sequence (edebug--frame-flags frame)) | ||
| 4087 | :source-available t))) | ||
| 4088 | (setf (edebug--frame-def-name frame) (and before-index def-name)) | ||
| 4089 | (setf (edebug--frame-before-index frame) before-index) | ||
| 4090 | (setf (edebug--frame-after-index frame) after-index)) | ||
| 4091 | |||
| 4092 | (defun edebug--backtrace-goto-source () | ||
| 4093 | (let* ((index (backtrace-get-index)) | ||
| 4094 | (frame (nth index backtrace-frames))) | ||
| 4095 | (when (edebug--frame-def-name frame) | ||
| 4096 | (let* ((data (get (edebug--frame-def-name frame) 'edebug)) | ||
| 4097 | (marker (nth 0 data)) | ||
| 4098 | (offsets (nth 2 data))) | ||
| 4099 | (pop-to-buffer (marker-buffer marker)) | ||
| 4100 | (goto-char (+ (marker-position marker) | ||
| 4101 | (aref offsets (edebug--frame-before-index frame)))))))) | ||
| 4102 | |||
| 4103 | (defun edebug-backtrace-show-instrumentation () | ||
| 4104 | "Show Edebug's instrumentation in an Edebug Backtrace buffer." | ||
| 4105 | (interactive) | ||
| 4106 | (unless (eq backtrace-frames edebug-instrumented-backtrace-frames) | ||
| 4107 | (setq backtrace-frames edebug-instrumented-backtrace-frames) | ||
| 4108 | (revert-buffer))) | ||
| 4109 | |||
| 4110 | (defun edebug-backtrace-hide-instrumentation () | ||
| 4111 | "Show Edebug's instrumentation in an Edebug Backtrace buffer." | ||
| 4112 | (interactive) | ||
| 4113 | (unless (eq backtrace-frames edebug-backtrace-frames) | ||
| 4114 | (setq backtrace-frames edebug-backtrace-frames) | ||
| 4115 | (revert-buffer))) | ||
| 4076 | 4116 | ||
| 4077 | ;;; Trace display | 4117 | ;;; Trace display |
| 4078 | 4118 | ||
| @@ -4246,7 +4286,7 @@ It is removed when you hit any char." | |||
| 4246 | ["Bounce to Current Point" edebug-bounce-point t] | 4286 | ["Bounce to Current Point" edebug-bounce-point t] |
| 4247 | ["View Outside Windows" edebug-view-outside t] | 4287 | ["View Outside Windows" edebug-view-outside t] |
| 4248 | ["Previous Result" edebug-previous-result t] | 4288 | ["Previous Result" edebug-previous-result t] |
| 4249 | ["Show Backtrace" edebug-backtrace t] | 4289 | ["Show Backtrace" edebug-pop-to-backtrace t] |
| 4250 | ["Display Freq Count" edebug-display-freq-count t]) | 4290 | ["Display Freq Count" edebug-display-freq-count t]) |
| 4251 | 4291 | ||
| 4252 | ("Eval" | 4292 | ("Eval" |
diff --git a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el index f3fc78d4e12..97dead057a9 100644 --- a/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el +++ b/test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | (defun edebug-test-code-range (num) | 41 | (defun edebug-test-code-range (num) |
| 42 | !start!(let ((index 0) | 42 | !start!(let ((index 0) |
| 43 | (result nil)) | 43 | (result nil)) |
| 44 | (while (< index num)!test! | 44 | (while !lt!(< index num)!test! |
| 45 | (push index result)!loop! | 45 | (push index result)!loop! |
| 46 | (cl-incf index))!end-loop! | 46 | (cl-incf index))!end-loop! |
| 47 | (nreverse result))) | 47 | (nreverse result))) |
diff --git a/test/lisp/emacs-lisp/edebug-tests.el b/test/lisp/emacs-lisp/edebug-tests.el index 7d780edf285..7880aaf95bc 100644 --- a/test/lisp/emacs-lisp/edebug-tests.el +++ b/test/lisp/emacs-lisp/edebug-tests.el | |||
| @@ -432,9 +432,11 @@ test and possibly others should be updated." | |||
| 432 | (verify-keybinding "P" 'edebug-view-outside) ;; same as v | 432 | (verify-keybinding "P" 'edebug-view-outside) ;; same as v |
| 433 | (verify-keybinding "W" 'edebug-toggle-save-windows) | 433 | (verify-keybinding "W" 'edebug-toggle-save-windows) |
| 434 | (verify-keybinding "?" 'edebug-help) | 434 | (verify-keybinding "?" 'edebug-help) |
| 435 | (verify-keybinding "d" 'edebug-backtrace) | 435 | (verify-keybinding "d" 'edebug-pop-to-backtrace) |
| 436 | (verify-keybinding "-" 'negative-argument) | 436 | (verify-keybinding "-" 'negative-argument) |
| 437 | (verify-keybinding "=" 'edebug-temp-display-freq-count))) | 437 | (verify-keybinding "=" 'edebug-temp-display-freq-count) |
| 438 | (should (eq (lookup-key backtrace-mode-map "n") 'backtrace-forward-frame)) | ||
| 439 | (should (eq (lookup-key backtrace-mode-map "s") 'backtrace-goto-source)))) | ||
| 438 | 440 | ||
| 439 | (ert-deftest edebug-tests-stop-point-at-start-of-first-instrumented-function () | 441 | (ert-deftest edebug-tests-stop-point-at-start-of-first-instrumented-function () |
| 440 | "Edebug stops at the beginning of an instrumented function." | 442 | "Edebug stops at the beginning of an instrumented function." |
| @@ -924,5 +926,17 @@ test and possibly others should be updated." | |||
| 924 | "g" | 926 | "g" |
| 925 | (should (equal edebug-tests-@-result "The result of applying + to (1 x) is 11"))))) | 927 | (should (equal edebug-tests-@-result "The result of applying + to (1 x) is 11"))))) |
| 926 | 928 | ||
| 929 | (ert-deftest edebug-tests-backtrace-goto-source () | ||
| 930 | "Edebug can jump to instrumented source from its *Edebug-Backtrace* buffer." | ||
| 931 | (edebug-tests-with-normal-env | ||
| 932 | (edebug-tests-setup-@ "range" '(2) t) | ||
| 933 | (edebug-tests-run-kbd-macro | ||
| 934 | "@ SPC SPC" | ||
| 935 | (edebug-tests-should-be-at "range" "lt") | ||
| 936 | "dns" ; Pop to backtrace, next frame, goto source. | ||
| 937 | (edebug-tests-should-be-at "range" "start") | ||
| 938 | "g" | ||
| 939 | (should (equal edebug-tests-@-result '(0 1)))))) | ||
| 940 | |||
| 927 | (provide 'edebug-tests) | 941 | (provide 'edebug-tests) |
| 928 | ;;; edebug-tests.el ends here | 942 | ;;; edebug-tests.el ends here |