;;; edebug.el --- a source-level debugger for Emacs Lisp
-;; Copyright (C) 1988,89,90,91,92,93,94,95,97,1999,2000,01,03,2004
-;; Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1997, 1999,
+;; 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@holonexus.org>
;; Maintainer: FSF
;;; Form spec utilities.
-;;;###autoload
-(defmacro def-edebug-spec (symbol spec)
- "Set the `edebug-form-spec' property of SYMBOL according to SPEC.
-Both SYMBOL and SPEC are unevaluated. The SPEC can be 0, t, a symbol
-\(naming a function), or a list."
- `(put (quote ,symbol) 'edebug-form-spec (quote ,spec)))
-
(defmacro def-edebug-form-spec (symbol spec-form)
"For compatibility with old version."
(def-edebug-spec symbol (eval spec-form)))
edebug-form-spec
))
+;;;###autoload
+(defun edebug-basic-spec (spec)
+ "Return t if SPEC uses only extant spec symbols.
+An extant spec symbol is a symbol that is not a function and has a
+`edebug-form-spec' property."
+ (cond ((listp spec)
+ (catch 'basic
+ (while spec
+ (unless (edebug-basic-spec (car spec)) (throw 'basic nil))
+ (setq spec (cdr spec)))
+ t))
+ ((symbolp spec)
+ (unless (functionp spec) (get spec 'edebug-form-spec)))))
+
;;; Utilities
;; Define edebug-gensym - from old cl.el
;; Compatibility with old versions.
(defalias 'edebug-all-defuns 'edebug-all-defs)
+;;;###autoload
(defun edebug-all-defs ()
"Toggle edebugging of all definitions."
(interactive)
(if edebug-all-defs "on" "off")))
+;;;###autoload
(defun edebug-all-forms ()
"Toggle edebugging of all forms."
(interactive)
;; Leave point before the next token, skipping white space and comments.
(skip-chars-forward " \t\r\n\f")
(while (= (following-char) ?\;)
- ;; \r is counted as a comment terminator to support selective display.
- (skip-chars-forward "^\n\r") ; skip the comment
+ (skip-chars-forward "^\n") ; skip the comment
(skip-chars-forward " \t\r\n\f")))
(defvar edebug-outside-o-a-p) ; outside overlay-arrow-position
(defvar edebug-outside-o-a-s) ; outside overlay-arrow-string
(defvar edebug-outside-c-i-e-a) ; outside cursor-in-echo-area
+(defvar edebug-outside-d-c-i-n-s-w) ; outside default-cursor-in-non-selected-windows
(defvar edebug-eval-list nil) ;; List of expressions to evaluate.
(edebug-outside-buffer (current-buffer))
(edebug-outside-point (point))
(edebug-outside-mark (edebug-mark))
+ (edebug-outside-unread-command-events unread-command-events)
edebug-outside-windows ; window or screen configuration
edebug-buffer-points
(edebug-outside-o-a-p overlay-arrow-position)
(edebug-outside-o-a-s overlay-arrow-string)
- (edebug-outside-c-i-e-a cursor-in-echo-area))
+ (edebug-outside-c-i-e-a cursor-in-echo-area)
+ (edebug-outside-d-c-i-n-s-w default-cursor-in-non-selected-windows))
(unwind-protect
(let ((overlay-arrow-position overlay-arrow-position)
(overlay-arrow-string overlay-arrow-string)
(cursor-in-echo-area nil)
+ (default-cursor-in-non-selected-windows t)
+ (unread-command-events unread-command-events)
;; any others??
)
(if (not (buffer-name edebug-buffer))
(t (message "")))
+ (setq unread-command-events nil)
(if (eq 'after edebug-arg-mode)
(progn
;; Display result of previous evaluation.
(if (and edebug-break
(not (eq edebug-execution-mode 'Continue-fast)))
- (sit-for 1)) ; Show break message.
+ (edebug-sit-for edebug-sit-for-seconds)) ; Show message.
(edebug-previous-result)))
(cond
(edebug-break
(cond
- ((eq edebug-execution-mode 'continue) (edebug-sit-for 1))
+ ((eq edebug-execution-mode 'continue)
+ (edebug-sit-for edebug-sit-for-seconds))
((eq edebug-execution-mode 'Continue-fast) (edebug-sit-for 0))
(t (setq edebug-stop t))))
;; not edebug-break
((eq edebug-execution-mode 'trace)
(edebug-sit-for edebug-sit-for-seconds)) ; Force update and pause.
((eq edebug-execution-mode 'Trace-fast)
- (edebug-sit-for 0)) ; Force update and continue.
- )
+ (edebug-sit-for 0))) ; Force update and continue.
(unwind-protect
(if (or edebug-stop
) ; if edebug-save-windows
;; Restore current buffer always, in case application needs it.
- (set-buffer edebug-outside-buffer)
+ (if (buffer-name edebug-outside-buffer)
+ (set-buffer edebug-outside-buffer))
;; Restore point, and mark.
;; Needed even if restoring windows because
;; that doesn't restore point and mark in the current buffer.
(with-timeout-unsuspend edebug-with-timeout-suspend)
;; Reset global variables to outside values in case they were changed.
(setq
+ unread-command-events edebug-outside-unread-command-events
overlay-arrow-position edebug-outside-o-a-p
overlay-arrow-string edebug-outside-o-a-s
- cursor-in-echo-area edebug-outside-c-i-e-a)
+ cursor-in-echo-area edebug-outside-c-i-e-a
+ default-cursor-in-non-selected-windows edebug-outside-d-c-i-n-s-w)
)))
(edebug-outside-last-input-event last-input-event)
(edebug-outside-last-command-event last-command-event)
- (edebug-outside-unread-command-events unread-command-events)
(edebug-outside-last-event-frame last-event-frame)
(edebug-outside-last-nonmenu-event last-nonmenu-event)
(edebug-outside-track-mouse track-mouse)
;; More for Emacs 19
(last-input-event nil)
(last-command-event nil)
- (unread-command-events nil)
(last-event-frame nil)
(last-nonmenu-event nil)
(track-mouse nil)
(edebug-overlay-arrow))
(setq buffer-read-only edebug-buffer-read-only)
(use-local-map edebug-outside-map)
+ (remove-hook 'kill-buffer-hook 'edebug-kill-buffer t)
)
;; gotta have a buffer to let its buffer local variables be set
(get-buffer-create " bogus edebug buffer"))
last-command edebug-outside-last-command
this-command edebug-outside-this-command
unread-command-char edebug-outside-unread-command-char
- unread-command-events edebug-outside-unread-command-events
current-prefix-arg edebug-outside-current-prefix-arg
last-input-char edebug-outside-last-input-char
last-input-event edebug-outside-last-input-event
func)
(t
(let ((loc (find-function-noselect func)))
+ (unless (cdr loc)
+ (error "Could not find the definition in its file"))
(with-current-buffer (car loc)
(goto-char (cdr loc))
(edebug-eval-top-level-form)
(overlay-arrow-position edebug-outside-o-a-p)
(overlay-arrow-string edebug-outside-o-a-s)
(cursor-in-echo-area edebug-outside-c-i-e-a)
+ (default-cursor-in-non-selected-windows edebug-outside-d-c-i-n-s-w)
)
(unwind-protect
(save-excursion ; of edebug-buffer
edebug-outside-o-a-p overlay-arrow-position
edebug-outside-o-a-s overlay-arrow-string
edebug-outside-c-i-e-a cursor-in-echo-area
+ edebug-outside-d-c-i-n-s-w default-cursor-in-non-selected-windows
)
;; Restore the outside saved values; don't alter
(print-level (or edebug-print-level print-level))
(print-circle (or edebug-print-circle print-circle))
(print-readably nil)) ;; lemacs uses this.
- (edebug-prin1-to-string value)))
+ (condition-case nil
+ (edebug-prin1-to-string value)
+ (error "#Apparently circular structure#"))))
(defun edebug-compute-previous-result (edebug-previous-value)
(if edebug-unwrap-results
specific commands. E.g. `edebug-step-mode' is bound to \\[edebug-step-mode]
in the Edebug buffer and \\<global-map>\\[edebug-step-mode] in any buffer.
-Also see bindings for the eval list buffer, *edebug*.
+Also see bindings for the eval list buffer *edebug* in `edebug-eval-mode'.
The edebug buffer commands:
\\{edebug-mode-map}
edebug-unwrap-results
edebug-global-break-condition
"
+ ;; If the user kills the buffer in which edebug is currently active,
+ ;; exit to top level, because the edebug command loop can't usefully
+ ;; continue running in such a case.
+ (add-hook 'kill-buffer-hook 'edebug-kill-buffer nil t)
(use-local-map edebug-mode-map))
+(defun edebug-kill-buffer ()
+ "Used on `kill-buffer-hook' when Edebug is operating in a buffer of Lisp code."
+ (let (kill-buffer-hook)
+ (kill-buffer (current-buffer)))
+ (top-level))
+
;;; edebug eval list mode
;; A list of expressions and their evaluations is displayed in *edebug*.
Eval list buffer commands:
\\{edebug-eval-mode-map}
-Global commands prefixed by global-edebug-prefix:
+Global commands prefixed by `global-edebug-prefix':
\\{global-edebug-map}")
;;; Interface with standard debugger.