;;; 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 Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu>
;; Simon Marshall <simon@gnu.org>
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
:group 'processes)
(defgroup comint-completion nil
- "Completion facilities in comint"
+ "Completion facilities in comint."
:group 'comint)
(defgroup comint-source nil
- "Source finding facilities in comint"
+ "Source finding facilities in comint."
:prefix "comint-"
:group 'comint)
(defvar comint-prompt-regexp "^"
- "Regexp to recognise prompts in the inferior process.
+ "Regexp to recognize prompts in the inferior process.
Defaults to \"^\", the null string at BOL.
This variable is only used if the variable
:version "22.1")
(defvar comint-delimiter-argument-list ()
- "List of characters to recognise as separate arguments in input.
+ "List of characters to recognize as separate arguments in input.
Strings comprising a character in this list will separate the arguments
surrounding them, and also be regarded as arguments in their own right (unlike
whitespace). See `comint-arguments'.
"\\(\\([Oo]ld \\|[Nn]ew \\|'s \\|login \\|\
Kerberos \\|CVS \\|UNIX \\| SMB \\|^\\)\
\[Pp]assword\\( (again)\\)?\\|\
-pass phrase\\|\\(Enter\\|Repeat\\) passphrase\\)\
-\\( for [^:]+\\)?:\\s *\\'"
+pass phrase\\|\\(Enter\\|Repeat\\|Bad\\) passphrase\\)\
+\\(?:, try again\\)?\\(?: for [^:]+\\)?:\\s *\\'"
"*Regexp matching prompts for passwords in the inferior process.
This is used by `comint-watch-for-password-prompt'."
:type 'regexp
"*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'.
"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)
Setting variable `comint-eol-on-send' means jump to the end of the line
before submitting new input.
-This mode is customised to create major modes such as Inferior Lisp
+This mode is customized to create major modes such as Inferior Lisp
mode, Shell mode, etc. This can be done by setting the hooks
`comint-input-filter-functions', `comint-input-filter', `comint-input-sender'
and `comint-get-old-input' to appropriate functions, and the variable
(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)
;; This makes it really work to keep point at the bottom.
(make-local-variable 'scroll-conservatively)
(setq scroll-conservatively 10000)
(set (make-local-variable 'next-line-add-newlines) nil))
(defun comint-check-proc (buffer)
- "Return t if there is a living process associated w/buffer BUFFER.
+ "Return non-nil if there is a living process associated w/buffer BUFFER.
Living means the status is `open', `run', or `stop'.
BUFFER can be either a buffer or the name of one."
(let ((proc (get-buffer-process buffer)))
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
+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."
;; for events without parameters.
(interactive (list last-input-event))
(let ((pos (point)))
- (if event (mouse-set-point event))
+ (if event (posn-set-point (event-end event)))
(if (not (eq (get-char-property (point) 'field) 'input))
;; No input at POS, fall back to the global definition.
(let* ((keys (this-command-keys))
(message "Hit space to flush")
(setq comint-dynamic-list-input-ring-window-conf conf)
(let ((ch (read-event)))
- (if (eq ch ?\ )
+ (if (eq ch ?\s)
(set-window-configuration conf)
(setq unread-command-events (list ch)))))))
(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
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."
(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.
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)
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."
;; 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.
(defun comint-snapshot-last-prompt ()
"`snapshot' any current `comint-last-prompt-overlay'.
-freeze its attributes in place, even when more input comes a long
+Freeze its attributes in place, even when more input comes along
and moves the prompt overlay."
(when comint-last-prompt-overlay
(let ((inhibit-read-only t)
(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
+and `this-command' is an insertion command. Insertion commands recognized
are `self-insert-command', `comint-magic-space', `yank', and `hilit-yank'.
Depends on the value of `comint-scroll-to-bottom-on-input'.
(= (point) (point-max)))
(save-excursion
(goto-char (point-max))
- (recenter -1)))
+ (recenter (- -1 scroll-margin))))
(select-window selected)))))
nil t))
(set-buffer current))))
"Put the end of the buffer at the bottom of the window."
(interactive)
(goto-char (point-max))
- (recenter -1))
+ (recenter (- -1 scroll-margin)))
(defun comint-get-old-input-default ()
"Default for `comint-get-old-input'.
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.
(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.
(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))))))
(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'.
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)
(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
-source-file processing command. nil if there hasn't been one yet.
+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.
Typically, (lisp-mode) or (scheme-mode).
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.
(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 ()
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:
: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
(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)
(defun comint-replace-by-expanded-filename ()
"Dynamically expand and complete the filename at point.
-Replace the filename with an expanded, canonicalised and completed replacement.
+Replace the filename with an expanded, canonicalized and completed replacement.
\"Expanded\" means environment variables (e.g., $HOME) and `~'s are replaced
-with the corresponding directories. \"Canonicalised\" means `..' and `.' are
+with the corresponding directories. \"Canonicalized\" means `..' and `.' are
removed, and the filename is made absolute instead of relative. For expansion
see `expand-file-name' and `substitute-in-file-name'. For completion see
`comint-dynamic-complete-filename'."
(progn
(mouse-choose-completion first)
(set-window-configuration comint-dynamic-list-completions-config))
- (unless (eq first ?\ )
- (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 ()
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.")