emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Interactive macro expansion added


From: Johannes Weiner
Subject: Re: [PATCH] Interactive macro expansion added
Date: Mon, 20 Aug 2007 03:31:26 +0200
User-agent: Mutt/1.5.16 (2007-06-11)

Hi,

On Mon, Aug 20, 2007 at 12:08:06AM +0200, Johannes Weiner wrote:
> Hi Emacs-hackers,
> 
> here is a patch that extracts last-sexp from already existing code so that one
> can use last-sexp for other purposes too.

My real goals where of course, interactive macro expansion while editing lisp
code. So I implemented that also.  The result is now a more generalized
operation functionality on the sexp before point.

I promise to write documentation for the rest of the new functions if the
actual code is agreed upon.

> Note: I ripped out the let-binding of `stap' in the original code because it
> looked stale. Please correct me if I am wrong.

The old patch is superseeded by the new one.

        Hannes
diff -Naur emacs.orig/lisp/emacs-lisp/lisp-mode.el 
emacs/lisp/emacs-lisp/lisp-mode.el
--- emacs.orig/lisp/emacs-lisp/lisp-mode.el     2007-08-20 00:00:43.000000000 
+0200
+++ emacs/lisp/emacs-lisp/lisp-mode.el  2007-08-20 03:18:27.000000000 +0200
@@ -444,6 +444,23 @@
 Entry to this mode calls the value of `lisp-interaction-mode-hook'
 if that value is non-nil.")
 
+(defun eval-last-sexp-and-print-1 (&optional expand-only)
+  "Evaluates or expands sexp before point, depending on `expand-only'.
+The value is printed into the current buffer.
+
+If `eval-expression-debug-on-error' is non-nil, which is the
+default, this command arranges for all errors to enter the
+debugger.
+
+Note that printing the result is controlled by the variables
+`eval-expression-print-length' and `eval-expression-print-level'."
+  (let ((standard-output (current-buffer)))
+    (terpri)
+    (if expand-only
+       (macroexpand-last-sexp t)
+      (eval-last-sexp t))
+    (terpri)))
+
 (defun eval-print-last-sexp ()
   "Evaluate sexp before point; print value into current buffer.
 
@@ -454,11 +471,19 @@
 `eval-expression-print-length' and `eval-expression-print-level',
 which see."
   (interactive)
-  (let ((standard-output (current-buffer)))
-    (terpri)
-    (eval-last-sexp t)
-    (terpri)))
+  (eval-last-sexp-and-print-1))
 
+(defun macroexpand-print-last-sexp ()
+  "Macroexpand sexp before point; print value into current buffer.
+
+If `eval-expression-debug-on-error' is non-nil, which is the
+default, this command arranges for all errors to enter the
+debugger.
+
+Note that printing the result is controlled by the variables
+`eval-expression-print-length' and `eval-expression-print-level'."
+  (interactive)
+  (eval-last-sexp-and-print-1 t))
 
 (defun last-sexp-setup-props (beg end value alt1 alt2)
   "Set up text properties for the output of `eval-last-sexp-1'.
@@ -538,65 +563,59 @@
              (= (car (read-from-string string)) char)
              string))))
 
+(defun last-sexp ()
+  "Return sexp before the point."
+  (let ((opoint (point))
+       ignore-quotes
+       expr)
+    (save-excursion
+      (with-syntax-table emacs-lisp-mode-syntax-table
+       ;; If this sexp appears to be enclosed in `...'
+       ;; then ignore the surrounding quotes.
+       (setq ignore-quotes
+             (or (eq (following-char) ?\')
+                 (eq (preceding-char) ?\')))
+       (forward-sexp -1)
+       ;; If we were after `?\e' (or similar case),
+       ;; use the whole thing, not just the `e'.
+       (when (eq (preceding-char) ?\\)
+         (forward-char -1)
+         (when (eq (preceding-char) ??)
+           (forward-char -1)))
+       
+       ;; Skip over `#N='s.
+       (when (eq (preceding-char) ?=)
+         (let (labeled-p)
+           (save-excursion
+             (skip-chars-backward "0-9#=")
+             (setq labeled-p (looking-at "\\(#[0-9]+=\\)+")))
+           (when labeled-p
+             (forward-sexp -1))))
+       
+       (save-restriction
+         ;; address@hidden 30-Jul-1997: skip ` in
+         ;; `variable' so that the value is returned, not the
+         ;; name
+         (if (and ignore-quotes
+                  (eq (following-char) ?`))
+             (forward-char))
+         (narrow-to-region (point-min) opoint)
+         (setq expr (read (current-buffer)))
+         ;; If it's an (interactive ...) form, it's more
+         ;; useful to show how an interactive call would
+         ;; use it.
+         (and (consp expr)
+              (eq (car expr) 'interactive)
+              (setq expr
+                    (list 'call-interactively
+                          (list 'quote
+                                (list 'lambda
+                                      '(&rest args)
+                                      expr
+                                      'args)))))
+         expr)))))
 
-(defun eval-last-sexp-1 (eval-last-sexp-arg-internal)
-  "Evaluate sexp before point; print value in minibuffer.
-With argument, print output into current buffer."
-  (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t)))
-    (let ((value
-          (eval (let ((stab (syntax-table))
-                      (opoint (point))
-                      ignore-quotes
-                      expr)
-                  (save-excursion
-                    (with-syntax-table emacs-lisp-mode-syntax-table
-                      ;; If this sexp appears to be enclosed in `...'
-                      ;; then ignore the surrounding quotes.
-                      (setq ignore-quotes
-                            (or (eq (following-char) ?\')
-                                (eq (preceding-char) ?\')))
-                      (forward-sexp -1)
-                      ;; If we were after `?\e' (or similar case),
-                      ;; use the whole thing, not just the `e'.
-                      (when (eq (preceding-char) ?\\)
-                        (forward-char -1)
-                        (when (eq (preceding-char) ??)
-                          (forward-char -1)))
-
-                      ;; Skip over `#N='s.
-                      (when (eq (preceding-char) ?=)
-                        (let (labeled-p)
-                          (save-excursion
-                            (skip-chars-backward "0-9#=")
-                            (setq labeled-p (looking-at "\\(#[0-9]+=\\)+")))
-                          (when labeled-p
-                            (forward-sexp -1))))
-
-                      (save-restriction
-                        ;; address@hidden 30-Jul-1997: skip ` in
-                        ;; `variable' so that the value is returned, not the
-                        ;; name
-                        (if (and ignore-quotes
-                                 (eq (following-char) ?`))
-                            (forward-char))
-                        (narrow-to-region (point-min) opoint)
-                        (setq expr (read (current-buffer)))
-                        ;; If it's an (interactive ...) form, it's more
-                        ;; useful to show how an interactive call would
-                        ;; use it.
-                        (and (consp expr)
-                             (eq (car expr) 'interactive)
-                             (setq expr
-                                   (list 'call-interactively
-                                         (list 'quote
-                                               (list 'lambda
-                                                     '(&rest args)
-                                                     expr
-                                                     'args)))))
-                        expr)))))))
-      (eval-last-sexp-print-value value))))
-
-(defun eval-last-sexp-print-value (value)
+(defun operate-on-last-sexp-print-value (value)
   (let ((unabbreviated (let ((print-length nil) (print-level nil))
                         (prin1-to-string value)))
        (print-length eval-expression-print-length)
@@ -618,8 +637,25 @@
                               (buffer-substring-no-properties beg end))
        ))))
 
+(defun operate-on-last-sexp-1 (operation operate-on-last-sexp-arg-internal)
+  (let ((standard-output (if operate-on-last-sexp-arg-internal
+                            (current-buffer)
+                          t)))
+    (operate-on-last-sexp-print-value (funcall operation (last-sexp)))))
 
-(defvar eval-last-sexp-fake-value (make-symbol "t"))
+(defvar operate-on-last-sexp-fake-value (make-symbol "t"))
+
+(defun operate-on-last-sexp (operation operate-on-last-sexp-arg-internal)
+  (if (null eval-expression-debug-on-error)
+      (operate-on-last-sexp-1 operation operate-on-last-sexp-arg-internal)
+    (let ((value
+          (let ((debug-on-error operate-on-last-sexp-fake-value))
+            (cons (operate-on-last-sexp-1 operation
+                                          operate-on-last-sexp-arg-internal)
+                  debug-on-error))))
+      (unless (eq (cdr value) operate-on-last-sexp-fake-value)
+       (setq debug-on-error (cdr value)))
+      (car value))))
 
 (defun eval-last-sexp (eval-last-sexp-arg-internal)
   "Evaluate sexp before point; print value in minibuffer.
@@ -628,15 +664,16 @@
 If `eval-expression-debug-on-error' is non-nil, which is the default,
 this command arranges for all errors to enter the debugger."
   (interactive "P")
-  (if (null eval-expression-debug-on-error)
-      (eval-last-sexp-1 eval-last-sexp-arg-internal)
-    (let ((value
-          (let ((debug-on-error eval-last-sexp-fake-value))
-            (cons (eval-last-sexp-1 eval-last-sexp-arg-internal)
-                  debug-on-error))))
-      (unless (eq (cdr value) eval-last-sexp-fake-value)
-       (setq debug-on-error (cdr value)))
-      (car value))))
+  (operate-on-last-sexp 'eval eval-last-sexp-arg-internal))
+
+(defun macroexpand-last-sexp (macroexpand-last-sexp-arg-internal)
+  "Macroexpand sexp before point; print expansion in minibuffer.
+Interactively, with prefix argument, print expansion into current buffer.
+
+If `eval-expression-debug-on-error' is non-nil, which is the default,
+this command arranges for all errors to enter the debugger."
+  (interactive "P")
+  (operate-on-last-sexp 'macroexpand macroexpand-last-sexp-arg-internal))
 
 (defun eval-defun-1 (form)
   "Treat some expressions specially.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]