From 74c008ed2c8ad7bbf03a12c76cb091199388ee1e Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Sun, 27 Nov 2022 00:12:31 +0000 Subject: paredit-kill: Sprinkle some comments. No functional change intended. Comments are incomplete but maybe better than what was there before. --- paredit.el | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/paredit.el b/paredit.el index ea14a15..60420df 100644 --- a/paredit.el +++ b/paredit.el @@ -1572,16 +1572,17 @@ In that case, ensure there is at least one space between the eol (point))))))) -;;; Please do not try to understand this code unless you have a VERY -;;; good reason to do so. I gave up trying to figure it out well -;;; enough to explain it, long ago. +;;; Move to the end of the last S-expression that started on this line, +;;; or to the closing delimiter if the last S-expression in this list +;;; and the closing delimiter both lie on this line. Return true if +;;; the closing delimiter of this list is on this line, false if not. +;;; +;;; beginning is (point), and eol is (point-at-eol). Handling of +;;; `kill-whole-line' is trick, and probably kind of broken. (defun paredit-forward-sexps-to-kill (beginning eol) - (let ((end-of-list-p nil) - (firstp t)) - ;; Move to the end of the last S-expression that started on this - ;; line, or to the closing delimiter if the last S-expression in - ;; this list is on the line. + (let ((end-of-list-p nil) ;Have we hit a closing delimiter on this line? + (firstp t)) ;Is this still the first line? (catch 'return (while t ;; This and the `kill-whole-line' business below fix a bug that @@ -1590,26 +1591,57 @@ In that case, ensure there is at least one space between the ;; bizarre fix that I ought to document at some point, but I am ;; too busy at the moment to do so. (if (and kill-whole-line (eobp)) (throw 'return nil)) + ;; See if we can move forward, and stay on an S-expression that + ;; started on this line. (save-excursion (paredit-handle-sexp-errors (forward-sexp) + ;; Can't move forward -- we must have hit the end of a + ;; list. Stop here, but record whether the closing + ;; delimiter occurred on the starting line. (up-list) (setq end-of-list-p (eq (point-at-eol) eol)) (throw 'return nil)) - (if (or (and (not firstp) + ;; We can move forward. Where did we move to? Stop if: + ;; + ;; (a) we hit the end of the buffer in certain circumstances + ;; (XXX why are these circumstances? necessary according + ;; to tests, need explanation), because forward-sexp + ;; didn't/won't make any progress and we'll get stuck in + ;; a loop; or + ;; + ;; (b) the S-expression we moved to the end to actually + ;; started on line after where we started so it's not + ;; under our jurisdiction. + (if (or (and (not firstp) ;(a) (not kill-whole-line) (eobp)) - (paredit-handle-sexp-errors + (paredit-handle-sexp-errors ;(b) (progn (backward-sexp) nil) t) (not (eq (point-at-eol) eol))) (throw 'return nil))) + ;; Determined we can and should move forward. Do so. (forward-sexp) + ;; In certain other circumstances (XXX need explanation), if we + ;; hit the end of the buffer, stop here; otherwise the next + ;; forward-sexp will fail to make progress and we might get + ;; stuck in a loop. (if (and firstp (not kill-whole-line) (eobp)) (throw 'return nil)) + ;; We have made it past one S-expression. (setq firstp nil))) end-of-list-p)) + +;;; Handle the actual kill when `kill-whole-line' is enabled. +;;; +;;; XXX This has various broken edge cases (see the xfails in test.el) +;;; and it doesn't make paredit-kill/yank a noop on round-trip, in an +;;; attempt to avoid inadvertently joining S-expressions when it +;;; deletes the newline. It could use some input and logic from a user +;;; who relies on `kill-whole-line' and has a better sense of +;;; expectations. (defun paredit-kill-sexps-on-whole-line (beginning) (kill-region beginning -- cgit v1.2.1