;;; edebug.el --- a source-level debugger for Emacs Lisp
-;; Copyright (C) 1988, 89, 90, 91, 92, 93, 94, 95, 97, 1999, 2000, 01, 2003
+;; Copyright (C) 1988,89,90,91,92,93,94,95,97,1999,2000,01,03,2004
;; Free Software Foundation, Inc.
;; Author: Daniel LaLiberte <liberte@holonexus.org>
;;;###autoload
(defcustom edebug-all-defs nil
- "*If non-nil, evaluation of any defining forms will instrument for Edebug.
+ "*If non-nil, evaluating defining forms instruments for Edebug.
This applies to `eval-defun', `eval-region', `eval-buffer', and
`eval-current-buffer'. `eval-region' is also called by
`eval-last-sexp', and `eval-print-last-sexp'.
:group 'edebug)
(defcustom edebug-initial-mode 'step
- "*Initial execution mode for Edebug, if non-nil. If this variable
-is non-@code{nil}, it specifies the initial execution mode for Edebug
-when it is first activated. Possible values are step, next, go,
-Go-nonstop, trace, Trace-fast, continue, and Continue-fast."
+ "*Initial execution mode for Edebug, if non-nil.
+If this variable is non-nil, it specifies the initial execution mode
+for Edebug when it is first activated. Possible values are step, next,
+go, Go-nonstop, trace, Trace-fast, continue, and Continue-fast."
:type '(choice (const step) (const next) (const go)
(const Go-nonstop) (const trace)
(const Trace-fast) (const continue)
(defcustom edebug-print-length 50
- "*Default value of `print-length' to use while printing results in Edebug."
+ "*Default value of `print-length' for printing results in Edebug."
:type 'integer
:group 'edebug)
(defcustom edebug-print-level 50
- "*Default value of `print-level' to use while printing results in Edebug."
+ "*Default value of `print-level' for printing results in Edebug."
:type 'integer
:group 'edebug)
(defcustom edebug-print-circle t
- "*Default value of `print-circle' to use while printing results in Edebug."
+ "*Default value of `print-circle' for printing results in Edebug."
:type 'boolean
:group 'edebug)
If the current defun is actually a call to `defvar', then reset the
variable using its initial value expression even if the variable
already has some other value. (Normally `defvar' does not change the
-variable's value if it already has a value.)
+variable's value if it already has a value.) Treat `defcustom'
+similarly. Reinitialize the face according to `defface' specification.
With a prefix argument, instrument the code for Edebug.
((and (eq (car form) 'defcustom)
(default-boundp (nth 1 form)))
;; Force variable to be bound.
- (set-default (nth 1 form) (eval (nth 2 form)))))
+ (set-default (nth 1 form) (eval (nth 2 form))))
+ ((eq (car form) 'defface)
+ ;; Reset the face.
+ (setq face-new-frame-defaults
+ (assq-delete-all (nth 1 form) face-new-frame-defaults))
+ (put (nth 1 form) 'face-defface-spec nil)
+ ;; See comments in `eval-defun-1' for purpose of code below
+ (setq form (prog1 `(prog1 ,form
+ (put ',(nth 1 form) 'saved-face
+ ',(get (nth 1 form) 'saved-face))
+ (put ',(nth 1 form) 'customized-face
+ ,(nth 2 form)))
+ (put (nth 1 form) 'saved-face nil)))))
(setq edebug-result (eval form))
(if (not edebugging)
(princ edebug-result)
(if (and (eq (following-char) ?.)
(save-excursion
(forward-char 1)
- (and (>= (following-char) ?0)
- (<= (following-char) ?9))))
+ (or (and (eq (aref edebug-read-syntax-table (following-char))
+ 'symbol)
+ (not (= (following-char) ?\;)))
+ (memq (following-char) '(?\, ?\.)))))
'symbol
(aref edebug-read-syntax-table (following-char))))
(def-edebug-spec push (form sexp))
(def-edebug-spec pop (sexp))
+(def-edebug-spec 1value (form))
+(def-edebug-spec noreturn (form))
+
+
;; Anything else?
(defun edebug-display ()
+ (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
+ ;; which function we're talking about.
+ (debug))
;; Setup windows for edebug, determine mode, maybe enter recursive-edit.
;; Uses local variables of edebug-enter, edebug-before, edebug-after
;; and edebug-debugger.
(defun edebug-modify-breakpoint (flag &optional condition temporary)
- "Modify the breakpoint for the form at point or after it according
-to FLAG: set if t, clear if nil. Then move to that point.
+ "Modify the breakpoint for the form at point or after it.
+Set it if FLAG is non-nil, clear it otherwise. Then move to that point.
If CONDITION or TEMPORARY are non-nil, add those attributes to
the breakpoint. "
(let ((edebug-stop-point (edebug-find-stop-point)))
(defun edebug-set-global-break-condition (expression)
- (interactive (list (read-minibuffer
- "Global Condition: "
- (format "%s" edebug-global-break-condition))))
+ (interactive
+ (list
+ (let ((initial (and edebug-global-break-condition
+ (format "%s" edebug-global-break-condition))))
+ (read-from-minibuffer
+ "Global Condition: " initial read-expression-map t
+ (if (equal (car read-expression-history) initial)
+ '(read-expression-history . 1)
+ 'read-expression-history)))))
(setq edebug-global-break-condition expression))
(defun edebug-goto-here ()
- "Proceed to this stop point."
+ "Proceed to first stop-point at or after current position of point."
(interactive)
(edebug-go-mode t))
(edebug-prin1-to-string value)))
(defun edebug-compute-previous-result (edebug-previous-value)
+ (if edebug-unwrap-results
+ (setq edebug-previous-value
+ (edebug-unwrap* edebug-previous-value)))
(setq edebug-previous-result
- (if (and (integerp edebug-previous-value)
- (< edebug-previous-value 256)
- (>= edebug-previous-value 0))
- (format "Result: %s = %s" edebug-previous-value
- (single-key-description edebug-previous-value))
- (if edebug-unwrap-results
- (setq edebug-previous-value
- (edebug-unwrap* edebug-previous-value)))
- (concat "Result: "
- (edebug-safe-prin1-to-string edebug-previous-value)))))
+ (concat "Result: "
+ (edebug-safe-prin1-to-string edebug-previous-value)
+ (eval-expression-print-format edebug-previous-value))))
(defun edebug-previous-result ()
"Print the previous result."
(princ
(edebug-outside-excursion
(setq values (cons (edebug-eval edebug-expr) values))
- (edebug-safe-prin1-to-string (car values)))))
+ (concat (edebug-safe-prin1-to-string (car values))
+ (eval-expression-print-format (car values))))))
(defun edebug-eval-last-sexp ()
- "Evaluate sexp before point in the outside environment; value in minibuffer."
+ "Evaluate sexp before point in the outside environment.
+Print value in minibuffer."
(interactive)
(edebug-eval-expression (edebug-last-sexp)))
(defun edebug-eval-print-last-sexp ()
- "Evaluate sexp before point in the outside environment; insert the value.
+ "Evaluate sexp before point in outside environment; insert value.
This prints the value into current buffer."
(interactive)
(let* ((edebug-form (edebug-last-sexp))
(defvar edebug-eval-mode-map nil
"Keymap for Edebug Eval mode. Superset of Lisp Interaction mode.")
-(if edebug-eval-mode-map
- nil
- (setq edebug-eval-mode-map (copy-keymap lisp-interaction-mode-map))
+(unless edebug-eval-mode-map
+ (setq edebug-eval-mode-map (make-sparse-keymap))
+ (set-keymap-parent edebug-eval-mode-map lisp-interaction-mode-map)
(define-key edebug-eval-mode-map "\C-c\C-w" 'edebug-where)
(define-key edebug-eval-mode-map "\C-c\C-d" 'edebug-delete-eval-item)
(define-key edebug-eval-mode-map "\C-c\C-u" 'edebug-update-eval-list)
(define-key edebug-eval-mode-map "\C-x\C-e" 'edebug-eval-last-sexp)
- (define-key edebug-eval-mode-map "\C-j" 'edebug-eval-print-last-sexp)
- )
+ (define-key edebug-eval-mode-map "\C-j" 'edebug-eval-print-last-sexp))
(put 'edebug-eval-mode 'mode-class 'special)
-(defun edebug-eval-mode ()
+(define-derived-mode edebug-eval-mode lisp-interaction-mode "Edebug Eval"
"Mode for evaluation list buffer while in Edebug.
In addition to all Interactive Emacs Lisp commands there are local and
\\{edebug-eval-mode-map}
Global commands prefixed by global-edebug-prefix:
-\\{global-edebug-map}
-"
- (lisp-interaction-mode)
- (setq major-mode 'edebug-eval-mode)
- (setq mode-name "Edebug Eval")
- (use-local-map edebug-eval-mode-map))
+\\{global-edebug-map}")
;;; Interface with standard debugger.
;;; Frequency count and coverage
(defun edebug-display-freq-count ()
- "Display the frequency count data for each line of the current
-definition. The frequency counts are inserted as comment lines after
+ "Display the frequency count data for each line of the current definition.
+The frequency counts are inserted as comment lines after
each line, and you can undo all insertions with one `undo' command.
The counts are inserted starting under the `(' before an expression
(defalias 'edebug-window-live-p 'window-live-p)
-;; Mark takes an argument in Emacs 19.
(defun edebug-mark ()
- (mark t)) ;; Does this work for lemacs too?
+ (mark t))
(defun edebug-set-conditional-breakpoint (arg condition)
"Set a conditional breakpoint at nearest sexp.
(interactive
(list
current-prefix-arg
-;; Read condition as follows; getting previous condition is cumbersome:
+ ;; Read condition as follows; getting previous condition is cumbersome:
(let ((edebug-stop-point (edebug-find-stop-point)))
(if edebug-stop-point
(let* ((edebug-def-name (car edebug-stop-point))
(edebug-breakpoints (car (cdr edebug-data)))
(edebug-break-data (assq index edebug-breakpoints))
(edebug-break-condition (car (cdr edebug-break-data)))
- (edebug-expression-history
- ;; Prepend the current condition, if any.
- (if edebug-break-condition
- (cons edebug-break-condition read-expression-history)
- read-expression-history)))
- (prog1
- (read-from-minibuffer
- "Condition: " nil read-expression-map t
- 'edebug-expression-history)
- (setq read-expression-history edebug-expression-history)
- ))))))
+ (initial (and edebug-break-condition
+ (format "%s" edebug-break-condition))))
+ (read-from-minibuffer
+ "Condition: " initial read-expression-map t
+ (if (equal (car read-expression-history) initial)
+ '(read-expression-history . 1)
+ 'read-expression-history)))))))
(edebug-modify-breakpoint t condition arg))
-;;; The default for all above is Emacs.
-
-;; Epoch specific code was in a separate file: edebug-epoch.el.
-
(easy-menu-define edebug-menu edebug-mode-map "Edebug menus" edebug-mode-menus)
\f
;;; Byte-compiler