]> code.delx.au - gnu-emacs/blobdiff - lisp/comint.el
Merge from emacs--rel--22
[gnu-emacs] / lisp / comint.el
index 99ea2c44436e4e4eb3dae73bbdfef14bd5c18311..623eef17327457fce652543e74663fa6afa4493f 100644 (file)
@@ -1,7 +1,7 @@
 ;;; comint.el --- general command interpreter in a window stuff
 
 ;; Copyright (C) 1988, 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;;   2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Olin Shivers <shivers@cs.cmu.edu>
 ;;     Simon Marshall <simon@gnu.org>
@@ -12,7 +12,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;;  comint-eol-on-send                 boolean ...
 ;;  comint-process-echoes              boolean ...
 ;;  comint-scroll-to-bottom-on-input   symbol  For scroll behavior
-;;  comint-scroll-to-bottom-on-output  symbol  ...
+;;  comint-move-point-for-output       symbol  ...
 ;;  comint-scroll-show-maximum-output  boolean ...
 ;;  comint-accum-marker                        maker     For comint-accumulate
 ;;
@@ -333,12 +333,13 @@ This variable is buffer-local."
 ;; kinit prints a prompt like `Password for devnull@GNU.ORG: '.
 ;; ksu prints a prompt like `Kerberos password for devnull/root@GNU.ORG: '.
 ;; ssh-add prints a prompt like `Enter passphrase: '.
+;; plink prints a prompt like `Passphrase for key "root@GNU.ORG": '.
 ;; Some implementations of passwd use "Password (again)" as the 2nd prompt.
 (defcustom comint-password-prompt-regexp
   "\\(\\([Oo]ld \\|[Nn]ew \\|'s \\|login \\|\
-Kerberos \\|CVS \\|UNIX \\| SMB \\|^\\)\
+Kerberos \\|CVS \\|UNIX \\| SMB \\|LDAP \\|^\\)\
 \[Pp]assword\\( (again)\\)?\\|\
-pass phrase\\|\\(Enter\\|Repeat\\|Bad\\) passphrase\\)\
+pass phrase\\|\\(Enter \\|Repeat \\|Bad \\)?[Pp]assphrase\\)\
 \\(?:, try again\\)?\\(?: for [^:]+\\)?:\\s *\\'"
   "*Regexp matching prompts for passwords in the inferior process.
 This is used by `comint-watch-for-password-prompt'."
@@ -411,17 +412,15 @@ See `comint-send-input'."
   "*If non-nil, use `comint-prompt-regexp' to recognize prompts.
 If nil, then program output and user-input are given different `field'
 properties, which Emacs commands can use to distinguish them (in
-particular, common movement commands such as begining-of-line respect
-field boundaries in a natural way)."
+particular, common movement commands such as `beginning-of-line'
+respect field boundaries in a natural way)."
   :type 'boolean
   :group 'comint)
 
 ;; Autoload is necessary for Custom to recognize old alias.
 ;;;###autoload
-(defvaralias 'comint-use-prompt-regexp-instead-of-fields
-  'comint-use-prompt-regexp)
-(make-obsolete-variable 'comint-use-prompt-regexp-instead-of-fields
-                       'comint-use-prompt-regexp "22.1")
+(define-obsolete-variable-alias 'comint-use-prompt-regexp-instead-of-fields
+    'comint-use-prompt-regexp "22.1")
 
 (defcustom comint-mode-hook nil
   "Hook run upon entry to `comint-mode'.
@@ -460,7 +459,7 @@ executed once when the buffer is created."
     (define-key map "\C-c\C-c"           'comint-interrupt-subjob)
     (define-key map "\C-c\C-z"           'comint-stop-subjob)
     (define-key map "\C-c\C-\\"   'comint-quit-subjob)
-    (define-key map "\C-c\C-m"           'comint-insert-input)
+    (define-key map "\C-c\C-m"           'comint-copy-old-input)
     (define-key map "\C-c\C-o"           'comint-delete-output)
     (define-key map "\C-c\C-r"           'comint-show-output)
     (define-key map "\C-c\C-e"           'comint-show-maximum-output)
@@ -504,7 +503,7 @@ executed once when the buffer is created."
     (define-key map [menu-bar inout kill-input]
       '("Kill Current Input" . comint-kill-input))
     (define-key map [menu-bar inout copy-input]
-      '("Copy Old Input" . comint-insert-input))
+      '("Copy Old Input" . comint-copy-old-input))
     (define-key map [menu-bar inout forward-matching-history]
       '("Forward Matching Input..." . comint-forward-matching-input))
     (define-key map [menu-bar inout backward-matching-history]
@@ -560,6 +559,9 @@ This is to support the command \\[comint-get-next-from-history].")
   "Non-nil if you are accumulating input lines to send as input together.
 The command \\[comint-accumulate] sets this.")
 
+(defvar comint-stored-incomplete-input nil
+  "Stored input for history cycling.")
+
 (put 'comint-replace-by-expanded-history 'menu-enable 'comint-input-autoexpand)
 (put 'comint-input-ring 'permanent-local t)
 (put 'comint-input-ring-index 'permanent-local t)
@@ -640,15 +642,25 @@ Entry to this mode runs the hooks on `comint-mode-hook'."
   (make-local-variable 'comint-scroll-to-bottom-on-input)
   (make-local-variable 'comint-move-point-for-output)
   (make-local-variable 'comint-scroll-show-maximum-output)
+  (make-local-variable 'comint-stored-incomplete-input)
+  ;; Following disabled because it seems to break the case when
+  ;; comint-scroll-show-maximum-output is nil, and no-one can remember
+  ;; what the original problem was.  If there are problems with point
+  ;; not going to the end, consider re-enabling this.
+  ;; http://lists.gnu.org/archive/html/emacs-devel/2007-08/msg00827.html
+  ;;
   ;; This makes it really work to keep point at the bottom.
-  (make-local-variable 'scroll-conservatively)
-  (setq scroll-conservatively 10000)
+;;;  (make-local-variable 'scroll-conservatively)
+;;;  (setq scroll-conservatively 10000)
   (add-hook 'pre-command-hook 'comint-preinput-scroll-to-bottom t t)
   (make-local-variable 'comint-ptyp)
   (make-local-variable 'comint-process-echoes)
   (make-local-variable 'comint-file-name-chars)
   (make-local-variable 'comint-file-name-quote-list)
-  (set (make-local-variable 'comint-accum-marker) (make-marker))
+  (make-local-variable 'comint-accum-marker)
+  (setq comint-accum-marker (make-marker))
+  (make-local-variable 'font-lock-defaults)
+  (setq font-lock-defaults '(nil t))
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
   ;; This behavior is not useful in comint buffers, and is annoying
   (set (make-local-variable 'next-line-add-newlines) nil))
@@ -665,13 +677,13 @@ BUFFER can be either a buffer or the name of one."
   "Make a Comint process NAME in BUFFER, running PROGRAM.
 If BUFFER is nil, it defaults to NAME surrounded by `*'s.
 PROGRAM should be either a string denoting an executable program to create
-via `start-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP
-connection to be opened via `open-network-stream'.  If there is already a
-running process in that buffer, it is not restarted.  Optional fourth arg
+via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting
+a TCP connection to be opened via `open-network-stream'.  If there is already
+running process in that buffer, it is not restarted.  Optional fourth arg
 STARTFILE is the name of a file to send the contents of to the process.
 
 If PROGRAM is a string, any more args are arguments to PROGRAM."
-  (or (fboundp 'start-process)
+  (or (fboundp 'start-file-process)
       (error "Multi-processing is not supported for this system"))
   (setq buffer (get-buffer-create (or buffer (concat "*" name "*"))))
   ;; If no process, or nuked process, crank up a new one and put buffer in
@@ -688,9 +700,9 @@ If PROGRAM is a string, any more args are arguments to PROGRAM."
   "Make a Comint process NAME in a buffer, running PROGRAM.
 The name of the buffer is made by surrounding NAME with `*'s.
 PROGRAM should be either a string denoting an executable program to create
-via `start-process', or a cons pair of the form (HOST . SERVICE) denoting a TCP
-connection to be opened via `open-network-stream'.  If there is already a
-running process in that buffer, it is not restarted.  Optional third arg
+via `start-file-process', or a cons pair of the form (HOST . SERVICE) denoting
+a TCP connection to be opened via `open-network-stream'.  If there is already
+running process in that buffer, it is not restarted.  Optional third arg
 STARTFILE is the name of a file to send the contents of the process to.
 
 If PROGRAM is a string, any more args are arguments to PROGRAM."
@@ -763,7 +775,9 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
                    (format "COLUMNS=%d" (window-width)))
            (list "TERM=emacs"
                  (format "TERMCAP=emacs:co#%d:tc=unknown:" (window-width))))
-         (if (getenv "EMACS") nil (list "EMACS=t"))
+         (unless (getenv "EMACS")
+           (list "EMACS=t"))
+         (list (format "INSIDE_EMACS=%s,comint" emacs-version))
          process-environment))
        (default-directory
          (if (file-accessible-directory-p default-directory)
@@ -774,17 +788,19 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
                         ;; If the command has slashes, make sure we
                         ;; first look relative to the current directory.
                         (cons default-directory exec-path) exec-path)))
-      (setq proc (apply 'start-process name buffer command switches)))
+      (setq proc (apply 'start-file-process name buffer command switches)))
+    ;; Some file name handler cannot start a process, fe ange-ftp.
+    (unless (processp proc) (error "No process started"))
     (let ((coding-systems (process-coding-system proc)))
       (setq decoding (car coding-systems)
            encoding (cdr coding-systems)))
-    ;; If start-process decided to use some coding system for decoding
+    ;; If start-file-process decided to use some coding system for decoding
     ;; data sent from the process and the coding system doesn't
     ;; specify EOL conversion, we had better convert CRLF to LF.
     (if (vectorp (coding-system-eol-type decoding))
        (setq decoding (coding-system-change-eol-conversion decoding 'dos)
              changed t))
-    ;; Even if start-process left the coding system for encoding data
+    ;; Even if start-file-process left the coding system for encoding data
     ;; sent from the process undecided, we had better use the same one
     ;; as what we use for decoding.  But, we should suppress EOL
     ;; conversion.
@@ -795,22 +811,28 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
        (set-process-coding-system proc decoding encoding))
     proc))
 
-(defun comint-insert-input (&optional event)
-  "In a Comint buffer, set the current input to the previous input at point."
-  ;; This doesn't use "e" because it is supposed to work
-  ;; for events without parameters.
-  (interactive (list last-input-event))
-  (let ((pos (point)))
-    (if event (mouse-set-point event))
-    (if (not (eq (get-char-property (point) 'field) 'input))
-       ;; No input at POS, fall back to the global definition.
+(defun comint-insert-input (event)
+  "In a Comint buffer, set the current input to the previous input at point.
+If there is no previous input at point, run the command specified
+by the global keymap (usually `mouse-yank-at-point')."
+  (interactive "e")
+  (let ((pos (posn-point (event-end event)))
+       field input)
+    (with-selected-window (posn-window (event-end event))
+      (and (setq field (field-at-pos pos))
+          (setq input (field-string-no-properties pos))))
+    (if (or (null comint-accum-marker)
+           (not (eq field 'input)))
+       ;; Fall back to the global definition if (i) the selected
+       ;; buffer is not a comint buffer (which can happen if a
+       ;; non-comint window was selected and we clicked in a comint
+       ;; window), or (ii) there is no input at POS.
        (let* ((keys (this-command-keys))
               (last-key (and (vectorp keys) (aref keys (1- (length keys)))))
               (fun (and last-key (lookup-key global-map (vector last-key)))))
-         (goto-char pos)
-         (and fun (call-interactively fun)))
-      (setq pos (point))
-      ;; There's previous input at POS, insert it at the end of the buffer.
+         (and fun (not (eq fun 'comint-insert-input))
+              (call-interactively fun)))
+      ;; Otherwise, insert the previous input.
       (goto-char (point-max))
       ;; First delete any old unsent input at the end
       (delete-region
@@ -818,10 +840,7 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
           (process-mark (get-buffer-process (current-buffer))))
        (point))
       ;; Insert the input at point
-      (insert (buffer-substring-no-properties
-              (previous-single-char-property-change (1+ pos) 'field)
-              (next-single-char-property-change pos 'field))))))
-
+      (insert input))))
 \f
 ;; Input history processing in a buffer
 ;; ===========================================================================
@@ -886,7 +905,7 @@ See also `comint-input-ignoredups' and `comint-write-input-ring'."
                 ;; Watch for those date stamps in history files!
                 (goto-char (point-max))
                 (let (start end history)
-                  (while (and (< count comint-input-ring-size)
+                  (while (and (< count size)
                               (re-search-backward comint-input-ring-separator nil t)
                               (setq end (match-beginning 0)))
                     (if (re-search-backward comint-input-ring-separator nil t)
@@ -1017,6 +1036,16 @@ See also `comint-read-input-ring'."
        (t
         arg)))
 
+(defun comint-restore-input ()
+  "Restore unfinished input."
+  (interactive)
+  (when comint-input-ring-index
+    (comint-delete-input)
+    (when (> (length comint-stored-incomplete-input) 0)
+      (insert comint-stored-incomplete-input)
+      (message "Input restored"))
+    (setq comint-input-ring-index nil)))
+
 (defun comint-search-start (arg)
   "Index to start a directional search, starting at `comint-input-ring-index'."
   (if comint-input-ring-index
@@ -1037,9 +1066,18 @@ Moves relative to `comint-input-ring-index'."
                                arg)))
 
 (defun comint-previous-input (arg)
-  "Cycle backwards through input history."
+  "Cycle backwards through input history, saving input."
   (interactive "*p")
-  (comint-previous-matching-input "." arg))
+  (if (and comint-input-ring-index
+          (or                 ;; leaving the "end" of the ring
+           (and (< arg 0)              ; going down
+                (eq comint-input-ring-index 0))
+           (and (> arg 0)              ; going up
+                (eq comint-input-ring-index
+                    (1- (ring-length comint-input-ring)))))
+          comint-stored-incomplete-input)
+      (comint-restore-input)
+    (comint-previous-matching-input "." arg)))
 
 (defun comint-next-input (arg)
   "Cycle forwards through input history."
@@ -1079,35 +1117,43 @@ Moves relative to START, or `comint-input-ring-index'."
     (if (string-match regexp (ring-ref comint-input-ring n))
        n)))
 
-(defun comint-previous-matching-input (regexp arg)
+(defun comint-delete-input ()
+  "Delete all input between accumulation or process mark and point."
+  (delete-region
+   ;; Can't use kill-region as it sets this-command
+   (or  (marker-position comint-accum-marker)
+       (process-mark (get-buffer-process (current-buffer))))
+   (point-max)))
+
+(defun comint-previous-matching-input (regexp n)
   "Search backwards through input history for match for REGEXP.
 \(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."
   (interactive (comint-regexp-arg "Previous input matching (regexp): "))
-  (setq arg (comint-search-arg arg))
-  (let ((pos (comint-previous-matching-input-string-position regexp arg)))
+  (setq n (comint-search-arg n))
+  (let ((pos (comint-previous-matching-input-string-position regexp n)))
     ;; Has a match been found?
     (if (null pos)
        (error "Not found")
+      ;; If leaving the edit line, save partial input
+      (if (null comint-input-ring-index)       ;not yet on ring
+         (setq comint-stored-incomplete-input
+               (funcall comint-get-old-input)))
       (setq comint-input-ring-index pos)
       (message "History item: %d" (1+ pos))
-      (delete-region
-       ;; Can't use kill-region as it sets this-command
-       (or  (marker-position comint-accum-marker)
-           (process-mark (get-buffer-process (current-buffer))))
-       (point))
+      (comint-delete-input)
       (insert (ring-ref comint-input-ring pos)))))
 
-(defun comint-next-matching-input (regexp arg)
+(defun comint-next-matching-input (regexp n)
   "Search forwards through input history for match for REGEXP.
 \(Later history elements are more recent commands.)
 With prefix argument N, search for Nth following match.
 If N is negative, find the previous or Nth previous match."
   (interactive (comint-regexp-arg "Next input matching (regexp): "))
-  (comint-previous-matching-input regexp (- arg)))
+  (comint-previous-matching-input regexp (- n)))
 
-(defun comint-previous-matching-input-from-input (arg)
+(defun comint-previous-matching-input-from-input (n)
   "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.
@@ -1124,15 +1170,15 @@ If N is negative, search forwards for the -Nth following match."
            comint-input-ring-index nil))
   (comint-previous-matching-input
    (concat "^" (regexp-quote comint-matching-input-from-input-string))
-   arg))
+   n))
 
-(defun comint-next-matching-input-from-input (arg)
+(defun comint-next-matching-input-from-input (n)
   "Search forwards through input history for match for current input.
 \(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)))
+  (comint-previous-matching-input-from-input (- n)))
 
 
 (defun comint-replace-by-expanded-history (&optional silent start)
@@ -1310,7 +1356,11 @@ Quotes are single and double."
 (defun comint-delim-arg (arg)
   "Return a list of arguments from ARG.
 Break it up at the delimiters in `comint-delimiter-argument-list'.
-Returned list is backwards."
+Returned list is backwards.
+
+Characters with non-nil values of the text property `literal' are
+assumed to have literal values (e.g., backslash-escaped
+characters), and are not considered to be delimiters."
   (if (null comint-delimiter-argument-list)
       (list arg)
     (let ((args nil)
@@ -1319,12 +1369,16 @@ Returned list is backwards."
       (while (< pos len)
        (let ((char (aref arg pos))
              (start pos))
-         (if (memq char comint-delimiter-argument-list)
+         (if (and (memq char comint-delimiter-argument-list)
+                  ;; Ignore backslash-escaped characters.
+                  (not (get-text-property pos 'literal arg)))
              (while (and (< pos len) (eq (aref arg pos) char))
                (setq pos (1+ pos)))
            (while (and (< pos len)
-                       (not (memq (aref arg pos)
-                                  comint-delimiter-argument-list)))
+                       (not (and (memq (aref arg pos)
+                                       comint-delimiter-argument-list)
+                                 (not (get-text-property
+                                       pos 'literal arg)))))
              (setq pos (1+ pos))))
          (setq args (cons (substring arg start pos) args))))
       args)))
@@ -1344,24 +1398,32 @@ Argument 0 is the command name."
   ;; The third matches '-quoted strings.
   ;; The fourth matches `-quoted strings.
   ;; This seems to fit the syntax of BASH 2.0.
-  (let* ((first (if (if (fboundp 'w32-shell-dos-semantics)
-                       (w32-shell-dos-semantics))
-                   "[^ \n\t\"'`]+\\|"
-                 "[^ \n\t\"'`\\]+\\|\\\\[\"'`\\ \t]+\\|"))
+  (let* ((backslash-escape (not (and (fboundp 'w32-shell-dos-semantics)
+                                    (w32-shell-dos-semantics))))
+        (first (if backslash-escape
+                   "[^ \n\t\"'`\\]\\|\\(\\\\.\\)\\|"
+                 "[^ \n\t\"'`]+\\|"))
         (argpart (concat first
                          "\\(\"\\([^\"\\]\\|\\\\.\\)*\"\\|\
 '[^']*'\\|\
 `[^`]*`\\)"))
+        (quote-subexpr (if backslash-escape 2 1))
         (args ()) (pos 0)
         (count 0)
         beg str quotes)
     ;; Build a list of all the args until we have as many as we want.
     (while (and (or (null mth) (<= count mth))
                (string-match argpart string pos))
+      ;; Apply the `literal' text property to backslash-escaped
+      ;; characters, so that `comint-delim-arg' won't break them up.
+      (and backslash-escape
+          (match-beginning 1)
+          (put-text-property (match-beginning 1) (match-end 1)
+                             'literal t string))
       (if (and beg (= pos (match-beginning 0)))
          ;; It's contiguous, part of the same arg.
          (setq pos (match-end 0)
-               quotes (or quotes (match-beginning 1)))
+               quotes (or quotes (match-beginning quote-subexpr)))
        ;; It's a new separate arg.
        (if beg
            ;; Put the previous arg, if there was one, onto ARGS.
@@ -1369,7 +1431,7 @@ Argument 0 is the command name."
                  args (if quotes (cons str args)
                         (nconc (comint-delim-arg str) args))))
        (setq count (length args))
-       (setq quotes (match-beginning 1))
+       (setq quotes (match-beginning quote-subexpr))
        (setq beg (match-beginning 0))
        (setq pos (match-end 0))))
     (if beg
@@ -1434,14 +1496,14 @@ If the interpreter is the csh,
        return the current line with any initial string matching the
        regexp `comint-prompt-regexp' removed.
     `comint-input-filter-functions' monitors input for \"cd\", \"pushd\", and
-       \"popd\" commands. When it sees one, it cd's the buffer.
-    comint-input-filter is the default: returns t if the input isn't all white
+       \"popd\" commands.  When it sees one, it cd's the buffer.
+    `comint-input-filter' is the default: returns t if the input isn't all white
        space.
 
 If the Comint is Lucid Common Lisp,
-    comint-get-old-input snarfs the sexp ending at point.
-    comint-input-filter-functions does nothing.
-    comint-input-filter returns nil if the input matches input-filter-regexp,
+    `comint-get-old-input' snarfs the sexp ending at point.
+    `comint-input-filter-functions' does nothing.
+    `comint-input-filter' returns nil if the input matches input-filter-regexp,
        which matches (1) all whitespace (2) :a, :c, etc.
 
 Similarly for Soar, Scheme, etc."
@@ -1449,6 +1511,7 @@ Similarly for Soar, Scheme, etc."
   ;; Note that the input string does not include its terminal newline.
   (let ((proc (get-buffer-process (current-buffer))))
     (if (not proc) (error "Current buffer has no process")
+        (widen)
        (let* ((pmark (process-mark proc))
               (intxt (if (>= (point) (marker-position pmark))
                          (progn (if comint-eol-on-send (end-of-line))
@@ -1485,23 +1548,23 @@ Similarly for Soar, Scheme, etc."
                                (concat input "\n")))
 
          (let ((beg (marker-position pmark))
-             (end (if no-newline (point) (1- (point))))
-             (inhibit-modification-hooks t))
+               (end (if no-newline (point) (1- (point))))
+               (inhibit-modification-hooks t))
            (when (> end beg)
-             ;; Set text-properties for the input field
-             (add-text-properties
-              beg end
-              '(front-sticky t
-                font-lock-face comint-highlight-input
-                mouse-face highlight
-                help-echo "mouse-2: insert after prompt as new input"))
+             (add-text-properties beg end
+                                  '(front-sticky t
+                                    font-lock-face comint-highlight-input))
              (unless comint-use-prompt-regexp
                ;; Give old user input a field property of `input', to
                ;; distinguish it from both process output and unsent
                ;; input.  The terminating newline is put into a special
                ;; `boundary' field to make cursor movement between input
                ;; and output fields smoother.
-               (put-text-property beg end 'field 'input)))
+               (add-text-properties
+                beg end
+                '(mouse-face highlight
+                  help-echo "mouse-2: insert after prompt as new input"
+                  field input))))
            (unless (or no-newline comint-use-prompt-regexp)
              ;; Cover the terminating newline
              (add-text-properties end (1+ end)
@@ -1552,7 +1615,11 @@ Similarly for Soar, Scheme, etc."
                  ;; problems when `comint-prompt-read-only' is non-nil.
                  (let ((inhibit-read-only t))
                    (delete-region comint-last-input-end
-                                  (+ comint-last-input-end echo-len))))))
+                                  (+ comint-last-input-end echo-len))
+                   (when comint-prompt-read-only
+                     (save-excursion
+                       (goto-char comint-last-input-end)
+                       (comint-update-fence)))))))
 
          ;; This used to call comint-output-filter-functions,
          ;; but that scrolled the buffer in undesirable ways.
@@ -1589,8 +1656,8 @@ and moves the prompt overlay."
     (let ((inhibit-read-only t)
          (inhibit-modification-hooks t))
       (add-text-properties (overlay-start comint-last-prompt-overlay)
-                           (overlay-end comint-last-prompt-overlay)
-                           (overlay-properties comint-last-prompt-overlay)))))
+                          (overlay-end comint-last-prompt-overlay)
+                          (overlay-properties comint-last-prompt-overlay)))))
 
 (defun comint-carriage-motion (start end)
   "Interpret carriage control characters in the region from START to END.
@@ -1868,6 +1935,17 @@ the current line with any initial string matching the regexp
       (comint-bol)
       (buffer-substring-no-properties (point) (line-end-position)))))
 
+(defun comint-copy-old-input ()
+  "Insert after prompt old input at point as new input to be edited.
+Calls `comint-get-old-input' to get old input."
+  (interactive)
+  (let ((input (funcall comint-get-old-input))
+       (process (get-buffer-process (current-buffer))))
+    (if (not process)
+       (error "Current buffer has no process")
+      (goto-char (process-mark process))
+      (insert input))))
+
 (defun comint-skip-prompt ()
   "Skip past the text matching regexp `comint-prompt-regexp'.
 If this takes us past the end of the current line, don't skip at all."
@@ -1884,11 +1962,16 @@ If this takes us past the end of the current line, don't skip at all."
   "Default function for sending to PROC input STRING.
 This just sends STRING plus a newline.  To override this,
 set the hook `comint-input-sender'."
-  (comint-send-string proc string)
-  (if comint-input-sender-no-newline
-      (if (not (string-equal string ""))
-         (process-send-eof))
-    (comint-send-string proc "\n")))
+  (let ((send-string
+         (if comint-input-sender-no-newline
+             string
+           ;; Sending as two separate strings does not work
+           ;; on Windows, so concat the \n before sending.
+           (concat string "\n"))))
+    (comint-send-string proc send-string))
+  (if (and comint-input-sender-no-newline
+          (not (string-equal string "")))
+      (process-send-eof)))
 
 (defun comint-line-beginning-position ()
   "Return the buffer position of the beginning of the line, after any prompt.
@@ -1937,15 +2020,21 @@ The string is sent using `comint-input-sender'.
 Security bug: your string can still be temporarily recovered with
 \\[view-lossage]; `clear-this-command-keys' can fix that."
   (interactive "P")                    ; Defeat snooping via C-x ESC ESC
-  (let ((proc (get-buffer-process (current-buffer))))
+  (let ((proc (get-buffer-process (current-buffer)))
+       (prefix
+        (if (eq (window-buffer (selected-window)) (current-buffer))
+            ""
+          (format "(In buffer %s) "
+                  (current-buffer)))))
     (if proc
-       (let ((str (read-passwd (or prompt "Non-echoed text: "))))
+       (let ((str (read-passwd (concat prefix
+                                       (or prompt "Non-echoed text: ")))))
          (if (stringp str)
              (progn
                (comint-snapshot-last-prompt)
                (funcall comint-input-sender proc str))
            (message "Warning: text will be echoed")))
-      (error "Current buffer has no process"))))
+      (error "Buffer %s has no process" (current-buffer)))))
 
 (defun comint-watch-for-password-prompt (string)
   "Prompt in the minibuffer for password and send without echoing.
@@ -2002,8 +2091,8 @@ Does not delete the prompt."
        (delete-region pmark (point))))
     ;; Output message and put back prompt
     (comint-output-filter proc replacement)))
-(defalias 'comint-kill-output 'comint-delete-output)
-(make-obsolete 'comint-kill-output 'comint-delete-output "21.1")
+(define-obsolete-function-alias 'comint-kill-output
+    'comint-delete-output "21.1")
 
 (defun comint-write-output (filename &optional append mustbenew)
   "Write output from interpreter since last input to FILENAME.
@@ -2052,7 +2141,11 @@ Sets mark to the value of point when this command is run."
           (set-window-start (selected-window) (point))
           (comint-skip-prompt))
          (t
-          (goto-char (field-beginning pos))
+          (let* ((beg (field-beginning pos))
+                 (pt (if (= (point-min) beg)
+                         (point-min)
+                       (1+ beg))))
+            (goto-char pt))
           (set-window-start (selected-window) (point))))))
 
 
@@ -2169,7 +2262,7 @@ If N is negative, find the next or Nth next match."
       (goto-char pos))))
 
 
-(defun comint-forward-matching-input (regexp arg)
+(defun comint-forward-matching-input (regexp n)
   "Search forward through buffer for input fields that match REGEXP.
 If `comint-use-prompt-regexp' is non-nil, then input fields are identified
 by lines that match `comint-prompt-regexp'.
@@ -2177,7 +2270,7 @@ by lines that match `comint-prompt-regexp'.
 With prefix argument N, search for Nth following match.
 If N is negative, find the previous or Nth previous match."
   (interactive (comint-regexp-arg "Forward input matching (regexp): "))
-  (comint-backward-matching-input regexp (- arg)))
+  (comint-backward-matching-input regexp (- n)))
 
 
 (defun comint-next-prompt (n)
@@ -2307,19 +2400,19 @@ preceding newline is removed."
           (when (eq (get-text-property (1- pt) 'read-only) 'fence)
             (remove-list-of-text-properties (1- pt) pt '(read-only)))))))
 
-(defun comint-kill-whole-line (&optional arg)
+(defun comint-kill-whole-line (&optional count)
   "Kill current line, ignoring read-only and field properties.
-With prefix arg, kill that many lines starting from the current line.
-If arg is negative, kill backward.  Also kill the preceding newline,
+With prefix arg COUNT, kill that many lines starting from the current line.
+If COUNT is negative, kill backward.  Also kill the preceding newline,
 instead of the trailing one.  \(This is meant to make \\[repeat] work well
 with negative arguments.)
-If arg is zero, kill current line but exclude the trailing newline.
+If COUNT is zero, kill current line but exclude the trailing newline.
 The read-only status of newlines is updated with `comint-update-fence',
 if necessary."
   (interactive "p")
   (let ((inhibit-read-only t) (inhibit-field-text-motion t))
-    (kill-whole-line arg)
-    (when (>= arg 0) (comint-update-fence))))
+    (kill-whole-line count)
+    (when (>= count 0) (comint-update-fence))))
 
 (defun comint-kill-region (beg end &optional yank-handler)
   "Like `kill-region', but ignores read-only properties, if safe.
@@ -2388,7 +2481,7 @@ updated using `comint-update-fence', if necessary."
 (defun comint-source-default (previous-dir/file source-modes)
   "Compute the defaults for `load-file' and `compile-file' commands.
 
-PREVIOUS-DIR/FILE is a pair (directory . filename) from the last
+PREVIOUS-DIR/FILE is a pair (DIRECTORY . FILENAME) from the last
 source-file processing command, or nil if there hasn't been one yet.
 SOURCE-MODES is a list used to determine what buffers contain source
 files: if the major mode of the buffer is in SOURCE-MODES, it's source.
@@ -2409,7 +2502,7 @@ processing command (i.e., PREVIOUS-DIR/FILE).  If this is the first time
 the command has been run (PREVIOUS-DIR/FILE is nil), the default directory
 is the cwd, with no default file.  (\"no default file\" = nil)
 
-SOURCE-REGEXP is typically going to be something like (tea-mode)
+SOURCE-MODES is typically going to be something like (tea-mode)
 for T programs, (lisp-mode) for Lisp programs, (soar-mode lisp-mode)
 for Soar programs, etc.
 
@@ -2440,7 +2533,7 @@ the load or compile."
          (set-buffer old-buffer)))))
 
 (defun comint-extract-string ()
-  "Return string around POINT, or nil."
+  "Return string around point, or nil."
   (let ((syntax (syntax-ppss)))
     (when (nth 3 syntax)
       (condition-case ()
@@ -2460,7 +2553,7 @@ See `comint-source-default' for more on determining defaults.
 PROMPT is the prompt string.  PREV-DIR/FILE is the (DIRECTORY . FILE) pair
 from the last source processing command.  SOURCE-MODES is a list of major
 modes used to determine what file buffers contain source files.  (These
-two arguments are used for determining defaults).  If MUSTMATCH-P is true,
+two arguments are used for determining defaults.)  If MUSTMATCH-P is true,
 then the filename reader will only accept a file that exists.
 
 A typical use:
@@ -2515,7 +2608,7 @@ its response can be seen."
         (proc-mark (process-mark proc)))
     (display-buffer proc-buf)
     (set-buffer proc-buf) ; but it's not the selected *window*
-    (let ((proc-win (get-buffer-window proc-buf))
+    (let ((proc-win (get-buffer-window proc-buf 0))
          (proc-pt (marker-position proc-mark)))
       (comint-send-string proc str) ; send the query
       (accept-process-output proc)  ; wait for some output
@@ -2587,6 +2680,7 @@ Note that this applies to `comint-dynamic-complete-filename' only."
   :type '(repeat (string :tag "Suffix"))
   :group 'comint-completion)
 
+;;;###autoload
 (defvar comint-file-name-prefix ""
   "Prefix prepended to absolute file names taken from process input.
 This is used by Comint's and shell's completion functions, and by shell's
@@ -2618,8 +2712,7 @@ This is a good thing to set in mode hooks.")
 (defun comint-word (word-chars)
   "Return the word of WORD-CHARS at point, or nil if none is found.
 Word constituents are considered to be those in WORD-CHARS, which is like the
-inside of a \"[...]\" (see `skip-chars-forward'),
-plus all non-ASCII characters."
+inside of a \"[...]\" (see `skip-chars-forward'), plus all non-ASCII characters."
   (save-excursion
     (let ((here (point))
          giveup)
@@ -2660,7 +2753,7 @@ interpreter (e.g., the percent notation of cmd.exe on NT)."
     name))
 
 (defun comint-match-partial-filename ()
-  "Return the filename at point, or nil if non is found.
+  "Return the filename at point, or nil if none is found.
 Environment variables are substituted.  See `comint-word'."
   (let ((filename (comint-word comint-file-name-chars)))
     (and filename (comint-substitute-in-file-name
@@ -2726,7 +2819,7 @@ Returns t if successful."
 (defun comint-dynamic-complete-as-filename ()
   "Dynamically complete at point as a filename.
 See `comint-dynamic-complete-filename'.  Returns t if successful."
-  (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt cygwin)))
+  (let* ((completion-ignore-case read-file-name-completion-ignore-case)
         (completion-ignored-extensions comint-completion-fignore)
         ;; If we bind this, it breaks remote directory tracking in rlogin.el.
         ;; I think it was originally bound to solve file completion problems,
@@ -2855,7 +2948,7 @@ See also `comint-dynamic-complete-filename'."
 (defun comint-dynamic-list-filename-completions ()
   "List in help buffer possible completions of the filename at point."
   (interactive)
-  (let* ((completion-ignore-case (memq system-type '(ms-dos windows-nt cygwin)))
+  (let* ((completion-ignore-case read-file-name-completion-ignore-case)
         ;; If we bind this, it breaks remote directory tracking in rlogin.el.
         ;; I think it was originally bound to solve file completion problems,
         ;; but subsequent changes may have made this unnecessary.  sm.
@@ -2881,7 +2974,7 @@ See also `comint-dynamic-complete-filename'."
 (defun comint-dynamic-list-completions (completions)
   "List in help buffer sorted COMPLETIONS.
 Typing SPC flushes the help buffer."
-  (let ((window (get-buffer-window "*Completions*")))
+  (let ((window (get-buffer-window "*Completions*" 0)))
     (setq completions (sort completions 'string-lessp))
     (if (and (eq last-command this-command)
             window (window-live-p window) (window-buffer window)
@@ -2930,10 +3023,9 @@ Typing SPC flushes the help buffer."
          (progn
            (mouse-choose-completion first)
            (set-window-configuration comint-dynamic-list-completions-config))
-       (unless (eq first ?\s)
-         (setq unread-command-events (listify-key-sequence key)))
-       (unless (eq first ?\t)
-         (set-window-configuration comint-dynamic-list-completions-config))))))
+       (if (eq first ?\s)
+           (set-window-configuration comint-dynamic-list-completions-config)
+         (setq unread-command-events (listify-key-sequence key)))))))
 
 \f
 (defun comint-get-next-from-history ()
@@ -3101,8 +3193,8 @@ When redirection is completed, the process filter is restored to
 this value.")
 
 (defvar comint-redirect-subvert-readonly nil
-  "Non-nil means comint-redirect can insert into otherwise-readonly buffers.
-The readonly status is toggled around insertion.
+  "Non-nil means `comint-redirect' can insert into read-only buffers.
+This works by binding `inhibit-read-only' around the insertion.
 This is useful, for instance, for insertion into Help mode buffers.
 You probably want to set it locally to the output buffer.")