branch: elpa/macrostep
commit 9d2c58c05b7982159e0d3f289a950da2a84ceec1
Author: joddie <[email protected]>
Commit: joddie <[email protected]>
Add option to expand in a separate buffer
Fixes #8.
---
macrostep-test.el | 46 +++++++++++++++++++++++++++++++++++-
macrostep.el | 70 ++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 101 insertions(+), 15 deletions(-)
diff --git a/macrostep-test.el b/macrostep-test.el
index 3363c9b..0d0233c 100644
--- a/macrostep-test.el
+++ b/macrostep-test.el
@@ -19,7 +19,8 @@
(defmacro macrostep-with-text (object &rest forms)
- (declare (indent 1))
+ (declare (indent 1)
+ (debug (&rest form)))
`(with-temp-buffer
(emacs-lisp-mode)
(let ((print-level nil)
@@ -215,6 +216,49 @@
(eq (get-char-property (point) 'font-lock-face)
'macrostep-macro-face))))))
+(ert-deftest macrostep-expand-in-separate-buffer ()
+ (defmacro macrostep-dummy-macro (&rest args)
+ `(expansion of ,@args))
+ (let ((macrostep-expand-in-separate-buffer t))
+ (macrostep-with-text
+ '(progn
+ (first form)
+ (second form)
+ (macrostep-dummy-macro (some (arguments)))
+ (final form))
+ (let ((original-buffer (current-buffer)))
+ (search-forward "(macrostep-dummy-macro")
+ (macrostep-expand)
+ (should (not (equal (current-buffer) original-buffer)))
+ (should macrostep-expansion-buffer)
+ (should (equal (read (copy-marker (point)))
+ '(expansion of (some (arguments)))))))))
+
+(ert-deftest macrostep-expand-macrolet-in-separate-buffer ()
+ (let ((macrostep-expand-in-separate-buffer t))
+ (macrostep-with-text
+ '(cl-macrolet
+ ((dummy-macro-1 (&rest args)
+ `(dummy-macro-2 ,@args))
+ (dummy-macro-2 (&rest args)
+ `(expansion of ,@args)))
+ (dummy-macro-1 (some (arguments))))
+ (let ((original-buffer (current-buffer)))
+ (search-forward "(dummy-macro-1 (some")
+ (goto-char (match-beginning 0))
+ (macrostep-expand)
+ (should (not (equal (current-buffer) original-buffer)))
+ (should macrostep-expansion-buffer)
+ (should (equal (read (copy-marker (point)))
+ '(dummy-macro-2 (some (arguments)))))
+
+ (macrostep-expand)
+ (should (equal (read (copy-marker (point)))
+ '(expansion of (some (arguments)))))
+
+ (macrostep-collapse)
+ (should (equal (read (copy-marker (point)))
+ '(dummy-macro-2 (some (arguments)))))))))
(when noninteractive
(load-file (expand-file-name "macrostep.el"
diff --git a/macrostep.el b/macrostep.el
index f0e5b92..43c6e35 100644
--- a/macrostep.el
+++ b/macrostep.el
@@ -218,9 +218,20 @@
(defvar macrostep-environment nil
"Local macro-expansion environment, including macros declared by
`cl-macrolet'.")
-(make-variable-buffer-local 'macrostep-environment)
-;;; Faces
+(defvar macrostep-expansion-buffer nil
+ "Non-nil if the current buffer is a macro-expansion buffer.")
+(make-variable-buffer-local 'macrostep-expansion-buffer)
+
+(defvar macrostep-outer-environment nil
+ "Outermost macro-expansion environment to use in a dedicated macro-expansion
buffers.
+
+This variable is used to save information about any enclosing
+`cl-macrolet' context when a macro form is expanded in a separate
+buffer.")
+(make-variable-buffer-local 'macrostep-outer-environment)
+
+;;; Customization options and faces
(defgroup macrostep nil
"Interactive macro stepper for Emacs Lisp."
:group 'lisp
@@ -274,6 +285,11 @@
"Face for macros in macro-expanded code."
:group 'macrostep)
+(defcustom macrostep-expand-in-separate-buffer nil
+ "When non-nil, show expansions in a separate buffer instead of inline."
+ :group 'macrostep
+ :type 'boolean)
+
;; Need the following for making the ring of faces
(defun macrostep-make-ring (&rest items)
"Make a ring containing all of ITEMS with no empty slots."
@@ -336,14 +352,18 @@ quit and return to normal editing.
(substitute-command-keys
"\\<macrostep-keymap>Entering macro stepper mode. Use
\\[macrostep-expand] to expand, \\[macrostep-collapse] to collapse,
\\[macrostep-collapse-all] to exit.")))
- ;; Exiting mode: collapse any remaining overlays
- (when macrostep-overlays (macrostep-collapse-all))
- ;; Restore undo info & read-only state
- (setq buffer-undo-list macrostep-saved-undo-list
- buffer-read-only macrostep-saved-read-only
- macrostep-saved-undo-list nil)
- ;; Remove our post-command hook
- (remove-hook 'post-command-hook 'macrostep-command-hook t)))
+ ;; Exiting mode
+ (if macrostep-expansion-buffer
+ ;; Kill dedicated expansion buffers
+ (quit-window t)
+ ;; Collapse any remaining overlays
+ (when macrostep-overlays (macrostep-collapse-all))
+ ;; Restore undo info & read-only state
+ (setq buffer-undo-list macrostep-saved-undo-list
+ buffer-read-only macrostep-saved-read-only
+ macrostep-saved-undo-list nil)
+ ;; Remove our post-command hook
+ (remove-hook 'post-command-hook 'macrostep-command-hook t))))
;; Post-command hook: bail out of macrostep-mode if the user types C-x
;; C-q to make the buffer writable again.
@@ -373,6 +393,22 @@ buffer and expand the next macro form found, if any."
(if (consp sexp)
(error "(%s ...) is not a macro form" (car sexp))
(error "Text at point is not a macro form.")))))
+
+ ;; Create a dedicated macro-expansion buffer and copy the text to
+ ;; be expanded into it, if required
+ (when (and macrostep-expand-in-separate-buffer
+ (not macrostep-expansion-buffer))
+ (let ((buffer
+ (get-buffer-create (generate-new-buffer-name "*macro
expansion*"))))
+ (set-buffer buffer)
+ (emacs-lisp-mode)
+ (setq macrostep-expansion-buffer t)
+ (setq macrostep-outer-environment macrostep-environment)
+ (save-excursion
+ (let ((print-level nil)
+ (print-length nil))
+ (print sexp (current-buffer))))
+ (pop-to-buffer buffer)))
(let* ((inhibit-read-only t)
(expansion (macrostep-expand-1 sexp))
@@ -398,11 +434,13 @@ buffer and expand the next macro form found, if any."
(let ((new-ol
(make-overlay (point)
(scan-sexps (point) 1))))
- ;; move overlay over newline to make it prettier
+ ;; Move overlay over newline to make it prettier
(when (equal (char-after (overlay-end new-ol)) ?\n)
(move-overlay new-ol
(overlay-start new-ol) (+ (overlay-end new-ol) 1)))
- (overlay-put new-ol 'face 'macrostep-expansion-highlight-face)
+ ;; Highlight the overlay in original source buffers only
+ (unless macrostep-expansion-buffer
+ (overlay-put new-ol 'face 'macrostep-expansion-highlight-face))
(overlay-put new-ol 'evaporate t)
(overlay-put new-ol 'priority priority)
(overlay-put new-ol 'macrostep-original-text text)
@@ -533,8 +571,12 @@ lambda expression that returns its expansion."
(enclosing-environment
(macrostep-environment-at-point)))
(append binding-environment enclosing-environment)))
- (`nil nil)
- (_ (macrostep-environment-at-point))))))
+ (`nil
+ (if macrostep-expansion-buffer
+ macrostep-outer-environment
+ nil))
+ (_
+ (macrostep-environment-at-point))))))
(defun macrostep-bindings-to-environment (bindings)
"Return the macro-expansion environment declared by BINDINGS as an alist.