diff options
| author | Sebastian Miele | 2024-06-19 15:48:59 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2024-06-27 10:48:18 +0300 |
| commit | 058bb4ca25adb8f4bf78cc0f09a65d730dbd797d (patch) | |
| tree | 8c361b2ac539898c038903439a6ee18da67086a6 | |
| parent | e45173d114e37d5a652b5393ce7bcab1acea3f1a (diff) | |
| download | emacs-058bb4ca25adb8f4bf78cc0f09a65d730dbd797d.tar.gz emacs-058bb4ca25adb8f4bf78cc0f09a65d730dbd797d.zip | |
kill-whole-line: Honor visibility; fix kill-ring when read-only (bug#65734)
* lisp/simple.el (kill-whole-line): Use visibility state before
performing any edits as reference instead of expecting that visibility
cannot change. First of the two calls to `kill-region' may trigger
`after-change-functions' that might alter the visibility state.
Make sure that we populate the `kill-ring' with the contents of the
whole line when buffer is in `read-only-mode'.
| -rw-r--r-- | lisp/simple.el | 69 |
1 files changed, 47 insertions, 22 deletions
diff --git a/lisp/simple.el b/lisp/simple.el index c798ee010b1..17625fad66f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -6703,28 +6703,53 @@ If ARG is zero, kill current line but exclude the trailing newline." | |||
| 6703 | (unless (eq last-command 'kill-region) | 6703 | (unless (eq last-command 'kill-region) |
| 6704 | (kill-new "") | 6704 | (kill-new "") |
| 6705 | (setq last-command 'kill-region)) | 6705 | (setq last-command 'kill-region)) |
| 6706 | (cond ((zerop arg) | 6706 | ;; - We need to kill in two steps, because the previous command |
| 6707 | ;; We need to kill in two steps, because the previous command | 6707 | ;; could have been a kill command, in which case the text before |
| 6708 | ;; could have been a kill command, in which case the text | 6708 | ;; point needs to be prepended to the current kill ring entry and |
| 6709 | ;; before point needs to be prepended to the current kill | 6709 | ;; the text after point appended. |
| 6710 | ;; ring entry and the text after point appended. Also, we | 6710 | ;; - We need to be careful to avoid copying text twice to the kill |
| 6711 | ;; need to use save-excursion to avoid copying the same text | 6711 | ;; ring in read-only buffers. |
| 6712 | ;; twice to the kill ring in read-only buffers. | 6712 | ;; - We need to determine the boundaries of visible lines before we |
| 6713 | (save-excursion | 6713 | ;; do the first kill. Otherwise `after-change-functions' may |
| 6714 | (kill-region (point) (progn (forward-visible-line 0) (point)))) | 6714 | ;; change visibility (bug#65734). |
| 6715 | (kill-region (point) (progn (end-of-visible-line) (point)))) | 6715 | (let (;; The beginning of both regions to kill |
| 6716 | ((< arg 0) | 6716 | (regions-begin (point-marker)) |
| 6717 | (save-excursion | 6717 | ;; The end of the first region to kill. Moreover, after |
| 6718 | (kill-region (point) (progn (end-of-visible-line) (point)))) | 6718 | ;; evaluation of the value form, (point) will be the end of |
| 6719 | (kill-region (point) | 6719 | ;; the second region to kill. |
| 6720 | (progn (forward-visible-line (1+ arg)) | 6720 | (region1-end (cond ((zerop arg) |
| 6721 | (unless (bobp) (backward-char)) | 6721 | (prog1 (save-excursion |
| 6722 | (point)))) | 6722 | (forward-visible-line 0) |
| 6723 | (t | 6723 | (point-marker)) |
| 6724 | (save-excursion | 6724 | (end-of-visible-line))) |
| 6725 | (kill-region (point) (progn (forward-visible-line 0) (point)))) | 6725 | ((< arg 0) |
| 6726 | (kill-region (point) | 6726 | (prog1 (save-excursion |
| 6727 | (progn (forward-visible-line arg) (point)))))) | 6727 | (end-of-visible-line) |
| 6728 | (point-marker)) | ||
| 6729 | (forward-visible-line (1+ arg)) | ||
| 6730 | (unless (bobp) (backward-char)))) | ||
| 6731 | (t | ||
| 6732 | (prog1 (save-excursion | ||
| 6733 | (forward-visible-line 0) | ||
| 6734 | (point-marker)) | ||
| 6735 | (forward-visible-line arg)))))) | ||
| 6736 | ;; - Pass the marker positions and not the markers themselves. | ||
| 6737 | ;; kill-region determines whether to prepend or append to a | ||
| 6738 | ;; previous kill by checking the direction of the region. But | ||
| 6739 | ;; it deletes the content and hence moves the markers before | ||
| 6740 | ;; that. That effectively makes every region delimited by | ||
| 6741 | ;; markers an (empty) forward region. | ||
| 6742 | ;; - Make the first kill-region emit a non-local exit only if the | ||
| 6743 | ;; second kill-region below would not operate on a non-empty | ||
| 6744 | ;; region. | ||
| 6745 | (let ((kill-read-only-ok (or kill-read-only-ok | ||
| 6746 | (/= regions-begin (point))))) | ||
| 6747 | (kill-region (marker-position regions-begin) | ||
| 6748 | (marker-position region1-end))) | ||
| 6749 | (kill-region (marker-position regions-begin) | ||
| 6750 | (point)) | ||
| 6751 | (set-marker regions-begin nil) | ||
| 6752 | (set-marker region1-end nil))) | ||
| 6728 | 6753 | ||
| 6729 | (defun forward-visible-line (arg) | 6754 | (defun forward-visible-line (arg) |
| 6730 | "Move forward by ARG lines, ignoring currently invisible newlines only. | 6755 | "Move forward by ARG lines, ignoring currently invisible newlines only. |