X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/e7654b4a743e7c54c08629ee336e10a5f1089da6..be415ea70e7653e4ce342016c6596499006120fb:/lisp/comint.el diff --git a/lisp/comint.el b/lisp/comint.el index 8e3a1bb230..42c2fb8830 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -65,14 +65,15 @@ ;; Comint Mode Commands: (common to all derived modes, like shell & cmulisp ;; mode) ;; -;; m-p comint-previous-input Cycle backwards in input history -;; m-n comint-next-input Cycle forwards +;; m-p comint-previous-input Cycle backwards in input history +;; m-n comint-next-input Cycle forwards ;; m-r comint-previous-matching-input Previous input matching a regexp ;; m-s comint-next-matching-input Next input that matches -;; m-c-l comint-show-output Show last batch of process output +;; m-c-l comint-show-output Show last batch of process output ;; return comint-send-input -;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff -;; c-c c-a comint-bol Beginning of line; skip prompt +;; c-d comint-delchar-or-maybe-eof Delete char unless at end of buff +;; c-c c-a comint-bol-or-process-mark First time, move point to bol; +;; second time, move to process-mark. ;; c-c c-u comint-kill-input ^u ;; c-c c-w backward-kill-word ^w ;; c-c c-c comint-interrupt-subjob ^c @@ -98,6 +99,11 @@ ;; comint-continue-subjob Send CONT signal to buffer's process ;; group. Useful if you accidentally ;; suspend your process (with C-c C-z). +;; comint-get-next-from-history Fetch successive input history lines +;; comint-accumulate Combine lines to send them together +;; as input. +;; comint-goto-process-mark Move point to where process-mark is. +;; comint-set-process-mark Set process-mark to point. ;; comint-mode-hook is the comint mode hook. Basically for your keybindings. @@ -115,6 +121,7 @@ ;; comint-input-ring-size integer For the input history ;; comint-input-ring ring mechanism ;; comint-input-ring-index number ... +;; comint-save-input-ring-index number ... ;; comint-input-autoexpand symbol ... ;; comint-input-ignoredups boolean ... ;; comint-last-input-match string ... @@ -133,6 +140,7 @@ ;; comint-scroll-to-bottom-on-input symbol For scroll behavior ;; comint-scroll-to-bottom-on-output symbol ... ;; comint-scroll-show-maximum-output boolean ... +;; comint-accum-marker maker For comint-accumulate ;; ;; Comint mode non-buffer local variables: ;; comint-completion-addsuffix boolean/cons For file name @@ -189,9 +197,9 @@ into the buffer's input ring. See also `comint-magic-space' and This variable is buffer-local." :type '(choice (const :tag "off" nil) - (const :tag "on" t) (const input) - (const history)) + (const history) + (other :tag "on" t)) :group 'comint) (defcustom comint-input-ignoredups nil @@ -359,10 +367,18 @@ This is to work around a bug in Emacs process signaling.") "Index of last matched history element.") (defvar comint-matching-input-from-input-string "" "Input previously used to match input history.") +(defvar comint-save-input-ring-index + "Last input ring index which you copied. +This is to support the command \\[comint-get-next-from-history].") + +(defvar comint-accum-marker nil + "Non-nil if you are accumulating input lines to send as input together. +The command \\[comint-accumulate] sets this.") (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) +(put 'comint-save-input-ring-index 'permanent-local t) (put 'comint-input-autoexpand 'permanent-local t) (put 'comint-input-filter-functions 'permanent-local t) (put 'comint-output-filter-functions 'permanent-local t) @@ -432,8 +448,11 @@ Entry to this mode runs the hooks on `comint-mode-hook'." (or (and (boundp 'comint-input-ring) comint-input-ring) (setq comint-input-ring (make-ring comint-input-ring-size))) (make-local-variable 'comint-input-ring-index) + (make-local-variable 'comint-save-input-ring-index) (or (and (boundp 'comint-input-ring-index) comint-input-ring-index) (setq comint-input-ring-index nil)) + (or (and (boundp 'comint-save-input-ring-index) comint-save-input-ring-index) + (setq comint-save-input-ring-index nil)) (make-local-variable 'comint-matching-input-from-input-string) (make-local-variable 'comint-input-autoexpand) (make-local-variable 'comint-input-ignoredups) @@ -456,6 +475,9 @@ Entry to this mode runs the hooks on `comint-mode-hook'." (make-local-variable 'comint-process-echoes) (make-local-variable 'comint-file-name-chars) (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) (run-hooks 'comint-mode-hook)) (if comint-mode-map @@ -468,12 +490,14 @@ Entry to this mode runs the hooks on `comint-mode-hook'." (define-key comint-mode-map [C-down] 'comint-next-input) (define-key comint-mode-map "\er" 'comint-previous-matching-input) (define-key comint-mode-map "\es" 'comint-next-matching-input) - (define-key comint-mode-map [?\A-\M-r] 'comint-previous-matching-input-from-input) - (define-key comint-mode-map [?\A-\M-s] 'comint-next-matching-input-from-input) + (define-key comint-mode-map [?\C-c ?\M-r] 'comint-previous-matching-input-from-input) + (define-key comint-mode-map [?\C-c ?\M-s] 'comint-next-matching-input-from-input) (define-key comint-mode-map "\e\C-l" 'comint-show-output) (define-key comint-mode-map "\C-m" 'comint-send-input) (define-key comint-mode-map "\C-d" 'comint-delchar-or-maybe-eof) - (define-key comint-mode-map "\C-c\C-a" 'comint-bol) + (define-key comint-mode-map "\C-c " 'comint-accumulate) + (define-key comint-mode-map "\C-c\C-x" 'comint-get-next-from-history) + (define-key comint-mode-map "\C-c\C-a" 'comint-bol-or-process-mark) (define-key comint-mode-map "\C-c\C-u" 'comint-kill-input) (define-key comint-mode-map "\C-c\C-w" 'backward-kill-word) (define-key comint-mode-map "\C-c\C-c" 'comint-interrupt-subjob) @@ -657,8 +681,28 @@ buffer. The hook `comint-exec-hook' is run after each exec." (default-directory (if (file-accessible-directory-p default-directory) default-directory - (char-to-string directory-sep-char)))) - (apply 'start-process name buffer command switches))) + (char-to-string directory-sep-char))) + proc decoding encoding changed) + (setq proc (apply 'start-process name buffer command switches)) + (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 + ;; data sent form 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 + ;; sent from the process undecided, we had better use the same one + ;; as what we use for decoding. But, we should suppress EOL + ;; conversion. + (if (and decoding (not encoding)) + (setq encoding (coding-system-change-eol-conversion decoding 'unix) + changed t)) + (if changed + (set-process-coding-system proc decoding encoding)) + proc)) ;; Input history processing in a buffer ;; =========================================================================== @@ -897,7 +941,9 @@ If N is negative, find the next or Nth next match." (message "History item: %d" (1+ pos)) (delete-region ;; Can't use kill-region as it sets this-command - (process-mark (get-buffer-process (current-buffer))) (point)) + (or (marker-position comint-accum-marker) + (process-mark (get-buffer-process (current-buffer)))) + (point)) (insert (ring-ref comint-input-ring pos))))) (defun comint-next-matching-input (regexp arg) @@ -919,7 +965,8 @@ If N is negative, search forwards for the -Nth following match." ;; Starting a new search (setq comint-matching-input-from-input-string (buffer-substring - (process-mark (get-buffer-process (current-buffer))) + (or (marker-position comint-accum-marker) + (process-mark (get-buffer-process (current-buffer)))) (point)) comint-input-ring-index nil)) (comint-previous-matching-input @@ -935,7 +982,7 @@ If N is negative, search backwards for the -Nth previous match." (comint-previous-matching-input-from-input (- arg))) -(defun comint-replace-by-expanded-history (&optional silent) +(defun comint-replace-by-expanded-history (&optional silent start) "Expand input command history references before point. Expansion is dependent on the value of `comint-input-autoexpand'. @@ -949,6 +996,10 @@ it cannot expand absolute input line number references. If the optional argument SILENT is non-nil, never complain even if history reference seems erroneous. +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. + See `comint-magic-space' and `comint-replace-by-expanded-history-before-point'. Returns t if successful." @@ -959,17 +1010,20 @@ Returns t if successful." (looking-at comint-prompt-regexp))) ;; Looks like there might be history references in the command. (let ((previous-modified-tick (buffer-modified-tick))) - (message "Expanding history references...") - (comint-replace-by-expanded-history-before-point silent) + (comint-replace-by-expanded-history-before-point silent start) (/= previous-modified-tick (buffer-modified-tick))))) -(defun comint-replace-by-expanded-history-before-point (silent) +(defun comint-replace-by-expanded-history-before-point (silent &optional start) "Expand directory stack reference before point. -See `comint-replace-by-expanded-history'. Returns t if successful." +See `comint-replace-by-expanded-history'. Returns t if successful. + +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 (progn (comint-bol nil) (point)))) + (start (or start (progn (comint-bol nil) (point))))) (while (progn (skip-chars-forward "^!^" (save-excursion @@ -1051,7 +1105,7 @@ See `comint-replace-by-expanded-history'. Returns t if successful." (replace-match new t t) (message "History item: substituted")))) (t - (goto-char (match-end 0)))))))) + (forward-char 1))))))) (defun comint-magic-space (arg) @@ -1223,14 +1277,14 @@ Similarly for Soar, Scheme, etc." ;; Just whatever's already there intxt ;; Expand and leave it visible in buffer - (comint-replace-by-expanded-history t) + (comint-replace-by-expanded-history t pmark) (buffer-substring pmark (point)))) (history (if (not (eq comint-input-autoexpand 'history)) input ;; This is messy 'cos ultimately the original ;; functions used do insertion, rather than return ;; strings. We have to expand, then insert back. - (comint-replace-by-expanded-history t) + (comint-replace-by-expanded-history t pmark) (let ((copy (buffer-substring pmark (point))) (start (point))) (insert input) @@ -1248,12 +1302,15 @@ Similarly for Soar, Scheme, etc." (ring-insert comint-input-ring history)) (run-hook-with-args 'comint-input-filter-functions (concat input "\n")) + (setq comint-save-input-ring-index comint-input-ring-index) (setq comint-input-ring-index nil) ;; Update the markers before we send the input ;; in case we get output amidst sending the input. (set-marker comint-last-input-start pmark) (set-marker comint-last-input-end (point)) (set-marker (process-mark proc) (point)) + ;; clear the "accumulation" marker + (set-marker comint-accum-marker nil) (funcall comint-input-sender proc input) ;; This used to call comint-output-filter-functions, ;; but that scrolled the buffer in undesirable ways. @@ -1365,7 +1422,8 @@ This function should be in the list `comint-output-filter-functions'." (and (eq scroll 'this) (eq selected window)) (and (eq scroll 'others) (not (eq selected window))) ;; If point was at the end, keep it at end. - (>= (point) comint-last-output-start))) + (and (marker-position comint-last-output-start) + (>= (point) comint-last-output-start)))) (goto-char (process-mark process))) ;; Optionally scroll so that the text ;; ends at the bottom of the window. @@ -1940,13 +1998,9 @@ This is used by comint's and shell's completion functions, and by shell's directory tracking functions.") (defvar comint-file-name-chars - (cond - ((eq system-type 'ms-dos) - "~/A-Za-z0-9_^$!#%&{}@`'.()-") - ((eq system-type 'windows-nt) - "~/A-Za-z0-9_^$!#%&{}@`'.,:()-") - (t - "~/A-Za-z0-9+@:_.$#%,={}-")) + (if (memq system-type '(ms-dos windows-nt)) + "~/A-Za-z0-9_^$!#%&{}@`'.,:()-" + "~/A-Za-z0-9+@:_.$#%,={}-") "String of characters valid in a file name. Note that all non-ASCII characters are considered valid in a file name regardless of what this variable says. @@ -2238,6 +2292,66 @@ Typing SPC flushes the help buffer." (set-window-configuration conf) (setq unread-command-events (listify-key-sequence key))))))) +(defun comint-get-next-from-history () + "After fetching a line from input history, this fetches the following line. +In other words, this recalls the input line after the line you recalled last. +You can use this to repeat a sequence of input lines." + (interactive) + (if comint-save-input-ring-index + (progn + (setq comint-input-ring-index (1+ comint-save-input-ring-index)) + (comint-next-input 1)) + (message "No previous history command"))) + +(defun comint-accumulate () + "Accumulate a line to send as input along with more lines. +This inserts a newline so that you can enter more text +to be sent along with this line. Use \\[comint-send-input] +to send all the accumulated input, at once. +The entire accumulated text becomes one item in the input history +when you send it." + (interactive) + (insert "\n") + (set-marker comint-accum-marker (point)) + (if comint-input-ring-index + (setq comint-save-input-ring-index + (- comint-input-ring-index 1)))) + +(defun comint-goto-process-mark () + "Move point to the process mark. +The process mark separates output, and input already sent, +from input that has not yet been sent." + (interactive) + (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"))) + +(defun comint-bol-or-process-mark () + "Move point beginning of line (after prompt) or to the process mark. +The first time you use this command, it moves to the beginning of the line +\(but after the prompt, if any). If you repeat it again immediately, +it moves point to the process mark. + +The process mark separates the process output, along with input already sent, +from input that has not yet been sent. Ordinarily, the process mark +is at the beginning of the current input line; but if you have +used \\[comint-accumulate] to send multiple lines at once, +the process mark is at the beginning of the accumulated input." + (interactive) + (if (not (eq last-command 'comint-bol-or-process-mark)) + (comint-bol nil) + (comint-goto-process-mark))) + +(defun comint-set-process-mark () + "Set the process mark at point." + (interactive) + (let ((proc (or (get-buffer-process (current-buffer)) + (error "Current buffer has no process")))) + (set-marker (process-mark proc) (point)) + (message "Process mark set"))) + + ;; Converting process modes to use comint mode ;; =========================================================================== ;; The code in the Emacs 19 distribution has all been modified to use comint