]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/edebug.el
Add new function dom-remove-node
[gnu-emacs] / lisp / emacs-lisp / edebug.el
index 7faa101299e4dfd138ddcc713e6cd8d611bb8533..c283c168b5e18f39e90f317b029735c88c655ea1 100644 (file)
@@ -1,6 +1,6 @@
 ;;; edebug.el --- a source-level debugger for Emacs Lisp  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1988-1995, 1997, 1999-2015 Free Software Foundation,
+;; Copyright (C) 1988-1995, 1997, 1999-2016 Free Software Foundation,
 ;; Inc.
 
 ;; Author: Daniel LaLiberte <liberte@holonexus.org>
@@ -85,7 +85,7 @@ This applies to `eval-defun', `eval-region', `eval-buffer', and
 
 You can use the command `edebug-all-defs' to toggle the value of this
 variable.  You may wish to make it local to each buffer with
-\(make-local-variable 'edebug-all-defs) in your
+\(make-local-variable \\='edebug-all-defs) in your
 `emacs-lisp-mode-hook'."
   :type 'boolean
   :group 'edebug)
@@ -225,6 +225,7 @@ After execution is resumed, the error is signaled again."
   "If non-nil, an expression to test for at every stop point.
 If the result is non-nil, then break.  Errors are ignored."
   :type 'sexp
+  :risky t
   :group 'edebug)
 
 (defcustom edebug-sit-for-seconds 1
@@ -232,6 +233,12 @@ If the result is non-nil, then break.  Errors are ignored."
   :type 'number
   :group 'edebug)
 
+(defcustom edebug-sit-on-break t
+  "Whether or not to pause for `edebug-sit-for-seconds' on reaching a break."
+  :type 'boolean
+  :group 'edebug
+  :version "25.2")
+
 ;;; Form spec utilities.
 
 (defun get-edebug-spec (symbol)
@@ -561,7 +568,7 @@ already is one.)"
 (defun edebug-install-read-eval-functions ()
   (interactive)
   (add-function :around load-read-function #'edebug--read)
-  (advice-add 'eval-defun :override 'edebug-eval-defun))
+  (advice-add 'eval-defun :override #'edebug-eval-defun))
 
 (defun edebug-uninstall-read-eval-functions ()
   (interactive)
@@ -600,7 +607,7 @@ list of a symbol.")
 (defun edebug-get-form-data-entry (pnt &optional end-point)
   ;; Find the edebug form data entry which is closest to PNT.
   ;; If END-POINT is supplied, match must be exact.
-  ;; Return `nil' if none found.
+  ;; Return nil if none found.
   (let ((rest edebug-form-data)
        closest-entry
        (closest-dist 999999))  ;; Need maxint here.
@@ -1725,6 +1732,17 @@ expressions; a `progn' form will be returned enclosing these forms."
           (t
            (error "Bad spec: %s" specs)))))
 
+       ((eq 'vector spec)
+       (if (vectorp form)
+           ;; Special case: match a vector with the specs.
+           (let ((result (edebug-match-sublist
+                          (edebug-new-cursor
+                           form (cdr (edebug-top-offset cursor)))
+                          (cdr specs))))
+             (edebug-move-cursor cursor)
+             (list (apply 'vector result)))
+         (edebug-no-match cursor "Expected" specs)))
+
        ((listp form)
        (prog1
            (list (edebug-match-sublist
@@ -1734,15 +1752,6 @@ expressions; a `progn' form will be returned enclosing these forms."
                   specs))
          (edebug-move-cursor cursor)))
 
-       ((and (eq 'vector spec) (vectorp form))
-       ;; Special case: match a vector with the specs.
-       (let ((result (edebug-match-sublist
-                      (edebug-new-cursor
-                       form (cdr (edebug-top-offset cursor)))
-                      (cdr specs))))
-         (edebug-move-cursor cursor)
-         (list (apply 'vector result))))
-
        (t (edebug-no-match cursor "Expected" specs)))
       )))
 
@@ -1869,8 +1878,13 @@ expressions; a `progn' form will be returned enclosing these forms."
   ;; Like body but body is wrapped in edebug-enter form.
   ;; The body is assumed to be executing inside of the function context.
   ;; Not to be used otherwise.
-  (let ((edebug-inside-func t))
-    (list (edebug-wrap-def-body (edebug-forms cursor)))))
+  (let* ((edebug-inside-func t)
+         (forms (edebug-forms cursor)))
+    ;; If there's no form, there's nothing to wrap!
+    ;; This happens to handle bug#20281, tho maybe a better fix would be to
+    ;; improve the `defun' spec.
+    (when forms
+      (list (edebug-wrap-def-body forms)))))
 
 
 ;;;; Edebug Form Specs
@@ -2358,6 +2372,12 @@ MSG is printed after `::::} '."
 (defalias 'edebug-mark-marker 'mark-marker)
 
 (defun edebug--display (value offset-index arg-mode)
+  ;; edebug--display-1 is too big, we should split it.  This function
+  ;; here was just introduced to avoid making edebug--display-1
+  ;; yet a bit deeper.
+  (save-excursion (edebug--display-1 value offset-index arg-mode)))
+
+(defun edebug--display-1 (value offset-index arg-mode)
   (unless (marker-position edebug-def-mark)
     ;; The buffer holding the source has been killed.
     ;; Let's at least show a backtrace so the user can figure out
@@ -2440,18 +2460,6 @@ MSG is printed after `::::} '."
                               edebug-function)
                 ))
 
-         (setcdr edebug-window-data
-                 (edebug-adjust-window (cdr edebug-window-data)))
-
-         ;; Test if there is input, not including keyboard macros.
-         (if (input-pending-p)
-             (progn
-               (setq edebug-execution-mode 'step
-                     edebug-stop t)
-               (edebug-stop)
-               ;;          (discard-input)             ; is this unfriendly??
-               ))
-
           ;; Make sure we bind those in the right buffer (bug#16410).
           (let ((overlay-arrow-position overlay-arrow-position)
                 (overlay-arrow-string overlay-arrow-string))
@@ -2487,6 +2495,7 @@ MSG is printed after `::::} '."
                 (progn
                   ;; Display result of previous evaluation.
                   (if (and edebug-break
+                           edebug-sit-on-break
                            (not (eq edebug-execution-mode 'Continue-fast)))
                       (sit-for edebug-sit-for-seconds)) ; Show message.
                   (edebug-previous-result)))
@@ -2504,14 +2513,18 @@ MSG is printed after `::::} '."
              ((eq edebug-execution-mode 'Trace-fast)
               (sit-for 0)))            ; Force update and continue.
 
+            (when (input-pending-p)
+             (setq edebug-stop t)
+             (setq edebug-execution-mode 'step) ; for `edebug-overlay-arrow'
+             (edebug-stop))
+
+           (edebug-overlay-arrow)
+
             (unwind-protect
                 (if (or edebug-stop
                         (memq edebug-execution-mode '(step next))
                         (eq arg-mode 'error))
-                    (progn
-                      ;; (setq edebug-execution-mode 'step)
-                      ;; (edebug-overlay-arrow)        ; This doesn't always show up.
-                      (edebug--recursive-edit arg-mode))) ; <--- Recursive edit
+                   (edebug--recursive-edit arg-mode)) ; <--- Recursive edit
 
               ;; Reset the edebug-window-data to whatever it is now.
               (let ((window (if (eq (window-buffer) edebug-buffer)
@@ -2671,12 +2684,6 @@ MSG is printed after `::::} '."
              (defining-kbd-macro
                (if edebug-continue-kbd-macro defining-kbd-macro))
 
-             ;; Disable command hooks.  This is essential when
-             ;; a hook function is instrumented - to avoid infinite loop.
-             ;; This may be more than we need, however.
-             (pre-command-hook nil)
-             (post-command-hook nil)
-
              ;; others??
              )
 
@@ -2705,8 +2712,9 @@ MSG is printed after `::::} '."
            (if (buffer-name edebug-buffer) ; if it still exists
                (progn
                  (set-buffer edebug-buffer)
-                 (if (memq edebug-execution-mode '(go Go-nonstop))
-                     (edebug-overlay-arrow))
+                 (when (memq edebug-execution-mode '(go Go-nonstop))
+                   (edebug-overlay-arrow)
+                   (sit-for 0))
                   (edebug-mode -1))
              ;; gotta have a buffer to let its buffer local variables be set
              (get-buffer-create " bogus edebug buffer"))
@@ -2716,31 +2724,6 @@ MSG is printed after `::::} '."
 
 ;;; Display related functions
 
-(defun edebug-adjust-window (old-start)
-  ;; If pos is not visible, adjust current window to fit following context.
-  ;; (message "window: %s old-start: %s window-start: %s pos: %s"
-  ;;          (selected-window) old-start (window-start) (point)) (sit-for 5)
-  (if (not (pos-visible-in-window-p))
-      (progn
-       ;; First try old-start
-       (if old-start
-           (set-window-start (selected-window) old-start))
-       (if (not (pos-visible-in-window-p))
-           (progn
-       ;; (message "resetting window start") (sit-for 2)
-       (set-window-start
-        (selected-window)
-        (save-excursion
-          (forward-line
-           (if (< (point) (window-start)) -1   ; one line before if in back
-             (- (/ (window-height) 2)) ; center the line moving forward
-             ))
-          (beginning-of-line)
-          (point)))))))
-  (window-start))
-
-
-
 (defconst edebug-arrow-alist
   '((Continue-fast . "=")
     (Trace-fast . "-")
@@ -2749,7 +2732,7 @@ MSG is printed after `::::} '."
     (step . "=>")
     (next . "=>")
     (go . "<>")
-    (Go-nonstop . "..")  ; not used
+    (Go-nonstop . "..")
     )
   "Association list of arrows for each edebug mode.")
 
@@ -3187,12 +3170,12 @@ Do this when stopped before the form or it will be too late.
 One side effect of using this command is that the next time the
 function or macro is called, Edebug will be called there as well."
   (interactive)
-  (if (not (looking-at "\("))
+  (if (not (looking-at "("))
       (error "You must be before a list form")
     (let ((func
           (save-excursion
             (down-list 1)
-            (if (looking-at "\(")
+            (if (looking-at "(")
                 (edebug--form-data-name
                  (edebug-get-form-data-entry (point)))
               (read (current-buffer))))))
@@ -3241,57 +3224,45 @@ This is useful for exiting even if `unwind-protect' code may be executed."
   (setq edebug-execution-mode 'Go-nonstop)
   (top-level))
 
-
 ;;(defun edebug-exit-out ()
 ;;  "Go until the current function exits."
 ;;  (interactive)
 ;;  (edebug-set-mode 'exiting "Exit..."))
 
-
-;;; The following initial mode setting definitions are not used yet.
-
-'(defconst edebug-initial-mode-alist
-  '((edebug-Continue-fast . Continue-fast)
-    (edebug-Trace-fast . Trace-fast)
-    (edebug-continue . continue)
-    (edebug-trace . trace)
-    (edebug-go . go)
-    (edebug-step-through . step)
-    (edebug-Go-nonstop . Go-nonstop)
-    )
+(defconst edebug-initial-mode-alist
+  '((edebug-step-mode . step)
+    (edebug-next-mode . next)
+    (edebug-trace-mode . trace)
+    (edebug-Trace-fast-mode . Trace-fast)
+    (edebug-go-mode . go)
+    (edebug-continue-mode . continue)
+    (edebug-Continue-fast-mode . Continue-fast)
+    (edebug-Go-nonstop-mode . Go-nonstop))
   "Association list between commands and the modes they set.")
 
+(defvar edebug-mode-map)               ; will be defined fully later.
 
-'(defun edebug-set-initial-mode ()
-  "Ask for the initial mode of the enclosing function.
+(defun edebug-set-initial-mode ()
+  "Set the initial execution mode of Edebug.
 The mode is requested via the key that would be used to set the mode in
 edebug-mode."
   (interactive)
-  (let* ((this-function (edebug-which-function))
-        (keymap (if (eq edebug-mode-map (current-local-map))
-                    edebug-mode-map))
-        (old-mode (or (get this-function 'edebug-initial-mode)
-                      edebug-initial-mode))
+  (let* ((old-mode edebug-initial-mode)
         (key (read-key-sequence
               (format
-               "Change initial edebug mode for %s from %s (%s) to (enter key): "
-                      this-function
-                      old-mode
-                      (where-is-internal
-                       (car (rassq old-mode edebug-initial-mode-alist))
-                       keymap 'firstonly
-                       ))))
-        (mode (cdr (assq (key-binding key) edebug-initial-mode-alist)))
-        )
-    (if (and mode
-            (or (get this-function 'edebug-initial-mode)
-                (not (eq mode edebug-initial-mode))))
+               "Change initial edebug mode from %s (%c) to (enter key): "
+               old-mode
+               (aref (where-is-internal
+                      (car (rassq old-mode edebug-initial-mode-alist))
+                      edebug-mode-map 'firstonly)
+                     0))))
+        (mode (cdr (assq (lookup-key edebug-mode-map key)
+                         edebug-initial-mode-alist))))
+    (if mode
        (progn
-         (put this-function 'edebug-initial-mode mode)
-         (message "Initial mode for %s is now: %s"
-                  this-function mode))
-      (error "Key must map to one of the mode changing commands")
-      )))
+         (setq edebug-initial-mode mode)
+         (message "Edebug's initial mode is now: %s" mode))
+      (error "Key must map to one of the mode changing commands"))))
 
 ;;; Evaluation of expressions
 
@@ -3317,6 +3288,9 @@ Return the result of the last expression."
      ;; Restore outside context.
      (setq-default cursor-in-non-selected-windows edebug-outside-d-c-i-n-s-w)
      (unwind-protect
+         ;; FIXME: This restoring of edebug-outside-buffer and
+         ;; edebug-outside-point is redundant now that backtrace-eval does it
+         ;; for us.
          (with-current-buffer edebug-outside-buffer ; of edebug-buffer
            (goto-char edebug-outside-point)
            (if (marker-buffer (edebug-mark-marker))
@@ -3395,7 +3369,7 @@ Return the result of the last expression."
 (defalias 'edebug-prin1 'prin1)
 (defalias 'edebug-print 'print)
 (defalias 'edebug-prin1-to-string 'prin1-to-string)
-(defalias 'edebug-format 'format)
+(defalias 'edebug-format 'format-message)
 (defalias 'edebug-message 'message)
 
 (defun edebug-eval-expression (expr)
@@ -3447,7 +3421,9 @@ be installed in `emacs-lisp-mode-map'.")
   (define-key emacs-lisp-mode-map "\C-x\C-a\C-s" 'edebug-step-mode)
   (define-key emacs-lisp-mode-map "\C-x\C-a\C-n" 'edebug-next-mode)
   (define-key emacs-lisp-mode-map "\C-x\C-a\C-c" 'edebug-go-mode)
-  (define-key emacs-lisp-mode-map "\C-x\C-a\C-l" 'edebug-where))
+  (define-key emacs-lisp-mode-map "\C-x\C-a\C-l" 'edebug-where)
+  ;; The following isn't a GUD binding.
+  (define-key emacs-lisp-mode-map "\C-x\C-a\C-m" 'edebug-set-initial-mode))
 
 (defvar edebug-mode-map
   (let ((map (copy-keymap emacs-lisp-mode-map)))
@@ -3812,10 +3788,10 @@ Otherwise call `debug' normally."
       (if t (progn
 
       ;; Delete interspersed edebug internals.
-      (while (re-search-forward "^  \(?edebug" nil t)
+      (while (re-search-forward "^  (?edebug" nil t)
        (beginning-of-line)
        (cond
-        ((looking-at "^  \(edebug-after")
+        ((looking-at "^  (edebug-after")
          ;; Previous lines may contain code, so just delete this line.
          (setq last-ok-point (point))
          (forward-line 1)