]> code.delx.au - gnu-emacs/blobdiff - lisp/comint.el
(comint-exec-1): Force a local copy of the environment.
[gnu-emacs] / lisp / comint.el
index a244aadf6599f00b4d6b5e2a58fec4a06c323f55..0bb6116c31ad15bd4f17ea03d780cea1f05e628b 100644 (file)
@@ -1,6 +1,6 @@
 ;;; comint.el --- general command interpreter in a window stuff
 
-;; Copyright (C) 1988, 1990, 1992, 1993 Free Software Foundation, Inc.
+;; Copyright (C) 1988, 1990, 1992, 1993, 1994 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
 ;; Adapted-by: Simon Marshall <s.marshall@dcs.hull.ac.uk>
@@ -67,7 +67,7 @@
 ;;; m-n            comint-next-input               Cycle forwards
 ;;; m-r     comint-previous-matching-input  Previous input matching a regexp
 ;;; m-s     comint-next-matching-input      Next input that matches
-;;; m-c-r   comint-previous-input-matching  Search backwards in input history
+;;; m-c-l   comint-show-output             Show last batch of process output
 ;;; return  comint-send-input
 ;;; c-a     comint-bol                      Beginning of line; skip prompt
 ;;; c-d            comint-delchar-or-maybe-eof     Delete char unless at end of buff
 Defaults to \"^\", the null string at BOL.
 
 Good choices:
-  Canonical Lisp: \"^[^> ]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
+  Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
   Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
   franz: \"^\\\\(->\\\\|<[0-9]*>:\\\\) *\"
   kcl: \"^>+ *\"
-  shell: \"^[^#$%>]*[#$%>] *\"
+  shell: \"^[^#$%>\\n]*[#$%>] *\"
   T: \"^>+ *\"
 
 This is a good thing to set in mode hooks.")
@@ -159,7 +159,7 @@ Good choices:
 
 This is a good thing to set in mode hooks.")
 
-(defvar comint-input-autoexpand 'history
+(defvar comint-input-autoexpand nil
   "*If non-nil, expand input command history references on completion.
 This mirrors the optional behavior of tcsh (its autoexpand and histlit).
 
@@ -182,35 +182,33 @@ See also `comint-read-input-ring' and `comint-write-input-ring'.
 
 This variable is buffer-local, and is a good thing to set in mode hooks.")
 
-(defvar comint-scroll-to-bottom-on-input
-  nil
+(defvar comint-scroll-to-bottom-on-input nil
   "*Controls whether input to interpreter causes window to scroll.
 If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
 If `this', scroll only the selected window.
 
-The default nil.
+The default is nil.
 
 See `comint-preinput-scroll-to-bottom'.  This variable is buffer-local.")
 
-(defvar comint-scroll-to-bottom-on-output 
-  nil
+(defvar comint-scroll-to-bottom-on-output nil
   "*Controls whether interpreter output causes window to scroll.
 If nil, then do not scroll.  If t or `all', scroll all windows showing buffer.
 If `this', scroll only the selected window.
 If `others', scroll only those that are not the selected window.
-The default is `this' for fast terminals, nil for slower ones.
+
+The default is nil.
 
 See variable `comint-scroll-show-maximum-output' and function
 `comint-postoutput-scroll-to-bottom'.  This variable is buffer-local.")
-(defvar comint-scroll-show-maximum-output t
+
+(defvar comint-scroll-show-maximum-output nil
   "*Controls how interpreter output causes window to scroll.
 If non-nil, then show the maximum output when the window is scrolled.
+
 See variable `comint-scroll-to-bottom-on-output' and function
 `comint-postoutput-scroll-to-bottom'.  This variable is buffer-local.")
+
 (defvar comint-input-ring-size 32
   "Size of input history ring.")
 
@@ -304,6 +302,7 @@ This is to work around a bug in Emacs process signalling.")
 (defvar comint-input-ring nil)
 (defvar comint-last-input-start)
 (defvar comint-last-input-end)
+(defvar comint-last-output-start)
 (defvar comint-input-ring-index nil
   "Index of last matched history element.")
 (defvar comint-matching-input-from-input-string ""
@@ -408,6 +407,7 @@ Entry to this mode runs the hooks on `comint-mode-hook'."
   (define-key comint-mode-map "\es" 'comint-next-matching-input)
   (define-key comint-mode-map [?\A-\M-r] 'comint-previous-matching-input-from-input)
   (define-key comint-mode-map [?\A-\M-s] 'comint-next-matching-input-from-input)
+  (define-key comint-mode-map "\e\C-l" 'comint-show-output)
   (define-key comint-mode-map "\C-m" 'comint-send-input)
   (define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof)
   (define-key comint-mode-map "\C-a" 'comint-bol)
@@ -574,7 +574,7 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
 ;;; the appropriate environment.
 
 (defun comint-exec-1 (name buffer command switches)
-  (let ((process-environment process-environment))
+  (let ((process-environment (copy-sequence process-environment)))
     (setenv "TERMCAP" (format "emacs:co#%d:tc=unknown" (frame-width)))
     (setenv "TERM" "emacs")
     (setenv "EMACS" "t")
@@ -602,21 +602,27 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
 ;;; comint-read-input-ring              Read into comint-input-ring...
 ;;; comint-write-input-ring             Write to comint-input-ring-file-name.
 
-(defun comint-read-input-ring ()
+(defun comint-read-input-ring (&optional silent)
   "Sets the buffer's `comint-input-ring' from a history file.
 The name of the file is given by the variable `comint-input-ring-file-name'.
 The history ring is of size `comint-input-ring-size', regardless of file size.
 If `comint-input-ring-file-name' is nil this function does nothing.
 
-Useful within mode or mode hooks.
+If the optional argument SILENT is non-nil, we say nothing about a
+failure to read the history file.
 
-The structure of the history file should be one input command per line, and
-most recent command last.
+This function is useful for major mode commands and mode hooks.
+
+The structure of the history file should be one input command per line,
+with the most recent command last.
 See also `comint-input-ignoredups' and `comint-write-input-ring'."
-  (cond ((null comint-input-ring-file-name)
+  (cond ((or (null comint-input-ring-file-name)
+            (equal comint-input-ring-file-name ""))
         nil)
        ((not (file-readable-p comint-input-ring-file-name))
-        (message "Cannot read history file %s" comint-input-ring-file-name))
+        (or silent
+            (message "Cannot read history file %s"
+                     comint-input-ring-file-name)))
        (t
         (let ((history-buf (get-file-buffer comint-input-ring-file-name))
               (ring (make-ring comint-input-ring-size)))
@@ -652,6 +658,7 @@ Useful within process sentinels.
 
 See also `comint-read-input-ring'."
   (cond ((or (null comint-input-ring-file-name)
+            (equal comint-input-ring-file-name "")
             (null comint-input-ring) (ring-empty-p comint-input-ring))
         nil)
        ((not (file-writable-p comint-input-ring-file-name))
@@ -822,7 +829,7 @@ If N is negative, find the previous or Nth previous match."
   "Search backwards through input history for match for current input.
 \(Previous history elements are earlier commands.)
 With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
+If N is negative, search forwards for the -Nth following match."
   (interactive "p")
   (if (not (memq last-command '(comint-previous-matching-input-from-input
                                comint-next-matching-input-from-input)))
@@ -838,14 +845,14 @@ If N is negative, find the next or Nth next match."
 
 (defun comint-next-matching-input-from-input (arg)
   "Search forwards through input history for match for current input.
-\(Previous history elements are earlier commands.)
-With prefix argument N, search for Nth previous match.
-If N is negative, find the next or Nth next match."
+\(Following history elements are more recent commands.)
+With prefix argument N, search for Nth following match.
+If N is negative, search backwards for the -Nth previous match."
   (interactive "p")
   (comint-previous-matching-input-from-input (- arg)))
 
 
-(defun comint-replace-by-expanded-history ()
+(defun comint-replace-by-expanded-history (&optional silent)
   "Expand input command history references before point.
 This function depends on the buffer's idea of the input history, which may not
 match the command interpreter's idea, assuming it has one.
@@ -854,13 +861,21 @@ Assumes history syntax is like typical Un*x shells'.  However, since emacs
 cannot know the interpreter's idea of input line numbers, assuming it has one,
 it cannot expand absolute input line number references.
 
+If the optional argument SILENT is non-nil, never complain
+even if history reference seems erroneous.
+
 See also `comint-magic-space'."
   (interactive)
   (save-excursion
     (let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
          (start (progn (comint-bol nil) (point))))
-      (while (re-search-forward
-             "[!^]" (save-excursion (end-of-line nil) (- (point) toend)) t)
+      (while (progn
+              (skip-chars-forward "^!^"
+                                  (save-excursion
+                                    (end-of-line nil) (- (point) toend)))
+              (< (point)
+                 (save-excursion
+                   (end-of-line nil) (- (point) toend))))
        ;; This seems a bit complex.  We look for references such as !!, !-num,
        ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
        ;; If that wasn't enough, the plings can be suffixed with argument
@@ -868,11 +883,10 @@ See also `comint-magic-space'."
        ;; Argument ranges are complex too, so we hive off the input line,
        ;; referenced with plings, with the range string to `comint-args'.
        (setq comint-input-ring-index nil)
-       (goto-char (match-beginning 0))
        (cond ((or (= (preceding-char) ?\\)
                   (comint-within-quotes start (point)))
               ;; The history is quoted, or we're in quotes.
-              (goto-char (match-end 0)))
+              (goto-char (1+ (point))))
              ((looking-at "![0-9]+\\($\\|[^-]\\)")
               ;; We cannot know the interpreter's idea of input line numbers.
               (goto-char (match-end 0))
@@ -908,9 +922,10 @@ See also `comint-magic-space'."
                             (comint-previous-matching-input-string-position
                              (concat pref (regexp-quote exp)) 1))))
                 (if (null pos)
-                    (progn (message "Not found")
-                           (goto-char (match-end 0))
-                           (ding))
+                    (or silent
+                        (progn (message "Not found")
+                               (goto-char (match-end 0))
+                               (ding)))
                   (setq comint-input-ring-index pos)
                   (message "History item: %d" (1+ pos))
                   (replace-match
@@ -927,8 +942,10 @@ See also `comint-magic-space'."
                 (goto-char (match-beginning 0))
                 (if (search-forward old pos t)
                     (replace-match new t t)
-                  (message "Not found")
-                  (ding))))
+                  (or silent
+                      (progn
+                        (message "Not found")
+                        (ding))))))
              (t
               (goto-char (match-end 0))))))))
 
@@ -983,9 +1000,15 @@ Quotes are single and double."
   (if (or (null comint-delimiter-argument-list)
          (string-match "[\"\'\`]" arg))
       (list arg)
-    (let ((not-delim (format "[^%s]+" (mapconcat
-                                      (function (lambda (d) (regexp-quote d)))
-                                      comint-delimiter-argument-list "")))
+    (let ((not-delim (concat
+                     (format "\\([^%s]" (mapconcat
+                                       (function (lambda (d) (regexp-quote d)))
+                                       comint-delimiter-argument-list ""))
+                     "\\|"
+                     (mapconcat (function (lambda (d)
+                                            (concat "\\\\" (regexp-quote d))))
+                                comint-delimiter-argument-list "\\|")
+                     "\\)+"))
          (delim-str (mapconcat (function (lambda (d)
                                            (concat (regexp-quote d) "+")))
                                comint-delimiter-argument-list "\\|"))
@@ -1072,18 +1095,18 @@ Similarly for Soar, Scheme, etc."
                          ;; Just whatever's already there
                          intxt
                        ;; Expand and leave it visible in buffer
-                       (comint-replace-by-expanded-history)
+                       (comint-replace-by-expanded-history t)
                        (buffer-substring pmark (point))))
               (history (if (not (eq comint-input-autoexpand 'history))
-                           (comint-arguments input 0 nil)
+                           input
                          ;; This is messy 'cos ultimately the original
                          ;; functions used do insertion, rather than return
                          ;; strings.  We have to expand, then insert back.
-                         (comint-replace-by-expanded-history)
+                         (comint-replace-by-expanded-history t)
                          (let ((copy (buffer-substring pmark (point))))
                            (delete-region pmark (point))
                            (insert input)
-                           (comint-arguments copy 0 nil)))))
+                           copy))))
           (if comint-process-echoes
               (delete-region pmark (point))
            (insert ?\n))
@@ -1102,86 +1125,85 @@ Similarly for Soar, Scheme, etc."
          (set-marker (process-mark proc) (point))
          ;; A kludge to prevent the delay between insert and process output
          ;; affecting the display.  A case for a comint-send-input-hook?
-         (let ((functions comint-output-filter-functions))
-           (while functions
-             (funcall (car functions) (concat input "\n"))
-             (setq functions (cdr functions))))))))
+         (if (eq (process-filter proc) 'comint-output-filter)
+             (let ((functions comint-output-filter-functions))
+               (while functions
+                 (funcall (car functions) (concat input "\n"))
+                 (setq functions (cdr functions)))))))))
 
 ;; The purpose of using this filter for comint processes
 ;; is to keep comint-last-input-end from moving forward
 ;; when output is inserted.
 (defun comint-output-filter (process string)
   ;; First check for killed buffer
-  (if (not (comint-check-proc (process-buffer process)))
-      (message
-       "comint-output-filter: buffer %s received output with no process"
-       (process-buffer process))
-    (let ((obuf (current-buffer))
-         (opoint nil) (obeg nil) (oend nil))
-      (set-buffer (process-buffer process))
-      (setq opoint (point))
-      (setq obeg (point-min))
-      (setq oend (point-max))
-      (let ((buffer-read-only nil)
-           (nchars (length string))
-           (ostart nil))
-       (widen)
-       (goto-char (process-mark process))
-       (setq ostart (point))
-       (if (<= (point) opoint)
-           (setq opoint (+ opoint nchars)))
-       ;; Insert after old_begv, but before old_zv.
-       (if (< (point) obeg)
-           (setq obeg (+ obeg nchars)))
-       (if (<= (point) oend)
-           (setq oend (+ oend nchars)))
-       (insert-before-markers string)
-       ;; Don't insert initial prompt outside the top of the window.
-       (if (= (window-start (selected-window)) (point))
-           (set-window-start (selected-window) (- (point) (length string))))
-       (if (and comint-last-input-end
-                (marker-buffer comint-last-input-end)
-                (= (point) comint-last-input-end))
-           (set-marker comint-last-input-end (- comint-last-input-end nchars)))
-       (set-marker comint-last-output-start ostart)
-       (set-marker (process-mark process) (point))
-       (force-mode-line-update))
-
-      (narrow-to-region obeg oend)
-      (goto-char opoint)
-      (let ((functions comint-output-filter-functions))
-       (while functions
-         (funcall (car functions) string)
-         (setq functions (cdr functions))))
-      (set-buffer obuf))))
+  (let ((oprocbuf (process-buffer process)))
+    (if (and oprocbuf (buffer-name oprocbuf))
+       (let ((obuf (current-buffer))
+             (opoint nil) (obeg nil) (oend nil))
+         (set-buffer oprocbuf)
+         (setq opoint (point))
+         (setq obeg (point-min))
+         (setq oend (point-max))
+         (let ((buffer-read-only nil)
+               (nchars (length string))
+               (ostart nil))
+           (widen)
+           (goto-char (process-mark process))
+           (setq ostart (point))
+           (if (<= (point) opoint)
+               (setq opoint (+ opoint nchars)))
+           ;; Insert after old_begv, but before old_zv.
+           (if (< (point) obeg)
+               (setq obeg (+ obeg nchars)))
+           (if (<= (point) oend)
+               (setq oend (+ oend nchars)))
+           (insert-before-markers string)
+           ;; Don't insert initial prompt outside the top of the window.
+           (if (= (window-start (selected-window)) (point))
+               (set-window-start (selected-window) (- (point) (length string))))
+           (if (and comint-last-input-end
+                    (marker-buffer comint-last-input-end)
+                    (= (point) comint-last-input-end))
+               (set-marker comint-last-input-end (- comint-last-input-end nchars)))
+           (set-marker comint-last-output-start ostart)
+           (set-marker (process-mark process) (point))
+           (force-mode-line-update))
+
+         (narrow-to-region obeg oend)
+         (goto-char opoint)
+         (let ((functions comint-output-filter-functions))
+           (while functions
+             (funcall (car functions) string)
+             (setq functions (cdr functions))))
+         (set-buffer obuf)))))
 
 (defun comint-preinput-scroll-to-bottom ()
   "Go to the end of buffer in all windows showing it.
 Movement occurs if point in the selected window is not after the process mark,
 and `this-command' is an insertion command.  Insertion commands recognised
-are `self-insert-command', `yank', `mouse-yank-at-click', and `hilit-yank'.
+are `self-insert-command', `comint-magic-space', `yank', and `hilit-yank'.
 Depends on the value of `comint-scroll-to-bottom-on-input'.
 
 This function should be a pre-command hook."
   (if (and comint-scroll-to-bottom-on-input
-          (memq this-command '(self-insert-command yank mouse-yank-at-click
+          (memq this-command '(self-insert-command comint-magic-space yank
                                hilit-yank)))
       (let* ((selected (selected-window))
             (current (current-buffer))
             (process (get-buffer-process current))
             (scroll comint-scroll-to-bottom-on-input))
-       (if (and process (< (point) (process-mark process))
-                scroll (not (window-minibuffer-p selected)))
-           (walk-windows
-            (function (lambda (window)
-              (if (and (eq (window-buffer window) current)
-                       (or (eq scroll t) (eq scroll 'all)
-                           (and (eq scroll 'this) (eq selected window))))
-                  (progn
-                    (select-window window)
-                    (goto-char (point-max))
-                    (select-window selected)))))
-            'not-minibuf t)))))
+       (if (and process (< (point) (process-mark process)))
+           (if (eq scroll 'this)
+               (goto-char (point-max))
+             (walk-windows
+              (function (lambda (window)
+                (if (and (eq (window-buffer window) current)
+                         (or (eq scroll t) (eq scroll 'all)))
+                    (progn
+                      (select-window window)
+                      (goto-char (point-max))
+                      (select-window selected)))))
+              nil t))))))
 
 (defun comint-postoutput-scroll-to-bottom (string)
   "Go to the end of buffer in all windows showing it.
@@ -1194,30 +1216,32 @@ This function should be in the list `comint-output-filter-functions'."
         (current (current-buffer))
         (process (get-buffer-process current))
         (scroll comint-scroll-to-bottom-on-output))
-    (if (and process scroll (not (window-minibuffer-p selected)))
-       (walk-windows
-        (function (lambda (window)
-          (if (eq (window-buffer window) current)
-              (progn
-                (select-window window)
-                (if (or (eq scroll t) (eq scroll 'all)
-                        ;; Maybe user wants point to jump to the end.
-                        (and (eq scroll 'this) (eq selected window))
-                        (and (eq scroll 'others) (not (eq selected window)))
-                        ;; If point was at the end, keep it at the end.
-                        (and (>= (point)
-                                 (- (process-mark process) (length string)))
-                             (< (point) (process-mark process))))
-                    (goto-char (process-mark process)))
-                ;; Optionally scroll so that the text
-                ;; ends at the bottom of the window.
-                (if (and comint-scroll-show-maximum-output
-                         (>= (point) (process-mark process)))
-                    (save-excursion
-                      (goto-char (point-max))
-                      (recenter -1)))
-                (select-window selected)))))
-        'not-minibuf t))))
+    (unwind-protect
+       (if process
+           (walk-windows
+            (function (lambda (window)
+              (if (eq (window-buffer window) current)
+                  (progn
+                    (select-window window)
+                    (if (and (< (point) (process-mark process))
+                             (or (eq scroll t) (eq scroll 'all)
+                                 ;; Maybe user wants point to jump to the end.
+                                 (and (eq scroll 'this) (eq selected window))
+                                 (and (eq scroll 'others) (not (eq selected window)))
+                                 ;; If point was at the end, keep it at the end.
+                                 (>= (point)
+                                     (- (process-mark process) (length string)))))
+                        (goto-char (process-mark process)))
+                    ;; Optionally scroll so that the text
+                    ;; ends at the bottom of the window.
+                    (if (and comint-scroll-show-maximum-output
+                             (>= (point) (process-mark process)))
+                        (save-excursion
+                          (goto-char (point-max))
+                          (recenter -1)))
+                    (select-window selected)))))
+            nil t))
+      (set-buffer current))))
 
 (defun comint-show-maximum-output ()
   "Put the end of the buffer at the bottom of the window."
@@ -1394,13 +1418,12 @@ Does not delete the prompt."
   "Display start of this batch of interpreter output at top of window.
 Also put cursor there if the current position is not visible."
   (interactive)
+  (push-mark)
   (let ((pos (point)))
-    (goto-char comint-last-input-end)
+    (goto-char (or (marker-position comint-last-input-end) (point-max)))
     (beginning-of-line 0)
     (set-window-start (selected-window) (point))
-    (if (pos-visible-in-window-p pos)
-       (goto-char pos)
-      (comint-skip-prompt))))
+    (comint-skip-prompt)))
 
 (defun comint-interrupt-subjob ()
   "Interrupt the current subjob."
@@ -1744,11 +1767,11 @@ directory tracking functions.")
   "Return the filename at point, or signal an error.
 Environment variables are substituted."
   (save-excursion
-    (if (re-search-backward "[^~/A-Za-z0-9_.$#,={}()-]" nil 'move)
+    (if (re-search-backward "[^~/A-Za-z0-9+@:_.$#,={}-]" nil 'move)
        (forward-char 1))
     ;; Anchor the search forwards.
-    (if (not (looking-at "[~/A-Za-z0-9_.$#,={}()-]")) (error ""))
-    (re-search-forward "[~/A-Za-z0-9_.$#,={}()-]+")
+    (if (not (looking-at "[~/A-Za-z0-9+@:_.$#,={}-]")) (error ""))
+    (re-search-forward "[~/A-Za-z0-9+@:_.$#,={}-]+")
     (substitute-in-file-name
      (buffer-substring (match-beginning 0) (match-end 0)))))
 
@@ -1815,6 +1838,8 @@ Completion is dependent on the value of `comint-completion-addsuffix' and
 dependent on the value of `comint-completion-autolist'."
   (interactive)
   (let* ((completion-ignore-case nil)
+        ;; For shell completion, treat all files as equally interesting.
+        (completion-ignored-extensions nil)
         (filename (comint-match-partial-filename))
          (pathdir (file-name-directory filename))
          (pathnondir (file-name-nondirectory filename))
@@ -1967,6 +1992,8 @@ See also `comint-dynamic-complete-filename'."
   "List in help buffer possible completions of the filename at point."
   (interactive)
   (let* ((completion-ignore-case nil)
+        ;; For shell completion, treat all files as equally interesting.
+        (completion-ignored-extensions nil)
         (filename (comint-match-partial-filename))
         (pathdir (file-name-directory filename))
         (pathnondir (file-name-nondirectory filename))
@@ -1984,12 +2011,24 @@ Typing SPC flushes the help buffer."
   (let ((conf (current-window-configuration)))
     (with-output-to-temp-buffer " *Completions*"
       (display-completion-list (sort completions 'string-lessp)))
-    (sit-for 0)
     (message "Hit space to flush")
-    (let ((ch (read-event)))
-      (if (eq ch ?\ )
-         (set-window-configuration conf)
-       (setq unread-command-events (list ch))))))
+    (let (key first)
+      (if (save-excursion
+           (set-buffer (get-buffer " *Completions*"))
+           (setq key (read-key-sequence nil)
+                 first (aref key 0))
+           (and (consp first)
+                (eq (window-buffer (posn-window (event-start first)))
+                    (get-buffer " *Completions*"))
+                (eq (key-binding key) 'mouse-choose-completion)))
+         ;; If the user does mouse-choose-completion with the mouse,
+         ;; execute the command, then delete the completion window.
+         (progn
+           (mouse-choose-completion first)
+           (set-window-configuration conf))
+       (if (eq first ?\ )
+           (set-window-configuration conf)
+         (setq unread-command-events (append key nil)))))))
 \f
 ;;; Converting process modes to use comint mode
 ;;; ===========================================================================
@@ -2044,17 +2083,21 @@ Typing SPC flushes the help buffer."
 ;;; comint-mode will take care of it. The following example, from shell.el,
 ;;; is typical:
 ;;; 
+;;; (defvar shell-mode-map '())
+;;; (cond ((not shell-mode-map)
+;;;        (setq shell-mode-map (full-copy-sparse-keymap comint-mode-map))
+;;;        (define-key shell-mode-map "\C-c\C-f" 'shell-forward-command)
+;;;        (define-key shell-mode-map "\C-c\C-b" 'shell-backward-command)
+;;;        (define-key shell-mode-map "\t" 'comint-dynamic-complete)
+;;;        (define-key shell-mode-map "\M-?"
+;;;          'comint-dynamic-list-filename-completions)))
+;;;
 ;;; (defun shell-mode ()
 ;;;   (interactive)
 ;;;   (comint-mode)
 ;;;   (setq comint-prompt-regexp shell-prompt-pattern)
 ;;;   (setq major-mode 'shell-mode)
 ;;;   (setq mode-name "Shell")
-;;;   (cond ((not shell-mode-map)
-;;;         (setq shell-mode-map (full-copy-sparse-keymap comint-mode-map))
-;;;         (define-key shell-mode-map "\M-\t" 'comint-dynamic-complete)
-;;;         (define-key shell-mode-map "\M-?"
-;;;                      'comint-dynamic-list-filename-completions)))
 ;;;   (use-local-map shell-mode-map)
 ;;;   (make-local-variable 'shell-directory-stack)
 ;;;   (setq shell-directory-stack nil)