1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-26 10:49:33 +00:00

(comint-use-prompt-regexp-instead-of-fields): New variable.

(comint-prompt-regexp, comint-get-old-input): Document dependence on
  comint-use-prompt-regexp-instead-of-fields.
(comint-send-input): Add `input' field property to stuff we send to
  the process, if comint-use-prompt-regexp-instead-of-fields is nil.
(comint-output-filter): Add `output' field property to process
  output, if comint-use-prompt-regexp-instead-of-fields is nil.
(comint-replace-by-expanded-history)
(comint-get-old-input-default, comint-show-output)
(comint-backward-matching-input, comint-forward-matching-input)
(comint-next-prompt, comint-previous-prompt):  Use field
  properties if comint-use-prompt-regexp-instead-of-fields is nil.
(comint-line-beginning-position): New function.
(comint-bol): Use comint-line-beginning-position.  Make ARG optional.
(comint-replace-by-expanded-history-before-point): Use
  comint-line-beginning-position and line-end-position.
(comint-last-output-overlay): New variable.
(comint-mode): Make `comint-last-output-overlay' buffer-local.
This commit is contained in:
Miles Bader 2000-08-07 14:50:09 +00:00
parent 70fc58b397
commit 2953392320

View File

@ -141,6 +141,7 @@
;; comint-scroll-to-bottom-on-output symbol ... ;; comint-scroll-to-bottom-on-output symbol ...
;; comint-scroll-show-maximum-output boolean ... ;; comint-scroll-show-maximum-output boolean ...
;; comint-accum-marker maker For comint-accumulate ;; comint-accum-marker maker For comint-accumulate
;; comint-last-output-overlay overlay
;; ;;
;; Comint mode non-buffer local variables: ;; Comint mode non-buffer local variables:
;; comint-completion-addsuffix boolean/cons For file name ;; comint-completion-addsuffix boolean/cons For file name
@ -160,11 +161,13 @@
:prefix "comint-" :prefix "comint-"
:group 'comint) :group 'comint)
(defvar comint-prompt-regexp "^" (defvar comint-prompt-regexp "^"
"Regexp to recognise prompts in the inferior process. "Regexp to recognise prompts in the inferior process.
Defaults to \"^\", the null string at BOL. Defaults to \"^\", the null string at BOL.
This variable is only used if the variable
`comint-use-prompt-regexp-instead-of-fields' is non-nil.
Good choices: Good choices:
Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp) Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\" Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
@ -309,10 +312,12 @@ This is used by `comint-watch-for-password-prompt'."
;; Here are the per-interpreter hooks. ;; Here are the per-interpreter hooks.
(defvar comint-get-old-input (function comint-get-old-input-default) (defvar comint-get-old-input (function comint-get-old-input-default)
"Function that returns old text in comint mode. "Function that returns old text in comint mode.
This function is called when return is typed while the point is in old text. This function is called when return is typed while the point is in old
It returns the text to be submitted as process input. The default is text. It returns the text to be submitted as process input. The
`comint-get-old-input-default', which grabs the current line, and strips off default is `comint-get-old-input-default', which either grabs the
leading text matching `comint-prompt-regexp'.") current input field or grabs the current line and strips off leading
text matching `comint-prompt-regexp', depending on the value of
`comint-use-prompt-regexp-instead-of-fields'.")
(defvar comint-dynamic-complete-functions (defvar comint-dynamic-complete-functions
'(comint-replace-by-expanded-history comint-dynamic-complete-filename) '(comint-replace-by-expanded-history comint-dynamic-complete-filename)
@ -359,6 +364,18 @@ See `comint-send-input'."
:type 'boolean :type 'boolean
:group 'comint) :group 'comint)
;; Note: If it is decided to purge comint-prompt-regexp from the source
;; entirely, searching for uses of this variable will help to identify
;; places that need attention.
(defcustom comint-use-prompt-regexp-instead-of-fields nil
"*If non-nil, use `comint-prompt-regexp' to distinguish prompts from user-input.
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)."
:type 'boolean
:group 'comint)
(defcustom comint-mode-hook '() (defcustom comint-mode-hook '()
"Called upon entry into comint-mode "Called upon entry into comint-mode
This is run before the process is cranked up." This is run before the process is cranked up."
@ -462,6 +479,7 @@ Entry to this mode runs the hooks on `comint-mode-hook'."
(set-marker comint-last-input-end (point-min)) (set-marker comint-last-input-end (point-min))
(make-local-variable 'comint-last-output-start) (make-local-variable 'comint-last-output-start)
(setq comint-last-output-start (make-marker)) (setq comint-last-output-start (make-marker))
(make-local-variable 'comint-last-output-overlay)
(make-local-variable 'comint-prompt-regexp) ; Don't set; default (make-local-variable 'comint-prompt-regexp) ; Don't set; default
(make-local-variable 'comint-input-ring-size) ; ...to global val. (make-local-variable 'comint-input-ring-size) ; ...to global val.
(make-local-variable 'comint-input-ring) (make-local-variable 'comint-input-ring)
@ -1070,8 +1088,13 @@ Returns t if successful."
(interactive) (interactive)
(if (and comint-input-autoexpand (if (and comint-input-autoexpand
(string-match "!\\|^\\^" (funcall comint-get-old-input)) (string-match "!\\|^\\^" (funcall comint-get-old-input))
(save-excursion (beginning-of-line) (if comint-use-prompt-regexp-instead-of-fields
(looking-at comint-prompt-regexp))) ;; Use comint-prompt-regexp
(save-excursion (beginning-of-line)
(looking-at 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))))
;; Looks like there might be history references in the command. ;; Looks like there might be history references in the command.
(let ((previous-modified-tick (buffer-modified-tick))) (let ((previous-modified-tick (buffer-modified-tick)))
(comint-replace-by-expanded-history-before-point silent start) (comint-replace-by-expanded-history-before-point silent start)
@ -1086,15 +1109,11 @@ If the optional argument START is non-nil, that specifies the
start of the text to scan for history references, rather start of the text to scan for history references, rather
than the logical beginning of line." than the logical beginning of line."
(save-excursion (save-excursion
(let ((toend (- (save-excursion (end-of-line nil) (point)) (point))) (let ((toend (- (line-end-position) (point)))
(start (or start (progn (comint-bol nil) (point))))) (start (comint-line-beginning-position)))
(while (progn (while (progn
(skip-chars-forward "^!^" (skip-chars-forward "^!^" (- (line-end-position) toend))
(save-excursion (< (point) (- (line-end-position) toend)))
(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, ;; This seems a bit complex. We look for references such as !!, !-num,
;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^. ;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
;; If that wasn't enough, the plings can be suffixed with argument ;; If that wasn't enough, the plings can be suffixed with argument
@ -1317,8 +1336,10 @@ The values of `comint-get-old-input', `comint-input-filter-functions', and
in the buffer. E.g., in the buffer. E.g.,
If the interpreter is the csh, If the interpreter is the csh,
comint-get-old-input is the default: take the current line, discard any comint-get-old-input is the default: either return the current
initial string matching regexp comint-prompt-regexp. field, or take the current line and discard any
initial string matching regexp `comint-prompt-regexp', depending
on the value of `comint-use-prompt-regexp-instead-of-fields'.
comint-input-filter-functions monitors input for \"cd\", \"pushd\", and comint-input-filter-functions monitors input for \"cd\", \"pushd\", and
\"popd\" commands. When it sees one, it cd's the buffer. \"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 comint-input-filter is the default: returns t if the input isn't all white
@ -1360,9 +1381,11 @@ Similarly for Soar, Scheme, etc."
(insert input) (insert input)
(delete-region pmark start) (delete-region pmark start)
copy)))) copy))))
(if comint-process-echoes (if comint-process-echoes
(delete-region pmark (point)) (delete-region pmark (point))
(insert-before-markers ?\n)) (insert-before-markers ?\n))
(if (and (funcall comint-input-filter history) (if (and (funcall comint-input-filter history)
(or (null comint-input-ignoredups) (or (null comint-input-ignoredups)
(not (ring-p comint-input-ring)) (not (ring-p comint-input-ring))
@ -1370,17 +1393,33 @@ Similarly for Soar, Scheme, etc."
(not (string-equal (ring-ref comint-input-ring 0) (not (string-equal (ring-ref comint-input-ring 0)
history)))) history))))
(ring-insert comint-input-ring history)) (ring-insert comint-input-ring history))
(run-hook-with-args 'comint-input-filter-functions (run-hook-with-args 'comint-input-filter-functions
(concat input "\n")) (concat input "\n"))
(let ((beg (marker-position pmark)) (let ((beg (marker-position pmark))
(end (1- (point)))) (end (1- (point))))
(when (and comint-highlight-input (when (not (> beg end)) ; handle a special case
;; handle a special case ;; Make an overlay for the input field
(not (> beg end)))
(let ((over (make-overlay beg end))) (let ((over (make-overlay beg end)))
(overlay-put over 'face comint-highlight-face) (unless comint-use-prompt-regexp-instead-of-fields
(overlay-put over 'mouse-face 'highlight) ;; 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.
(overlay-put over 'field 'input)
(overlay-put over 'front-sticky t))
(when comint-highlight-input
(overlay-put over 'face comint-highlight-face)
(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))))
(overlay-put over 'field 'boundary)
(overlay-put over 'evaporate t)))) (overlay-put over 'evaporate t))))
(setq comint-save-input-ring-index comint-input-ring-index) (setq comint-save-input-ring-index comint-input-ring-index)
(setq comint-input-ring-index nil) (setq comint-input-ring-index nil)
;; Update the markers before we send the input ;; Update the markers before we send the input
@ -1409,6 +1448,11 @@ redirection buffer.
This variable is permanent-local.") This variable is permanent-local.")
;; When non-nil, this is the last overlay used for output.
;; It is kept around so that we can extend it instead of creating
;; multiple contiguous overlays for multiple contiguous output chunks.
(defvar comint-last-output-overlay nil)
;; The purpose of using this filter for comint processes ;; The purpose of using this filter for comint processes
;; is to keep comint-last-input-end from moving forward ;; is to keep comint-last-input-end from moving forward
;; when output is inserted. ;; when output is inserted.
@ -1439,6 +1483,23 @@ This variable is permanent-local.")
(if (<= (point) oend) (if (<= (point) oend)
(setq oend (+ oend nchars))) (setq oend (+ oend nchars)))
(insert-before-markers string) (insert-before-markers string)
(unless comint-use-prompt-regexp-instead-of-fields
;; We check to see if the last overlay used for output has
;; already been extended to include STRING (because it was
;; inserted with insert-before-markers?), and only make
;; a new overlay if it hasn't.
(unless (and comint-last-output-overlay
(= (overlay-end comint-last-output-overlay)
(point)))
;; Create a new overlay
(let ((over (make-overlay ostart (point))))
(overlay-put over 'field 'output)
(overlay-put over 'rear-nonsticky t)
(overlay-put over 'inhibit-line-move-field-capture t)
(overlay-put over 'evaporate t)
(setq comint-last-output-overlay over))))
;; Don't insert initial prompt outside the top of the window. ;; Don't insert initial prompt outside the top of the window.
(if (= (window-start (selected-window)) (point)) (if (= (window-start (selected-window)) (point))
(set-window-start (selected-window) (- (point) (length string)))) (set-window-start (selected-window) (- (point) (length string))))
@ -1552,14 +1613,19 @@ This function could be on `comint-output-filter-functions' or bound to a key."
(defun comint-get-old-input-default () (defun comint-get-old-input-default ()
"Default for `comint-get-old-input'. "Default for `comint-get-old-input'.
Take the current line, and discard any initial text matching Returns either the current field, or the current line with any initial
`comint-prompt-regexp'." text matching `comint-prompt-regexp' stripped off, depending on the
(save-excursion value of `comint-use-prompt-regexp-instead-of-fields'."
(beginning-of-line) (if comint-use-prompt-regexp-instead-of-fields
(comint-skip-prompt) (save-excursion
(let ((beg (point))) (beginning-of-line)
(end-of-line) (comint-skip-prompt)
(buffer-substring beg (point))))) (let ((beg (point)))
(end-of-line)
(buffer-substring beg (point))))
;; Return the contents of the field at the current point.
(field-string)))
(defun comint-copy-old-input () (defun comint-copy-old-input ()
"Insert after prompt old input at point as new input to be edited. "Insert after prompt old input at point as new input to be edited.
@ -1592,15 +1658,38 @@ set the hook `comint-input-sender'."
(comint-send-string proc string) (comint-send-string proc string)
(comint-send-string proc "\n")) (comint-send-string proc "\n"))
(defun comint-bol (arg) (defun comint-line-beginning-position ()
"Goes to the beginning of line, then skips past the prompt, if any. "Returns the buffer position of the beginning of the line, after any prompt.
If prefix argument is given (\\[universal-argument]) the prompt is not skipped. If `comint-use-prompt-regexp-instead-of-fields' is non-nil, then the
prompt skip is done by skipping text matching the regular expression
`comint-prompt-regexp', a buffer local variable."
(if comint-use-prompt-regexp-instead-of-fields
;; Use comint-prompt-regexp
(save-excursion
(beginning-of-line)
(comint-skip-prompt)
(point))
;; Use input fields. Note that, unlike the behavior of
;; `line-beginning-position' inside a field, this function will
;; return the position of the end of a prompt, even if the point is
;; already inside the prompt. In order to do this, it assumes that
;; if there are two fields on a line, then the first one is the
;; prompt, and the second one is an input field, and is front-sticky
;; (as input fields should be).
(constrain-to-field (line-beginning-position) (line-end-position))))
The prompt skip is done by skipping text matching the regular expression (defun comint-bol (&optional arg)
"Goes to the beginning of line, then skips past the prompt, if any.
If prefix argument is given (\\[universal-argument]) the prompt is not skipped.
If `comint-use-prompt-regexp-instead-of-fields' is non-nil, then the
prompt skip is done by skipping text matching the regular expression
`comint-prompt-regexp', a buffer local variable." `comint-prompt-regexp', a buffer local variable."
(interactive "P") (interactive "P")
(beginning-of-line) (if arg
(if (null arg) (comint-skip-prompt))) ;; Disregard prompt
(let ((inhibit-field-text-motion t))
(beginning-of-line))
(goto-char (comint-line-beginning-position))))
;; These three functions are for entering text you don't want echoed or ;; These three functions are for entering text you don't want echoed or
;; saved -- typically passwords to ftp, telnet, or somesuch. ;; saved -- typically passwords to ftp, telnet, or somesuch.
@ -1721,11 +1810,16 @@ Does not delete the prompt."
Sets mark to the value of point when this command is run." Sets mark to the value of point when this command is run."
(interactive) (interactive)
(push-mark) (push-mark)
(let ((pos (point))) (let ((pos (or (marker-position comint-last-input-end) (point-max))))
(goto-char (or (marker-position comint-last-input-end) (point-max))) (cond (comint-use-prompt-regexp-instead-of-fields
(beginning-of-line 0) (goto-char pos)
(set-window-start (selected-window) (point)) (beginning-of-line 0)
(comint-skip-prompt))) (set-window-start (selected-window) (point))
(comint-skip-prompt))
(t
(goto-char (field-beginning pos))
(set-window-start (selected-window) (point))))))
(defun comint-interrupt-subjob () (defun comint-interrupt-subjob ()
"Interrupt the current subjob. "Interrupt the current subjob.
@ -1793,24 +1887,42 @@ Sends an EOF only if point is at the end of the buffer and there is no input."
(defun comint-backward-matching-input (regexp arg) (defun comint-backward-matching-input (regexp arg)
"Search backward through buffer for match for REGEXP. "Search backward through buffer for input fields that match REGEXP.
Matches are searched for on lines that match `comint-prompt-regexp'. If `comint-use-prompt-regexp-instead-of-fields' is non-nil, then input
fields are identified by lines that match `comint-prompt-regexp'.
With prefix argument N, search for Nth previous match. With prefix argument N, search for Nth previous match.
If N is negative, find the next or Nth next match." If N is negative, find the next or Nth next match."
(interactive (comint-regexp-arg "Backward input matching (regexp): ")) (interactive (comint-regexp-arg "Backward input matching (regexp): "))
(let* ((re (concat comint-prompt-regexp ".*" regexp)) (if comint-use-prompt-regexp-instead-of-fields
(pos (save-excursion (end-of-line (if (> arg 0) 0 1)) ;; Use comint-prompt-regexp
(if (re-search-backward re nil t arg) (let* ((re (concat comint-prompt-regexp ".*" regexp))
(point))))) (pos (save-excursion (end-of-line (if (> arg 0) 0 1))
(if (null pos) (if (re-search-backward re nil t arg)
(progn (message "Not found") (point)))))
(ding)) (if (null pos)
(goto-char pos) (progn (message "Not found")
(comint-bol nil)))) (ding))
(goto-char pos)
(comint-bol nil)))
;; Use input fields
(let* ((dir (if (< arg 0) -1 1))
(pos
(save-excursion
(while (/= arg 0)
(unless (re-search-backward regexp nil t dir)
(error "Not found"))
(when (eq (get-char-property (point) 'field) 'input)
(setq arg (- arg dir))))
(field-beginning))))
(goto-char pos))))
(defun comint-forward-matching-input (regexp arg) (defun comint-forward-matching-input (regexp arg)
"Search forward through buffer for match for REGEXP. "Search forward through buffer for input fields that match REGEXP.
Matches are searched for on lines that match `comint-prompt-regexp'. If `comint-use-prompt-regexp-instead-of-fields' is non-nil, then input
fields are identified by lines that match `comint-prompt-regexp'.
With prefix argument N, search for Nth following match. With prefix argument N, search for Nth following match.
If N is negative, find the previous or Nth previous match." If N is negative, find the previous or Nth previous match."
(interactive (comint-regexp-arg "Forward input matching (regexp): ")) (interactive (comint-regexp-arg "Forward input matching (regexp): "))
@ -1819,16 +1931,39 @@ If N is negative, find the previous or Nth previous match."
(defun comint-next-prompt (n) (defun comint-next-prompt (n)
"Move to end of Nth next prompt in the buffer. "Move to end of Nth next prompt in the buffer.
See `comint-prompt-regexp'." If `comint-use-prompt-regexp-instead-of-fields' is nil, then this means
the beginning of the Nth next `input' field, otherwise, it means the Nth
occurance of text matching `comint-prompt-regexp'."
(interactive "p") (interactive "p")
(let ((paragraph-start comint-prompt-regexp)) (if comint-use-prompt-regexp-instead-of-fields
(end-of-line (if (> n 0) 1 0)) ;; Use comint-prompt-regexp
(forward-paragraph n) (let ((paragraph-start comint-prompt-regexp))
(comint-skip-prompt))) (end-of-line (if (> n 0) 1 0))
(forward-paragraph n)
(comint-skip-prompt))
;; Use input fields
(let ((pos (point))
(input-pos nil))
(while (/= n 0)
(setq pos
(if (> n 0)
(next-single-char-property-change pos 'field)
(previous-single-char-property-change pos 'field)))
(cond ((null pos)
;; Ran off the end of the buffer.
(setq n 0))
((eq (get-char-property pos 'field) 'input)
(setq n (if (< n 0) (1+ n) (1- n)))
(setq input-pos pos))))
(when input-pos
(goto-char input-pos)))))
(defun comint-previous-prompt (n) (defun comint-previous-prompt (n)
"Move to end of Nth previous prompt in the buffer. "Move to end of Nth previous prompt in the buffer.
See `comint-prompt-regexp'." If `comint-use-prompt-regexp-instead-of-fields' is nil, then this means
the beginning of the Nth previous `input' field, otherwise, it means the Nth
occurance of text matching `comint-prompt-regexp'."
(interactive "p") (interactive "p")
(comint-next-prompt (- n))) (comint-next-prompt (- n)))
@ -2468,6 +2603,10 @@ the process mark is at the beginning of the accumulated input."
;; a prompt in the comint buffer; however, it is still important to ensure that ;; a prompt in the comint buffer; however, it is still important to ensure that
;; this prompt is set correctly. ;; this prompt is set correctly.
;; ;;
;; XXX: This doesn't work so well unless comint-prompt-regexp is set;
;; perhaps it should prompt for a terminating string (with an
;; appropriate magic default by examining what we think is the prompt)?
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Variables ;; Variables