;;; edebug.el --- a source-level debugger for Emacs Lisp -*- lexical-binding: t -*-
-;; Copyright (C) 1988-1995, 1997, 1999-2012 Free Software Foundation, Inc.
+;; Copyright (C) 1988-1995, 1997, 1999-2013 Free Software Foundation,
+;; Inc.
;; Author: Daniel LaLiberte <liberte@holonexus.org>
;; Maintainer: FSF
(require 'macroexp)
(eval-when-compile (require 'cl-lib))
+(eval-when-compile (require 'pcase))
;;; Options
This version, from Edebug, maybe instruments the expression. But the
STREAM must be the current buffer to do so. Whether it instruments is
-also dependent on the values of `edebug-all-defs' and
-`edebug-all-forms'."
+also dependent on the values of the option `edebug-all-defs' and
+the option `edebug-all-forms'."
(or stream (setq stream standard-input))
(if (eq stream (current-buffer))
(edebug-read-and-maybe-wrap-form)
With a prefix argument, instrument the code for Edebug.
-Setting `edebug-all-defs' to a non-nil value reverses the meaning of
-the prefix argument. Code is then instrumented when this function is
+Setting option `edebug-all-defs' to a non-nil value reverses the meaning
+of the prefix argument. Code is then instrumented when this function is
invoked without a prefix argument
If acting on a `defun' for FUNCTION, and the function was instrumented,
(defvar edebug-active nil) ;; Non-nil when edebug is active
-;;; add minor-mode-alist entry
-(or (assq 'edebug-active minor-mode-alist)
- (setq minor-mode-alist (cons (list 'edebug-active " *Debugging*")
- minor-mode-alist)))
-
(defvar edebug-stack nil)
;; Stack of active functions evaluated via edebug.
;; Should be nil at the top level.
;; Start up a recursive edit inside of edebug.
;; The current buffer is the edebug-buffer, which is put into edebug-mode.
;; Assume that none of the variables below are buffer-local.
- (let ((edebug-buffer-read-only buffer-read-only)
- ;; match-data must be done in the outside buffer
+ (let (;; match-data must be done in the outside buffer
(edebug-outside-match-data
(with-current-buffer edebug-outside-buffer ; in case match buffer different
(match-data)))
;; during a recursive-edit
edebug-inside-windows
- (edebug-outside-map (current-local-map))
-
;; Save the outside value of executing macro. (here??)
(edebug-outside-executing-macro executing-kbd-macro)
(edebug-outside-pre-command-hook
(not (memq arg-mode '(after error))))
(message "Break"))
- (setq buffer-read-only t)
(setq signal-hook-function nil)
- (edebug-mode)
+ (edebug-mode 1)
(unwind-protect
(recursive-edit) ; <<<<<<<<<< Recursive edit
(set-buffer edebug-buffer)
(if (memq edebug-execution-mode '(go Go-nonstop))
(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)
- )
+ (edebug-mode -1))
;; gotta have a buffer to let its buffer local variables be set
(get-buffer-create " bogus edebug buffer"))
));; inner let
(interactive)
(describe-function 'edebug-mode))
-(defun edebug-mode ()
+(defvar edebug--mode-saved-vars nil)
+
+(define-minor-mode edebug-mode
"Mode for Emacs Lisp buffers while in Edebug.
In addition to all Emacs Lisp commands (except those that modify the
`edebug-on-signal'
`edebug-unwrap-results'
`edebug-global-break-condition'"
+ :lighter " *Debugging*"
+ :keymap edebug-mode-map
;; 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))
+ ;;
+ (if (not edebug-mode)
+ (progn
+ (while edebug--mode-saved-vars
+ (let ((setting (pop edebug--mode-saved-vars)))
+ (if (consp setting)
+ (set (car setting) (cdr setting))
+ (kill-local-variable setting))))
+ (remove-hook 'kill-buffer-hook 'edebug-kill-buffer t))
+ (pcase-dolist (`(,var . ,val) '((buffer-read-only . t)))
+ (push
+ (if (local-variable-p var) (cons var (symbol-value var)) var)
+ edebug--mode-saved-vars)
+ (set (make-local-variable var) val))
+ ;; Append `edebug-kill-buffer' to the hook to avoid interfering with
+ ;; other entries that are unguarded against deleted buffer.
+ (add-hook 'kill-buffer-hook 'edebug-kill-buffer t t)))
(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))
+ (run-with-timer 0 nil #'top-level))
;;; edebug eval list mode
It is removed when you hit any char."
;; This seems not to work with Emacs 18.59. It undoes too far.
(interactive)
- (let ((buffer-read-only nil))
+ (let ((inhibit-read-only t))
(undo-boundary)
(edebug-display-freq-count)
(setq unread-command-events
(defun edebug-unload-function ()
"Unload the Edebug source level debugger."
(when edebug-active
+ (setq edebug-active nil)
(unwind-protect
(abort-recursive-edit)
- (setq edebug-active nil)
- (edebug-unload-function)))
- (save-current-buffer
- (dolist (buffer (buffer-list))
- (set-buffer buffer)
- (when (eq major-mode 'edebug-mode) (emacs-lisp-mode))))
+ ;; We still want to run unload-feature to completion
+ (run-with-idle-timer 0 nil #'(lambda () (unload-feature 'edebug)))))
(remove-hook 'called-interactively-p-functions
'edebug--called-interactively-skip)
(remove-hook 'cl-read-load-hooks 'edebug--require-cl-read)