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