1 ;;; eval-expr.el --- enhanced eval-expression command
3 ;; Copyright (C) 1991 Free Software Foundation, Inc.
4 ;; Copyright (C) 1991 Joe Wells
5 ;; Copyright (C) 1998 Noah S. Friedman
7 ;; Author: Noah Friedman <friedman@splode.com>
8 ;; Maintainer: friedman@splode.com
9 ;; Keywords: extensions
10 ;; Created: 1998-07-30
12 ;; $Id: eval-expr.el,v 1.2 1998/08/04 02:43:59 friedman Exp $
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation; either version 2, or (at your option)
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 ;; GNU General Public License for more details.
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program; if not, you can either send email to this
26 ;; program's maintainer or write to: The Free Software Foundation,
27 ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
31 ;; Updates of this program may be available via the URL
32 ;; http://www.splode.com/~friedman/software/emacs-lisp/
34 ;; To use this package, put this in your .emacs:
36 ;; (require 'eval-expr)
37 ;; (eval-expr-install)
41 ;; * When reading the Lisp object interactively from the minibuffer, the
42 ;; minibuffer uses the Emacs Lisp Mode syntax table. (Emacs 19.18 or
45 ;; * If you type an incomplete or otherwise syntactically invalid
46 ;; expression (e.g. you forget a closing paren), you can fix your
47 ;; mistake without having to type it all over again.
49 ;; * Displays the result in a buffer if it is too big to fit in the echo
50 ;; area. This buffer is placed in Emacs Lisp Mode.
51 ;; (If you give a prefix arg, the result is placed in the current
52 ;; buffer instead of the echo area or a separate temporary buffer.)
54 ;; * The variables `eval-expr-print-level' and `eval-expr-print-length'
55 ;; can be used to constrain the attempt to print recursive data
56 ;; structures. These variables are independent of the global
57 ;; `print-level' and `print-length' variables so that eval-expression
58 ;; can be used more easily for debugging.
60 ;; This program is loosely based on an earlier implemention written by Joe
61 ;; Wells <jbw@cs.bu.edu> called eval-expression-fix.el (last revised
62 ;; 1991-10-12). That version was originally written for Emacs 18 and,
63 ;; while it worked with some quirky side effects in Emacs 19, created even
64 ;; more problems in Emacs 20 and didn't work in XEmacs at all.
66 ;; This rewrite should work in Emacs 19.18 or later, Emacs 20,
67 ;; and any version of XEmacs. It will not work in Emacs 18.
72 (defvar eval-expr-error-message-delay 3
73 "*Amount of time, in seconds, to display in echo area before continuing.")
76 (defvar eval-expr-prompt "Eval: "
77 "*Prompt used by eval-expr.")
80 (defvar eval-expr-honor-debug-on-error t
81 "*If non-nil, do not trap evaluation errors.
82 Instead, allow errors to throw user into the debugger, provided
83 debug-on-error specifies that the particular error is a debuggable condition.")
86 (defvar eval-expr-print-level (default-value 'print-level)
87 "*Like print-level, but affect results printed by `eval-expr' only.")
90 (defvar eval-expr-print-length (default-value 'print-length)
91 "*Like print-length, but affect results printed by `eval-expr' only.")
93 (defvar eval-expr-output-buffer-name "*Eval Expression Output*")
94 (defvar eval-expr-error-buffer-name "*Eval Expression Error*")
96 (defvar eval-expr-whitespace
97 (mapcar 'string-to-char '(" " "\t" "\n")))
99 (defalias 'eval-expr-orig-command nil)
103 (defun eval-expr-install ()
104 "Replace standard eval-expression command with enhanced eval-expr."
106 (or (symbol-function 'eval-expr-orig-command)
107 (fset 'eval-expr-orig-command (symbol-function 'eval-expression)))
108 (defalias 'eval-expression 'eval-expr))
110 (defun eval-expr-uninstall ()
111 "Restore original, unenhanced eval-expression command."
113 (fset 'eval-expression (symbol-function 'eval-expr-orig-command)))
116 (defun eval-expr (ee::expression &optional ee::insert-value)
117 "Evaluate EXPRESSION and print value in minibuffer, temp, or current buffer.
118 A temp output buffer is used if there is more than one line in the
120 If invoked with a prefix arg, or second lisp argument EE::INSERT-VALUE is
121 non-nil, then insert final value into the current buffer at point.
123 Value is also consed on to front of the variable `values'."
124 (interactive (list (eval-expr-read-lisp-object-minibuffer eval-expr-prompt)
126 (let* ((ee::error nil)
127 (ee::result (cond ((and eval-expr-honor-debug-on-error
129 (eval ee::expression))
131 (condition-case ee::err-data
132 (eval ee::expression)
134 (setq ee::error ee::err-data)))))))
136 (eval-expr-error-message ee::error nil t)
139 (eval-expr-print 'prin1 ee::result (current-buffer)))
141 (setq values (cons ee::result values))
142 (eval-expr-display-message eval-expr-output-buffer-name
144 (eval-expr-print 'prin1 ee::result))))))
147 (defun eval-expr-read-lisp-object-minibuffer (prompt &optional input)
149 (setq input (eval-expr-print 'prin1-to-string input)))
151 (let ((minibuffer-setup-hook minibuffer-setup-hook)
157 (add-hook 'minibuffer-setup-hook 'eval-expr-minibuffer-setup)
159 (condition-case err-data
162 (read-from-minibuffer prompt
164 (cons input (1+ index))
166 (and (boundp 'read-expression-map)
169 'read-expression-history))
172 (setq result (read-from-string input))
173 (setq expr (car result))
174 (setq index (cdr result))
177 ;; This mimics a useful test done in read_minbuf (which is
178 ;; called by Fread_from_minibuffer) when expflag is true. But
179 ;; this test doesn't happen when calling Fread_from_string
180 ;; directly as we've done here, so do it now in lisp.
181 (while (< i (length input))
182 (or (memq (aref input i) eval-expr-whitespace)
183 (error "Trailing garbage following expression"))
188 (eval-expr-error-message err-data t))))
191 (defun eval-expr-minibuffer-setup ()
192 (set-syntax-table emacs-lisp-mode-syntax-table))
197 (defun eval-expr-error-message (condition-data &optional waitp raw-error)
198 (let ((error (car condition-data))
199 (data (cdr condition-data))
200 (cursor-in-echo-area t)
205 (setq error (car error)))
209 (setq data (car data)))
213 (setq error-str (get error 'error-message)))
215 (and (eval-expr-display-message eval-expr-error-buffer-name
217 (format "Error: %s" (or error-str error)))
219 (format "Error: %s" data))
221 (format "%s: %s" error-str data))
223 (format "Error: %s; Data: %s" error data))))
225 (sit-for eval-expr-error-message-delay))))
227 (defun eval-expr-display-message (output-buffer thunk)
228 (let* ((buffer (generate-new-buffer " *"))
229 (standard-output buffer)
233 (cond ((stringp thunk) ; this is a cheat
237 (goto-char (point-min))
238 (move-to-column (1- (frame-width)))
240 (< (point) (window-width (minibuffer-window))))
241 (message "%s" (buffer-substring (point-min) (point-max))))
243 (setq echo-area-p nil)
244 (with-output-to-temp-buffer output-buffer
246 (set-buffer output-buffer)
247 (or (eq major-mode 'emacs-lisp-mode)
249 (insert-buffer buffer))))))
253 (put 'eval-expr-display-message 'lisp-indent-function 1)
255 (defun eval-expr-print (func &rest args)
256 (let ((print-level eval-expr-print-level)
257 (print-length eval-expr-print-length))
262 ;;; eval-expr.el ends here.