Fix up comment convention on the arch-tag lines.
[bpt/emacs.git] / lisp / ielm.el
CommitLineData
813f532d 1;;; ielm.el --- interaction mode for Emacs Lisp
b578f267 2
c90f2757 3;; Copyright (C) 1994, 2001, 2002, 2003, 2004, 2005,
409cc4a3 4;; 2006, 2007, 2008 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
b4aa6026 15;; the Free Software Foundation; either version 3, or (at your option)
813f532d
RS
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
6546555e 172 (if (featurep 'xemacs)
813f532d
RS
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
6ad18d45 303(defun ielm-is-whitespace-or-comment (string)
2ef180f7 304 "Return non-nil if STRING is all whitespace or a comment."
6ad18d45
BG
305 (or (string= string "")
306 (string-match "\\`[ \t\n]*\\(?:;.*\\)*\\'" string)))
813f532d 307
813f532d
RS
308;;; Evaluation
309
e848854a
RS
310(defun ielm-eval-input (ielm-string)
311 "Evaluate the Lisp expression IELM-STRING, and pretty-print the result."
813f532d 312 ;; This is the function that actually `sends' the input to the
e848854a 313 ;; `inferior Lisp process'. All comint-send-input does is works out
813f532d
RS
314 ;; what that input is. What this function does is evaluates that
315 ;; input and produces `output' which gets inserted into the buffer,
316 ;; along with a new prompt. A better way of doing this might have
317 ;; been to actually send the output to the `cat' process, and write
318 ;; this as in output filter that converted sexps in the output
319 ;; stream to their evaluated value. But that would have involved
320 ;; more process coordination than I was happy to deal with.
e848854a
RS
321 ;;
322 ;; NOTE: all temporary variables in this function will be in scope
323 ;; during the eval, and so need to have non-clashing names.
324 (let (ielm-form ; form to evaluate
325 ielm-pos ; End posn of parse in string
326 ielm-result ; Result, or error message
327 ielm-error-type ; string, nil if no error
328 (ielm-output "") ; result to display
329 (ielm-wbuf ielm-working-buffer) ; current buffer after evaluation
330 (ielm-pmark (ielm-pm)))
6ad18d45 331 (if (not (ielm-is-whitespace-or-comment ielm-string))
813f532d
RS
332 (progn
333 (condition-case err
334 (let (rout)
e848854a
RS
335 (setq rout (read-from-string ielm-string))
336 (setq ielm-form (car rout))
337 (setq ielm-pos (cdr rout)))
568bbe5e 338 (error (setq ielm-result (error-message-string err))
e848854a
RS
339 (setq ielm-error-type "Read error")))
340 (if ielm-error-type nil
341 ;; Make sure working buffer has not been killed
342 (if (not (buffer-name ielm-working-buffer))
343 (setq ielm-result "Working buffer has been killed"
344 ielm-error-type "IELM Error"
345 ielm-wbuf (current-buffer))
6ad18d45
BG
346 (if (ielm-is-whitespace-or-comment
347 (substring ielm-string ielm-pos))
5d9655bb
RS
348 ;; To correctly handle the ielm-local variables *,
349 ;; ** and ***, we need a temporary buffer to be
350 ;; current at entry to the inner of the next two let
351 ;; forms. We need another temporary buffer to exit
352 ;; that same let. To avoid problems, neither of
353 ;; these buffers should be alive during the
354 ;; evaluation of ielm-form.
355 (let ((*1 *)
356 (*2 **)
357 (*3 ***)
358 ielm-temp-buffer)
565f89ec 359 (set-match-data ielm-match-data)
e848854a 360 (save-excursion
5d9655bb
RS
361 (with-temp-buffer
362 (condition-case err
363 (unwind-protect
364 ;; The next let form creates default
365 ;; bindings for *, ** and ***. But
366 ;; these default bindings are
367 ;; identical to the ielm-local
368 ;; bindings. Hence, during the
369 ;; evaluation of ielm-form, the
370 ;; ielm-local values are going to be
371 ;; used in all buffers except for
372 ;; other ielm buffers, which override
373 ;; them. Normally, the variables *1,
374 ;; *2 and *3 also have default
375 ;; bindings, which are not overridden.
376 (let ((* *1)
377 (** *2)
378 (*** *3))
379 (kill-buffer (current-buffer))
380 (set-buffer ielm-wbuf)
381 (setq ielm-result (eval ielm-form))
382 (setq ielm-wbuf (current-buffer))
383 (setq
384 ielm-temp-buffer
385 (generate-new-buffer " *ielm-temp*"))
386 (set-buffer ielm-temp-buffer))
387 (when ielm-temp-buffer
388 (kill-buffer ielm-temp-buffer)))
5967d963 389 (error (setq ielm-result (error-message-string err))
5d9655bb
RS
390 (setq ielm-error-type "Eval error"))
391 (quit (setq ielm-result "Quit during evaluation")
392 (setq ielm-error-type "Eval error")))))
565f89ec 393 (setq ielm-match-data (match-data)))
e848854a
RS
394 (setq ielm-error-type "IELM error")
395 (setq ielm-result "More than one sexp in input"))))
813f532d
RS
396
397 ;; If the eval changed the current buffer, mention it here
e848854a
RS
398 (if (eq ielm-wbuf ielm-working-buffer) nil
399 (message "current buffer is now: %s" ielm-wbuf)
400 (setq ielm-working-buffer ielm-wbuf))
813f532d 401
e848854a
RS
402 (goto-char ielm-pmark)
403 (if (not ielm-error-type)
813f532d
RS
404 (condition-case err
405 ;; Self-referential objects cause loops in the printer, so
406 ;; trap quits here. May as well do errors, too
e848854a
RS
407 (setq ielm-output (concat ielm-output (pp-to-string ielm-result)))
408 (error (setq ielm-error-type "IELM Error")
409 (setq ielm-result "Error during pretty-printing (bug in pp)"))
410 (quit (setq ielm-error-type "IELM Error")
411 (setq ielm-result "Quit during pretty-printing"))))
412 (if ielm-error-type
813f532d
RS
413 (progn
414 (if ielm-noisy (ding))
e848854a
RS
415 (setq ielm-output (concat ielm-output "*** " ielm-error-type " *** "))
416 (setq ielm-output (concat ielm-output ielm-result)))
d38e7d5f 417 ;; There was no error, so shift the *** values
71d54f88
RS
418 (setq *** **)
419 (setq ** *)
420 (setq * ielm-result))
e848854a 421 (setq ielm-output (concat ielm-output "\n"))))
016b8f71 422 (setq ielm-output (concat ielm-output ielm-prompt-internal))
e848854a 423 (comint-output-filter (ielm-process) ielm-output)))
813f532d
RS
424
425;;; Process and marker utilities
426
427(defun ielm-process nil
e848854a 428 ;; Return the current buffer's process.
813f532d
RS
429 (get-buffer-process (current-buffer)))
430
431(defun ielm-pm nil
e848854a 432 ;; Return the process mark of the current buffer.
813f532d
RS
433 (process-mark (get-buffer-process (current-buffer))))
434
435(defun ielm-set-pm (pos)
e848854a 436 ;; Set the process mark in the current buffer to POS.
813f532d
RS
437 (set-marker (process-mark (get-buffer-process (current-buffer))) pos))
438
439;;; Major mode
440
95b20f3b
RS
441(put 'inferior-emacs-lisp-mode 'mode-class 'special)
442
813f532d 443(defun inferior-emacs-lisp-mode nil
e848854a
RS
444 "Major mode for interactively evaluating Emacs Lisp expressions.
445Uses the interface provided by `comint-mode' (which see).
446
66f06793
SM
447* \\<ielm-map>\\[ielm-send-input] evaluates the sexp following the prompt. There must be at most
448 one top level sexp per prompt.
813f532d 449
e848854a
RS
450* \\[ielm-return] inserts a newline and indents, or evaluates a
451 complete expression (but see variable `ielm-dynamic-return').
452 Inputs longer than one line are moved to the line following the
453 prompt (but see variable `ielm-dynamic-multiline-inputs').
454
690ec649 455* \\[comint-dynamic-complete] completes Lisp symbols (or filenames, within strings),
e848854a 456 or indents the line if there is nothing to complete.
813f532d 457
e848854a
RS
458The current working buffer may be changed (with a call to
459`set-buffer', or with \\[ielm-change-working-buffer]), and its value
460is preserved between successive evaluations. In this way, expressions
461may be evaluated in a different buffer than the *ielm* buffer.
76364803
JB
462By default, its name is shown on the mode line; you can always display
463it with \\[ielm-print-working-buffer], or the buffer itself with \\[ielm-display-working-buffer].
813f532d 464
5d9655bb
RS
465During evaluations, the values of the variables `*', `**', and `***'
466are the results of the previous, second previous and third previous
467evaluations respectively. If the working buffer is another IELM
468buffer, then the values in the working buffer are used. The variables
469`*1', `*2' and `*3', yield the process buffer values.
470
e848854a
RS
471Expressions evaluated by IELM are not subject to `debug-on-quit' or
472`debug-on-error'.
813f532d 473
291cfc0c 474The behavior of IELM may be customized with the following variables:
0382cf8f 475* To stop beeping on error, set `ielm-noisy' to nil.
813f532d 476* If you don't like the prompt, you can change it by setting `ielm-prompt'.
759f960a
LT
477* If you do not like that the prompt is (by default) read-only, set
478 `ielm-prompt-read-only' to nil.
0382cf8f 479* Set `ielm-dynamic-return' to nil for bindings like `lisp-interaction-mode'.
813f532d
RS
480* Entry to this mode runs `comint-mode-hook' and `ielm-mode-hook'
481 (in that order).
482
0382cf8f 483Customized bindings may be defined in `ielm-map', which currently contains:
813f532d
RS
484\\{ielm-map}"
485 (interactive)
9c5e65b2
LT
486 (delay-mode-hooks
487 (comint-mode))
813f532d 488 (setq comint-prompt-regexp (concat "^" (regexp-quote ielm-prompt)))
85ab9f4e 489 (set (make-local-variable 'paragraph-separate) "\\'")
813f532d
RS
490 (make-local-variable 'paragraph-start)
491 (setq paragraph-start comint-prompt-regexp)
492 (setq comint-input-sender 'ielm-input-sender)
493 (setq comint-process-echoes nil)
27cfbf4b 494 (make-local-variable 'comint-dynamic-complete-functions)
016b8f71
LT
495 (set (make-local-variable 'ielm-prompt-internal) ielm-prompt)
496 (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only)
690ec649 497 (setq comint-dynamic-complete-functions
813f532d 498 '(ielm-tab comint-replace-by-expanded-history ielm-complete-filename ielm-complete-symbol))
e848854a 499 (setq comint-get-old-input 'ielm-get-old-input)
34ce46c8 500 (make-local-variable 'comint-completion-addsuffix)
016b8f71 501 (setq comint-completion-addsuffix '("/" . ""))
813f532d
RS
502 (setq major-mode 'inferior-emacs-lisp-mode)
503 (setq mode-name "IELM")
76364803 504 (setq mode-line-process '(":%s on " (:eval (buffer-name ielm-working-buffer))))
813f532d
RS
505 (use-local-map ielm-map)
506 (set-syntax-table emacs-lisp-mode-syntax-table)
507
508 (make-local-variable 'indent-line-function)
509 (make-local-variable 'ielm-working-buffer)
510 (setq ielm-working-buffer (current-buffer))
511 (setq indent-line-function 'ielm-indent-line)
950086e6
KH
512 (make-local-variable 'fill-paragraph-function)
513 (setq fill-paragraph-function 'lisp-fill-paragraph)
813f532d 514
e848854a 515 ;; Value holders
fed9da13 516 (make-local-variable '*)
5d9655bb 517 (setq * nil)
fed9da13 518 (make-local-variable '**)
5d9655bb 519 (setq ** nil)
fed9da13 520 (make-local-variable '***)
5d9655bb 521 (setq *** nil)
565f89ec 522 (set (make-local-variable 'ielm-match-data) nil)
813f532d 523
9d42eea3
RS
524 ;; font-lock support
525 (make-local-variable 'font-lock-defaults)
690ec649 526 (setq font-lock-defaults
9d42eea3 527 '(ielm-font-lock-keywords nil nil ((?: . "w") (?- . "w") (?* . "w"))))
690ec649 528
813f532d 529 ;; A dummy process to keep comint happy. It will never get any input
20b13009 530 (unless (comint-check-proc (current-buffer))
33a65176
JR
531 ;; Was cat, but on non-Unix platforms that might not exist, so
532 ;; use hexl instead, which is part of the Emacs distribution.
66f06793
SM
533 (condition-case nil
534 (start-process "ielm" (current-buffer) "hexl")
535 (file-error (start-process "ielm" (current-buffer) "cat")))
e5927b52 536 (set-process-query-on-exit-flag (ielm-process) nil)
813f532d 537 (goto-char (point-max))
71296446 538
20b13009
MB
539 ;; Lisp output can include raw characters that confuse comint's
540 ;; carriage control code.
541 (set (make-local-variable 'comint-inhibit-carriage-motion) t)
542
813f532d
RS
543 ;; Add a silly header
544 (insert ielm-header)
545 (ielm-set-pm (point-max))
85ab9f4e 546 (unless comint-use-prompt-regexp
76364803
JB
547 (let ((inhibit-read-only t))
548 (add-text-properties
549 (point-min) (point-max)
550 '(rear-nonsticky t field output inhibit-line-move-field-capture t))))
016b8f71 551 (comint-output-filter (ielm-process) ielm-prompt-internal)
813f532d
RS
552 (set-marker comint-last-input-start (ielm-pm))
553 (set-process-filter (get-buffer-process (current-buffer)) 'comint-output-filter))
20b13009 554
d395b3b5 555 (run-mode-hooks 'ielm-mode-hook))
813f532d 556
e848854a
RS
557(defun ielm-get-old-input nil
558 ;; Return the previous input surrounding point
559 (save-excursion
560 (beginning-of-line)
561 (if (looking-at comint-prompt-regexp) nil
562 (re-search-backward comint-prompt-regexp))
563 (comint-skip-prompt)
564 (buffer-substring (point) (progn (forward-sexp 1) (point)))))
565
813f532d
RS
566;;; User command
567
9e983c78
RS
568;;;###autoload (add-hook 'same-window-buffer-names "*ielm*")
569
e848854a 570;;;###autoload
813f532d 571(defun ielm nil
e848854a 572 "Interactively evaluate Emacs Lisp expressions.
9e983c78 573Switches to the buffer `*ielm*', or creates it if it does not exist."
813f532d 574 (interactive)
ee9cd72d
LT
575 (let (old-point)
576 (unless (comint-check-proc "*ielm*")
577 (with-current-buffer (get-buffer-create "*ielm*")
016b8f71 578 (unless (zerop (buffer-size)) (setq old-point (point)))
ee9cd72d
LT
579 (inferior-emacs-lisp-mode)))
580 (pop-to-buffer "*ielm*")
581 (when old-point (push-mark old-point))))
813f532d 582
896546cd
RS
583(provide 'ielm)
584
cbee283d 585;; arch-tag: ef60e4c0-9c4f-4bdb-8402-271313329790
e848854a 586;;; ielm.el ends here