comparison lisp/ilisp/comint-v18.el @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children ac2d302a0011
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 ;;; -*-Emacs-Lisp-*- General command interpreter in a window stuff
2 ;;; Copyright Olin Shivers (1988).
3 ;;; Please imagine a long, tedious, legalistic 5-page gnu-style copyright
4 ;;; notice appearing here to the effect that you may use this code any
5 ;;; way you like, as long as you don't charge money for it, remove this
6 ;;; notice, or hold me liable for its results.
7
8 ;;; This hopefully generalises shell mode, lisp mode, tea mode, soar mode,...
9 ;;; Hacked from tea.el and shell.el by Olin Shivers (shivers@cs.cmu.edu). 8/88
10
11 ;;; This file defines a general command-interpreter-in-a-buffer package
12 ;;; (comint mode). The idea is that you can build specific process-in-a-buffer
13 ;;; modes on top of comint mode -- e.g., lisp, shell, scheme, T, soar, ....
14 ;;; This way, all these specific packages share a common base functionality,
15 ;;; and a common set of bindings, which makes them easier to use (and
16 ;;; saves code, implementation time, etc., etc.).
17 ;;;
18 ;;; Several packages are already defined using comint mode:
19 ;;; - The file cmushell.el defines cmushell and cmulisp mode.
20 ;;; Cmushell and cmulisp mode are similar to, and intended to replace,
21 ;;; their counterparts in the standard gnu emacs release (in shell.el).
22 ;;; These replacements are more featureful, robust, and uniform than the
23 ;;; released versions. The key bindings in lisp mode are also more compatible
24 ;;; with the bindings of Hemlock and Zwei (the Lisp Machine emacs).
25 ;;;
26 ;;; - The file cmuscheme.el defines inferior-scheme mode.
27 ;;; - The file tea.el tunes scheme and inferior-scheme modes for T.
28 ;;; - The file soar.el tunes lisp and inferior-lisp modes for Soar.
29
30 ;;; For documentation on the functionality provided by comint mode, and
31 ;;; the hooks available for customising it, see the comments below.
32 ;;; For further information on the standard derived modes (shell,
33 ;;; inferior-lisp, inferior-scheme, ...), see the relevant source files.
34
35 ;;; Please send me bug reports, bug fixes, and extensions, so that I can
36 ;;; merge them into the master source.
37
38 ;;; For hints on converting existing process modes (e.g., tex-mode,
39 ;;; background, dbx, gdb, kermit, prolog, telnet) to use comint-mode
40 ;;; instead of shell-mode, see the notes at the end of this file.
41
42 (provide 'comint)
43
44
45 ;;; Brief Command Documentation:
46 ;;;============================================================================
47 ;;; Comint Mode Commands: (common to all derived modes, like cmushell & cmulisp
48 ;;; mode)
49 ;;;
50 ;;; m-p comint-previous-input Cycle backwards in input history
51 ;;; m-n comint-next-input Cycle forwards
52 ;;; c-c r comint-previous-input-matching Search backwards in input history
53 ;;; return comint-send-input
54 ;;; c-a comint-bol Beginning of line; skip prompt.
55 ;;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
56 ;;; c-c c-u comint-kill-input ^u
57 ;;; c-c c-w backward-kill-word ^w
58 ;;; c-c c-c comint-interrupt-subjob ^c
59 ;;; c-c c-z comint-stop-subjob ^z
60 ;;; c-c c-\ comint-quit-subjob ^\
61 ;;; c-c c-o comint-kill-output Delete last batch of process output
62 ;;; c-c c-r comint-show-output Show last batch of process output
63 ;;;
64 ;;; Not bound by default in comint-mode
65 ;;; send-invisible Read a line w/o echo, and send to proc
66 ;;; (These are bound in shell-mode)
67 ;;; comint-dynamic-complete Complete filename at point.
68 ;;; comint-dynamic-list-completions List completions in help buffer.
69 ;;; comint-replace-by-expanded-filename Expand and complete filename at point;
70 ;;; replace with expanded/completed name.
71 ;;; comint-kill-subjob No mercy.
72 ;;; comint-continue-subjob Send CONT signal to buffer's process
73 ;;; group. Useful if you accidentally
74 ;;; suspend your process (with C-c C-z).
75 ;;;
76 ;;; Bound for RMS -- I prefer the input history stuff, but you might like 'em.
77 ;;; m-P comint-msearch-input Search backwards for prompt
78 ;;; m-N comint-psearch-input Search forwards for prompt
79 ;;; C-cR comint-msearch-input-matching Search backwards for prompt & string
80
81 ;;; comint-mode-hook is the comint mode hook. Basically for your keybindings.
82 ;;; comint-load-hook is run after loading in this package.
83
84
85 ;;; Buffer Local Variables:
86 ;;;============================================================================
87 ;;; Comint mode buffer local variables:
88 ;;; comint-prompt-regexp - string comint-bol uses to match prompt.
89 ;;; comint-last-input-end - marker For comint-kill-output command
90 ;;; input-ring-size - integer For the input history
91 ;;; input-ring - ring mechanism
92 ;;; input-ring-index - marker ...
93 ;;; comint-last-input-match - string ...
94 ;;; comint-get-old-input - function Hooks for specific
95 ;;; comint-input-sentinel - function process-in-a-buffer
96 ;;; comint-input-filter - function modes.
97 (defvar comint-prompt-regexp "^"
98 "Regexp to recognise prompts in the inferior process.
99 Defaults to \"^\", the null string at BOL.
100
101 Good choices:
102 Canonical Lisp: \"^[^> ]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
103 Lucid Common Lisp: \"^\\(>\\|\\(->\\)+\\) *\"
104 franz: \"^\\(->\\|<[0-9]*>:\\) *\"
105 kcl: \"^>+ *\"
106 shell: \"^[^#$%>]*[#$%>] *\"
107 T: \"^>+ *\"
108
109 This is a good thing to set in mode hooks.")
110
111 (defvar input-ring-size 30
112 "Size of input history ring.")
113
114 ;;; Here are the per-interpreter hooks.
115 (defvar comint-get-old-input (function comint-get-old-input-default)
116 "Function that submits old text in comint mode.
117 This function is called when return is typed while the point is in old text.
118 It returns the text to be submitted as process input. The default is
119 comint-get-old-input-default, which grabs the current line, and strips off
120 leading text matching comint-prompt-regexp")
121
122 (defvar comint-input-sentinel (function ignore)
123 "Called on each input submitted to comint mode process by comint-send-input.
124 Thus it can, for instance, track cd/pushd/popd commands issued to the csh.")
125
126 (defvar comint-input-filter
127 (function (lambda (str) (not (string-match "\\`\\s *\\'" str))))
128 "Predicate for filtering additions to input history.
129 Only inputs answering true to this function are saved on the input
130 history list. Default is to save anything that isn't all whitespace")
131
132 (defvar comint-mode-hook '()
133 "Called upon entry into comint-mode")
134
135 (defvar comint-mode-map nil)
136
137 ;; Added for ILISP
138 (defvar comint-input-chunk-size 512)
139
140
141
142 (defun comint-mode ()
143 "Major mode for interacting with an inferior interpreter.
144 Interpreter name is same as buffer name, sans the asterisks.
145 Return at end of buffer sends line as input.
146 Return not at end copies rest of line to end and sends it.
147
148 This mode is typically customised to create inferior-lisp-mode,
149 shell-mode, etc.. This can be done by setting the hooks
150 comint-input-sentinel, comint-input-filter, and comint-get-old-input to
151 appropriate functions, and the variable comint-prompt-regexp to
152 the appropriate regular expression.
153
154 An input history is maintained of size input-ring-size, and
155 can be accessed with the commands comint-next-input [\\[comint-next-input]] and
156 comint-previous-input [\\[comint-previous-input]]. Commands not keybound by
157 default are send-invisible, comint-dynamic-complete, and
158 comint-list-dynamic-completions.
159 \\{comint-mode-map}
160 If you accidentally suspend your process, use \\[comint-continue-subjob]
161 to continue it.
162
163 Entry to this mode runs the hooks on comint-mode-hook"
164 (interactive)
165 (let ((old-ring (and (assq 'input-ring (buffer-local-variables))
166 (boundp 'input-ring)
167 input-ring)))
168 (kill-all-local-variables)
169 (setq major-mode 'comint-mode)
170 (setq mode-name "Comint")
171 (setq mode-line-process '(": %s"))
172 (use-local-map comint-mode-map)
173 (make-local-variable 'comint-last-input-end)
174 (setq comint-last-input-end (make-marker))
175 (make-local-variable 'comint-last-input-match)
176 (setq comint-last-input-match "")
177 (make-variable-buffer-local 'comint-prompt-regexp) ; Don't set; default
178 (make-variable-buffer-local 'input-ring-size) ; ...to global val.
179 (make-local-variable 'input-ring)
180 (make-local-variable 'input-ring-index)
181 (setq input-ring-index 0)
182 (make-variable-buffer-local 'comint-get-old-input)
183 (make-variable-buffer-local 'comint-input-sentinel)
184 (make-variable-buffer-local 'comint-input-filter)
185 (run-hooks 'comint-mode-hook)
186 ;Do this after the hook so the user can mung INPUT-RING-SIZE w/his hook.
187 ;The test is so we don't lose history if we run comint-mode twice in
188 ;a buffer.
189 (setq input-ring (if (ring-p old-ring) old-ring
190 (make-ring input-ring-size)))))
191
192 (if comint-mode-map
193 nil
194 (setq comint-mode-map (make-sparse-keymap))
195 (define-key comint-mode-map "\ep" 'comint-previous-input)
196 (define-key comint-mode-map "\en" 'comint-next-input)
197 (define-key comint-mode-map "\C-m" 'comint-send-input)
198 (define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof)
199 (define-key comint-mode-map "\C-a" 'comint-bol)
200 (define-key comint-mode-map "\C-c\C-u" 'comint-kill-input)
201 (define-key comint-mode-map "\C-c\C-w" 'backward-kill-word)
202 (define-key comint-mode-map "\C-c\C-c" 'comint-interrupt-subjob)
203 (define-key comint-mode-map "\C-c\C-z" 'comint-stop-subjob)
204 (define-key comint-mode-map "\C-c\C-\\" 'comint-quit-subjob)
205 (define-key comint-mode-map "\C-c\C-o" 'comint-kill-output)
206 (define-key comint-mode-map "\C-cr" 'comint-previous-input-matching)
207 (define-key comint-mode-map "\C-c\C-r" 'comint-show-output)
208 ;;; Here's the prompt-search stuff I installed for RMS to try...
209 (define-key comint-mode-map "\eP" 'comint-msearch-input)
210 (define-key comint-mode-map "\eN" 'comint-psearch-input)
211 (define-key comint-mode-map "\C-cR" 'comint-msearch-input-matching))
212
213
214 ;;; This function is used to make a full copy of the comint mode map,
215 ;;; so that client modes won't interfere with each other. This function
216 ;;; isn't necessary in emacs 18.5x, but we keep it around for 18.4x versions.
217 (defun full-copy-sparse-keymap (km)
218 "Recursively copy the sparse keymap KM"
219 (cond ((consp km)
220 (cons (full-copy-sparse-keymap (car km))
221 (full-copy-sparse-keymap (cdr km))))
222 (t km)))
223
224 (defun comint-check-proc (buffer-name)
225 "True if there is a process associated w/buffer BUFFER-NAME, and
226 it is alive (status RUN or STOP)."
227 (let ((proc (get-buffer-process buffer-name)))
228 (and proc (memq (process-status proc) '(run stop)))))
229
230 ;;; Note that this guy, unlike shell.el's make-shell, barfs if you pass it ()
231 ;;; for the second argument (program).
232 (defun make-comint (name program &optional startfile &rest switches)
233 (let* ((buffer (get-buffer-create (concat "*" name "*")))
234 (proc (get-buffer-process buffer)))
235 ;; If no process, or nuked process, crank up a new one and put buffer in
236 ;; comint mode. Otherwise, leave buffer and existing process alone.
237 (cond ((or (not proc) (not (memq (process-status proc) '(run stop))))
238 (comint-exec buffer name program startfile switches)
239 (save-excursion
240 (set-buffer buffer)
241 (comint-mode)))) ; Install local vars, mode, keymap, ...
242 buffer))
243
244 (defun comint-exec (buffer name command startfile switches)
245 "Fires up a process in buffer for comint modes.
246 Blasts any old process running in the buffer. Doesn't set the buffer mode.
247 You can use this to cheaply run a series of processes in the same comint
248 buffer."
249 (save-excursion
250 (set-buffer buffer)
251 (let ((proc (get-buffer-process buffer))) ; Blast any old process.
252 (if proc (delete-process proc)))
253 ;; Crank up a new process
254 (let ((proc (apply 'start-process name buffer (concat exec-directory "env")
255 (format "TERMCAP=emacs:co#%d:tc=unknown:"
256 (screen-width))
257 "TERM=emacs" "EMACS=t" "-" command switches)))
258 ;; Feed it the startfile.
259 (cond (startfile
260 ;;This is guaranteed to wait long enough
261 ;;but has bad results if the comint does not prompt at all
262 ;; (while (= size (buffer-size))
263 ;; (sleep-for 1))
264 ;;I hope 1 second is enough!
265 (sleep-for 1)
266 (goto-char (point-max))
267 (insert-file-contents startfile)
268 (setq startfile (buffer-substring (point) (point-max)))
269 (delete-region (point) (point-max))
270 (process-send-string proc startfile)))
271 ;; Jump to the end, and set the process mark.
272 (goto-char (point-max))
273 (set-marker (process-mark proc) (point)))
274 buffer))
275
276
277
278 ;;; Ring Code
279 ;;;============================================================================
280 ;;; This code defines a ring data structure. A ring is a
281 ;;; (hd-index tl-index . vector)
282 ;;; list. You can insert to, remove from, and rotate a ring. When the ring
283 ;;; fills up, insertions cause the oldest elts to be quietly dropped.
284 ;;;
285 ;;; HEAD = index of the newest item on the ring.
286 ;;; TAIL = index of the oldest item on the ring.
287 ;;;
288 ;;; These functions are used by the input history mechanism, but they can
289 ;;; be used for other purposes as well.
290
291 (defun ring-p (x)
292 "T if X is a ring; NIL otherwise."
293 (and (consp x) (integerp (car x))
294 (consp (cdr x)) (integerp (car (cdr x)))
295 (vectorp (cdr (cdr x)))))
296
297 (defun make-ring (size)
298 "Make a ring that can contain SIZE elts"
299 (cons 1 (cons 0 (make-vector (+ size 1) nil))))
300
301 (defun ring-plus1 (index veclen)
302 "INDEX+1, with wraparound"
303 (let ((new-index (+ index 1)))
304 (if (= new-index veclen) 0 new-index)))
305
306 (defun ring-minus1 (index veclen)
307 "INDEX-1, with wraparound"
308 (- (if (= 0 index) veclen index) 1))
309
310 (defun ring-length (ring)
311 (let ((hd (car ring)) (tl (car (cdr ring))) (siz (length (cdr (cdr ring)))))
312 (let ((len (if (<= hd tl) (+ 1 (- tl hd)) (+ 1 tl (- siz hd)))))
313 (if (= len siz) 0 len))))
314
315 (defun ring-empty-p (ring)
316 (= 0 (ring-length ring)))
317
318 (defun ring-insert (ring item)
319 "Insert a new item onto the ring. If the ring is full, dump the oldest
320 item to make room."
321 (let* ((vec (cdr (cdr ring))) (len (length vec))
322 (new-hd (ring-minus1 (car ring) len)))
323 (setcar ring new-hd)
324 (aset vec new-hd item)
325 (if (ring-empty-p ring) ;overflow -- dump one off the tail.
326 (setcar (cdr ring) (ring-minus1 (car (cdr ring)) len)))))
327
328 (defun ring-remove (ring)
329 "Remove the oldest item retained on the ring."
330 (if (ring-empty-p ring) (error "Ring empty")
331 (let ((tl (car (cdr ring))) (vec (cdr (cdr ring))))
332 (set-car (cdr ring) (ring-minus1 tl (length vec)))
333 (aref vec tl))))
334
335 ;;; This isn't actually used in this package. I just threw it in in case
336 ;;; someone else wanted it. If you want rotating-ring behavior on your history
337 ;;; retrieval (analagous to kill ring behavior), this function is what you
338 ;;; need. I should write the yank-input and yank-pop-input-or-kill to go with
339 ;;; this, and not bind it to a key by default, so it would be available to
340 ;;; people who want to bind it to a key. But who would want it? Blech.
341 (defun ring-rotate (ring n)
342 (if (not (= n 0))
343 (if (ring-empty-p ring) ;Is this the right error check?
344 (error "ring empty")
345 (let ((hd (car ring)) (tl (car (cdr ring))) (vec (cdr (cdr ring))))
346 (let ((len (length vec)))
347 (while (> n 0)
348 (setq tl (ring-plus1 tl len))
349 (aset ring tl (aref ring hd))
350 (setq hd (ring-plus1 hd len))
351 (setq n (- n 1)))
352 (while (< n 0)
353 (setq hd (ring-minus1 hd len))
354 (aset vec hd (aref vec tl))
355 (setq tl (ring-minus1 tl len))
356 (setq n (- n 1))))
357 (set-car ring hd)
358 (set-car (cdr ring) tl)))))
359
360 (defun comint-mod (n m)
361 "Returns N mod M. M is positive. Answer is guaranteed to be non-negative,
362 and less than m."
363 (let ((n (% n m)))
364 (if (>= n 0) n
365 (+ n
366 (if (>= m 0) m (- m)))))) ; (abs m)
367
368 (defun ring-ref (ring index)
369 (let ((numelts (ring-length ring)))
370 (if (= numelts 0) (error "indexed empty ring")
371 (let* ((hd (car ring)) (tl (car (cdr ring))) (vec (cdr (cdr ring)))
372 (index (comint-mod index numelts))
373 (vec-index (comint-mod (+ index hd)
374 (length vec))))
375 (aref vec vec-index)))))
376
377
378 ;;; Input history retrieval commands
379 ;;; M-p -- previous input M-n -- next input
380 ;;; C-c r -- previous input matching
381 ;;; ===========================================================================
382
383 (defun comint-previous-input (arg)
384 "Cycle backwards through input history."
385 (interactive "*p")
386 (let ((len (ring-length input-ring)))
387 (cond ((<= len 0)
388 (message "Empty input ring")
389 (ding))
390 ((not (comint-after-pmark-p))
391 (message "Not after process mark")
392 (ding))
393 (t
394 (cond ((eq last-command 'comint-previous-input)
395 (delete-region (mark) (point))
396 (set-mark (point)))
397 (t
398 (setq input-ring-index
399 (if (> arg 0) -1
400 (if (< arg 0) 1 0)))
401 (push-mark (point))))
402 (setq input-ring-index (comint-mod (+ input-ring-index arg) len))
403 (message "%d" (1+ input-ring-index))
404 (insert (ring-ref input-ring input-ring-index))
405 (setq this-command 'comint-previous-input))
406 (t (ding)))))
407
408 (defun comint-next-input (arg)
409 "Cycle forwards through input history."
410 (interactive "*p")
411 (comint-previous-input (- arg)))
412
413 (defvar comint-last-input-match ""
414 "Last string searched for by comint input history search, for defaulting.
415 Buffer local variable.")
416
417 (defun comint-previous-input-matching (str)
418 "Searches backwards through input history for substring match"
419 (interactive (let ((s (read-from-minibuffer
420 (format "Command substring (default %s): "
421 comint-last-input-match))))
422 (list (if (string= s "") comint-last-input-match s))))
423 ; (interactive "sCommand substring: ")
424 (setq comint-last-input-match str) ; update default
425 (let ((str (regexp-quote str))
426 (len (ring-length input-ring))
427 (n 0))
428 (while (and (<= n len) (not (string-match str (ring-ref input-ring n))))
429 (setq n (+ n 1)))
430 (cond ((<= n len) (comint-previous-input (+ n 1)))
431 (t (error "Not found.")))))
432
433 ;;; These next three commands are alternatives to the input history commands --
434 ;;; comint-next-input, comint-previous-input and
435 ;;; comint-previous-input-matching. They search through the process buffer
436 ;;; text looking for occurrences of the prompt. RMS likes them better;
437 ;;; I don't. Bound to M-P, M-N, and C-c R (uppercase P, N, and R) for
438 ;;; now. Try'em out. Go with what you like...
439
440 ;;; comint-msearch-input-matching prompts for a string, not a regexp.
441 ;;; This could be considered to be the wrong thing. I decided to keep it
442 ;;; simple, and not make the user worry about regexps. This, of course,
443 ;;; limits functionality.
444
445 (defun comint-psearch-input ()
446 "Search forwards for next occurrence of prompt and skip to end of line.
447 \(prompt is anything matching regexp comint-prompt-regexp)"
448 (interactive)
449 (if (re-search-forward comint-prompt-regexp (point-max) t)
450 (end-of-line)
451 (error "No occurrence of prompt found")))
452
453 (defun comint-msearch-input ()
454 "Search backwards for previous occurrence of prompt and skip to end of line.
455 Search starts from beginning of current line."
456 (interactive)
457 (let ((p (save-excursion
458 (beginning-of-line)
459 (cond ((re-search-backward comint-prompt-regexp (point-min) t)
460 (end-of-line)
461 (point))
462 (t nil)))))
463 (if p (goto-char p)
464 (error "No occurrence of prompt found"))))
465
466 (defun comint-msearch-input-matching (str)
467 "Search backwards for occurrence of prompt followed by STRING.
468 STRING is prompted for, and is NOT a regular expression."
469 (interactive (let ((s (read-from-minibuffer
470 (format "Command (default %s): "
471 comint-last-input-match))))
472 (list (if (string= s "") comint-last-input-match s))))
473 ; (interactive "sCommand: ")
474 (setq comint-last-input-match str) ; update default
475 (let* ((r (concat comint-prompt-regexp (regexp-quote str)))
476 (p (save-excursion
477 (beginning-of-line)
478 (cond ((re-search-backward r (point-min) t)
479 (end-of-line)
480 (point))
481 (t nil)))))
482 (if p (goto-char p)
483 (error "No match"))))
484
485 (defun comint-send-input ()
486 "Send input to process. After the process output mark, sends all text
487 from the process mark to point as input to the process. Before the
488 process output mark, calls value of variable comint-get-old-input to retrieve
489 old input, copies it to the end of the buffer, and sends it. A terminal
490 newline is also inserted into the buffer and sent to the process. In either
491 case, value of variable comint-input-sentinel is called on the input before
492 sending it. The input is entered into the input history ring, if value of
493 variable comint-input-filter returns T when called on the input.
494
495 comint-get-old-input, comint-input-sentinel, and comint-input-filter are chosen
496 according to the command interpreter running in the buffer. E.g.,
497 If the interpreter is the csh,
498 comint-get-old-input is the default: take the current line, discard any
499 initial string matching regexp comint-prompt-regexp.
500 comint-input-sentinel monitors input for \"cd\", \"pushd\", and \"popd\"
501 commands. When it sees one, it cd's the buffer.
502 comint-input-filter is the default: returns T if the input isn't all white
503 space.
504
505 If the comint is Lucid Common Lisp,
506 comint-get-old-input snarfs the sexp ending at point.
507 comint-input-sentinel does nothing.
508 comint-input-filter returns NIL if the input matches input-filter-regexp,
509 which matches (1) all whitespace (2) :a, :c, etc.
510
511 Similarly for Soar, Scheme, etc.."
512 (interactive)
513 ;; Note that the input string does not include its terminal newline.
514 (let ((proc (get-buffer-process (current-buffer))))
515 (if (not proc) (error "Current buffer has no process")
516 (let* ((pmark (process-mark proc))
517 (pmark-val (marker-position pmark))
518 (input (if (>= (point) pmark-val)
519 (buffer-substring pmark (point))
520 (let ((copy (funcall comint-get-old-input)))
521 (goto-char pmark)
522 (insert copy)
523 copy))))
524 (insert ?\n)
525 (if (funcall comint-input-filter input) (ring-insert input-ring input))
526 (funcall comint-input-sentinel input)
527 (process-send-string proc input)
528 (process-send-string proc "\n")
529 (set-marker (process-mark proc) (point))
530 (set-marker comint-last-input-end (point))))))
531
532 (defun comint-get-old-input-default ()
533 "Default for comint-get-old-input: take the current line, and discard
534 any initial text matching comint-prompt-regexp."
535 (save-excursion
536 (beginning-of-line)
537 (comint-skip-prompt)
538 (let ((beg (point)))
539 (end-of-line)
540 (buffer-substring beg (point)))))
541
542 (defun comint-skip-prompt ()
543 "Skip past the text matching regexp comint-prompt-regexp.
544 If this takes us past the end of the current line, don't skip at all."
545 (let ((eol (save-excursion (end-of-line) (point))))
546 (if (and (looking-at comint-prompt-regexp)
547 (<= (match-end 0) eol))
548 (goto-char (match-end 0)))))
549
550
551 (defun comint-after-pmark-p ()
552 "Is point after the process output marker?"
553 ;; Since output could come into the buffer after we looked at the point
554 ;; but before we looked at the process marker's value, we explicitly
555 ;; serialise. This is just because I don't know whether or not emacs
556 ;; services input during execution of lisp commands.
557 (let ((proc-pos (marker-position
558 (process-mark (get-buffer-process (current-buffer))))))
559 (<= proc-pos (point))))
560
561 (defun comint-bol (arg)
562 "Goes to the beginning of line, then skips past the prompt, if any.
563 If a prefix argument is given (\\[universal-argument]), then no prompt skip
564 -- go straight to column 0.
565
566 The prompt skip is done by skipping text matching the regular expression
567 comint-prompt-regexp, a buffer local variable.
568
569 If you don't like this command, reset c-a to beginning-of-line
570 in your hook, comint-mode-hook."
571 (interactive "P")
572 (beginning-of-line)
573 (if (null arg) (comint-skip-prompt)))
574
575 ;;; These two functions are for entering text you don't want echoed or
576 ;;; saved -- typically passwords to ftp, telnet, or somesuch.
577 ;;; Just enter m-x send-invisible and type in your line.
578
579 (defun comint-read-noecho (prompt)
580 "Prompt the user with argument PROMPT. Read a single line of text
581 without echoing, and return it. Note that the keystrokes comprising
582 the text can still be recovered (temporarily) with \\[view-lossage]. This
583 may be a security bug for some applications."
584 (let ((echo-keystrokes 0)
585 (answ "")
586 tem)
587 (if (and (stringp prompt) (not (string= (message prompt) "")))
588 (message prompt))
589 (while (not(or (= (setq tem (read-char)) ?\^m)
590 (= tem ?\n)))
591 (setq answ (concat answ (char-to-string tem))))
592 (message "")
593 answ))
594
595 (defun send-invisible (str)
596 "Read a string without echoing, and send it to the process running
597 in the current buffer. A new-line is additionally sent. String is not
598 saved on comint input history list.
599 Security bug: your string can still be temporarily recovered with
600 \\[view-lossage]."
601 ; (interactive (list (comint-read-noecho "Enter non-echoed text")))
602 (interactive "P") ; Defeat snooping via C-x esc
603 (let ((proc (get-buffer-process (current-buffer))))
604 (if (not proc) (error "Current buffer has no process")
605 (process-send-string proc
606 (if (stringp str) str
607 (comint-read-noecho "Enter non-echoed text")))
608 (process-send-string proc "\n"))))
609
610 ;;; Random input hackage
611
612 (defun comint-kill-output ()
613 "Kill all output from interpreter since last input."
614 (interactive)
615 (let ((pmark (process-mark (get-buffer-process (current-buffer)))))
616 (kill-region comint-last-input-end pmark)
617 (goto-char pmark)
618 (insert "*** output flushed ***\n")
619 (set-marker pmark (point))))
620
621 (defun comint-show-output ()
622 "Display start of this batch of interpreter output at top of window.
623 Also put cursor there."
624 (interactive)
625 (goto-char comint-last-input-end)
626 (backward-char)
627 (beginning-of-line)
628 (set-window-start (selected-window) (point))
629 (end-of-line))
630
631 (defun comint-interrupt-subjob ()
632 "Interrupt the current subjob."
633 (interactive)
634 (interrupt-process nil t))
635
636 (defun comint-kill-subjob ()
637 "Send kill signal to the current subjob."
638 (interactive)
639 (kill-process nil t))
640
641 (defun comint-quit-subjob ()
642 "Send quit signal to the current subjob."
643 (interactive)
644 (quit-process nil t))
645
646 (defun comint-stop-subjob ()
647 "Stop the current subjob.
648 WARNING: if there is no current subjob, you can end up suspending
649 the top-level process running in the buffer. If you accidentally do
650 this, use \\[comint-continue-subjob] to resume the process. (This
651 is not a problem with most shells, since they ignore this signal.)"
652 (interactive)
653 (stop-process nil t))
654
655 (defun comint-continue-subjob ()
656 "Send CONT signal to process buffer's process group.
657 Useful if you accidentally suspend the top-level process."
658 (interactive)
659 (continue-process nil t))
660
661 (defun comint-kill-input ()
662 "Kill all text from last stuff output by interpreter to point."
663 (interactive)
664 (let* ((pmark (process-mark (get-buffer-process (current-buffer))))
665 (p-pos (marker-position pmark)))
666 (if (> (point) p-pos)
667 (kill-region pmark (point)))))
668
669 (defun comint-delchar-or-maybe-eof (arg)
670 "Delete ARG characters forward, or send an EOF to lisp if at end of buffer."
671 (interactive "p")
672 (if (eobp)
673 (process-send-eof)
674 (delete-char arg)))
675
676
677
678
679 ;;; Support for source-file processing commands.
680 ;;;============================================================================
681 ;;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have
682 ;;; commands that process files of source text (e.g. loading or compiling
683 ;;; files). So the corresponding process-in-a-buffer modes have commands
684 ;;; for doing this (e.g., lisp-load-file). The functions below are useful
685 ;;; for defining these commands.
686 ;;;
687 ;;; Alas, these guys don't do exactly the right thing for Lisp, Scheme
688 ;;; and Soar, in that they don't know anything about file extensions.
689 ;;; So the compile/load interface gets the wrong default occasionally.
690 ;;; The load-file/compile-file default mechanism could be smarter -- it
691 ;;; doesn't know about the relationship between filename extensions and
692 ;;; whether the file is source or executable. If you compile foo.lisp
693 ;;; with compile-file, then the next load-file should use foo.bin for
694 ;;; the default, not foo.lisp. This is tricky to do right, particularly
695 ;;; because the extension for executable files varies so much (.o, .bin,
696 ;;; .lbin, .mo, .vo, .ao, ...).
697
698
699 ;;; COMINT-SOURCE-DEFAULT -- determines defaults for source-file processing
700 ;;; commands.
701 ;;;
702 ;;; COMINT-CHECK-SOURCE -- if FNAME is in a modified buffer, asks you if you
703 ;;; want to save the buffer before issuing any process requests to the command
704 ;;; interpreter.
705 ;;;
706 ;;; COMINT-GET-SOURCE -- used by the source-file processing commands to prompt
707 ;;; for the file to process.
708
709 ;;; (COMINT-SOURCE-DEFAULT previous-dir/file source-modes)
710 ;;;============================================================================
711 ;;; This function computes the defaults for the load-file and compile-file
712 ;;; commands for tea, soar, cmulisp, and cmuscheme modes.
713 ;;;
714 ;;; - PREVIOUS-DIR/FILE is a pair (directory . filename) from the last
715 ;;; source-file processing command. NIL if there hasn't been one yet.
716 ;;; - SOURCE-MODES is a list used to determine what buffers contain source
717 ;;; files: if the major mode of the buffer is in SOURCE-MODES, it's source.
718 ;;; Typically, (lisp-mode) or (scheme-mode).
719 ;;;
720 ;;; If the command is given in a file buffer whose major modes is in
721 ;;; SOURCE-MODES, then the the filename is the default file, and the
722 ;;; file's directory is the default directory.
723 ;;;
724 ;;; If the buffer isn't a source file buffer (e.g., it's the process buffer),
725 ;;; then the default directory & file are what was used in the last source-file
726 ;;; processing command (i.e., PREVIOUS-DIR/FILE). If this is the first time
727 ;;; the command has been run (PREVIOUS-DIR/FILE is nil), the default directory
728 ;;; is the cwd, with no default file. (\"no default file\" = nil)
729 ;;;
730 ;;; SOURCE-REGEXP is typically going to be something like (tea-mode)
731 ;;; for T programs, (lisp-mode) for Lisp programs, (soar-mode lisp-mode)
732 ;;; for Soar programs, etc.
733 ;;;
734 ;;; The function returns a pair: (default-directory . default-file).
735
736 (defun comint-source-default (previous-dir/file source-modes)
737 (cond ((and buffer-file-name (memq major-mode source-modes))
738 (cons (file-name-directory buffer-file-name)
739 (file-name-nondirectory buffer-file-name)))
740 (previous-dir/file)
741 (t
742 (cons default-directory nil))))
743
744
745 ;;; (COMINT-CHECK-SOURCE fname)
746 ;;;============================================================================
747 ;;; Prior to loading or compiling (or otherwise processing) a file (in the CMU
748 ;;; process-in-a-buffer modes), this function can be called on the filename.
749 ;;; If the file is loaded into a buffer, and the buffer is modified, the user
750 ;;; is queried to see if he wants to save the buffer before proceeding with
751 ;;; the load or compile.
752
753 (defun comint-check-source (fname)
754 (let ((buff (get-file-buffer fname)))
755 (if (and buff
756 (buffer-modified-p buff)
757 (y-or-n-p (format "Save buffer %s first? "
758 (buffer-name buff))))
759 ;; save BUFF.
760 (let ((old-buffer (current-buffer)))
761 (set-buffer buff)
762 (save-buffer)
763 (set-buffer old-buffer)))))
764
765
766 ;;; (COMINT-GET-SOURCE prompt prev-dir/file source-modes mustmatch-p)
767 ;;;============================================================================
768 ;;; COMINT-GET-SOURCE is used to prompt for filenames in command-interpreter
769 ;;; commands that process source files (like loading or compiling a file).
770 ;;; It prompts for the filename, provides a default, if there is one,
771 ;;; and returns the result filename.
772 ;;;
773 ;;; See COMINT-SOURCE-DEFAULT for more on determining defaults.
774 ;;;
775 ;;; PROMPT is the prompt string. PREV-DIR/FILE is the (directory . file) pair
776 ;;; from the last source processing command. SOURCE-MODES is a list of major
777 ;;; modes used to determine what file buffers contain source files. (These
778 ;;; two arguments are used for determining defaults). If MUSTMATCH-P is true,
779 ;;; then the filename reader will only accept a file that exists.
780 ;;;
781 ;;; A typical use:
782 ;;; (interactive (comint-get-source "Compile file: " prev-lisp-dir/file
783 ;;; "\\.lisp\\'" t))
784
785 (defun comint-get-source (prompt prev-dir/file source-regexp mustmatch-p)
786 (let* ((def (comint-source-default prev-dir/file source-regexp))
787 (defdir (car def))
788 (deffile (cdr def))
789 (ans (read-file-name (if deffile (format "%s(default %s) "
790 prompt deffile)
791 prompt)
792 defdir
793 (concat defdir deffile)
794 mustmatch-p)))
795 (list (expand-file-name (substitute-in-file-name ans)))))
796
797
798 ;;; Filename completion in a buffer
799 ;;; ===========================================================================
800 ;;; Useful completion functions, courtesy of the Ergo group.
801 ;;; M-<Tab> will complete the filename at the cursor as much as possible
802 ;;; M-? will display a list of completions in the help buffer.
803
804 ;;; Three commands:
805 ;;; comint-dynamic-complete Complete filename at point.
806 ;;; comint-dynamic-list-completions List completions in help buffer.
807 ;;; comint-replace-by-expanded-filename Expand and complete filename at point;
808 ;;; replace with expanded/completed name.
809
810 ;;; These are not installed in the comint-mode keymap. But they are
811 ;;; available for people who want them. Shell-mode installs them:
812 ;;; (define-key cmushell-mode-map "\M-\t" 'comint-dynamic-complete)
813 ;;; (define-key cmushell-mode-map "\M-?" 'comint-dynamic-list-completions)))
814 ;;;
815 ;;; Commands like this are fine things to put in load hooks if you
816 ;;; want them present in specific modes. Example:
817 ;;; (setq cmushell-load-hook
818 ;;; '((lambda () (define-key lisp-mode-map "\M-\t"
819 ;;; 'comint-replace-by-expanded-filename))))
820 ;;;
821
822
823 (defun comint-match-partial-pathname ()
824 "Returns the string of an existing filename or causes and error."
825 (if (save-excursion (backward-char 1) (looking-at "\\s ")) ""
826 (save-excursion
827 (re-search-backward "[^~/A-Za-z0-9---_.$#,]+")
828 (re-search-forward "[~/A-Za-z0-9---_.$#,]+")
829 (substitute-in-file-name
830 (buffer-substring (match-beginning 0) (match-end 0))))))
831
832 (defun comint-replace-by-expanded-filename ()
833 "Replace filename at point with expanded, completed name"
834 (interactive)
835 (let* ((pathname (comint-match-partial-pathname))
836 (pathdir (file-name-directory pathname))
837 (pathnondir (file-name-nondirectory pathname))
838 (completion (file-name-completion pathnondir
839 (or pathdir default-directory))))
840 (cond ((null completion)
841 (message "No completions of %s." pathname)
842 (ding))
843 ((eql completion t)
844 (message "Unique completion."))
845 (t ; this means a string was returned.
846 (delete-region (match-beginning 0) (match-end 0))
847 (insert pathdir completion)))))
848
849 (defun comint-dynamic-complete ()
850 "Dynamically complete the filename at point."
851 (interactive)
852 (let* ((pathname (comint-match-partial-pathname))
853 (pathdir (file-name-directory pathname))
854 (pathnondir (file-name-nondirectory pathname))
855 (completion (file-name-completion pathnondir
856 (or pathdir default-directory))))
857 (cond ((null completion)
858 (message "No completions of %s." pathname)
859 (ding))
860 ((eql completion t)
861 (message "Unique completion."))
862 (t ; this means a string was returned.
863 (insert (substring completion (length pathnondir)))))))
864
865 (defun comint-dynamic-list-completions ()
866 "List in help buffer all possible completions of the filename at point."
867 (interactive)
868 (let* ((pathname (comint-match-partial-pathname))
869 (pathdir (file-name-directory pathname))
870 (pathnondir (file-name-nondirectory pathname))
871 (completions
872 (file-name-all-completions pathnondir
873 (or pathdir default-directory))))
874 (cond ((null completions)
875 (message "No completions of %s." pathname)
876 (ding))
877 (t (with-output-to-temp-buffer "*Help*"
878 (display-completion-list completions))))))
879
880 ; Ergo bindings
881 ; (global-set-key "\M-\t" 'comint-replace-by-expanded-filename)
882 ; (global-set-key "\M-?" 'comint-dynamic-list-completions)
883 ; (define-key shell-mode-map "\M-\t" 'comint-dynamic-complete)
884
885 ;;; Log the user, so I know who's using the package during the beta test
886 ;;; period. This just inserts the user's name and current time into a
887 ;;; central file.
888 (defun comint-log-user ()
889 (interactive)
890 (if (file-writable-p "/afs/cs/user/shivers/lib/emacs/logdir/comint.log")
891 (let ((u (getenv "USER"))
892 (old-buff (current-buffer)))
893 (message "logging user in beta test database...")
894 (find-file "/afs/cs/user/shivers/lib/emacs/logdir/comint.log")
895 (cond ((search-forward u nil 'to-end)
896 (search-forward "| ")
897 (kill-line 1))
898 (t (insert (format "%s\t%s\t| " u (current-time-string)))))
899 (insert (format "%s\n" (current-time-string)))
900 (let ((make-backup-files nil)) (save-buffer))
901 (kill-buffer (current-buffer))
902 (set-buffer old-buff))))
903 (comint-log-user)
904
905
906 ;;; Converting process modes to use comint mode
907 ;;; ===========================================================================
908 ;;; Several gnu packages (tex-mode, background, dbx, gdb, kermit, prolog,
909 ;;; telnet are some) use the shell package as clients. Most of them would
910 ;;; be better off using the comint package, but they predate it.
911 ;;;
912 ;;; Altering these packages to use comint mode should greatly
913 ;;; improve their functionality, and is fairly easy.
914 ;;;
915 ;;; Renaming variables
916 ;;; Most of the work is renaming variables and functions. These are the common
917 ;;; ones:
918 ;;; Local variables:
919 ;;; last-input-end comint-last-input-end
920 ;;; last-input-start <unnecessary>
921 ;;; shell-prompt-pattern comint-prompt-regexp
922 ;;; shell-set-directory-error-hook <no equivalent>
923 ;;; Miscellaneous:
924 ;;; shell-set-directory <unnecessary>
925 ;;; shell-mode-map comint-mode-map
926 ;;; Commands:
927 ;;; shell-send-input comint-send-input
928 ;;; shell-send-eof comint-delchar-or-maybe-eof
929 ;;; kill-shell-input comint-kill-input
930 ;;; interrupt-shell-subjob comint-interrupt-subjob
931 ;;; stop-shell-subjob comint-stop-subjob
932 ;;; quit-shell-subjob comint-quit-subjob
933 ;;; kill-shell-subjob comint-kill-subjob
934 ;;; kill-output-from-shell comint-kill-output
935 ;;; show-output-from-shell comint-show-output
936 ;;; copy-last-shell-input Use comint-previous-input/comint-next-input
937 ;;;
938 ;;; LAST-INPUT-START is no longer necessary because inputs are stored on the
939 ;;; input history ring. SHELL-SET-DIRECTORY is gone, its functionality taken
940 ;;; over by SHELL-DIRECTORY-TRACKER, the shell mode's comint-input-sentinel.
941 ;;; Comint mode does not provide functionality equivalent to
942 ;;; shell-set-directory-error-hook; it is gone.
943 ;;;
944 ;;; If you are implementing some process-in-a-buffer mode, called foo-mode, do
945 ;;; *not* create the comint-mode local variables in your foo-mode function.
946 ;;; This is not modular. Instead, call comint-mode, and let *it* create the
947 ;;; necessary comint-specific local variables. Then create the
948 ;;; foo-mode-specific local variables in foo-mode. Set the buffer's keymap to
949 ;;; be foo-mode-map, and it's mode to be foo-mode. Set the comint-mode hooks
950 ;;; (comint-prompt-regexp, comint-input-filter, comint-input-sentinel,
951 ;;; comint-get-old-input) that need to be different from the defaults. Call
952 ;;; foo-mode-hook, and you're done. Don't run the comint-mode hook yourself;
953 ;;; comint-mode will take care of it. The following example, from cmushell.el,
954 ;;; is typical:
955 ;;;
956 ;;; (defun shell-mode ()
957 ;;; (interactive)
958 ;;; (comint-mode)
959 ;;; (setq comint-prompt-regexp shell-prompt-pattern)
960 ;;; (setq major-mode 'shell-mode)
961 ;;; (setq mode-name "Shell")
962 ;;; (cond ((not shell-mode-map)
963 ;;; (setq shell-mode-map (full-copy-sparse-keymap comint-mode-map))
964 ;;; (define-key shell-mode-map "\M-\t" 'comint-dynamic-complete)
965 ;;; (define-key shell-mode-map "\M-?"
966 ;;; 'comint-dynamic-list-completions)))
967 ;;; (use-local-map shell-mode-map)
968 ;;; (make-local-variable 'shell-directory-stack)
969 ;;; (setq shell-directory-stack nil)
970 ;;; (setq comint-input-sentinel 'shell-directory-tracker)
971 ;;; (run-hooks 'shell-mode-hook))
972 ;;;
973 ;;;
974 ;;; Note that make-comint is different from make-shell in that it
975 ;;; doesn't have a default program argument. If you give make-shell
976 ;;; a program name of NIL, it cleverly chooses one of explicit-shell-name,
977 ;;; $ESHELL, $SHELL, or /bin/sh. If you give make-comint a program argument
978 ;;; of NIL, it barfs. Adjust your code accordingly...
979 ;;;
980
981 ;;; Do the user's customisation...
982
983 (defvar comint-load-hook nil
984 "This hook is run when comint is loaded in.
985 This is a good place to put keybindings.")
986
987 (run-hooks 'comint-load-hook)