;;; comint.el --- general command interpreter in a window stuff
-;; Copyright (C) 1988, 90, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+;; Copyright (C) 1988, 90, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001
;; Free Software Foundation, Inc.
;; Author: Olin Shivers <shivers@cs.cmu.edu> then
(defcustom comint-highlight-input t
"*If non-nil, highlight input; also allow choosing previous input with a mouse.
-See also `comint-highlight-face'."
+The face used is `comint-highlight-input'."
:type 'boolean
:group 'comint)
-(defface comint-highlight-input-face '((t (:bold t)))
+(defface comint-highlight-input '((t (:bold t)))
"Face to use to highlight input when `comint-highlight-input' is non-nil."
:group 'comint)
(defcustom comint-highlight-prompt t
"*If non-nil, highlight program prompts.
-See also `comint-highlight-face'."
+The face used is `comint-highlight-prompt'."
:type 'boolean
:group 'comint)
-(defface comint-highlight-prompt-face
+(defface comint-highlight-prompt
'((((background dark)) (:foreground "cyan"))
(t (:foreground "dark blue")))
"Face to use to highlight prompt when `comint-highlight-prompt' is non-nil."
(defvar comint-input-ring-separator "\n"
"Separator between commands in the history file.")
+(defvar comint-input-history-ignore "^#"
+ "Regexp for history entries that should be ignored when comint initializes.")
+
(defcustom comint-process-echoes nil
"*If non-nil, assume that the subprocess echoes any input.
If so, delete one copy of the input so that only one copy eventually
;; ssh-add prints a prompt like `Enter passphrase: '.
;; Some implementations of passwd use "Password (again)" as the 2nd prompt.
(defcustom comint-password-prompt-regexp
- "\\(\\([Oo]ld \\|[Nn]ew \\|Kerberos \\|'s \\|login \\|^\\)\
+ "\\(\\([Oo]ld \\|[Nn]ew \\|Kerberos \\|'s \\|login \\|CVS \\|^\\)\
[Pp]assword\\( (again)\\)?\\|pass phrase\\|Enter passphrase\\)\
\\( for [^@ \t\n]+@[^@ \t\n]+\\)?:\\s *\\'"
"*Regexp matching prompts for passwords in the inferior process.
(make-local-variable 'comint-scroll-to-bottom-on-input)
(make-local-variable 'comint-scroll-to-bottom-on-output)
(make-local-variable 'comint-scroll-show-maximum-output)
- (make-local-hook 'pre-command-hook)
(add-hook 'pre-command-hook 'comint-preinput-scroll-to-bottom t t)
(make-local-hook 'comint-output-filter-functions)
(make-local-hook 'comint-exec-hook)
(make-local-variable 'comint-file-name-quote-list)
(make-local-variable 'comint-accum-marker)
(setq comint-accum-marker (make-marker))
- (set-marker comint-accum-marker nil))
+ (set-marker comint-accum-marker nil)
+ ;; This behavior is not useful in comint buffers, and is annoying
+ (set (make-local-variable 'next-line-add-newlines) nil))
(if comint-mode-map
nil
(cons "In/Out" (make-sparse-keymap "In/Out")))
(define-key comint-mode-map [menu-bar inout delete-output]
'("Delete Current Output Group" . comint-delete-output))
- (define-key comint-mode-map [menu-bar inout write-output]
- '("Write Current Output Group to File" . comint-write-output))
(define-key comint-mode-map [menu-bar inout append-output-to-file]
'("Append Current Output Group to File" . comint-append-output-to-file))
+ (define-key comint-mode-map [menu-bar inout write-output]
+ '("Write Current Output Group to File" . comint-write-output))
(define-key comint-mode-map [menu-bar inout next-prompt]
'("Forward Output Group" . comint-next-prompt))
(define-key comint-mode-map [menu-bar inout previous-prompt]
(let ((proc (get-buffer-process buffer)))
(and proc (memq (process-status proc) '(open run stop)))))
+;;;###autoload
+(defun make-comint-in-buffer (name buffer program &optional startfile &rest switches)
+ "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 third 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)
+ (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
+ ;; comint mode. Otherwise, leave buffer and existing process alone.
+ (unless (comint-check-proc buffer)
+ (with-current-buffer buffer
+ (comint-mode)) ; Install local vars, mode, keymap, ...
+ (comint-exec buffer name program startfile switches))
+ buffer)
+
;;;###autoload
(defun make-comint (name program &optional startfile &rest switches)
"Make a comint process NAME in a buffer, running PROGRAM.
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)
- (error "Multi-processing is not supported for this system"))
- (let ((buffer (get-buffer-create (concat "*" name "*"))))
- ;; If no process, or nuked process, crank up a new one and put buffer in
- ;; comint mode. Otherwise, leave buffer and existing process alone.
- (unless (comint-check-proc buffer)
- (with-current-buffer buffer
- (comint-mode)) ; Install local vars, mode, keymap, ...
- (comint-exec buffer name program startfile switches))
- buffer))
+ (apply #'make-comint-in-buffer name nil program startfile switches))
;;;###autoload
(defun comint-run (program)
This function is useful for major mode commands and mode hooks.
The commands stored in the history file are separated by the
-`comint-input-ring-separator'. The most recent command comes last.
+`comint-input-ring-separator', and entries that match
+`comint-input-history-ignore' are ignored. The most recent command
+comes last.
See also `comint-input-ignoredups' and `comint-write-input-ring'."
(cond ((or (null comint-input-ring-file-name)
(setq start (point-min)))
(setq history (buffer-substring start end))
(goto-char start)
- (if (or (null comint-input-ignoredups)
- (ring-empty-p ring)
- (not (string-equal (ring-ref ring 0) history)))
+ (if (and (not (string-match comint-input-history-ignore history))
+ (or (null comint-input-ignoredups)
+ (ring-empty-p ring)
+ (not (string-equal (ring-ref ring 0) history))))
(progn
(ring-insert-at-beginning ring history)
(setq count (1+ count)))))))
Returns t if successful."
(interactive)
(if (and comint-input-autoexpand
- (string-match "!\\|^\\^" (funcall comint-get-old-input))
(if comint-use-prompt-regexp-instead-of-fields
;; Use comint-prompt-regexp
- (save-excursion (beginning-of-line)
- (looking-at comint-prompt-regexp))
+ (save-excursion
+ (beginning-of-line)
+ (looking-at (concat comint-prompt-regexp "!\\|\\^")))
;; Use input fields. User input that hasn't been entered
;; yet, at the end of the buffer, has a nil `field' property.
- (null (get-char-property (point) 'field))))
+ (and (null (get-char-property (point) 'field))
+ (string-match "!\\|^\\^" (field-string)))))
;; Looks like there might be history references in the command.
(let ((previous-modified-tick (buffer-modified-tick)))
(comint-replace-by-expanded-history-before-point silent start)
(save-excursion
(let ((toend (- (line-end-position) (point)))
(start (comint-line-beginning-position)))
+ (goto-char start)
(while (progn
(skip-chars-forward "^!^" (- (line-end-position) toend))
(< (point) (- (line-end-position) toend)))
;;
;; Input processing stuff
;;
+(defun comint-add-to-input-history (cmd)
+ "Add CMD to the input history.
+Ignore duplicates if `comint-input-ignoredups' is non-nil."
+ (if (and (funcall comint-input-filter cmd)
+ (or (null comint-input-ignoredups)
+ (not (ring-p comint-input-ring))
+ (ring-empty-p comint-input-ring)
+ (not (string-equal (ring-ref comint-input-ring 0)
+ cmd))))
+ (ring-insert comint-input-ring cmd)))
(defun comint-send-input ()
"Send input to process.
(delete-region pmark (point))
(insert ?\n))
- (if (and (funcall comint-input-filter history)
- (or (null comint-input-ignoredups)
- (not (ring-p comint-input-ring))
- (ring-empty-p comint-input-ring)
- (not (string-equal (ring-ref comint-input-ring 0)
- history))))
- (ring-insert comint-input-ring history))
+ (comint-add-to-input-history history)
(run-hook-with-args 'comint-input-filter-functions
(concat input "\n"))
;; input. The terminating newline is put into a special
;; `boundary' field to make cursor movement between input
;; and output fields smoother.
- (overlay-put over 'field 'input)
- (overlay-put over 'front-sticky t))
+ (overlay-put over 'field 'input))
(when comint-highlight-input
- (overlay-put over 'face 'comint-highlight-input-face)
+ (overlay-put over 'face 'comint-highlight-input)
(overlay-put over 'mouse-face 'highlight)
(overlay-put over 'evaporate t))))
(unless comint-use-prompt-regexp-instead-of-fields
;; Make an overlay for the terminating newline
(let ((over (make-overlay end (1+ end) nil t nil)))
(overlay-put over 'field 'boundary)
- (overlay-put over 'rear-nonsticky t)
(overlay-put over 'evaporate t))))
(comint-snapshot-last-prompt)
(let ((over (make-overlay comint-last-output-start (point))))
(overlay-put over 'field 'output)
(overlay-put over 'inhibit-line-move-field-capture t)
- (overlay-put over 'front-sticky t)
- (overlay-put over 'rear-nonsticky t)
(overlay-put over 'evaporate t)
(setq comint-last-output-overlay over))))
(move-overlay comint-last-prompt-overlay
prompt-start (point))
;; Need to create the overlay
- (let ((over (make-overlay prompt-start (point))))
- (overlay-put over 'face 'comint-highlight-prompt-face)
- (overlay-put over 'front-sticky t)
- (overlay-put over 'rear-nonsticky t)
- (setq comint-last-prompt-overlay over))))))
+ (setq comint-last-prompt-overlay
+ (make-overlay prompt-start (point)))
+ (overlay-put comint-last-prompt-overlay
+ 'face 'comint-highlight-prompt)))))
(goto-char saved-point)
(end-of-line)
(buffer-substring beg (point))))
;; Return the contents of the field at the current point.
- (field-string)))
-
+ (let ((pos (field-beginning (point))))
+ (unless (eq (get-char-property pos 'field) 'input)
+ (error "Not an input field"))
+ (field-string pos))))
(defun comint-copy-old-input ()
"Insert after prompt old input at point as new input to be edited.
(defun comint-send-string (process string)
"Like `process-send-string', but also does extra bookkeeping for comint mode."
- (with-current-buffer (process-buffer process)
+ (if process
+ (with-current-buffer (if (processp process)
+ (process-buffer process)
+ (get-buffer process))
+ (comint-snapshot-last-prompt))
(comint-snapshot-last-prompt))
(process-send-string process string))
(defun comint-send-region (process start end)
"Like `process-send-region', but also does extra bookkeeping for comint mode."
- (with-current-buffer (process-buffer process)
+ (if process
+ (with-current-buffer (if (processp process)
+ (process-buffer process)
+ (get-buffer process))
+ (comint-snapshot-last-prompt))
(comint-snapshot-last-prompt))
(process-send-region process start end))
\f
(defalias 'comint-kill-output 'comint-delete-output)
(make-obsolete 'comint-kill-output 'comint-delete-output "21.1")
-(defun comint-write-output (filename &optional mustbenew)
+(defun comint-write-output (filename &optional append mustbenew)
"Write output from interpreter since last input to FILENAME.
Any prompt at the end of the output is not written.
-If the optional argument MUSTBENEW (the prefix argument when interactive),
-is non-nil, check for an existing file with the same name. If MUSTBENEW
-is `excl', that means to get an error if the file already exists; never
-overwrite. If MUSTBENEW is neither nil nor `excl', that means ask for
-confirmation before overwriting, but do go ahead and overwrite the file
-if the user confirms."
- (interactive "FWrite output to file: \np")
+If the optional argument APPEND (the prefix argument when interactive)
+is non-nil, the output is appended to the file instead.
+
+If the optional argument MUSTBENEW is non-nil, check for an existing
+file with the same name. If MUSTBENEW is `excl', that means to get an
+error if the file already exists; never overwrite. If MUSTBENEW is
+neither nil nor `excl', that means ask for confirmation before
+overwriting, but do go ahead and overwrite the file if the user
+confirms. When interactive, MUSTBENEW is nil when appending, and t
+otherwise."
+ (interactive
+ (list (read-file-name
+ (if current-prefix-arg
+ "Append output to file: "
+ "Write output to file: "))
+ current-prefix-arg
+ (not current-prefix-arg)))
(save-excursion
(goto-char (process-mark (get-buffer-process (current-buffer))))
(forward-line 0)
- (write-region comint-last-input-end (point)
- filename nil nil nil mustbenew)))
+ (write-region comint-last-input-end (point) filename
+ append nil nil mustbenew)))
+;; This function exists for the benefit of the menu; from the keyboard,
+;; users can just use `comint-write-output' with a prefix arg.
(defun comint-append-output-to-file (filename)
"Append output from interpreter since last input to FILENAME.
Any prompt at the end of the output is not written."
- (interactive "FAppend output to file: ")
- (save-excursion
- (goto-char (process-mark (get-buffer-process (current-buffer))))
- (forward-line 0)
- (write-region comint-last-input-end (point) filename t)))
-
+ (interactive "fAppend output to file: ")
+ (comint-write-output filename t))
(defun comint-show-output ()
"Display start of this batch of interpreter output at top of window.
If a cons pair, it should be of the form (DIRSUFFIX . FILESUFFIX) where
DIRSUFFIX and FILESUFFIX are strings added on unambiguous or exact completion.
This mirrors the optional behavior of tcsh."
- :type 'boolean
+ :type '(choice (const :tag "None" nil)
+ (const :tag "Add /" t)
+ (cons :tag "Suffix pair"
+ (string :tag "Directory suffix")
+ (string :tag "File suffix")))
:group 'comint-completion)
(defcustom comint-completion-recexact nil
(let ((proc (or (get-buffer-process (current-buffer))
(error "Current buffer has no process"))))
(goto-char (process-mark proc))
- (message "Point is now at the process mark")))
+ (when (interactive-p)
+ (message "Point is now at the process mark"))))
(defun comint-bol-or-process-mark ()
"Move point to beginning of line (after prompt) or to the process mark.