1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-12-25 10:47:00 +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-show-maximum-output boolean ...
;; comint-accum-marker maker For comint-accumulate
;; comint-last-output-overlay overlay
;;
;; Comint mode non-buffer local variables:
;; comint-completion-addsuffix boolean/cons For file name
@ -160,11 +161,13 @@
:prefix "comint-"
:group 'comint)
(defvar comint-prompt-regexp "^"
"Regexp to recognise prompts in the inferior process.
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:
Canonical Lisp: \"^[^> \\n]*>+:? *\" (Lucid, franz, kcl, T, cscheme, oaklisp)
Lucid Common Lisp: \"^\\\\(>\\\\|\\\\(->\\\\)+\\\\) *\"
@ -309,10 +312,12 @@ This is used by `comint-watch-for-password-prompt'."
;; Here are the per-interpreter hooks.
(defvar comint-get-old-input (function comint-get-old-input-default)
"Function that returns old text in comint mode.
This function is called when return is typed while the point is in old text.
It returns the text to be submitted as process input. The default is
`comint-get-old-input-default', which grabs the current line, and strips off
leading text matching `comint-prompt-regexp'.")
This function is called when return is typed while the point is in old
text. It returns the text to be submitted as process input. The
default is `comint-get-old-input-default', which either grabs the
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
'(comint-replace-by-expanded-history comint-dynamic-complete-filename)
@ -359,6 +364,18 @@ See `comint-send-input'."
:type 'boolean
: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 '()
"Called upon entry into comint-mode
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))
(make-local-variable 'comint-last-output-start)
(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-input-ring-size) ; ...to global val.
(make-local-variable 'comint-input-ring)
@ -1070,8 +1088,13 @@ Returns t if successful."
(interactive)
(if (and comint-input-autoexpand
(string-match "!\\|^\\^" (funcall comint-get-old-input))
(save-excursion (beginning-of-line)
(looking-at comint-prompt-regexp)))
(if comint-use-prompt-regexp-instead-of-fields
;; 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.
(let ((previous-modified-tick (buffer-modified-tick)))
(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
than the logical beginning of line."
(save-excursion
(let ((toend (- (save-excursion (end-of-line nil) (point)) (point)))
(start (or start (progn (comint-bol nil) (point)))))
(let ((toend (- (line-end-position) (point)))
(start (comint-line-beginning-position)))
(while (progn
(skip-chars-forward "^!^"
(save-excursion
(end-of-line nil) (- (point) toend)))
(< (point)
(save-excursion
(end-of-line nil) (- (point) toend))))
(skip-chars-forward "^!^" (- (line-end-position) toend))
(< (point) (- (line-end-position) toend)))
;; This seems a bit complex. We look for references such as !!, !-num,
;; !foo, !?foo, !{bar}, !?{bar}, ^oh, ^my^, ^god^it, ^never^ends^.
;; 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.,
If the interpreter is the csh,
comint-get-old-input is the default: take the current line, discard any
initial string matching regexp comint-prompt-regexp.
comint-get-old-input is the default: either return the current
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
\"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
@ -1360,9 +1381,11 @@ Similarly for Soar, Scheme, etc."
(insert input)
(delete-region pmark start)
copy))))
(if comint-process-echoes
(delete-region pmark (point))
(insert-before-markers ?\n))
(if (and (funcall comint-input-filter history)
(or (null comint-input-ignoredups)
(not (ring-p comint-input-ring))
@ -1370,17 +1393,33 @@ Similarly for Soar, Scheme, etc."
(not (string-equal (ring-ref comint-input-ring 0)
history))))
(ring-insert comint-input-ring history))
(run-hook-with-args 'comint-input-filter-functions
(concat input "\n"))
(let ((beg (marker-position pmark))
(end (1- (point))))
(when (and comint-highlight-input
;; handle a special case
(not (> beg end)))
(when (not (> beg end)) ; handle a special case
;; Make an overlay for the input field
(let ((over (make-overlay beg end)))
(overlay-put over 'face comint-highlight-face)
(overlay-put over 'mouse-face 'highlight)
(unless comint-use-prompt-regexp-instead-of-fields
;; 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))))
(setq comint-save-input-ring-index comint-input-ring-index)
(setq comint-input-ring-index nil)
;; Update the markers before we send the input
@ -1409,6 +1448,11 @@ redirection buffer.
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
;; is to keep comint-last-input-end from moving forward
;; when output is inserted.
@ -1439,6 +1483,23 @@ This variable is permanent-local.")
(if (<= (point) oend)
(setq oend (+ oend nchars)))
(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.
(if (= (window-start (selected-window)) (point))
(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 ()
"Default for `comint-get-old-input'.
Take the current line, and discard any initial text matching
`comint-prompt-regexp'."
(save-excursion
(beginning-of-line)
(comint-skip-prompt)
(let ((beg (point)))
(end-of-line)
(buffer-substring beg (point)))))
Returns either the current field, or the current line with any initial
text matching `comint-prompt-regexp' stripped off, depending on the
value of `comint-use-prompt-regexp-instead-of-fields'."
(if comint-use-prompt-regexp-instead-of-fields
(save-excursion
(beginning-of-line)
(comint-skip-prompt)
(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 ()
"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 "\n"))
(defun comint-bol (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.
(defun comint-line-beginning-position ()
"Returns the buffer position of the beginning of the line, after any prompt.
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."
(interactive "P")
(beginning-of-line)
(if (null arg) (comint-skip-prompt)))
(if arg
;; 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
;; 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."
(interactive)
(push-mark)
(let ((pos (point)))
(goto-char (or (marker-position comint-last-input-end) (point-max)))
(beginning-of-line 0)
(set-window-start (selected-window) (point))
(comint-skip-prompt)))
(let ((pos (or (marker-position comint-last-input-end) (point-max))))
(cond (comint-use-prompt-regexp-instead-of-fields
(goto-char pos)
(beginning-of-line 0)
(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 ()
"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)
"Search backward through buffer for match for REGEXP.
Matches are searched for on lines that match `comint-prompt-regexp'.
"Search backward through buffer for input fields that match 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.
If N is negative, find the next or Nth next match."
(interactive (comint-regexp-arg "Backward input matching (regexp): "))
(let* ((re (concat comint-prompt-regexp ".*" regexp))
(pos (save-excursion (end-of-line (if (> arg 0) 0 1))
(if (re-search-backward re nil t arg)
(point)))))
(if (null pos)
(progn (message "Not found")
(ding))
(goto-char pos)
(comint-bol nil))))
(if comint-use-prompt-regexp-instead-of-fields
;; Use comint-prompt-regexp
(let* ((re (concat comint-prompt-regexp ".*" regexp))
(pos (save-excursion (end-of-line (if (> arg 0) 0 1))
(if (re-search-backward re nil t arg)
(point)))))
(if (null pos)
(progn (message "Not found")
(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)
"Search forward through buffer for match for REGEXP.
Matches are searched for on lines that match `comint-prompt-regexp'.
"Search forward through buffer for input fields that match 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.
If N is negative, find the previous or Nth previous match."
(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)
"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")
(let ((paragraph-start comint-prompt-regexp))
(end-of-line (if (> n 0) 1 0))
(forward-paragraph n)
(comint-skip-prompt)))
(if comint-use-prompt-regexp-instead-of-fields
;; Use comint-prompt-regexp
(let ((paragraph-start comint-prompt-regexp))
(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)
"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")
(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
;; 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