diff options
Diffstat (limited to 'lisp/comint.el')
| -rw-r--r-- | lisp/comint.el | 147 |
1 files changed, 131 insertions, 16 deletions
diff --git a/lisp/comint.el b/lisp/comint.el index 57e785dce47..12d8e1fcbb7 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -171,6 +171,31 @@ Good choices: | |||
| 171 | 171 | ||
| 172 | This is a good thing to set in mode hooks.") | 172 | This is a good thing to set in mode hooks.") |
| 173 | 173 | ||
| 174 | (defcustom comint-prompt-read-only nil | ||
| 175 | "If non-nil, the comint prompt is read only. | ||
| 176 | The read only region includes the newline before the prompt. | ||
| 177 | This does not affect existing prompts. | ||
| 178 | Certain derived modes may override this option. | ||
| 179 | |||
| 180 | If you set this option to t, then the safe way to temporarily | ||
| 181 | override the read-only-ness of comint prompts is to call | ||
| 182 | `comint-kill-whole-line' or `comint-kill-region' with no | ||
| 183 | narrowing in effect. This way you will be certain that none of | ||
| 184 | the remaining prompts will be accidentally messed up. You may | ||
| 185 | wish to put something like the following in your `.emacs' file: | ||
| 186 | |||
| 187 | \(add-hook 'comint-mode-hook | ||
| 188 | '(lambda () | ||
| 189 | (define-key comint-mode-map \"\C-w\" 'comint-kill-region) | ||
| 190 | (define-key comint-mode-map [C-S-backspace] | ||
| 191 | 'comint-kill-whole-line))) | ||
| 192 | |||
| 193 | If you sometimes use comint-mode on text-only terminals or with `emacs-nw', | ||
| 194 | you might wish to use another binding for `comint-kill-whole-line'." | ||
| 195 | :type 'boolean | ||
| 196 | :group 'comint | ||
| 197 | :version "21.4") | ||
| 198 | |||
| 174 | (defvar comint-delimiter-argument-list () | 199 | (defvar comint-delimiter-argument-list () |
| 175 | "List of characters to recognise as separate arguments in input. | 200 | "List of characters to recognise as separate arguments in input. |
| 176 | Strings comprising a character in this list will separate the arguments | 201 | Strings comprising a character in this list will separate the arguments |
| @@ -1157,7 +1182,7 @@ start of the text to scan for history references, rather | |||
| 1157 | than the logical beginning of line." | 1182 | than the logical beginning of line." |
| 1158 | (save-excursion | 1183 | (save-excursion |
| 1159 | (let ((toend (- (line-end-position) (point))) | 1184 | (let ((toend (- (line-end-position) (point))) |
| 1160 | (start (comint-line-beginning-position))) | 1185 | (start (or start (comint-line-beginning-position)))) |
| 1161 | (goto-char start) | 1186 | (goto-char start) |
| 1162 | (while (progn | 1187 | (while (progn |
| 1163 | (skip-chars-forward "^!^" (- (line-end-position) toend)) | 1188 | (skip-chars-forward "^!^" (- (line-end-position) toend)) |
| @@ -1457,7 +1482,8 @@ Similarly for Soar, Scheme, etc." | |||
| 1457 | (concat input "\n"))) | 1482 | (concat input "\n"))) |
| 1458 | 1483 | ||
| 1459 | (let ((beg (marker-position pmark)) | 1484 | (let ((beg (marker-position pmark)) |
| 1460 | (end (if no-newline (point) (1- (point))))) | 1485 | (end (if no-newline (point) (1- (point)))) |
| 1486 | (inhibit-modification-hooks t)) | ||
| 1461 | (when (> end beg) | 1487 | (when (> end beg) |
| 1462 | ;; Set text-properties for the input field | 1488 | ;; Set text-properties for the input field |
| 1463 | (add-text-properties | 1489 | (add-text-properties |
| @@ -1553,7 +1579,8 @@ See `comint-carriage-motion' for details.") | |||
| 1553 | freeze its attributes in place, even when more input comes a long | 1579 | freeze its attributes in place, even when more input comes a long |
| 1554 | and moves the prompt overlay." | 1580 | and moves the prompt overlay." |
| 1555 | (when comint-last-prompt-overlay | 1581 | (when comint-last-prompt-overlay |
| 1556 | (let ((inhibit-read-only t)) | 1582 | (let ((inhibit-read-only t) |
| 1583 | (inhibit-modification-hooks t)) | ||
| 1557 | (add-text-properties (overlay-start comint-last-prompt-overlay) | 1584 | (add-text-properties (overlay-start comint-last-prompt-overlay) |
| 1558 | (overlay-end comint-last-prompt-overlay) | 1585 | (overlay-end comint-last-prompt-overlay) |
| 1559 | (overlay-properties comint-last-prompt-overlay))))) | 1586 | (overlay-properties comint-last-prompt-overlay))))) |
| @@ -1684,19 +1711,30 @@ Make backspaces delete the previous character." | |||
| 1684 | (goto-char (process-mark process)) ; in case a filter moved it | 1711 | (goto-char (process-mark process)) ; in case a filter moved it |
| 1685 | 1712 | ||
| 1686 | (unless comint-use-prompt-regexp-instead-of-fields | 1713 | (unless comint-use-prompt-regexp-instead-of-fields |
| 1687 | (let ((inhibit-read-only t)) | 1714 | (let ((inhibit-read-only t) |
| 1715 | (inhibit-modification-hooks t)) | ||
| 1688 | (add-text-properties comint-last-output-start (point) | 1716 | (add-text-properties comint-last-output-start (point) |
| 1689 | '(rear-nonsticky t | 1717 | '(rear-nonsticky t |
| 1690 | field output | 1718 | field output |
| 1691 | inhibit-line-move-field-capture t)))) | 1719 | inhibit-line-move-field-capture t)))) |
| 1692 | 1720 | ||
| 1693 | ;; Highlight the prompt, where we define `prompt' to mean | 1721 | ;; Highlight the prompt, where we define `prompt' to mean |
| 1694 | ;; the most recent output that doesn't end with a newline. | 1722 | ;; the most recent output that doesn't end with a newline. |
| 1695 | (unless (and (bolp) (null comint-last-prompt-overlay)) | 1723 | (let ((prompt-start (save-excursion (forward-line 0) (point))) |
| 1696 | ;; Need to create or move the prompt overlay (in the case | 1724 | (inhibit-read-only t) |
| 1697 | ;; where there is no prompt ((bolp) == t), we still do | 1725 | (inhibit-modification-hooks t)) |
| 1698 | ;; this if there's already an existing overlay). | 1726 | (when comint-prompt-read-only |
| 1699 | (let ((prompt-start (save-excursion (forward-line 0) (point)))) | 1727 | (or (= (point-min) prompt-start) |
| 1728 | (get-text-property (1- prompt-start) 'read-only) | ||
| 1729 | (put-text-property | ||
| 1730 | (1- prompt-start) prompt-start 'read-only 'fence)) | ||
| 1731 | (add-text-properties | ||
| 1732 | prompt-start (point) | ||
| 1733 | '(read-only t rear-non-sticky t front-sticky (read-only)))) | ||
| 1734 | (unless (and (bolp) (null comint-last-prompt-overlay)) | ||
| 1735 | ;; Need to create or move the prompt overlay (in the case | ||
| 1736 | ;; where there is no prompt ((bolp) == t), we still do | ||
| 1737 | ;; this if there's already an existing overlay). | ||
| 1700 | (if comint-last-prompt-overlay | 1738 | (if comint-last-prompt-overlay |
| 1701 | ;; Just move an existing overlay | 1739 | ;; Just move an existing overlay |
| 1702 | (move-overlay comint-last-prompt-overlay | 1740 | (move-overlay comint-last-prompt-overlay |
| @@ -2006,7 +2044,8 @@ This function could be in the list `comint-output-filter-functions'." | |||
| 2006 | Does not delete the prompt." | 2044 | Does not delete the prompt." |
| 2007 | (interactive) | 2045 | (interactive) |
| 2008 | (let ((proc (get-buffer-process (current-buffer))) | 2046 | (let ((proc (get-buffer-process (current-buffer))) |
| 2009 | (replacement nil)) | 2047 | (replacement nil) |
| 2048 | (inhibit-read-only t)) | ||
| 2010 | (save-excursion | 2049 | (save-excursion |
| 2011 | (let ((pmark (progn (goto-char (process-mark proc)) | 2050 | (let ((pmark (progn (goto-char (process-mark proc)) |
| 2012 | (forward-line 0) | 2051 | (forward-line 0) |
| @@ -2293,6 +2332,84 @@ This command is like `M-.' in bash." | |||
| 2293 | (just-one-space))) | 2332 | (just-one-space))) |
| 2294 | 2333 | ||
| 2295 | 2334 | ||
| 2335 | ;; Support editing with `comint-prompt-read-only' set to t. | ||
| 2336 | |||
| 2337 | (defun comint-update-fence () | ||
| 2338 | "Update read-only status of newline before point. | ||
| 2339 | The `fence' read-only property is used to indicate that a newline | ||
| 2340 | is read-only for no other reason than to \"fence off\" a | ||
| 2341 | following front-sticky read-only region. This is used to | ||
| 2342 | implement comint read-only prompts. If the text after a newline | ||
| 2343 | changes, the read-only status of that newline may need updating. | ||
| 2344 | That is what this function does. | ||
| 2345 | |||
| 2346 | This function does nothing if point is not at the beginning of a | ||
| 2347 | line, or is at the beginning of the accessible portion of the buffer. | ||
| 2348 | Otherwise, if the character after point has a front-sticky | ||
| 2349 | read-only property, then the preceding newline is given a | ||
| 2350 | read-only property of `fence', unless it already is read-only. | ||
| 2351 | If the character after point does not have a front-sticky | ||
| 2352 | read-only property, any read-only property of `fence' on the | ||
| 2353 | preceding newline is removed." | ||
| 2354 | (let* ((pt (point)) (lst (get-text-property pt 'front-sticky)) | ||
| 2355 | (inhibit-modification-hooks t)) | ||
| 2356 | (and (bolp) | ||
| 2357 | (not (bobp)) | ||
| 2358 | (if (and (get-text-property pt 'read-only) | ||
| 2359 | (if (listp lst) (memq 'read-only lst) t)) | ||
| 2360 | (unless (get-text-property (1- pt) 'read-only) | ||
| 2361 | (put-text-property (1- pt) pt 'read-only 'fence)) | ||
| 2362 | (when (eq (get-text-property (1- pt) 'read-only) 'fence) | ||
| 2363 | (remove-list-of-text-properties (1- pt) pt '(read-only))))))) | ||
| 2364 | |||
| 2365 | (defun comint-kill-whole-line (&optional arg) | ||
| 2366 | "Kill current line, ignoring read-only and field properties. | ||
| 2367 | With prefix arg, kill that many lines starting from the current line. | ||
| 2368 | If arg is negative, kill backward. Also kill the preceding newline, | ||
| 2369 | instead of the trailing one. \(This is meant to make C-x z work well | ||
| 2370 | with negative arguments.) | ||
| 2371 | If arg is zero, kill current line but exclude the trailing newline. | ||
| 2372 | The read-only status of newlines is updated with `comint-update-fence', | ||
| 2373 | if necessary." | ||
| 2374 | (interactive "p") | ||
| 2375 | (let ((inhibit-read-only t) (inhibit-field-text-motion t)) | ||
| 2376 | (kill-whole-line arg) | ||
| 2377 | (when (>= arg 0) (comint-update-fence)))) | ||
| 2378 | |||
| 2379 | (defun comint-kill-region (beg end &optional yank-handler) | ||
| 2380 | "Like `kill-region', but ignores read-only properties, if safe. | ||
| 2381 | This command assumes that the buffer contains read-only | ||
| 2382 | \"prompts\" which are regions with front-sticky read-only | ||
| 2383 | properties at the beginning of a line, with the preceding newline | ||
| 2384 | being read-only to protect the prompt. This is true of the | ||
| 2385 | comint prompts if `comint-prompt-read-only' is non-nil. This | ||
| 2386 | command will not delete the region if this would create mutilated | ||
| 2387 | or out of place prompts. That is, if any part of a prompt is | ||
| 2388 | deleted, the entire prompt must be deleted and all remaining | ||
| 2389 | prompts should stay at the beginning of a line. If this is not | ||
| 2390 | the case, this command just calls `kill-region' with all | ||
| 2391 | read-only properties intact. The read-only status of newlines is | ||
| 2392 | updated using `comint-update-fence', if necessary." | ||
| 2393 | (interactive "r") | ||
| 2394 | (save-excursion | ||
| 2395 | (let* ((true-beg (min beg end)) | ||
| 2396 | (true-end (max beg end)) | ||
| 2397 | (beg-bolp (progn (goto-char true-beg) (bolp))) | ||
| 2398 | (beg-lst (get-text-property true-beg 'front-sticky)) | ||
| 2399 | (beg-bad (and (get-text-property true-beg 'read-only) | ||
| 2400 | (if (listp beg-lst) (memq 'read-only beg-lst) t))) | ||
| 2401 | (end-bolp (progn (goto-char true-end) (bolp))) | ||
| 2402 | (end-lst (get-text-property true-end 'front-sticky)) | ||
| 2403 | (end-bad (and (get-text-property true-end 'read-only) | ||
| 2404 | (if (listp end-lst) (memq 'read-only end-lst) t)))) | ||
| 2405 | (if (or (and (not beg-bolp) (or beg-bad end-bad)) | ||
| 2406 | (and (not end-bolp) end-bad)) | ||
| 2407 | (kill-region beg end yank-handler) | ||
| 2408 | (let ((inhibit-read-only t)) | ||
| 2409 | (kill-region beg end yank-handler) | ||
| 2410 | (comint-update-fence)))))) | ||
| 2411 | |||
| 2412 | |||
| 2296 | ;; Support for source-file processing commands. | 2413 | ;; Support for source-file processing commands. |
| 2297 | ;;============================================================================ | 2414 | ;;============================================================================ |
| 2298 | ;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have | 2415 | ;; Many command-interpreters (e.g., Lisp, Scheme, Soar) have |
| @@ -2854,10 +2971,8 @@ Typing SPC flushes the help buffer." | |||
| 2854 | 2971 | ||
| 2855 | ;; Read the next key, to process SPC. | 2972 | ;; Read the next key, to process SPC. |
| 2856 | (let (key first) | 2973 | (let (key first) |
| 2857 | (if (save-excursion | 2974 | (if (with-current-buffer (get-buffer "*Completions*") |
| 2858 | (set-buffer (get-buffer "*Completions*")) | 2975 | (set (make-local-variable 'comint-displayed-dynamic-completions) |
| 2859 | (set (make-local-variable | ||
| 2860 | 'comint-displayed-dynamic-completions) | ||
| 2861 | completions) | 2976 | completions) |
| 2862 | (setq key (read-key-sequence nil) | 2977 | (setq key (read-key-sequence nil) |
| 2863 | first (aref key 0)) | 2978 | first (aref key 0)) |