Subject: Re: bug#65734: [BUG] kill-whole-line on folded subtrees [9.6.8 (release_9.6.8-3-g21171d @ /home/w/usr/emacs/0/29/0/lisp/org/)]

From: Stefan Monnier <[email-masked]>
Date: Wed, 19 Jun 2024 10:50:31 -0400

> +  ;; - We need to kill in two steps, because the previous command
> +  ;;   could have been a kill command, in which case the text before
> +  ;;   point needs to be prepended to the current kill ring entry and
> +  ;;   the text after point appended.
> +  ;; - We need to be careful to avoid copying text twice to the kill
> +  ;;   ring in read-only buffers.
> +  ;; - We need to determine the boundaries of visible lines before we
> +  ;;   do the first kill.  Otherwise `after-change-functions' may
> +  ;;   change visibility (bug#65734).
> +  (let (;; The beginning of both regions to kill
> +        (regions-begin (point-marker))
> +        ;; The end of the first region to kill.  Moreover, after
> +        ;; evaluation of the value form, (point) will be the end of
> +        ;; the second region to kill.
> +        (region1-end (cond ((zerop arg)
> +                            (prog1 (save-excursion
> +                                     (forward-visible-line 0)
> +                                     (point-marker))
> +                              (end-of-visible-line)))
> +	                   ((< arg 0)
> +	                    (prog1 (save-excursion
> +                                     (end-of-visible-line)
> +                                     (point-marker))
> +                              (forward-visible-line (1+ arg))
> +	                      (unless (bobp) (backward-char))))
> +	                   (t
> +	                    (prog1 (save-excursion
> +                                     (forward-visible-line 0)
> +                                     (point-marker))
> +	                      (forward-visible-line arg))))))
> +    ;; - Pass the marker positions and not the markers themselves.
> +    ;;   kill-region determines whether to prepend or append to a
> +    ;;   previous kill by checking the direction of the region.  But
> +    ;;   it deletes the content and hence moves the markers before
> +    ;;   that.  That effectively makes every region delimited by
> +    ;;   markers an (empty) forward region.
> +    ;; - Make the first kill-region emit a non-local exit only if the
> +    ;;   second kill-region below would not operate on a non-empty
> +    ;;   region.
> +    (let ((kill-read-only-ok (or kill-read-only-ok
> +                                 (/= regions-begin (point)))))
> +      (kill-region (marker-position regions-begin)
> +                   (marker-position region1-end)))
> +    (kill-region (marker-position regions-begin)
> +                 (point))
> +    (set-marker regions-begin nil)
> +    (set-marker region1-end nil)))

Thanks, that seems sensible.
[ Tho at the same time, it's sad to think such a "trivial" operation
  requires such delicate treatment.  ]

        Stefan