Mercurial > hg > xemacs-beta
comparison lisp/edebug/eval-reg.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | b82b59fe008d |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; eval-reg.el --- Redefine eval-region, and subrs that use it, in Lisp | |
2 | |
3 ;; Copyright (C) 1994 Daniel LaLiberte | |
4 | |
5 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu> | |
6 ;; Keywords: lisp | |
7 | |
8 ;; This file is part of GNU Emacs. | |
9 | |
10 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
11 ;; it under the terms of the GNU General Public License as published by | |
12 ;; the Free Software Foundation; either version 2, or (at your option) | |
13 ;; any later version. | |
14 | |
15 ;; GNU Emacs is distributed in the hope that it will be useful, | |
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 ;; GNU General Public License for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
21 ;; along with GNU Emacs; see the file COPYING. If not, write to | |
22 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
23 | |
24 ;;;; Commentary: | |
25 | |
26 ;;; eval-region, eval-buffer, and eval-current-buffer are redefined in | |
27 ;;; Lisp to allow customizations by Lisp code. eval-region calls | |
28 ;;; `read', `eval', and `prin1', so Lisp replacements of these | |
29 ;;; functions will affect eval-region and anything else that calls it. | |
30 ;;; eval-buffer and eval-current-buffer are redefined in Lisp to call | |
31 ;;; eval-region on the buffer. | |
32 | |
33 ;;; Because of dynamic binding, all local variables are protected from | |
34 ;;; being seen by eval by giving them funky names. But variables in | |
35 ;;; routines that call eval-region are similarly exposed. | |
36 | |
37 ;;; Perhaps this should be one of several files in an `elisp' package | |
38 ;;; that replaces Emacs Lisp subroutines with Lisp versions of the | |
39 ;;; same. | |
40 | |
41 ;;; Eval-region may be installed, after loading, by calling: | |
42 ;;; (elisp-eval-region-install). Installation can be undone with: | |
43 ;;; (elisp-eval-region-uninstall). | |
44 | |
45 '(defpackage "elisp-eval-region" | |
46 (:nicknames "elisp") | |
47 (:use "elisp") | |
48 (:export | |
49 elisp-eval-region-install | |
50 elisp-eval-region-uninstall | |
51 elisp-eval-region-level | |
52 with-elisp-eval-region | |
53 eval-region | |
54 eval-buffer | |
55 eval-current-buffer | |
56 )) | |
57 '(in-package elisp-eval-region) | |
58 | |
59 ;; Save standard versions. | |
60 (if (not (fboundp 'original-eval-region)) | |
61 (defalias 'original-eval-region (symbol-function 'eval-region))) | |
62 (if (not (fboundp 'original-eval-buffer)) | |
63 (defalias 'original-eval-buffer | |
64 (if (fboundp 'eval-buffer) ;; only in Emacs 19 | |
65 (symbol-function 'eval-buffer) | |
66 'undefined))) | |
67 (if (not (fboundp 'original-eval-current-buffer)) | |
68 (defalias 'original-eval-current-buffer | |
69 (symbol-function 'eval-current-buffer))) | |
70 | |
71 (defvar elisp-eval-region-level 0 | |
72 "If the value is 0, use the original version of `elisp-eval-region'. | |
73 Callers of `elisp-eval-region' should increment `elisp-eval-region-level' | |
74 while the Lisp version should be used. Installing `elisp-eval-region' | |
75 increments it once, and uninstalling decrements it.") | |
76 | |
77 ;; Installing and uninstalling should always be used in pairs, | |
78 ;; or just install once and never uninstall. | |
79 (defun elisp-eval-region-install () | |
80 (interactive) | |
81 (defalias 'eval-region 'elisp-eval-region) | |
82 (defalias 'eval-buffer 'elisp-eval-buffer) | |
83 (defalias 'eval-current-buffer 'elisp-eval-current-buffer) | |
84 (setq elisp-eval-region-level (1+ elisp-eval-region-level))) | |
85 | |
86 (defun elisp-eval-region-uninstall () | |
87 (interactive) | |
88 (if (> 1 elisp-eval-region-level) | |
89 (setq elisp-eval-region-level (1- elisp-eval-region-level)) | |
90 (setq elisp-eval-region-level 0) | |
91 (defalias 'eval-region (symbol-function 'original-eval-region)) | |
92 (defalias 'eval-buffer (symbol-function 'original-eval-buffer)) | |
93 (defalias 'eval-current-buffer | |
94 (symbol-function 'original-eval-current-buffer)) | |
95 )) | |
96 | |
97 (put 'with-elisp-eval-region 'lisp-indent-function 1) | |
98 (put 'with-elisp-eval-region 'lisp-indent-hook 1) | |
99 (put 'with-elisp-eval-region 'edebug-form-spec t) | |
100 | |
101 (defmacro with-elisp-eval-region (flag &rest body) | |
102 "If FLAG is nil, decrement `eval-region-level' while executing BODY. | |
103 The effect of decrementing all the way to zero is that `eval-region' | |
104 will use the original `eval-region', which may be the Emacs subr or some | |
105 previous redefinition. Before calling this macro, this package should | |
106 already have been installed, using `elisp-eval-region-install', which | |
107 increments the count once. So if another package still requires the | |
108 Lisp version of the code, the count will still be non-zero. | |
109 | |
110 The count is not bound locally by this macro, so changes by BODY to | |
111 its value will not be lost." | |
112 (` (let ((elisp-code (function (lambda () (,@ body))))) | |
113 (if (not (, flag)) | |
114 (unwind-protect | |
115 (progn | |
116 (setq elisp-eval-region-level (1- elisp-eval-region-level)) | |
117 (funcall elisp-code)) | |
118 (setq elisp-eval-region-level (1+ elisp-eval-region-level))) | |
119 (funcall elisp-code))))) | |
120 | |
121 | |
122 (defun elisp-eval-region (elisp-start elisp-end &optional elisp-output) | |
123 "Execute the region as Lisp code. | |
124 When called from programs, expects two arguments, | |
125 giving starting and ending indices in the current buffer | |
126 of the text to be executed. | |
127 Programs can pass third argument PRINTFLAG which controls printing of output: | |
128 nil means discard it; anything else is stream for print. | |
129 | |
130 This version, from `eval-reg.el', allows Lisp customization of read, | |
131 eval, and the printer." | |
132 | |
133 ;; Because this doesnt narrow to the region, one other difference | |
134 ;; concerns inserting whitespace after the expression being evaluated. | |
135 | |
136 (interactive "r") | |
137 (if (= 0 elisp-eval-region-level) | |
138 (original-eval-region elisp-start elisp-end elisp-output) | |
139 (let ((elisp-pnt (point)) | |
140 (elisp-buf (current-buffer));; Outside buffer | |
141 (elisp-inside-buf (current-buffer));; Buffer current while evaling | |
142 ;; Mark the end because it may move. | |
143 (elisp-end-marker (set-marker (make-marker) elisp-end)) | |
144 elisp-form | |
145 elisp-val) | |
146 (goto-char elisp-start) | |
147 (elisp-skip-whitespace) | |
148 (while (< (point) elisp-end-marker) | |
149 (setq elisp-form (read elisp-buf)) | |
150 | |
151 (let ((elisp-current-buffer (current-buffer))) | |
152 ;; Restore the inside current-buffer. | |
153 (set-buffer elisp-inside-buf) | |
154 (setq elisp-val (eval elisp-form)) | |
155 ;; Remember current buffer for next time. | |
156 (setq elisp-inside-buf (current-buffer)) | |
157 ;; Should this be protected? | |
158 (set-buffer elisp-current-buffer)) | |
159 | |
160 (if elisp-output | |
161 (let ((standard-output (or elisp-output t))) | |
162 (setq values (cons elisp-val values)) | |
163 (if (eq standard-output t) | |
164 (prin1 elisp-val) | |
165 (princ "\n") | |
166 (prin1 elisp-val) | |
167 (princ "\n") | |
168 ))) | |
169 (goto-char (min (max elisp-end-marker (point)) | |
170 (progn (elisp-skip-whitespace) (point)))) | |
171 ) ; while | |
172 (if elisp-output nil | |
173 ;; like save-excursion recovery, but done only if no error occurs | |
174 ;; but mark is not restored | |
175 (set-buffer elisp-buf) | |
176 (goto-char elisp-pnt)) | |
177 nil))) | |
178 | |
179 | |
180 (defun elisp-skip-whitespace () | |
181 ;; Leave point before the next token, skipping white space and comments. | |
182 (skip-chars-forward " \t\r\n\f") | |
183 (while (= (following-char) ?\;) | |
184 (skip-chars-forward "^\n\r") ; skip the comment | |
185 (skip-chars-forward " \t\r\n\f"))) | |
186 | |
187 | |
188 (defun elisp-eval-current-buffer (&optional elisp-output) | |
189 "Execute the current buffer as Lisp code. | |
190 Programs can pass argument PRINTFLAG which controls printing of output: | |
191 nil means discard it; anything else is stream for print. | |
192 | |
193 This version calls `eval-region' on the whole buffer." | |
194 ;; The standard eval-current-buffer doesn't use eval-region. | |
195 (interactive) | |
196 (eval-region (point-min) (point-max) elisp-output)) | |
197 | |
198 | |
199 (defun elisp-eval-buffer (&optional elisp-bufname elisp-printflag) | |
200 "Execute BUFFER as Lisp code. Use current buffer if BUFFER is nil. | |
201 Programs can pass argument PRINTFLAG which controls printing of | |
202 output: nil means discard it; anything else is stream for print. | |
203 | |
204 This version calls `eval-region' on the whole buffer." | |
205 (interactive) | |
206 (if (null elisp-bufname) | |
207 (setq elisp-bufname (current-buffer))) | |
208 (save-excursion | |
209 (set-buffer (or (get-buffer elisp-bufname) | |
210 (error "No such buffer: %s" elisp-bufname))) | |
211 (eval-region (point-min) (point-max) elisp-printflag))) | |
212 | |
213 | |
214 (provide 'eval-reg) | |
215 | |
216 ;;; eval-reg.el ends here |