New file.
[bpt/emacs.git] / lisp / comint.el
index cd5a9a9..f1d9243 100644 (file)
@@ -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,
@@ -333,12 +333,14 @@ 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": '.
+;; Ubuntu's sudo prompts like `[sudo] password for user:'
 ;; 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 \\|\\[sudo] \\|^\\)\
 \[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'."
@@ -642,9 +644,15 @@ Entry to this mode runs the hooks on `comint-mode-hook'."
   (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)
@@ -653,7 +661,7 @@ Entry to this mode runs the hooks on `comint-mode-hook'."
   (make-local-variable 'comint-accum-marker)
   (setq comint-accum-marker (make-marker))
   (make-local-variable 'font-lock-defaults)
-  (setq font-lock-defaults '(nil))
+  (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))
@@ -670,13 +678,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
@@ -693,9 +701,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."
@@ -781,17 +789,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.
@@ -803,17 +813,27 @@ buffer.  The hook `comint-exec-hook' is run after each exec."
     proc))
 
 (defun comint-insert-input (event)
-  "In a Comint buffer, set the current input to the previous input at point."
+  "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")
-  (mouse-set-point event)
-  (let ((pos (point)))
-    (if (not (eq (field-at-pos pos) 'input))
-       ;; No input at POS, fall back to the global definition.
+  (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)))))
-         (and fun (call-interactively fun)))
-      ;; 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
@@ -821,8 +841,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 (field-string-no-properties pos)))))
-
+      (insert input))))
 \f
 ;; Input history processing in a buffer
 ;; ===========================================================================
@@ -887,7 +906,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)
@@ -1338,7 +1357,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)
@@ -1347,12 +1370,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)))
@@ -1372,24 +1399,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.
@@ -1397,7 +1432,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
@@ -1477,6 +1512,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))
@@ -1621,8 +1657,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.
@@ -1927,11 +1963,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.
@@ -2568,7 +2609,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
@@ -2779,7 +2820,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,
@@ -2908,7 +2949,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.
@@ -2934,7 +2975,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)