]> code.delx.au - gnu-emacs/blob - lisp/eshell/esh-mode.el
Merge from emacs--devo--0
[gnu-emacs] / lisp / eshell / esh-mode.el
1 ;;; esh-mode.el --- user interface
2
3 ;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004,
4 ;; 2005, 2006, 2007 Free Software Foundation, Inc.
5
6 ;; Author: John Wiegley <johnw@gnu.org>
7
8 ;; This file is part of GNU Emacs.
9
10 ;; GNU Emacs is free software; you can redistribute it and/or modify
11 ;; it under the terms of the GNU General Public License as published by
12 ;; the Free Software Foundation; either version 2, or (at your option)
13 ;; any later version.
14
15 ;; GNU Emacs is distributed in the hope that it will be useful,
16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ;; GNU General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING. If not, write to the
22 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 ;; Boston, MA 02110-1301, USA.
24
25 (provide 'esh-mode)
26
27 (eval-when-compile (require 'esh-maint))
28
29 (defgroup eshell-mode nil
30 "This module contains code for handling input from the user."
31 :tag "User interface"
32 :group 'eshell)
33
34 ;;; Commentary:
35
36 ;; Basically, Eshell is used just like shell mode (<M-x shell>). The
37 ;; keystrokes for navigating the buffer, and accessing the command
38 ;; history, are identical. Unlike shell mode, however, Eshell mode's
39 ;; governing process is Emacs itself. With shell mode, an inferior
40 ;; shell process is executed that communicates with Emacs via comint
41 ;; -- a mode for handling sub-process interaction. Eshell mode, on
42 ;; the other hand, is a truly native Emacs shell. No subprocess are
43 ;; invoked except the ones requested by the user at the prompt.
44 ;;
45 ;; After entering a command, use <RET> to invoke it ([Command
46 ;; invocation]) . If there is a command on disk, it will be executed
47 ;; as in a normal shell. If there is no command by that name on disk,
48 ;; but a Lisp function with that name is defined, the Lisp function
49 ;; will be called, using the arguments passed on the command line.
50 ;;
51 ;; Some of the other features of the command interaction mode are:
52 ;;
53 ;; @ <M-RET> can be used to accumulate further commands while a
54 ;; command is currently running. Since all input is passed to the
55 ;; subprocess being executed, there is no automatic input queueing
56 ;; as there is with other shells.
57 ;;
58 ;; @ <C-c C-t> can be used to truncate the buffer if it grows too
59 ;; large.
60 ;;
61 ;; @ <C-c C-r> will move point to the beginning of the output of the
62 ;; last command. With a prefix argument, it will narrow to view
63 ;; only that output.
64 ;;
65 ;; @ <C-c C-o> will delete the output from the last command.
66 ;;
67 ;; @ <C-c C-f> will move forward a complete shell argument.
68 ;;
69 ;; @ <C-c C-b> will move backward a complete shell argument.
70
71 (require 'esh-module)
72 (require 'esh-cmd)
73 (require 'esh-io)
74 (require 'esh-var)
75
76 ;;; User Variables:
77
78 (defcustom eshell-mode-unload-hook nil
79 "*A hook that gets run when `eshell-mode' is unloaded."
80 :type 'hook
81 :group 'eshell-mode)
82
83 (defcustom eshell-mode-hook nil
84 "*A hook that gets run when `eshell-mode' is entered."
85 :type 'hook
86 :group 'eshell-mode)
87
88 (defcustom eshell-first-time-mode-hook nil
89 "*A hook that gets run the first time `eshell-mode' is entered.
90 That is to say, the first time during an Emacs session."
91 :type 'hook
92 :group 'eshell-mode)
93
94 (defcustom eshell-exit-hook '(eshell-query-kill-processes)
95 "*A hook that is run whenever `eshell' is exited.
96 This hook is only run if exiting actually kills the buffer."
97 :type 'hook
98 :group 'eshell-mode)
99
100 (defcustom eshell-kill-on-exit t
101 "*If non-nil, kill the Eshell buffer on the `exit' command.
102 Otherwise, the buffer will simply be buried."
103 :type 'boolean
104 :group 'eshell-mode)
105
106 (defcustom eshell-input-filter-functions nil
107 "*Functions to call before input is processed.
108 The input is contained in the region from `eshell-last-input-start' to
109 `eshell-last-input-end'."
110 :type 'hook
111 :group 'eshell-mode)
112
113 (defcustom eshell-send-direct-to-subprocesses nil
114 "*If t, send any input immediately to a subprocess."
115 :type 'boolean
116 :group 'eshell-mode)
117
118 (defcustom eshell-expand-input-functions nil
119 "*Functions to call before input is parsed.
120 Each function is passed two arguments, which bounds the region of the
121 current input text."
122 :type 'hook
123 :group 'eshell-mode)
124
125 (defcustom eshell-scroll-to-bottom-on-input nil
126 "*Controls whether input to interpreter causes window to scroll.
127 If nil, then do not scroll. If t or `all', scroll all windows showing
128 buffer. If `this', scroll only the selected window.
129
130 See `eshell-preinput-scroll-to-bottom'."
131 :type '(radio (const :tag "Do not scroll Eshell windows" nil)
132 (const :tag "Scroll all windows showing the buffer" all)
133 (const :tag "Scroll only the selected window" this))
134 :group 'eshell-mode)
135
136 (defcustom eshell-scroll-to-bottom-on-output nil
137 "*Controls whether interpreter output causes window to scroll.
138 If nil, then do not scroll. If t or `all', scroll all windows showing
139 buffer. If `this', scroll only the selected window. If `others',
140 scroll only those that are not the selected window.
141
142 See variable `eshell-scroll-show-maximum-output' and function
143 `eshell-postoutput-scroll-to-bottom'."
144 :type '(radio (const :tag "Do not scroll Eshell windows" nil)
145 (const :tag "Scroll all windows showing the buffer" all)
146 (const :tag "Scroll only the selected window" this)
147 (const :tag "Scroll all windows other than selected" this))
148 :group 'eshell-mode)
149
150 (defcustom eshell-scroll-show-maximum-output t
151 "*Controls how interpreter output causes window to scroll.
152 If non-nil, then show the maximum output when the window is scrolled.
153
154 See variable `eshell-scroll-to-bottom-on-output' and function
155 `eshell-postoutput-scroll-to-bottom'."
156 :type 'boolean
157 :group 'eshell-mode)
158
159 (defcustom eshell-buffer-maximum-lines 1024
160 "*The maximum size in lines for eshell buffers.
161 Eshell buffers are truncated from the top to be no greater than this
162 number, if the function `eshell-truncate-buffer' is on
163 `eshell-output-filter-functions'."
164 :type 'integer
165 :group 'eshell-mode)
166
167 (defcustom eshell-output-filter-functions
168 '(eshell-handle-control-codes
169 eshell-watch-for-password-prompt)
170 "*Functions to call before output is displayed.
171 These functions are only called for output that is displayed
172 interactively, and not for output which is redirected."
173 :type 'hook
174 :group 'eshell-mode)
175
176 (defcustom eshell-preoutput-filter-functions nil
177 "*Functions to call before output is inserted into the buffer.
178 These functions get one argument, a string containing the text to be
179 inserted. They return the string as it should be inserted."
180 :type 'hook
181 :group 'eshell-mode)
182
183 (defcustom eshell-password-prompt-regexp
184 "[Pp]ass\\(word\\|phrase\\).*:\\s *\\'"
185 "*Regexp matching prompts for passwords in the inferior process.
186 This is used by `eshell-watch-for-password-prompt'."
187 :type 'regexp
188 :group 'eshell-mode)
189
190 (defcustom eshell-skip-prompt-function nil
191 "*A function called from beginning of line to skip the prompt."
192 :type '(choice (const nil) function)
193 :group 'eshell-mode)
194
195 (defcustom eshell-status-in-modeline t
196 "*If non-nil, let the user know a command is running in the modeline."
197 :type 'boolean
198 :group 'eshell-mode)
199
200 (defvar eshell-first-time-p t
201 "A variable which is non-nil the first time Eshell is loaded.")
202
203 ;; Internal Variables:
204
205 ;; these are only set to `nil' initially for the sake of the
206 ;; byte-compiler, when compiling other files which `require' this one
207 (defvar eshell-mode nil)
208 (defvar eshell-mode-map nil)
209 (defvar eshell-command-running-string "--")
210 (defvar eshell-command-map nil)
211 (defvar eshell-command-prefix nil)
212 (defvar eshell-last-input-start nil)
213 (defvar eshell-last-input-end nil)
214 (defvar eshell-last-output-start nil)
215 (defvar eshell-last-output-block-begin nil)
216 (defvar eshell-last-output-end nil)
217
218 (defvar eshell-currently-handling-window nil)
219 (defvar eshell-mode-syntax-table nil)
220 (defvar eshell-mode-abbrev-table nil)
221
222 (define-abbrev-table 'eshell-mode-abbrev-table ())
223
224 (eval-when-compile
225 (unless (eshell-under-xemacs-p)
226 (defalias 'characterp 'ignore)
227 (defalias 'char-int 'ignore)))
228
229 (if (not eshell-mode-syntax-table)
230 (let ((i 0))
231 (setq eshell-mode-syntax-table (make-syntax-table))
232 (while (< i ?0)
233 (modify-syntax-entry i "_ " eshell-mode-syntax-table)
234 (setq i (1+ i)))
235 (setq i (1+ ?9))
236 (while (< i ?A)
237 (modify-syntax-entry i "_ " eshell-mode-syntax-table)
238 (setq i (1+ i)))
239 (setq i (1+ ?Z))
240 (while (< i ?a)
241 (modify-syntax-entry i "_ " eshell-mode-syntax-table)
242 (setq i (1+ i)))
243 (setq i (1+ ?z))
244 (while (< i 128)
245 (modify-syntax-entry i "_ " eshell-mode-syntax-table)
246 (setq i (1+ i)))
247 (modify-syntax-entry ? " " eshell-mode-syntax-table)
248 (modify-syntax-entry ?\t " " eshell-mode-syntax-table)
249 (modify-syntax-entry ?\f " " eshell-mode-syntax-table)
250 (modify-syntax-entry ?\n "> " eshell-mode-syntax-table)
251 ;; Give CR the same syntax as newline, for selective-display.
252 (modify-syntax-entry ?\^m "> " eshell-mode-syntax-table)
253 ;;; (modify-syntax-entry ?\; "< " eshell-mode-syntax-table)
254 (modify-syntax-entry ?` "' " eshell-mode-syntax-table)
255 (modify-syntax-entry ?' "' " eshell-mode-syntax-table)
256 (modify-syntax-entry ?, "' " eshell-mode-syntax-table)
257 ;; Used to be singlequote; changed for flonums.
258 (modify-syntax-entry ?. "_ " eshell-mode-syntax-table)
259 (modify-syntax-entry ?- "_ " eshell-mode-syntax-table)
260 (modify-syntax-entry ?| ". " eshell-mode-syntax-table)
261 (modify-syntax-entry ?# "' " eshell-mode-syntax-table)
262 (modify-syntax-entry ?\" "\" " eshell-mode-syntax-table)
263 (modify-syntax-entry ?\\ "/ " eshell-mode-syntax-table)
264 (modify-syntax-entry ?\( "() " eshell-mode-syntax-table)
265 (modify-syntax-entry ?\) ")( " eshell-mode-syntax-table)
266 (modify-syntax-entry ?\{ "(} " eshell-mode-syntax-table)
267 (modify-syntax-entry ?\} "){ " eshell-mode-syntax-table)
268 (modify-syntax-entry ?\[ "(] " eshell-mode-syntax-table)
269 (modify-syntax-entry ?\] ")[ " eshell-mode-syntax-table)
270 ;; All non-word multibyte characters should be `symbol'.
271 (if (eshell-under-xemacs-p)
272 (map-char-table
273 (function
274 (lambda (key val)
275 (and (characterp key)
276 (>= (char-int key) 256)
277 (/= (char-syntax key) ?w)
278 (modify-syntax-entry key "_ "
279 eshell-mode-syntax-table))))
280 (standard-syntax-table))
281 (map-char-table
282 (function
283 (lambda (key val)
284 (and (if (consp key)
285 (and (>= (car key) 128)
286 (/= (char-syntax (car key)) ?w))
287 (and (>= key 256)
288 (/= (char-syntax key) ?w)))
289 (modify-syntax-entry key "_ "
290 eshell-mode-syntax-table))))
291 (standard-syntax-table)))))
292
293 ;;; User Functions:
294
295 ;;;###autoload
296 (defun eshell-mode ()
297 "Emacs shell interactive mode.
298
299 \\{eshell-mode-map}"
300 (kill-all-local-variables)
301
302 (setq major-mode 'eshell-mode)
303 (setq mode-name "EShell")
304 (set (make-local-variable 'eshell-mode) t)
305
306 (make-local-variable 'eshell-mode-map)
307 (setq eshell-mode-map (make-sparse-keymap))
308 (use-local-map eshell-mode-map)
309
310 (when eshell-status-in-modeline
311 (make-local-variable 'eshell-command-running-string)
312 (let ((fmt (copy-sequence mode-line-format)))
313 (make-local-variable 'mode-line-format)
314 (setq mode-line-format fmt))
315 (let ((modeline (memq 'mode-line-modified mode-line-format)))
316 (if modeline
317 (setcar modeline 'eshell-command-running-string))))
318
319 (define-key eshell-mode-map [return] 'eshell-send-input)
320 (define-key eshell-mode-map [(control ?m)] 'eshell-send-input)
321 (define-key eshell-mode-map [(control ?j)] 'eshell-send-input)
322 (define-key eshell-mode-map [(meta return)] 'eshell-queue-input)
323 (define-key eshell-mode-map [(meta control ?m)] 'eshell-queue-input)
324 (define-key eshell-mode-map [(meta control ?l)] 'eshell-show-output)
325
326 (set (make-local-variable 'eshell-command-prefix)
327 (make-symbol "eshell-command-prefix"))
328 (fset eshell-command-prefix (make-sparse-keymap))
329 (set (make-local-variable 'eshell-command-map)
330 (symbol-function eshell-command-prefix))
331 (define-key eshell-mode-map [(control ?c)] eshell-command-prefix)
332
333 ;; without this, find-tag complains about read-only text being
334 ;; modified
335 (if (eq (key-binding [(meta ?.)]) 'find-tag)
336 (define-key eshell-mode-map [(meta ?.)] 'eshell-find-tag))
337 (define-key eshell-command-map [(meta ?o)] 'eshell-mark-output)
338 (define-key eshell-command-map [(meta ?d)] 'eshell-toggle-direct-send)
339
340 (define-key eshell-command-map [(control ?a)] 'eshell-bol)
341 (define-key eshell-command-map [(control ?b)] 'eshell-backward-argument)
342 (define-key eshell-command-map [(control ?e)] 'eshell-show-maximum-output)
343 (define-key eshell-command-map [(control ?f)] 'eshell-forward-argument)
344 (define-key eshell-command-map [return] 'eshell-copy-old-input)
345 (define-key eshell-command-map [(control ?m)] 'eshell-copy-old-input)
346 (define-key eshell-command-map [(control ?o)] 'eshell-kill-output)
347 (define-key eshell-command-map [(control ?r)] 'eshell-show-output)
348 (define-key eshell-command-map [(control ?t)] 'eshell-truncate-buffer)
349 (define-key eshell-command-map [(control ?u)] 'eshell-kill-input)
350 (define-key eshell-command-map [(control ?w)] 'backward-kill-word)
351 (define-key eshell-command-map [(control ?y)] 'eshell-repeat-argument)
352
353 (setq local-abbrev-table eshell-mode-abbrev-table)
354 (set-syntax-table eshell-mode-syntax-table)
355
356 (set (make-local-variable 'dired-directory) default-directory)
357 (set (make-local-variable 'list-buffers-directory)
358 (expand-file-name default-directory))
359
360 ;; always set the tab width to 8 in Eshell buffers, since external
361 ;; commands which do their own formatting almost always expect this
362 (set (make-local-variable 'tab-width) 8)
363
364 ;; don't ever use auto-fill in Eshell buffers
365 (setq auto-fill-function nil)
366
367 ;; always display everything from a return value
368 (if (boundp 'print-length)
369 (set (make-local-variable 'print-length) nil))
370 (if (boundp 'print-level)
371 (set (make-local-variable 'print-level) nil))
372
373 ;; set require-final-newline to nil; otherwise, all redirected
374 ;; output will end with a newline, whether or not the source
375 ;; indicated it!
376 (set (make-local-variable 'require-final-newline) nil)
377
378 (set (make-local-variable 'max-lisp-eval-depth)
379 (max 3000 max-lisp-eval-depth))
380 (set (make-local-variable 'max-specpdl-size)
381 (max 6000 max-lisp-eval-depth))
382
383 (set (make-local-variable 'eshell-last-input-start) (point-marker))
384 (set (make-local-variable 'eshell-last-input-end) (point-marker))
385 (set (make-local-variable 'eshell-last-output-start) (point-marker))
386 (set (make-local-variable 'eshell-last-output-end) (point-marker))
387 (set (make-local-variable 'eshell-last-output-block-begin) (point))
388
389 (let ((modules-list (copy-sequence eshell-modules-list)))
390 (make-local-variable 'eshell-modules-list)
391 (setq eshell-modules-list modules-list))
392
393 ;; load extension modules into memory. This will cause any global
394 ;; variables they define to be visible, since some of the core
395 ;; modules sometimes take advantage of their functionality if used.
396 (eshell-for module eshell-modules-list
397 (let ((module-fullname (symbol-name module))
398 module-shortname)
399 (if (string-match "^eshell-\\(.*\\)" module-fullname)
400 (setq module-shortname
401 (concat "em-" (match-string 1 module-fullname))))
402 (unless module-shortname
403 (error "Invalid Eshell module name: %s" module-fullname))
404 (unless (featurep (intern module-shortname))
405 (load module-shortname))))
406
407 (unless (file-exists-p eshell-directory-name)
408 (eshell-make-private-directory eshell-directory-name t))
409
410 ;; load core Eshell modules for this session
411 (eshell-for module (eshell-subgroups 'eshell)
412 (run-hooks (intern-soft (concat (symbol-name module)
413 "-load-hook"))))
414
415 ;; load extension modules for this session
416 (eshell-for module eshell-modules-list
417 (let ((load-hook (intern-soft (concat (symbol-name module)
418 "-load-hook"))))
419 (if (and load-hook (boundp load-hook))
420 (run-hooks load-hook))))
421
422 (if eshell-send-direct-to-subprocesses
423 (add-hook 'pre-command-hook 'eshell-intercept-commands t t))
424
425 (if eshell-scroll-to-bottom-on-input
426 (add-hook 'pre-command-hook 'eshell-preinput-scroll-to-bottom t t))
427
428 (when eshell-scroll-show-maximum-output
429 (set (make-local-variable 'scroll-conservatively) 1000))
430
431 (when eshell-status-in-modeline
432 (add-hook 'eshell-pre-command-hook 'eshell-command-started nil t)
433 (add-hook 'eshell-post-command-hook 'eshell-command-finished nil t))
434
435 (add-hook 'kill-buffer-hook
436 (function
437 (lambda ()
438 (run-hooks 'eshell-exit-hook))) t t)
439
440 (if eshell-first-time-p
441 (run-hooks 'eshell-first-time-mode-hook))
442 (run-mode-hooks 'eshell-mode-hook)
443 (run-hooks 'eshell-post-command-hook))
444
445 (put 'eshell-mode 'mode-class 'special)
446
447 (eshell-deftest mode major-mode
448 "Major mode is correct"
449 (eq major-mode 'eshell-mode))
450
451 (eshell-deftest mode eshell-mode-variable
452 "`eshell-mode' is true"
453 (eq eshell-mode t))
454
455 (eshell-deftest var window-height
456 "LINES equals window height"
457 (let ((eshell-stringify-t t))
458 (eshell-command-result-p "= $LINES (window-height)" "t\n")))
459
460 (defun eshell-command-started ()
461 "Indicate in the modeline that a command has started."
462 (setq eshell-command-running-string "**")
463 (force-mode-line-update))
464
465 (defun eshell-command-finished ()
466 "Indicate in the modeline that a command has finished."
467 (setq eshell-command-running-string "--")
468 (force-mode-line-update))
469
470 (eshell-deftest mode command-running-p
471 "Modeline shows no command running"
472 (or (eshell-under-xemacs-p)
473 (not eshell-status-in-modeline)
474 (and (memq 'eshell-command-running-string mode-line-format)
475 (equal eshell-command-running-string "--"))))
476
477 ;;; Internal Functions:
478
479 (defun eshell-toggle-direct-send ()
480 (interactive)
481 (if eshell-send-direct-to-subprocesses
482 (progn
483 (setq eshell-send-direct-to-subprocesses nil)
484 (remove-hook 'pre-command-hook 'eshell-intercept-commands t)
485 (message "Sending subprocess input on RET"))
486 (setq eshell-send-direct-to-subprocesses t)
487 (add-hook 'pre-command-hook 'eshell-intercept-commands t t)
488 (message "Sending subprocess input directly")))
489
490 (defun eshell-self-insert-command (N)
491 (interactive "i")
492 (process-send-string
493 (eshell-interactive-process)
494 (char-to-string (if (symbolp last-command-char)
495 (get last-command-char 'ascii-character)
496 last-command-char))))
497
498 (defun eshell-intercept-commands ()
499 (when (and (eshell-interactive-process)
500 (not (and (integerp last-input-event)
501 (memq last-input-event '(?\C-x ?\C-c)))))
502 (let ((possible-events (where-is-internal this-command))
503 (name (symbol-name this-command))
504 (intercept t))
505 ;; Assume that any multikey combination which does NOT target an
506 ;; Eshell command, is a combo the user wants invoked rather than
507 ;; sent to the underlying subprocess.
508 (unless (and (> (length name) 7)
509 (equal (substring name 0 7) "eshell-"))
510 (while possible-events
511 (if (> (length (car possible-events)) 1)
512 (setq intercept nil possible-events nil)
513 (setq possible-events (cdr possible-events)))))
514 (if intercept
515 (setq this-command 'eshell-self-insert-command)))))
516
517 (defun eshell-find-tag (&optional tagname next-p regexp-p)
518 "A special version of `find-tag' that ignores read-onlyness."
519 (interactive)
520 (require 'etags)
521 (let ((inhibit-read-only t)
522 (no-default (eobp))
523 (find-tag-default-function 'ignore))
524 (with-no-warnings
525 (setq tagname (car (find-tag-interactive "Find tag: "))))
526 (find-tag tagname next-p regexp-p)))
527
528 (defun eshell-move-argument (limit func property arg)
529 "Move forward ARG arguments."
530 (catch 'eshell-incomplete
531 (eshell-parse-arguments (save-excursion (eshell-bol) (point))
532 (line-end-position)))
533 (let ((pos (save-excursion
534 (funcall func 1)
535 (while (and (> arg 0) (/= (point) limit))
536 (if (get-text-property (point) property)
537 (setq arg (1- arg)))
538 (if (> arg 0)
539 (funcall func 1)))
540 (point))))
541 (goto-char pos)
542 (if (and (eq func 'forward-char)
543 (= (1+ pos) limit))
544 (forward-char 1))))
545
546 (eshell-deftest arg forward-arg
547 "Move across command arguments"
548 (eshell-insert-command "echo $(+ 1 (- 4 3)) \"alpha beta\" file" 'ignore)
549 (let ((here (point)) begin valid)
550 (eshell-bol)
551 (setq begin (point))
552 (eshell-forward-argument 4)
553 (setq valid (= here (point)))
554 (eshell-backward-argument 4)
555 (prog1
556 (and valid (= begin (point)))
557 (eshell-bol)
558 (delete-region (point) (point-max)))))
559
560 (defun eshell-forward-argument (&optional arg)
561 "Move forward ARG arguments."
562 (interactive "p")
563 (eshell-move-argument (point-max) 'forward-char 'arg-end arg))
564
565 (defun eshell-backward-argument (&optional arg)
566 "Move backward ARG arguments."
567 (interactive "p")
568 (eshell-move-argument (point-min) 'backward-char 'arg-begin arg))
569
570 (defun eshell-repeat-argument (&optional arg)
571 (interactive "p")
572 (let ((begin (save-excursion
573 (eshell-backward-argument arg)
574 (point))))
575 (kill-ring-save begin (point))
576 (yank)))
577
578 (defun eshell-bol ()
579 "Goes to the beginning of line, then skips past the prompt, if any."
580 (interactive)
581 (beginning-of-line)
582 (and eshell-skip-prompt-function
583 (funcall eshell-skip-prompt-function)))
584
585 (defsubst eshell-push-command-mark ()
586 "Push a mark at the end of the last input text."
587 (push-mark (1- eshell-last-input-end) t))
588
589 (custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark)
590
591 (defsubst eshell-goto-input-start ()
592 "Goto the start of the last command input.
593 Putting this function on `eshell-pre-command-hook' will mimic Plan 9's
594 9term behavior."
595 (goto-char eshell-last-input-start))
596
597 (custom-add-option 'eshell-pre-command-hook 'eshell-push-command-mark)
598
599 (defsubst eshell-interactive-print (string)
600 "Print STRING to the eshell display buffer."
601 (eshell-output-filter nil string))
602
603 (defsubst eshell-begin-on-new-line ()
604 "This function outputs a newline if not at beginning of line."
605 (save-excursion
606 (goto-char eshell-last-output-end)
607 (or (bolp)
608 (eshell-interactive-print "\n"))))
609
610 (defsubst eshell-reset (&optional no-hooks)
611 "Output a prompt on a new line, aborting any current input.
612 If NO-HOOKS is non-nil, then `eshell-post-command-hook' won't be run."
613 (goto-char (point-max))
614 (setq eshell-last-input-start (point-marker)
615 eshell-last-input-end (point-marker)
616 eshell-last-output-start (point-marker)
617 eshell-last-output-block-begin (point)
618 eshell-last-output-end (point-marker))
619 (eshell-begin-on-new-line)
620 (unless no-hooks
621 (run-hooks 'eshell-post-command-hook)
622 (goto-char (point-max))))
623
624 (defun eshell-parse-command-input (beg end &optional args)
625 "Parse the command input from BEG to END.
626 The difference is that `eshell-parse-command' expects a complete
627 command string (and will error if it doesn't get one), whereas this
628 function will inform the caller whether more input is required.
629
630 If nil is returned, more input is necessary (probably because a
631 multi-line input string wasn't terminated properly). Otherwise, it
632 will return the parsed command."
633 (let (delim command)
634 (if (setq delim
635 (catch 'eshell-incomplete
636 (ignore
637 (setq command (eshell-parse-command (cons beg end)
638 args t)))))
639 (ignore
640 (message "Expecting completion of delimeter %c ..."
641 (if (listp delim)
642 (car delim)
643 delim)))
644 command)))
645
646 (defun eshell-update-markers (pmark)
647 "Update the input and output markers relative to point and PMARK."
648 (set-marker eshell-last-input-start pmark)
649 (set-marker eshell-last-input-end (point))
650 (set-marker eshell-last-output-end (point)))
651
652 (defun eshell-queue-input (&optional use-region)
653 "Queue the current input text for execution by Eshell.
654 Particularly, don't send the text to the current process, even if it's
655 waiting for input."
656 (interactive "P")
657 (eshell-send-input use-region t))
658
659 (eshell-deftest mode queue-input
660 "Queue command input"
661 (eshell-insert-command "sleep 2")
662 (eshell-insert-command "echo alpha" 'eshell-queue-input)
663 (let ((count 10))
664 (while (and eshell-current-command
665 (> count 0))
666 (sit-for 1 0)
667 (setq count (1- count))))
668 (eshell-match-result "alpha\n"))
669
670 (defun eshell-send-input (&optional use-region queue-p no-newline)
671 "Send the input received to Eshell for parsing and processing.
672 After `eshell-last-output-end', sends all text from that marker to
673 point as input. Before that marker, calls `eshell-get-old-input' to
674 retrieve old input, copies it to the end of the buffer, and sends it.
675
676 If USE-REGION is non-nil, the current region (between point and mark)
677 will be used as input.
678
679 If QUEUE-P is non-nil, input will be queued until the next prompt,
680 rather than sent to the currently active process. If no process, the
681 input is processed immediately.
682
683 If NO-NEWLINE is non-nil, the input is sent without an implied final
684 newline."
685 (interactive "P")
686 ;; Note that the input string does not include its terminal newline.
687 (let ((proc-running-p (and (eshell-interactive-process)
688 (not queue-p)))
689 (inhibit-point-motion-hooks t)
690 after-change-functions)
691 (unless (and proc-running-p
692 (not (eq (process-status
693 (eshell-interactive-process)) 'run)))
694 (if (or proc-running-p
695 (>= (point) eshell-last-output-end))
696 (goto-char (point-max))
697 (let ((copy (eshell-get-old-input use-region)))
698 (goto-char eshell-last-output-end)
699 (insert-and-inherit copy)))
700 (unless (or no-newline
701 (and eshell-send-direct-to-subprocesses
702 proc-running-p))
703 (insert-before-markers-and-inherit ?\n))
704 (if proc-running-p
705 (progn
706 (eshell-update-markers eshell-last-output-end)
707 (if (or eshell-send-direct-to-subprocesses
708 (= eshell-last-input-start eshell-last-input-end))
709 (unless no-newline
710 (process-send-string (eshell-interactive-process) "\n"))
711 (process-send-region (eshell-interactive-process)
712 eshell-last-input-start
713 eshell-last-input-end)))
714 (if (= eshell-last-output-end (point))
715 (run-hooks 'eshell-post-command-hook)
716 (let (input)
717 (eshell-condition-case err
718 (progn
719 (setq input (buffer-substring-no-properties
720 eshell-last-output-end (1- (point))))
721 (run-hook-with-args 'eshell-expand-input-functions
722 eshell-last-output-end (1- (point)))
723 (let ((cmd (eshell-parse-command-input
724 eshell-last-output-end (1- (point)))))
725 (when cmd
726 (eshell-update-markers eshell-last-output-end)
727 (setq input (buffer-substring-no-properties
728 eshell-last-input-start
729 (1- eshell-last-input-end)))
730 (run-hooks 'eshell-input-filter-functions)
731 (and (catch 'eshell-terminal
732 (ignore
733 (if (eshell-invoke-directly cmd input)
734 (eval cmd)
735 (eshell-eval-command cmd input))))
736 (eshell-life-is-too-much)))))
737 (quit
738 (eshell-reset t)
739 (run-hooks 'eshell-post-command-hook)
740 (signal 'quit nil))
741 (error
742 (eshell-reset t)
743 (eshell-interactive-print
744 (concat (error-message-string err) "\n"))
745 (run-hooks 'eshell-post-command-hook)
746 (insert-and-inherit input)))))))))
747
748 ; (eshell-deftest proc send-to-subprocess
749 ; "Send input to a subprocess"
750 ; ;; jww (1999-12-06): what about when bc is unavailable?
751 ; (if (not (eshell-search-path "bc"))
752 ; t
753 ; (eshell-insert-command "bc")
754 ; (eshell-insert-command "1 + 2")
755 ; (sit-for 1 0)
756 ; (forward-line -1)
757 ; (prog1
758 ; (looking-at "3\n")
759 ; (eshell-insert-command "quit")
760 ; (sit-for 1 0))))
761
762 (defsubst eshell-kill-new ()
763 "Add the last input text to the kill ring."
764 (kill-ring-save eshell-last-input-start eshell-last-input-end))
765
766 (custom-add-option 'eshell-input-filter-functions 'eshell-kill-new)
767
768 (defun eshell-output-filter (process string)
769 "Send the output from PROCESS (STRING) to the interactive display.
770 This is done after all necessary filtering has been done."
771 (let ((oprocbuf (if process (process-buffer process)
772 (current-buffer)))
773 (inhibit-point-motion-hooks t)
774 after-change-functions)
775 (let ((functions eshell-preoutput-filter-functions))
776 (while (and functions string)
777 (setq string (funcall (car functions) string))
778 (setq functions (cdr functions))))
779 (if (and string oprocbuf (buffer-name oprocbuf))
780 (let ((obuf (current-buffer))
781 opoint obeg oend)
782 (set-buffer oprocbuf)
783 (setq opoint (point))
784 (setq obeg (point-min))
785 (setq oend (point-max))
786 (let ((buffer-read-only nil)
787 (nchars (length string))
788 (ostart nil))
789 (widen)
790 (goto-char eshell-last-output-end)
791 (setq ostart (point))
792 (if (<= (point) opoint)
793 (setq opoint (+ opoint nchars)))
794 (if (< (point) obeg)
795 (setq obeg (+ obeg nchars)))
796 (if (<= (point) oend)
797 (setq oend (+ oend nchars)))
798 (insert-before-markers string)
799 (if (= (window-start (selected-window)) (point))
800 (set-window-start (selected-window)
801 (- (point) nchars)))
802 (if (= (point) eshell-last-input-end)
803 (set-marker eshell-last-input-end
804 (- eshell-last-input-end nchars)))
805 (set-marker eshell-last-output-start ostart)
806 (set-marker eshell-last-output-end (point))
807 (force-mode-line-update))
808 (narrow-to-region obeg oend)
809 (goto-char opoint)
810 (eshell-run-output-filters)
811 (set-buffer obuf)))))
812
813 (defun eshell-run-output-filters ()
814 "Run the `eshell-output-filter-functions' on the current output."
815 (save-current-buffer
816 (run-hooks 'eshell-output-filter-functions))
817 (setq eshell-last-output-block-begin
818 (marker-position eshell-last-output-end)))
819
820 ;;; jww (1999-10-23): this needs testing
821 (defun eshell-preinput-scroll-to-bottom ()
822 "Go to the end of buffer in all windows showing it.
823 Movement occurs if point in the selected window is not after the
824 process mark, and `this-command' is an insertion command. Insertion
825 commands recognized are `self-insert-command', `yank', and
826 `hilit-yank'. Depends on the value of
827 `eshell-scroll-to-bottom-on-input'.
828
829 This function should be a pre-command hook."
830 (if (memq this-command '(self-insert-command yank hilit-yank))
831 (let* ((selected (selected-window))
832 (current (current-buffer))
833 (scroll eshell-scroll-to-bottom-on-input))
834 (if (< (point) eshell-last-output-end)
835 (if (eq scroll 'this)
836 (goto-char (point-max))
837 (walk-windows
838 (function
839 (lambda (window)
840 (when (and (eq (window-buffer window) current)
841 (or (eq scroll t) (eq scroll 'all)))
842 (select-window window)
843 (goto-char (point-max))
844 (select-window selected))))
845 nil t))))))
846
847 ;;; jww (1999-10-23): this needs testing
848 (defun eshell-postoutput-scroll-to-bottom ()
849 "Go to the end of buffer in all windows showing it.
850 Does not scroll if the current line is the last line in the buffer.
851 Depends on the value of `eshell-scroll-to-bottom-on-output' and
852 `eshell-scroll-show-maximum-output'.
853
854 This function should be in the list `eshell-output-filter-functions'."
855 (let* ((selected (selected-window))
856 (current (current-buffer))
857 (scroll eshell-scroll-to-bottom-on-output))
858 (unwind-protect
859 (walk-windows
860 (function
861 (lambda (window)
862 (if (eq (window-buffer window) current)
863 (progn
864 (select-window window)
865 (if (and (< (point) eshell-last-output-end)
866 (or (eq scroll t) (eq scroll 'all)
867 ;; Maybe user wants point to jump to end.
868 (and (eq scroll 'this)
869 (eq selected window))
870 (and (eq scroll 'others)
871 (not (eq selected window)))
872 ;; If point was at the end, keep it at end.
873 (>= (point) eshell-last-output-start)))
874 (goto-char eshell-last-output-end))
875 ;; Optionally scroll so that the text
876 ;; ends at the bottom of the window.
877 (if (and eshell-scroll-show-maximum-output
878 (>= (point) eshell-last-output-end))
879 (save-excursion
880 (goto-char (point-max))
881 (recenter -1)))
882 (select-window selected)))))
883 nil t)
884 (set-buffer current))))
885
886 (custom-add-option 'eshell-output-filter-functions
887 'eshell-postoutput-scroll-to-bottom)
888
889 (defun eshell-beginning-of-input ()
890 "Return the location of the start of the previous input."
891 eshell-last-input-start)
892
893 (defun eshell-beginning-of-output ()
894 "Return the location of the end of the previous output block."
895 eshell-last-input-end)
896
897 (defun eshell-end-of-output ()
898 "Return the location of the end of the previous output block."
899 (if (eshell-using-module 'eshell-prompt)
900 eshell-last-output-start
901 eshell-last-output-end))
902
903 (defun eshell-kill-output ()
904 "Kill all output from interpreter since last input.
905 Does not delete the prompt."
906 (interactive)
907 (save-excursion
908 (goto-char (eshell-beginning-of-output))
909 (insert "*** output flushed ***\n")
910 (delete-region (point) (eshell-end-of-output))))
911
912 (eshell-deftest io flush-output
913 "Flush previous output"
914 (eshell-insert-command "echo alpha")
915 (eshell-kill-output)
916 (and (eshell-match-result (regexp-quote "*** output flushed ***\n"))
917 (forward-line)
918 (= (point) eshell-last-output-start)))
919
920 (defun eshell-show-output (&optional arg)
921 "Display start of this batch of interpreter output at top of window.
922 Sets mark to the value of point when this command is run.
923 With a prefix argument, narrows region to last command output."
924 (interactive "P")
925 (goto-char (eshell-beginning-of-output))
926 (set-window-start (selected-window)
927 (save-excursion
928 (goto-char (eshell-beginning-of-input))
929 (line-beginning-position)))
930 (if arg
931 (narrow-to-region (eshell-beginning-of-output)
932 (eshell-end-of-output)))
933 (eshell-end-of-output))
934
935 (defun eshell-mark-output (&optional arg)
936 "Display start of this batch of interpreter output at top of window.
937 Sets mark to the value of point when this command is run.
938 With a prefix argument, narrows region to last command output."
939 (interactive "P")
940 (push-mark (eshell-show-output arg)))
941
942 (defun eshell-kill-input ()
943 "Kill all text from last stuff output by interpreter to point."
944 (interactive)
945 (if (> (point) eshell-last-output-end)
946 (kill-region eshell-last-output-end (point))
947 (let ((here (point)))
948 (eshell-bol)
949 (kill-region (point) here))))
950
951 (defun eshell-show-maximum-output (&optional interactive)
952 "Put the end of the buffer at the bottom of the window.
953 When run interactively, widen the buffer first."
954 (interactive "p")
955 (if interactive
956 (widen))
957 (goto-char (point-max))
958 (recenter -1))
959
960 (defun eshell-get-old-input (&optional use-current-region)
961 "Return the command input on the current line."
962 (if use-current-region
963 (buffer-substring (min (point) (mark))
964 (max (point) (mark)))
965 (save-excursion
966 (beginning-of-line)
967 (and eshell-skip-prompt-function
968 (funcall eshell-skip-prompt-function))
969 (let ((beg (point)))
970 (end-of-line)
971 (buffer-substring beg (point))))))
972
973 (defun eshell-copy-old-input ()
974 "Insert after prompt old input at point as new input to be edited."
975 (interactive)
976 (let ((input (eshell-get-old-input)))
977 (goto-char eshell-last-output-end)
978 (insert-and-inherit input)))
979
980 (eshell-deftest mode run-old-command
981 "Re-run an old command"
982 (eshell-insert-command "echo alpha")
983 (goto-char eshell-last-input-start)
984 (string= (eshell-get-old-input) "echo alpha"))
985
986 (defun eshell/exit ()
987 "Leave or kill the Eshell buffer, depending on `eshell-kill-on-exit'."
988 (throw 'eshell-terminal t))
989
990 (defun eshell-life-is-too-much ()
991 "Kill the current buffer (or bury it). Good-bye Eshell."
992 (interactive)
993 (if (not eshell-kill-on-exit)
994 (bury-buffer)
995 (kill-buffer (current-buffer))))
996
997 (defun eshell-truncate-buffer ()
998 "Truncate the buffer to `eshell-buffer-maximum-lines'.
999 This function could be on `eshell-output-filter-functions' or bound to
1000 a key."
1001 (interactive)
1002 (save-excursion
1003 (goto-char eshell-last-output-end)
1004 (let ((lines (count-lines 1 (point)))
1005 (inhibit-read-only t))
1006 (forward-line (- eshell-buffer-maximum-lines))
1007 (beginning-of-line)
1008 (let ((pos (point)))
1009 (if (bobp)
1010 (if (interactive-p)
1011 (message "Buffer too short to truncate"))
1012 (delete-region (point-min) (point))
1013 (if (interactive-p)
1014 (message "Truncated buffer from %d to %d lines (%.1fk freed)"
1015 lines eshell-buffer-maximum-lines
1016 (/ pos 1024.0))))))))
1017
1018 (custom-add-option 'eshell-output-filter-functions
1019 'eshell-truncate-buffer)
1020
1021 (defun eshell-send-invisible (str)
1022 "Read a string without echoing.
1023 Then send it to the process running in the current buffer."
1024 (interactive "P") ; Defeat snooping via C-x ESC ESC
1025 (let ((str (read-passwd
1026 (format "%s Password: "
1027 (process-name (eshell-interactive-process))))))
1028 (if (stringp str)
1029 (process-send-string (eshell-interactive-process)
1030 (concat str "\n"))
1031 (message "Warning: text will be echoed"))))
1032
1033 (defun eshell-watch-for-password-prompt ()
1034 "Prompt in the minibuffer for password and send without echoing.
1035 This function uses `eshell-send-invisible' to read and send a password to the
1036 buffer's process if STRING contains a password prompt defined by
1037 `eshell-password-prompt-regexp'.
1038
1039 This function could be in the list `eshell-output-filter-functions'."
1040 (when (eshell-interactive-process)
1041 (save-excursion
1042 (goto-char eshell-last-output-block-begin)
1043 (beginning-of-line)
1044 (if (re-search-forward eshell-password-prompt-regexp
1045 eshell-last-output-end t)
1046 (eshell-send-invisible nil)))))
1047
1048 (custom-add-option 'eshell-output-filter-functions
1049 'eshell-watch-for-password-prompt)
1050
1051 (defun eshell-handle-control-codes ()
1052 "Act properly when certain control codes are seen."
1053 (save-excursion
1054 (let ((orig (point)))
1055 (goto-char eshell-last-output-block-begin)
1056 (unless (eolp)
1057 (beginning-of-line))
1058 (while (< (point) eshell-last-output-end)
1059 (let ((char (char-after)))
1060 (cond
1061 ((eq char ?\r)
1062 (if (< (1+ (point)) eshell-last-output-end)
1063 (if (memq (char-after (1+ (point)))
1064 '(?\n ?\r))
1065 (delete-char 1)
1066 (let ((end (1+ (point))))
1067 (beginning-of-line)
1068 (delete-region (point) end)))
1069 (add-text-properties (point) (1+ (point))
1070 '(invisible t))
1071 (forward-char)))
1072 ((eq char ?\a)
1073 (delete-char 1)
1074 (beep))
1075 ((eq char ?\C-h)
1076 (delete-backward-char 1)
1077 (delete-char 1))
1078 (t
1079 (forward-char))))))))
1080
1081 (custom-add-option 'eshell-output-filter-functions
1082 'eshell-handle-control-codes)
1083
1084 ;;; Code:
1085
1086 ;;; arch-tag: ec65bc2b-da14-4547-81d3-a32af3a4dc57
1087 ;;; esh-mode.el ends here