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