summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--paredit.el52
1 files 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