From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Johannes Weiner Newsgroups: gmane.emacs.devel Subject: Re: [PATCH] Interactive macro expansion added Date: Mon, 20 Aug 2007 03:31:26 +0200 Message-ID: <20070820013126.GA24021@saeurebad.de> References: <20070819220806.GA14139@saeurebad.de> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="jI8keyz6grp/JLjh" X-Trace: sea.gmane.org 1187573505 464 80.91.229.12 (20 Aug 2007 01:31:45 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 20 Aug 2007 01:31:45 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Aug 20 03:31:44 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1IMw7K-0006hS-7R for ged-emacs-devel@m.gmane.org; Mon, 20 Aug 2007 03:31:42 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IMw7J-00010G-Cw for ged-emacs-devel@m.gmane.org; Sun, 19 Aug 2007 21:31:41 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1IMw7E-0000v8-7h for emacs-devel@gnu.org; Sun, 19 Aug 2007 21:31:36 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1IMw7C-0000rY-Ee for emacs-devel@gnu.org; Sun, 19 Aug 2007 21:31:35 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1IMw7C-0000rO-Ab for emacs-devel@gnu.org; Sun, 19 Aug 2007 21:31:34 -0400 Original-Received: from saeurebad.de ([85.214.36.134]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1IMw7B-0004cK-N4 for emacs-devel@gnu.org; Sun, 19 Aug 2007 21:31:34 -0400 Original-Received: by saeurebad.de (Postfix, from userid 1000) id 5704B2F03B2; Mon, 20 Aug 2007 03:31:26 +0200 (CEST) Mail-Followup-To: emacs-devel@gnu.org Content-Disposition: inline In-Reply-To: <20070819220806.GA14139@saeurebad.de> User-Agent: Mutt/1.5.16 (2007-06-11) X-Detected-Kernel: Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:76793 Archived-At: --jI8keyz6grp/JLjh Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 --jI8keyz6grp/JLjh Content-Type: text/x-diff; charset=us-ascii Content-Disposition: inline; filename="emacs-lisp-mode-interactive-macroexpand.patch" 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 + ;; vladimir@cs.ualberta.ca 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 - ;; vladimir@cs.ualberta.ca 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. --jI8keyz6grp/JLjh Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Emacs-devel mailing list Emacs-devel@gnu.org http://lists.gnu.org/mailman/listinfo/emacs-devel --jI8keyz6grp/JLjh--