Update years in copyright notice; nfc.
[bpt/emacs.git] / lisp / ielm.el
CommitLineData
813f532d 1;;; ielm.el --- interaction mode for Emacs Lisp
b578f267 2
aaef169d
TTN
3;; Copyright (C) 1994, 2002, 2003, 2004, 2005,
4;; 2006 Free Software Foundation, Inc.
813f532d
RS
5
6;; Author: David Smith <maa036@lancaster.ac.uk>
4228277d 7;; Maintainer: FSF
813f532d
RS
8;; Created: 25 Feb 1994
9;; Keywords: lisp
10
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
b578f267 24;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
25;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26;; Boston, MA 02110-1301, USA.
813f532d
RS
27
28;;; Commentary:
29
e848854a 30;; Provides a nice interface to evaluating Emacs Lisp expressions.
813f532d
RS
31;; Input is handled by the comint package, and output is passed
32;; through the pretty-printer.
33
813f532d
RS
34;; To start: M-x ielm. Type C-h m in the *ielm* buffer for more info.
35
813f532d
RS
36;;; Code:
37
38(require 'comint)
39(require 'pp)
40
41;;; User variables
42
94114394
RS
43(defgroup ielm nil
44 "Interaction mode for Emacs Lisp."
45 :group 'lisp)
46
47
48(defcustom ielm-noisy t
49 "*If non-nil, IELM will beep on error."
50 :type 'boolean
51 :group 'ielm)
813f532d 52
759f960a
LT
53(defcustom ielm-prompt-read-only t
54 "If non-nil, the IELM prompt is read only.
7655d378 55The read only region includes the newline before the prompt.
759f960a 56Setting this variable does not affect existing IELM runs.
016b8f71 57This works by setting the buffer-local value of `comint-prompt-read-only'.
7655d378
LT
58Setting that value directly affects new prompts in the current buffer.
59
60If this option is enabled, then the safe way to temporarily
61override the read-only-ness of ielm prompts is to call
62`comint-kill-whole-line' or `comint-kill-region' with no
63narrowing in effect. This way you will be certain that none of
64the remaining prompts will be accidentally messed up. You may
65wish to put something like the following in your `.emacs' file:
66
67\(add-hook 'ielm-mode-hook
68 '(lambda ()
1ab3c04f 69 (define-key ielm-map \"\\C-w\" 'comint-kill-region)
7655d378
LT
70 (define-key ielm-map [C-S-backspace]
71 'comint-kill-whole-line)))
72
73If you set `comint-prompt-read-only' to t, you might wish to use
74`comint-mode-hook' and `comint-mode-map' instead of
75`ielm-mode-hook' and `ielm-map'. That will affect all comint
76buffers, including ielm buffers. If you sometimes use ielm on
77text-only terminals or with `emacs -nw', you might wish to use
78another binding for `comint-kill-whole-line'."
759f960a
LT
79 :type 'boolean
80 :group 'ielm
bf247b6e 81 :version "22.1")
759f960a 82
40cf8f25 83(defcustom ielm-prompt "ELISP> "
759f960a 84 "Prompt used in IELM.
016b8f71 85Setting this variable does not affect existing IELM runs.
ee9cd72d
LT
86
87Interrupting the IELM process with \\<ielm-map>\\[comint-interrupt-subjob],
88and then restarting it using \\[ielm], makes the then current
016b8f71 89default value affect _new_ prompts. Unless the new prompt
ee9cd72d
LT
90differs only in text properties from the old one, IELM will no
91longer recognize the old prompts. However, executing \\[ielm]
92does not update the prompt of an *ielm* buffer with a running process.
9eca7c03 93For IELM buffers that are not called `*ielm*', you can execute
ee9cd72d
LT
94\\[inferior-emacs-lisp-mode] in that IELM buffer to update the value,
95for new prompts. This works even if the buffer has a running process."
40cf8f25 96 :type 'string
759f960a 97 :group 'ielm)
813f532d 98
016b8f71
LT
99(defvar ielm-prompt-internal "ELISP> "
100 "Stored value of `ielm-prompt' in the current IELM buffer.
101This is an internal variable used by IELM. Its purpose is to
102prevent a running IELM process from being messed up when the user
103customizes `ielm-prompt'.")
104
94114394 105(defcustom ielm-dynamic-return t
291cfc0c 106 "*Controls whether \\<ielm-map>\\[ielm-return] has intelligent behavior in IELM.
e848854a 107If non-nil, \\[ielm-return] evaluates input for complete sexps, or inserts a newline
94114394
RS
108and indents for incomplete sexps. If nil, always inserts newlines."
109 :type 'boolean
110 :group 'ielm)
e848854a 111
94114394 112(defcustom ielm-dynamic-multiline-inputs t
e848854a
RS
113 "*Force multiline inputs to start from column zero?
114If non-nil, after entering the first line of an incomplete sexp, a newline
115will be inserted after the prompt, moving the input to the next line.
116This gives more frame width for large indented sexps, and allows functions
94114394
RS
117such as `edebug-defun' to work with such inputs."
118 :type 'boolean
119 :group 'ielm)
813f532d 120
94114394
RS
121(defcustom ielm-mode-hook nil
122 "*Hooks to be run when IELM (`inferior-emacs-lisp-mode') is started."
10fea268 123 :options '(turn-on-eldoc-mode)
94114394
RS
124 :type 'hook
125 :group 'ielm)
813f532d 126
d38e7d5f
RS
127(defvar * nil
128 "Most recent value evaluated in IELM.")
129
130(defvar ** nil
131 "Second-most-recent value evaluated in IELM.")
132
133(defvar *** nil
134 "Third-most-recent value evaluated in IELM.")
690ec649 135
565f89ec
SM
136(defvar ielm-match-data nil
137 "Match data saved at the end of last command.")
138
1322516b 139(defvar *1 nil
5d9655bb
RS
140 "During IELM evaluation, most recent value evaluated in IELM.
141Normally identical to `*'. However, if the working buffer is an IELM
142buffer, distinct from the process buffer, then `*' gives the value in
71296446 143the working buffer, `*1' the value in the process buffer.
5d9655bb
RS
144The intended value is only accessible during IELM evaluation.")
145
146(defvar *2 nil
147 "During IELM evaluation, second-most-recent value evaluated in IELM.
148Normally identical to `**'. However, if the working buffer is an IELM
149buffer, distinct from the process buffer, then `**' gives the value in
150the working buffer, `*2' the value in the process buffer.
151The intended value is only accessible during IELM evaluation.")
152
153(defvar *3 nil
154 "During IELM evaluation, third-most-recent value evaluated in IELM.
155Normally identical to `***'. However, if the working buffer is an IELM
156buffer, distinct from the process buffer, then `***' gives the value in
157the working buffer, `*3' the value in the process buffer.
158The intended value is only accessible during IELM evaluation.")
159
813f532d
RS
160;;; System variables
161
162(defvar ielm-working-buffer nil
e848854a
RS
163 "Buffer in which IELM sexps will be evaluated.
164This variable is buffer-local.")
813f532d 165
690ec649 166(defvar ielm-header
0a13146e 167 "*** Welcome to IELM *** Type (describe-mode) for help.\n"
e848854a 168 "Message to display when IELM is started.")
813f532d
RS
169
170(defvar ielm-map nil)
171(if ielm-map nil
172 (if (string-match "Lucid" emacs-version)
173 ;; Lemacs
174 (progn
175 (setq ielm-map (make-sparse-keymap))
176 (set-keymap-parent ielm-map comint-mode-map))
177 ;; FSF
178 (setq ielm-map (cons 'keymap comint-mode-map)))
179 (define-key ielm-map "\t" 'comint-dynamic-complete)
180 (define-key ielm-map "\C-m" 'ielm-return)
e848854a
RS
181 (define-key ielm-map "\C-j" 'ielm-send-input)
182 (define-key ielm-map "\e\C-x" 'eval-defun) ; for consistency with
183 (define-key ielm-map "\e\t" 'lisp-complete-symbol) ; lisp-interaction-mode
690ec649 184 ;; These bindings are from `lisp-mode-shared-map' -- can you inherit
e848854a 185 ;; from more than one keymap??
690ec649 186 (define-key ielm-map "\e\C-q" 'indent-sexp)
e848854a
RS
187 (define-key ielm-map "\177" 'backward-delete-char-untabify)
188 ;; Some convenience bindings for setting the working buffer
189 (define-key ielm-map "\C-c\C-b" 'ielm-change-working-buffer)
190 (define-key ielm-map "\C-c\C-f" 'ielm-display-working-buffer)
191 (define-key ielm-map "\C-c\C-v" 'ielm-print-working-buffer))
813f532d 192
9d42eea3 193(defvar ielm-font-lock-keywords
016b8f71 194 '(("\\(^\\*\\*\\*[^*]+\\*\\*\\*\\)\\(.*$\\)"
883212ce
SM
195 (1 font-lock-comment-face)
196 (2 font-lock-constant-face)))
9d42eea3 197 "Additional expressions to highlight in ielm buffers.")
690ec649 198
813f532d
RS
199;;; Completion stuff
200
201(defun ielm-tab nil
e5927b52 202 "Possibly indent the current line as Lisp code."
813f532d
RS
203 (interactive)
204 (if (or (eq (preceding-char) ?\n)
205 (eq (char-syntax (preceding-char)) ? ))
206 (progn
207 (ielm-indent-line)
208 t)))
690ec649 209
813f532d 210(defun ielm-complete-symbol nil
e5927b52 211 "Complete the Lisp symbol before point."
e848854a
RS
212 ;; A wrapper for lisp-complete symbol that returns non-nil if
213 ;; completion has occurred
813f532d 214 (let* ((btick (buffer-modified-tick))
e58df0dc 215 (cbuffer (get-buffer "*Completions*"))
813f532d
RS
216 (ctick (and cbuffer (buffer-modified-tick cbuffer))))
217 (lisp-complete-symbol)
218 ;; completion has occurred if:
690ec649 219 (or
813f532d 220 ;; the buffer has been modified
690ec649 221 (not (= btick (buffer-modified-tick)))
a7acbbe4 222 ;; a completions buffer has been modified or created
813f532d
RS
223 (if cbuffer
224 (not (= ctick (buffer-modified-tick cbuffer)))
e58df0dc 225 (get-buffer "*Completions*")))))
813f532d
RS
226
227(defun ielm-complete-filename nil
e848854a 228 "Dynamically complete filename before point, if in a string."
813f532d
RS
229 (if (nth 3 (parse-partial-sexp comint-last-input-start (point)))
230 (comint-dynamic-complete-filename)))
690ec649 231
813f532d 232(defun ielm-indent-line nil
e848854a 233 "Indent the current line as Lisp code if it is not a prompt line."
3250010d 234 (when (save-excursion (comint-bol) (bolp))
813f532d
RS
235 (lisp-indent-line)))
236
e848854a
RS
237;;; Working buffer manipulation
238
239(defun ielm-print-working-buffer nil
240 "Print the current IELM working buffer's name in the echo area."
241 (interactive)
242 (message "The current working buffer is: %s" (buffer-name ielm-working-buffer)))
243
244(defun ielm-display-working-buffer nil
245 "Display the current IELM working buffer.
246Don't forget that selecting that buffer will change its value of `point'
247to its value of `window-point'!"
248 (interactive)
249 (display-buffer ielm-working-buffer)
250 (ielm-print-working-buffer))
251
252(defun ielm-change-working-buffer (buf)
253 "Change the current IELM working buffer to BUF.
254This is the buffer in which all sexps entered at the IELM prompt are
255evaluated. You can achieve the same effect with a call to
256`set-buffer' at the IELM prompt."
257 (interactive "bSet working buffer to: ")
258 (setq ielm-working-buffer (or (get-buffer buf) (error "No such buffer")))
259 (ielm-print-working-buffer))
260
813f532d
RS
261;;; Other bindings
262
263(defun ielm-return nil
e848854a
RS
264 "Newline and indent, or evaluate the sexp before the prompt.
265Complete sexps are evaluated; for incomplete sexps inserts a newline
266and indents. If however `ielm-dynamic-return' is nil, this always
267simply inserts a newline."
813f532d 268 (interactive)
690ec649
SS
269 (if ielm-dynamic-return
270 (let ((state
813f532d
RS
271 (save-excursion
272 (end-of-line)
273 (parse-partial-sexp (ielm-pm)
274 (point)))))
275 (if (and (< (car state) 1) (not (nth 3 state)))
276 (ielm-send-input)
e848854a
RS
277 (if (and ielm-dynamic-multiline-inputs
278 (save-excursion
279 (beginning-of-line)
280 (looking-at comint-prompt-regexp)))
281 (save-excursion
282 (goto-char (ielm-pm))
283 (newline 1)))
813f532d
RS
284 (newline-and-indent)))
285 (newline)))
286
94aba130
RS
287(defvar ielm-input)
288
813f532d 289(defun ielm-input-sender (proc input)
690ec649 290 ;; Just sets the variable ielm-input, which is in the scope of
e848854a 291 ;; `ielm-send-input's call.
813f532d
RS
292 (setq ielm-input input))
293
294(defun ielm-send-input nil
e848854a 295 "Evaluate the Emacs Lisp expression after the prompt."
813f532d 296 (interactive)
016b8f71 297 (let (ielm-input) ; set by ielm-input-sender
813f532d
RS
298 (comint-send-input) ; update history, markers etc.
299 (ielm-eval-input ielm-input)))
300
301;;; Utility functions
302
303(defun ielm-is-whitespace (string)
e848854a 304 "Return non-nil if STRING is all whitespace."
813f532d
RS
305 (or (string= string "") (string-match "\\`[ \t\n]+\\'" string)))
306
813f532d
RS
307;;; Evaluation
308
e848854a
RS
309(defun ielm-eval-input (ielm-string)
310 "Evaluate the Lisp expression IELM-STRING, and pretty-print the result."
813f532d 311 ;; This is the function that actually `sends' the input to the
e848854a 312 ;; `inferior Lisp process'. All comint-send-input does is works out
813f532d
RS
313 ;; what that input is. What this function does is evaluates that
314 ;; input and produces `output' which gets inserted into the buffer,
315 ;; along with a new prompt. A better way of doing this might have
316 ;; been to actually send the output to the `cat' process, and write
317 ;; this as in output filter that converted sexps in the output
318 ;; stream to their evaluated value. But that would have involved
319 ;; more process coordination than I was happy to deal with.
e848854a
RS
320 ;;
321 ;; NOTE: all temporary variables in this function will be in scope
322 ;; during the eval, and so need to have non-clashing names.
323 (let (ielm-form ; form to evaluate
324 ielm-pos ; End posn of parse in string
325 ielm-result ; Result, or error message
326 ielm-error-type ; string, nil if no error
327 (ielm-output "") ; result to display
328 (ielm-wbuf ielm-working-buffer) ; current buffer after evaluation
329 (ielm-pmark (ielm-pm)))
330 (if (not (ielm-is-whitespace ielm-string))
813f532d
RS
331 (progn
332 (condition-case err
333 (let (rout)
e848854a
RS
334 (setq rout (read-from-string ielm-string))
335 (setq ielm-form (car rout))
336 (setq ielm-pos (cdr rout)))
568bbe5e 337 (error (setq ielm-result (error-message-string err))
e848854a
RS
338 (setq ielm-error-type "Read error")))
339 (if ielm-error-type nil
340 ;; Make sure working buffer has not been killed
341 (if (not (buffer-name ielm-working-buffer))
342 (setq ielm-result "Working buffer has been killed"
343 ielm-error-type "IELM Error"
344 ielm-wbuf (current-buffer))
345 (if (ielm-is-whitespace (substring ielm-string ielm-pos))
5d9655bb
RS
346 ;; To correctly handle the ielm-local variables *,
347 ;; ** and ***, we need a temporary buffer to be
348 ;; current at entry to the inner of the next two let
349 ;; forms. We need another temporary buffer to exit
350 ;; that same let. To avoid problems, neither of
351 ;; these buffers should be alive during the
352 ;; evaluation of ielm-form.
353 (let ((*1 *)
354 (*2 **)
355 (*3 ***)
356 ielm-temp-buffer)
565f89ec 357 (set-match-data ielm-match-data)
e848854a 358 (save-excursion
5d9655bb
RS
359 (with-temp-buffer
360 (condition-case err
361 (unwind-protect
362 ;; The next let form creates default
363 ;; bindings for *, ** and ***. But
364 ;; these default bindings are
365 ;; identical to the ielm-local
366 ;; bindings. Hence, during the
367 ;; evaluation of ielm-form, the
368 ;; ielm-local values are going to be
369 ;; used in all buffers except for
370 ;; other ielm buffers, which override
371 ;; them. Normally, the variables *1,
372 ;; *2 and *3 also have default
373 ;; bindings, which are not overridden.
374 (let ((* *1)
375 (** *2)
376 (*** *3))
377 (kill-buffer (current-buffer))
378 (set-buffer ielm-wbuf)
379 (setq ielm-result (eval ielm-form))
380 (setq ielm-wbuf (current-buffer))
381 (setq
382 ielm-temp-buffer
383 (generate-new-buffer " *ielm-temp*"))
384 (set-buffer ielm-temp-buffer))
385 (when ielm-temp-buffer
386 (kill-buffer ielm-temp-buffer)))
5967d963 387 (error (setq ielm-result (error-message-string err))
5d9655bb
RS
388 (setq ielm-error-type "Eval error"))
389 (quit (setq ielm-result "Quit during evaluation")
390 (setq ielm-error-type "Eval error")))))
565f89ec 391 (setq ielm-match-data (match-data)))
e848854a
RS
392 (setq ielm-error-type "IELM error")
393 (setq ielm-result "More than one sexp in input"))))
813f532d
RS
394
395 ;; If the eval changed the current buffer, mention it here
e848854a
RS
396 (if (eq ielm-wbuf ielm-working-buffer) nil
397 (message "current buffer is now: %s" ielm-wbuf)
398 (setq ielm-working-buffer ielm-wbuf))
813f532d 399
e848854a
RS
400 (goto-char ielm-pmark)
401 (if (not ielm-error-type)
813f532d
RS
402 (condition-case err
403 ;; Self-referential objects cause loops in the printer, so
404 ;; trap quits here. May as well do errors, too
e848854a
RS
405 (setq ielm-output (concat ielm-output (pp-to-string ielm-result)))
406 (error (setq ielm-error-type "IELM Error")
407 (setq ielm-result "Error during pretty-printing (bug in pp)"))
408 (quit (setq ielm-error-type "IELM Error")
409 (setq ielm-result "Quit during pretty-printing"))))
410 (if ielm-error-type
813f532d
RS
411 (progn
412 (if ielm-noisy (ding))
e848854a
RS
413 (setq ielm-output (concat ielm-output "*** " ielm-error-type " *** "))
414 (setq ielm-output (concat ielm-output ielm-result)))
d38e7d5f 415 ;; There was no error, so shift the *** values
71d54f88
RS
416 (setq *** **)
417 (setq ** *)
418 (setq * ielm-result))
e848854a 419 (setq ielm-output (concat ielm-output "\n"))))
016b8f71 420 (setq ielm-output (concat ielm-output ielm-prompt-internal))
e848854a 421 (comint-output-filter (ielm-process) ielm-output)))
813f532d
RS
422
423;;; Process and marker utilities
424
425(defun ielm-process nil
e848854a 426 ;; Return the current buffer's process.
813f532d
RS
427 (get-buffer-process (current-buffer)))
428
429(defun ielm-pm nil
e848854a 430 ;; Return the process mark of the current buffer.
813f532d
RS
431 (process-mark (get-buffer-process (current-buffer))))
432
433(defun ielm-set-pm (pos)
e848854a 434 ;; Set the process mark in the current buffer to POS.
813f532d
RS
435 (set-marker (process-mark (get-buffer-process (current-buffer))) pos))
436
437;;; Major mode
438
95b20f3b
RS
439(put 'inferior-emacs-lisp-mode 'mode-class 'special)
440
813f532d 441(defun inferior-emacs-lisp-mode nil
e848854a
RS
442 "Major mode for interactively evaluating Emacs Lisp expressions.
443Uses the interface provided by `comint-mode' (which see).
444
66f06793
SM
445* \\<ielm-map>\\[ielm-send-input] evaluates the sexp following the prompt. There must be at most
446 one top level sexp per prompt.
813f532d 447
e848854a
RS
448* \\[ielm-return] inserts a newline and indents, or evaluates a
449 complete expression (but see variable `ielm-dynamic-return').
450 Inputs longer than one line are moved to the line following the
451 prompt (but see variable `ielm-dynamic-multiline-inputs').
452
690ec649 453* \\[comint-dynamic-complete] completes Lisp symbols (or filenames, within strings),
e848854a 454 or indents the line if there is nothing to complete.
813f532d 455
e848854a
RS
456The current working buffer may be changed (with a call to
457`set-buffer', or with \\[ielm-change-working-buffer]), and its value
458is preserved between successive evaluations. In this way, expressions
459may be evaluated in a different buffer than the *ielm* buffer.
76364803
JB
460By default, its name is shown on the mode line; you can always display
461it with \\[ielm-print-working-buffer], or the buffer itself with \\[ielm-display-working-buffer].
813f532d 462
5d9655bb
RS
463During evaluations, the values of the variables `*', `**', and `***'
464are the results of the previous, second previous and third previous
465evaluations respectively. If the working buffer is another IELM
466buffer, then the values in the working buffer are used. The variables
467`*1', `*2' and `*3', yield the process buffer values.
468
e848854a
RS
469Expressions evaluated by IELM are not subject to `debug-on-quit' or
470`debug-on-error'.
813f532d 471
291cfc0c 472The behavior of IELM may be customized with the following variables:
0382cf8f 473* To stop beeping on error, set `ielm-noisy' to nil.
813f532d 474* If you don't like the prompt, you can change it by setting `ielm-prompt'.
759f960a
LT
475* If you do not like that the prompt is (by default) read-only, set
476 `ielm-prompt-read-only' to nil.
0382cf8f 477* Set `ielm-dynamic-return' to nil for bindings like `lisp-interaction-mode'.
813f532d
RS
478* Entry to this mode runs `comint-mode-hook' and `ielm-mode-hook'
479 (in that order).
480
0382cf8f 481Customized bindings may be defined in `ielm-map', which currently contains:
813f532d
RS
482\\{ielm-map}"
483 (interactive)
9c5e65b2
LT
484 (delay-mode-hooks
485 (comint-mode))
813f532d 486 (setq comint-prompt-regexp (concat "^" (regexp-quote ielm-prompt)))
85ab9f4e 487 (set (make-local-variable 'paragraph-separate) "\\'")
813f532d
RS
488 (make-local-variable 'paragraph-start)
489 (setq paragraph-start comint-prompt-regexp)
490 (setq comint-input-sender 'ielm-input-sender)
491 (setq comint-process-echoes nil)
27cfbf4b 492 (make-local-variable 'comint-dynamic-complete-functions)
016b8f71
LT
493 (set (make-local-variable 'ielm-prompt-internal) ielm-prompt)
494 (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only)
690ec649 495 (setq comint-dynamic-complete-functions
813f532d 496 '(ielm-tab comint-replace-by-expanded-history ielm-complete-filename ielm-complete-symbol))
e848854a 497 (setq comint-get-old-input 'ielm-get-old-input)
34ce46c8 498 (make-local-variable 'comint-completion-addsuffix)
016b8f71 499 (setq comint-completion-addsuffix '("/" . ""))
813f532d
RS
500 (setq major-mode 'inferior-emacs-lisp-mode)
501 (setq mode-name "IELM")
76364803 502 (setq mode-line-process '(":%s on " (:eval (buffer-name ielm-working-buffer))))
813f532d
RS
503 (use-local-map ielm-map)
504 (set-syntax-table emacs-lisp-mode-syntax-table)
505
506 (make-local-variable 'indent-line-function)
507 (make-local-variable 'ielm-working-buffer)
508 (setq ielm-working-buffer (current-buffer))
509 (setq indent-line-function 'ielm-indent-line)
950086e6
KH
510 (make-local-variable 'fill-paragraph-function)
511 (setq fill-paragraph-function 'lisp-fill-paragraph)
813f532d 512
e848854a 513 ;; Value holders
fed9da13 514 (make-local-variable '*)
5d9655bb 515 (setq * nil)
fed9da13 516 (make-local-variable '**)
5d9655bb 517 (setq ** nil)
fed9da13 518 (make-local-variable '***)
5d9655bb 519 (setq *** nil)
565f89ec 520 (set (make-local-variable 'ielm-match-data) nil)
813f532d 521
9d42eea3
RS
522 ;; font-lock support
523 (make-local-variable 'font-lock-defaults)
690ec649 524 (setq font-lock-defaults
9d42eea3 525 '(ielm-font-lock-keywords nil nil ((?: . "w") (?- . "w") (?* . "w"))))
690ec649 526
813f532d 527 ;; A dummy process to keep comint happy. It will never get any input
20b13009 528 (unless (comint-check-proc (current-buffer))
33a65176
JR
529 ;; Was cat, but on non-Unix platforms that might not exist, so
530 ;; use hexl instead, which is part of the Emacs distribution.
66f06793
SM
531 (condition-case nil
532 (start-process "ielm" (current-buffer) "hexl")
533 (file-error (start-process "ielm" (current-buffer) "cat")))
e5927b52 534 (set-process-query-on-exit-flag (ielm-process) nil)
813f532d 535 (goto-char (point-max))
71296446 536
20b13009
MB
537 ;; Lisp output can include raw characters that confuse comint's
538 ;; carriage control code.
539 (set (make-local-variable 'comint-inhibit-carriage-motion) t)
540
813f532d
RS
541 ;; Add a silly header
542 (insert ielm-header)
543 (ielm-set-pm (point-max))
85ab9f4e 544 (unless comint-use-prompt-regexp
76364803
JB
545 (let ((inhibit-read-only t))
546 (add-text-properties
547 (point-min) (point-max)
548 '(rear-nonsticky t field output inhibit-line-move-field-capture t))))
016b8f71 549 (comint-output-filter (ielm-process) ielm-prompt-internal)
813f532d
RS
550 (set-marker comint-last-input-start (ielm-pm))
551 (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter))
20b13009 552
d395b3b5 553 (run-mode-hooks 'ielm-mode-hook))
813f532d 554
e848854a
RS
555(defun ielm-get-old-input nil
556 ;; Return the previous input surrounding point
557 (save-excursion
558 (beginning-of-line)
559 (if (looking-at comint-prompt-regexp) nil
560 (re-search-backward comint-prompt-regexp))
561 (comint-skip-prompt)
562 (buffer-substring (point) (progn (forward-sexp 1) (point)))))
563
813f532d
RS
564;;; User command
565
9e983c78
RS
566;;;###autoload (add-hook 'same-window-buffer-names "*ielm*")
567
e848854a 568;;;###autoload
813f532d 569(defun ielm nil
e848854a 570 "Interactively evaluate Emacs Lisp expressions.
9e983c78 571Switches to the buffer `*ielm*', or creates it if it does not exist."
813f532d 572 (interactive)
ee9cd72d
LT
573 (let (old-point)
574 (unless (comint-check-proc "*ielm*")
575 (with-current-buffer (get-buffer-create "*ielm*")
016b8f71 576 (unless (zerop (buffer-size)) (setq old-point (point)))
ee9cd72d
LT
577 (inferior-emacs-lisp-mode)))
578 (pop-to-buffer "*ielm*")
579 (when old-point (push-mark old-point))))
813f532d 580
896546cd
RS
581(provide 'ielm)
582
ab5796a9 583;;; arch-tag: ef60e4c0-9c4f-4bdb-8402-271313329790
e848854a 584;;; ielm.el ends here