]> code.delx.au - gnu-emacs/blob - lisp/shell.el
*** empty log message ***
[gnu-emacs] / lisp / shell.el
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 ;;; The changelog is at the end of file.
9
10 ;;; Please send me bug reports, bug fixes, and extensions, so that I can
11 ;;; merge them into the master source.
12 ;;; - Olin Shivers (shivers@cs.cmu.edu)
13
14 ;;; This file defines a a shell-in-a-buffer package (shell mode) built
15 ;;; on top of comint mode. This shell mode is similar to its
16 ;;; counterpart in the GNU Emacs 18 release, but is more featureful,
17 ;;; robust, and uniform than that version.
18
19 ;;; Since this mode is built on top of the general command-interpreter-in-
20 ;;; a-buffer mode (comint mode), it shares a common base functionality,
21 ;;; and a common set of bindings, with all modes derived from comint mode.
22 ;;; This makes these modes easier to use.
23
24 ;;; For documentation on the functionality provided by comint mode, and
25 ;;; the hooks available for customising it, see the file comint.el.
26 ;;; For further information on shell mode, see the comments below.
27
28 ;;; Needs fixin:
29 ;;; When sending text from a source file to a subprocess, the process-mark can
30 ;;; move off the window, so you can lose sight of the process interactions.
31 ;;; Maybe I should ensure the process mark is in the window when I send
32 ;;; text to the process? Switch selectable?
33
34 (require 'comint)
35 (provide 'shell)
36
37 ;; YOUR .EMACS FILE
38 ;;=============================================================================
39 ;; Some suggestions for your .emacs file.
40 ;;
41 ;; ; If shell lives in some non-standard directory, you must tell emacs
42 ;; ; where to get it. This may or may not be necessary.
43 ;; (setq load-path (cons (expand-file-name "~jones/lib/emacs") load-path))
44 ;;
45 ;; ; Autoload shell from file shell.el
46 ;; (autoload 'shell "shell"
47 ;; "Run an inferior shell process."
48 ;; t)
49 ;;
50 ;; ; Define C-c t to run my favorite command in shell mode:
51 ;; (setq shell-load-hook
52 ;; '((lambda ()
53 ;; (define-key shell-mode-map "\C-ct" 'favorite-cmd))))
54
55 \f
56 ;;; Brief Command Documentation:
57 ;;;============================================================================
58 ;;; Comint Mode Commands: (common to shell and all comint-derived modes)
59 ;;;
60 ;;; m-p comint-previous-input Cycle backwards in input history
61 ;;; m-n comint-next-input Cycle forwards
62 ;;; m-c-r comint-previous-input-matching Search backwards in input history
63 ;;; return comint-send-input
64 ;;; c-a comint-bol Beginning of line; skip prompt.
65 ;;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff.
66 ;;; c-c c-u comint-kill-input ^u
67 ;;; c-c c-w backward-kill-word ^w
68 ;;; c-c c-c comint-interrupt-subjob ^c
69 ;;; c-c c-z comint-stop-subjob ^z
70 ;;; c-c c-\ comint-quit-subjob ^\
71 ;;; c-c c-o comint-kill-output Delete last batch of process output
72 ;;; c-c c-r comint-show-output Show last batch of process output
73 ;;; send-invisible Read line w/o echo & send to proc
74 ;;; comint-continue-subjob Useful if you accidentally suspend
75 ;;; top-level job.
76 ;;; comint-mode-hook is the comint mode hook.
77
78 ;;; Shell Mode Commands:
79 ;;; shell Fires up the shell process.
80 ;;; tab comint-dynamic-complete Complete a partial file name
81 ;;; m-? comint-dynamic-list-completions List completions in help buffer
82 ;;; dirs Resync the buffer's dir stack.
83 ;;; dirtrack-toggle Turn dir tracking on/off.
84 ;;;
85 ;;; The shell mode hook is shell-mode-hook
86 ;;; The shell-load-hook is run after this file is loaded.
87 ;;; comint-prompt-regexp is initialised to shell-prompt-pattern, for backwards
88 ;;; compatibility.
89
90 ;;; Read the rest of this file for more information.
91 \f
92 ;;; Emacs 18 SHELL.EL COMPATIBILITY
93 ;;;
94 ;;; The below notes were written before this shell package became the
95 ;;; official shell mode of the standard Emacs distribution, and talk
96 ;;; about getting this package to work well with the old shell package
97 ;;; and its users. This issue isn't quite as relevant now as it was
98 ;;; then, but the notes below should still be useful for people
99 ;;; modifying elisp packages that used the old shell mode to use this
100 ;;; one. Note that some of the variables referred to have lost their
101 ;;; `cmu-' prefix.
102 ;;;
103 ;;;============================================================================
104 ;;; In brief: this package should have no trouble coexisting with shell.el.
105 ;;;
106 ;;; Most customising variables -- e.g., explicit-shell-file-name -- are the
107 ;;; same, so the users shouldn't have much trouble. Hooks have different
108 ;;; names, however, so you can customise shell mode differently from shell
109 ;;; mode. You basically just have to remember to type M-x cmushell instead of
110 ;;; M-x shell.
111 ;;;
112 ;;; It would be nice if this file was completely plug-compatible with the old
113 ;;; shell package -- if you could just name this file shell.el, and have it
114 ;;; transparently replace the old one. But you can't. Several other packages
115 ;;; (tex-mode, background, dbx, gdb, kermit, monkey, prolog, telnet) are also
116 ;;; clients of shell mode. These packages assume detailed knowledge of shell
117 ;;; mode internals in ways that are incompatible with cmushell mode (mostly
118 ;;; because of cmushell mode's greater functionality). So, unless we are
119 ;;; willing to port all of these packages, we can't have this file be a
120 ;;; complete replacement for shell.el -- that is, we can't name this file
121 ;;; shell.el, and its main entry point (shell), because dbx.el will break
122 ;;; when it loads it in and tries to use it.
123 ;;;
124 ;;; There are two ways to fix this. One: rewrite these other modes to use the
125 ;;; new package. This is a win, but can't be assumed. The other, backwards
126 ;;; compatible route, is to make this package non-conflict with shell.el, so
127 ;;; both files can be loaded in at the same time. And *that* is why some
128 ;;; functions and variables have different names: (cmushell),
129 ;;; cmushell-mode-map, that sort of thing. All the names have been carefully
130 ;;; chosen so that shell.el and cmushell.el won't tromp on each other.
131 \f
132 ;;; Customisation and Buffer Variables
133 ;;; ===========================================================================
134 ;;;
135
136 ;In loaddefs.el now.
137 ;(defconst shell-prompt-pattern
138 ; "^[^#$%>]*[#$%>] *"
139 ; "*Regexp used by Newline command to match subshell prompts.
140 ;;; Change the doc string for shell-prompt-pattern:
141 (put 'shell-prompt-pattern 'variable-documentation
142 "Regexp to match prompts in the inferior shell.
143 Defaults to \"^[^#$%>]*[#$%>] *\", which works pretty well.
144 This variable is used to initialise comint-prompt-regexp in the
145 shell buffer.
146
147 This is a fine thing to set in your .emacs file.")
148
149 (defvar shell-popd-regexp "popd"
150 "*Regexp to match subshell commands equivalent to popd.")
151
152 (defvar shell-pushd-regexp "pushd"
153 "*Regexp to match subshell commands equivalent to pushd.")
154
155 (defvar shell-cd-regexp "cd"
156 "*Regexp to match subshell commands equivalent to cd.")
157
158 (defvar explicit-shell-file-name nil
159 "*If non-nil, is file name to use for explicitly requested inferior shell.")
160
161 (defvar explicit-csh-args
162 (if (eq system-type 'hpux)
163 ;; -T persuades HP's csh not to think it is smarter
164 ;; than us about what terminal modes to use.
165 '("-i" "-T")
166 '("-i"))
167 "*Args passed to inferior shell by M-x shell, if the shell is csh.
168 Value is a list of strings, which may be nil.")
169
170 ;;; All the above vars aren't prefixed "shell-" to make them
171 ;;; backwards compatible w/shell.el and old .emacs files.
172
173 (defvar shell-dirstack nil
174 "List of directories saved by pushd in this buffer's shell.")
175
176 (defvar shell-dirstack-query "dirs"
177 "Command used by shell-resync-dirlist to query shell.")
178
179 (defvar shell-mode-map '())
180 (cond ((not shell-mode-map)
181 (setq shell-mode-map (full-copy-sparse-keymap comint-mode-map))
182 (define-key shell-mode-map "\t" 'comint-dynamic-complete)
183 (define-key shell-mode-map "\M-?" 'comint-dynamic-list-completions)))
184
185 (defvar shell-mode-hook '()
186 "*Hook for customising shell mode")
187
188 \f
189 ;;; Basic Procedures
190 ;;; ===========================================================================
191 ;;;
192
193 (defun shell-mode ()
194 "Major mode for interacting with an inferior shell.
195 Return after the end of the process' output sends the text from the
196 end of process to the end of the current line.
197 Return before end of process output copies rest of line to end (skipping
198 the prompt) and sends it.
199 M-x send-invisible reads a line of text without echoing it, and sends it to
200 the shell.
201
202 If you accidentally suspend your process, use \\[comint-continue-subjob]
203 to continue it.
204
205 cd, pushd and popd commands given to the shell are watched by Emacs to keep
206 this buffer's default directory the same as the shell's working directory.
207 M-x dirs queries the shell and resyncs Emacs' idea of what the current
208 directory stack is.
209 M-x dirtrack-toggle turns directory tracking on and off.
210
211 \\{shell-mode-map}
212 Customisation: Entry to this mode runs the hooks on comint-mode-hook and
213 shell-mode-hook (in that order).
214
215 Variables shell-cd-regexp, shell-pushd-regexp and shell-popd-regexp are used
216 to match their respective commands."
217 (interactive)
218 (comint-mode)
219 (setq comint-prompt-regexp shell-prompt-pattern)
220 (setq major-mode 'shell-mode)
221 (setq mode-name "shell")
222 (use-local-map shell-mode-map)
223 (make-local-variable 'shell-dirstack)
224 (setq shell-dirstack nil)
225 (make-local-variable 'shell-dirtrackp)
226 (setq shell-dirtrackp t)
227 (setq comint-input-sentinel 'shell-directory-tracker)
228 (run-hooks 'shell-mode-hook))
229
230 \f
231 (defun shell ()
232 "Run an inferior shell, with I/O through buffer *shell*.
233 If buffer exists but shell process is not running, make new shell.
234 If buffer exists and shell process is running,
235 just switch to buffer *shell*.
236 Program used comes from variable explicit-shell-file-name,
237 or (if that is nil) from the ESHELL environment variable,
238 or else from SHELL if there is no ESHELL.
239 If a file ~/.emacs_SHELLNAME exists, it is given as initial input
240 (Note that this may lose due to a timing error if the shell
241 discards input when it starts up.)
242 The buffer is put in shell-mode, giving commands for sending input
243 and controlling the subjobs of the shell. See shell-mode.
244 See also variable shell-prompt-pattern.
245
246 The shell file name (sans directories) is used to make a symbol name
247 such as `explicit-csh-arguments'. If that symbol is a variable,
248 its value is used as a list of arguments when invoking the shell.
249 Otherwise, one argument `-i' is passed to the shell.
250
251 \(Type \\[describe-mode] in the shell buffer for a list of commands.)"
252 (interactive)
253 (cond ((not (comint-check-proc "*shell*"))
254 (let* ((prog (or explicit-shell-file-name
255 (getenv "ESHELL")
256 (getenv "SHELL")
257 "/bin/sh"))
258 (name (file-name-nondirectory prog))
259 (startfile (concat "~/.emacs_" name))
260 (xargs-name (intern-soft (concat "explicit-" name "-args"))))
261 (set-buffer (apply 'make-comint "shell" prog
262 (if (file-exists-p startfile) startfile)
263 (if (and xargs-name (boundp xargs-name))
264 (symbol-value xargs-name)
265 '("-i"))))
266 (shell-mode))))
267 (switch-to-buffer "*shell*"))
268
269 \f
270 ;;; Directory tracking
271 ;;; ===========================================================================
272 ;;; This code provides the shell mode input sentinel
273 ;;; SHELL-DIRECTORY-TRACKER
274 ;;; that tracks cd, pushd, and popd commands issued to the shell, and
275 ;;; changes the current directory of the shell buffer accordingly.
276 ;;;
277 ;;; This is basically a fragile hack, although it's more accurate than
278 ;;; the released version in shell.el. It has the following failings:
279 ;;; 1. It doesn't know about the cdpath shell variable.
280 ;;; 2. It only spots the first command in a command sequence. E.g., it will
281 ;;; miss the cd in "ls; cd foo"
282 ;;; 3. More generally, any complex command (like ";" sequencing) is going to
283 ;;; throw it. Otherwise, you'd have to build an entire shell interpreter in
284 ;;; emacs lisp. Failing that, there's no way to catch shell commands where
285 ;;; cd's are buried inside conditional expressions, aliases, and so forth.
286 ;;;
287 ;;; The whole approach is a crock. Shell aliases mess it up. File sourcing
288 ;;; messes it up. You run other processes under the shell; these each have
289 ;;; separate working directories, and some have commands for manipulating
290 ;;; their w.d.'s (e.g., the lcd command in ftp). Some of these programs have
291 ;;; commands that do *not* affect the current w.d. at all, but look like they
292 ;;; do (e.g., the cd command in ftp). In shells that allow you job
293 ;;; control, you can switch between jobs, all having different w.d.'s. So
294 ;;; simply saying %3 can shift your w.d..
295 ;;;
296 ;;; The solution is to relax, not stress out about it, and settle for
297 ;;; a hack that works pretty well in typical circumstances. Remember
298 ;;; that a half-assed solution is more in keeping with the spirit of Unix,
299 ;;; anyway. Blech.
300 ;;;
301 ;;; One good hack not implemented here for users of programmable shells
302 ;;; is to program up the shell w.d. manipulation commands to output
303 ;;; a coded command sequence to the tty. Something like
304 ;;; ESC | <cwd> |
305 ;;; where <cwd> is the new current working directory. Then trash the
306 ;;; directory tracking machinery currently used in this package, and
307 ;;; replace it with a process filter that watches for and strips out
308 ;;; these messages.
309
310 ;;; REGEXP is a regular expression. STR is a string. START is a fixnum.
311 ;;; Returns T if REGEXP matches STR where the match is anchored to start
312 ;;; at position START in STR. Sort of like LOOKING-AT for strings.
313 (defun shell-front-match (regexp str start)
314 (eq start (string-match regexp str start)))
315
316 (defun shell-directory-tracker (str)
317 "Tracks cd, pushd and popd commands issued to the shell.
318 This function is called on each input passed to the shell.
319 It watches for cd, pushd and popd commands and sets the buffer's
320 default directory to track these commands.
321
322 You may toggle this tracking on and off with M-x dirtrack-toggle.
323 If emacs gets confused, you can resync with the shell with M-x dirs.
324
325 See variables shell-cd-regexp, shell-pushd-regexp, and shell-popd-regexp.
326 Environment variables are expanded, see function substitute-in-file-name."
327 (condition-case err
328 (cond (shell-dirtrackp
329 (string-match "^\\s *" str) ; skip whitespace
330 (let ((bos (match-end 0))
331 (x nil))
332 (cond ((setq x (shell-match-cmd-w/optional-arg shell-popd-regexp
333 str bos))
334 (shell-process-popd (substitute-in-file-name x)))
335 ((setq x (shell-match-cmd-w/optional-arg shell-pushd-regexp
336 str bos))
337 (shell-process-pushd (substitute-in-file-name x)))
338 ((setq x (shell-match-cmd-w/optional-arg shell-cd-regexp
339 str bos))
340 (shell-process-cd (substitute-in-file-name x)))))))
341 (error (message (car (cdr err))))))
342
343
344 ;;; Try to match regexp CMD to string, anchored at position START.
345 ;;; CMD may be followed by a single argument. If a match, then return
346 ;;; the argument, if there is one, or the empty string if not. If
347 ;;; no match, return nil.
348
349 (defun shell-match-cmd-w/optional-arg (cmd str start)
350 (and (shell-front-match cmd str start)
351 (let ((eoc (match-end 0))) ; end of command
352 (cond ((shell-front-match "\\s *\\(\;\\|$\\)" str eoc)
353 "") ; no arg
354 ((shell-front-match "\\s +\\([^ \t\;]+\\)\\s *\\(\;\\|$\\)"
355 str eoc)
356 (substring str (match-beginning 1) (match-end 1))) ; arg
357 (t nil))))) ; something else.
358 ;;; The first regexp is [optional whitespace, (";" or the end of string)].
359 ;;; The second regexp is [whitespace, (an arg), optional whitespace,
360 ;;; (";" or end of string)].
361
362
363 ;;; popd [+n]
364 (defun shell-process-popd (arg)
365 (let ((num (if (zerop (length arg)) 0 ; no arg means +0
366 (shell-extract-num arg))))
367 (if (and num (< num (length shell-dirstack)))
368 (if (= num 0) ; condition-case because the CD could lose.
369 (condition-case nil (progn (cd (car shell-dirstack))
370 (setq shell-dirstack
371 (cdr shell-dirstack))
372 (shell-dirstack-message))
373 (error (message "Couldn't cd.")))
374 (let* ((ds (cons nil shell-dirstack))
375 (cell (nthcdr (- num 1) ds)))
376 (rplacd cell (cdr (cdr cell)))
377 (setq shell-dirstack (cdr ds))
378 (shell-dirstack-message)))
379 (message "Bad popd."))))
380
381
382 ;;; cd [dir]
383 (defun shell-process-cd (arg)
384 (condition-case nil (progn (cd (if (zerop (length arg)) (getenv "HOME")
385 arg))
386 (shell-dirstack-message))
387 (error (message "Couldn't cd."))))
388
389
390 ;;; pushd [+n | dir]
391 (defun shell-process-pushd (arg)
392 (if (zerop (length arg))
393 ;; no arg -- swap pwd and car of shell stack
394 (condition-case nil (if shell-dirstack
395 (let ((old default-directory))
396 (cd (car shell-dirstack))
397 (setq shell-dirstack
398 (cons old (cdr shell-dirstack)))
399 (shell-dirstack-message))
400 (message "Directory stack empty."))
401 (message "Couldn't cd."))
402
403 (let ((num (shell-extract-num arg)))
404 (if num ; pushd +n
405 (if (> num (length shell-dirstack))
406 (message "Directory stack not that deep.")
407 (let* ((ds (cons default-directory shell-dirstack))
408 (dslen (length ds))
409 (front (nthcdr num ds))
410 (back (reverse (nthcdr (- dslen num) (reverse ds))))
411 (new-ds (append front back)))
412 (condition-case nil
413 (progn (cd (car new-ds))
414 (setq shell-dirstack (cdr new-ds))
415 (shell-dirstack-message))
416 (error (message "Couldn't cd.")))))
417
418 ;; pushd <dir>
419 (let ((old-wd default-directory))
420 (condition-case nil
421 (progn (cd arg)
422 (setq shell-dirstack
423 (cons old-wd shell-dirstack))
424 (shell-dirstack-message))
425 (error (message "Couldn't cd."))))))))
426
427 ;; If STR is of the form +n, for n>0, return n. Otherwise, nil.
428 (defun shell-extract-num (str)
429 (and (string-match "^\\+[1-9][0-9]*$" str)
430 (string-to-int str)))
431
432
433 (defun shell-dirtrack-toggle ()
434 "Turn directory tracking on and off in a shell buffer."
435 (interactive)
436 (setq shell-dirtrackp (not shell-dirtrackp))
437 (message "directory tracking %s."
438 (if shell-dirtrackp "ON" "OFF")))
439
440 ;;; For your typing convenience:
441 (fset 'dirtrack-toggle 'shell-dirtrack-toggle)
442
443
444 (defun shell-resync-dirs ()
445 "Resync the buffer's idea of the current directory stack.
446 This command queries the shell with the command bound to
447 shell-dirstack-query (default \"dirs\"), reads the next
448 line output and parses it to form the new directory stack.
449 DON'T issue this command unless the buffer is at a shell prompt.
450 Also, note that if some other subprocess decides to do output
451 immediately after the query, its output will be taken as the
452 new directory stack -- you lose. If this happens, just do the
453 command again."
454 (interactive)
455 (let* ((proc (get-buffer-process (current-buffer)))
456 (pmark (process-mark proc)))
457 (goto-char pmark)
458 (insert shell-dirstack-query) (insert "\n")
459 (sit-for 0) ; force redisplay
460 (comint-send-string proc shell-dirstack-query)
461 (comint-send-string proc "\n")
462 (set-marker pmark (point))
463 (let ((pt (point))) ; wait for 1 line
464 ;; This extra newline prevents the user's pending input from spoofing us.
465 (insert "\n") (backward-char 1)
466 (while (not (looking-at ".+\n"))
467 (accept-process-output proc)
468 (goto-char pt)))
469 (goto-char pmark) (delete-char 1) ; remove the extra newline
470 ;; That's the dirlist. grab it & parse it.
471 (let* ((dl (buffer-substring (match-beginning 0) (- (match-end 0) 1)))
472 (dl-len (length dl))
473 (ds '()) ; new dir stack
474 (i 0))
475 (while (< i dl-len)
476 ;; regexp = optional whitespace, (non-whitespace), optional whitespace
477 (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
478 (setq ds (cons (substring dl (match-beginning 1) (match-end 1))
479 ds))
480 (setq i (match-end 0)))
481 (let ((ds (reverse ds)))
482 (condition-case nil
483 (progn (cd (car ds))
484 (setq shell-dirstack (cdr ds))
485 (shell-dirstack-message))
486 (error (message "Couldn't cd.")))))))
487
488 ;;; For your typing convenience:
489 (fset 'dirs 'shell-resync-dirs)
490
491
492 ;;; Show the current dirstack on the message line.
493 ;;; Pretty up dirs a bit by changing "/usr/jqr/foo" to "~/foo".
494 ;;; (This isn't necessary if the dirlisting is generated with a simple "dirs".)
495 ;;; All the commands that mung the buffer's dirstack finish by calling
496 ;;; this guy.
497 (defun shell-dirstack-message ()
498 (let ((msg "")
499 (ds (cons default-directory shell-dirstack)))
500 (while ds
501 (let ((dir (car ds)))
502 (if (string-match (format "^%s\\(/\\|$\\)" (getenv "HOME")) dir)
503 (setq dir (concat "~/" (substring dir (match-end 0)))))
504 (if (string-equal dir "~/") (setq dir "~"))
505 (setq msg (concat msg dir " "))
506 (setq ds (cdr ds))))
507 (message msg)))
508
509
510 \f
511 ;;; Interfacing to client packages (and converting them)
512 ;;;============================================================================
513 ;;; Several gnu packages (tex-mode, background, dbx, gdb, kermit, prolog,
514 ;;; telnet are some) use the shell package as clients. Most of them would
515 ;;; be better off using the comint package directly, but they predate it.
516 ;;; The catch is that most of these packages (dbx, gdb, prolog, telnet)
517 ;;; assume total knowledge of all the local variables that shell mode
518 ;;; functions depend on. So they (kill-all-local-variables), then create
519 ;;; the few local variables that shell.el functions depend on. Alas,
520 ;;; cmushell.el functions depend on a different set of vars (for example,
521 ;;; the input history ring is a local variable in cmushell.el's shell mode,
522 ;;; whereas there is no input history ring in shell.el's shell mode).
523 ;;; So we have a situation where the greater functionality of cmushell.el
524 ;;; is biting us -- you can't just replace shell will cmushell.
525 ;;;
526 ;;; Altering these packages to use comint mode directly should *greatly*
527 ;;; improve their functionality, and is actually pretty easy. It's
528 ;;; mostly a matter of renaming a few variable names. See comint.el for more.
529 ;;; -Olin
530
531
532
533 ;;; Do the user's customisation...
534 ;;;===============================
535 (defvar shell-load-hook nil
536 "This hook is run when shell is loaded in.
537 This is a good place to put keybindings.")
538
539 (run-hooks 'shell-load-hook)
540
541 ;;; Change Log
542 ;;; ===========================================================================
543 ;;; Olin 8/88
544 ;;; Created.
545 ;;;
546 ;;; Olin 5/26/90
547 ;;; - Split cmulisp and cmushell modes into separate files.
548 ;;; Not only is this a good idea, it's apparently the way it'll be rel 19.
549 ;;; - Souped up the directory tracking; it now can handle pushd, pushd +n,
550 ;;; and popd +n.
551 ;;; - Added cmushell-dirtrack-toggle command to toggle the directory
552 ;;; tracking that cmushell tries to do. This is useful, for example,
553 ;;; when you are running ftp -- it prevents the ftp "cd" command from
554 ;;; spoofing the tracking machinery. This command is also named
555 ;;; dirtrack-toggle, so you need only type M-x dirtrack to run it.
556 ;;; - Added cmushell-resync-dirs command. This queries the shell
557 ;;; for the current directory stack, and resets the buffer's stack
558 ;;; accordingly. This command is also named dirs, so you need only type
559 ;;; M-x dirs to run it.
560 ;;; - Bits of the new directory tracking code were adapted from source
561 ;;; contributed by Vince Broman, Jeff Peck, and Barry Warsaw.
562 ;;; - See also the improvements made to comint.el at the same time.
563 ;;; - Renamed several variables. Mostly this comprised changing "shell"
564 ;;; to "cmushell" in the names. The only variables that are not prefixed
565 ;;; with "cmushell-" are the ones that are common with shell.el:
566 ;;; explicit-shell-file-name shell-prompt-pattern explicit-csh-args
567 ;;; and shell-cd/popd/pushd-regexp
568 ;;; The variables and functions that were changed to have "cmushell-"
569 ;;; prefixes are:
570 ;;; shell-directory-stack (v), shell-directory-tracker (f)
571 ;;; This should not affect users, only elisp hackers. Hopefully
572 ;;; one day shell.el will just go away, and we can drop all this
573 ;;; "cmushell" bullshit.
574 ;;; - Upgraded process sends to use comint-send-string instead of
575 ;;; process-send-string.
576 ;;;
577 ;;; Olin 6/14/90
578 ;;; - If your shell is named <shellname>, and a variable named
579 ;;; explicit-<shellname>-args exists, cmushell is supposed
580 ;;; to use its value as the arglist to the shell invocation.
581 ;;; E.g., if you define explicit-csh-args to be
582 ;;; ("-ifx"), then when cmushell cranks up a csh, it execs it
583 ;;; as "csh -ifx". This is what is documented. What has actually
584 ;;; been the case is that the variable checked is
585 ;;; explicit-<shellname>-arguments, not explicit-<shellname>-args.
586 ;;; The documentation has been changed to conform to the code (for
587 ;;; backwards compatibility with shell.el). This bug is inherited from
588 ;;; the same bug in shell.el.
589 ;;; This bug reported by Stephen Anderson.
590 ;;;
591 ;;; Olin 9/5/90
592 ;;; - Arguments to cd, popd, and pushd now have their env vars expanded
593 ;;; out by the tracking machinery. So if you say "cd $SRCDIR/funs", the
594 ;;; $SRCDIR var will be replaced by its value *in emacs' process
595 ;;; environment*. If this is different from the shell's binding of the
596 ;;; variable, you lose. Several users needed this feature, fragile
597 ;;; though it may be. The fix was contributed by sk@thp.Uni-Koeln.DE.
598 ;;;
599 ;;; Olin 3/12/91
600 ;;; - Moved comint-dynamic-complete (filename completion) from M-tab to tab.