aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSohum Banerjea <sohumb@gmail.com>2023-11-18 11:53:07 +1100
committerGitHub <noreply@github.com>2023-11-17 16:53:07 -0800
commit615b0f5591c922292e7c51cafc7bb0d2c8821f07 (patch)
tree36e06523de832c7fbdc91f4e7c0b77163b11929d
parent49701675a8ebff41756c0ff3acd094fa531df5f2 (diff)
Preserve marks as well as points (#198)
Marks are processed in almost exactly the same way as point; in particular going through exactly the same `apheleia--align-point` function. This works with minimal changes because markers act like numbers, but also can be passed to `set-marker` to mutate their state. --------- Co-authored-by: Radon Rosborough <radon@intuitiveexplanations.com>
-rw-r--r--CHANGELOG.md3
-rw-r--r--apheleia-rcs.el82
2 files changed, 54 insertions, 31 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0137b11..9d10a8b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,8 @@ The format is based on [Keep a Changelog].
* Prettier is now enabled in `svelte-mode`.
* More tree-sitter based major modes have been added to
`apheleia-mode-alist` ([#191]).
+* All marks (the current `(mark)`, and the `mark-ring`) are now
+ adjusted, alongside `(point)` ([#197]).
* Built-in formatters now use a new `"apheleia-npx"` built-in script
instead of the legacy `npx` keyword. The effect of the new script is
the same, except that it also works with Yarn PNP projects as well
@@ -104,6 +106,7 @@ The format is based on [Keep a Changelog].
[#182]: https://github.com/radian-software/apheleia/pull/182
[#187]: https://github.com/radian-software/apheleia/pull/187
[#196]: https://github.com/radian-software/apheleia/pull/196
+[#197]: https://github.com/radian-software/apheleia/issues/197
[#208]: https://github.com/radian-software/apheleia/discussions/208
[#209]: https://github.com/radian-software/apheleia/pull/209
[#213]: https://github.com/radian-software/apheleia/pull/213
diff --git a/apheleia-rcs.el b/apheleia-rcs.el
index 914b28d..2e10c12 100644
--- a/apheleia-rcs.el
+++ b/apheleia-rcs.el
@@ -120,12 +120,18 @@ contains the patch."
(apheleia--log
'rcs "Applying RCS patch from %S to %S" patch-buffer content-buffer)
(let ((commands nil)
- (point-list nil)
+ (pos-list nil)
(window-line-list nil))
(with-current-buffer content-buffer
- (push (cons nil (point)) point-list)
+ (push `(:type point :pos ,(point)) pos-list)
+ (when (marker-position (mark-marker))
+ (push `(:type marker :pos ,(mark-marker)) pos-list))
+ (dolist (m mark-ring)
+ (when (marker-position m)
+ (push `(:type marker :pos ,m) pos-list)))
(dolist (w (get-buffer-window-list nil nil t))
- (push (cons w (window-point w)) point-list)
+ (push
+ `(:type window-point :pos ,(window-point w) :window ,w) pos-list)
(push (cons w (count-lines (window-start w) (point)))
window-line-list)))
(with-current-buffer patch-buffer
@@ -173,10 +179,12 @@ contains the patch."
(let ((text-start (alist-get 'marker deletion)))
(forward-line (alist-get 'lines deletion))
(let ((text-end (point)))
- (dolist (entry point-list)
- ;; Check if the (window) point is within the
- ;; replaced region.
- (cl-destructuring-bind (w . p) entry
+ (dolist (pos-spec pos-list)
+ (let ((p (plist-get pos-spec :pos)))
+ ;; Check if the point, or marker, or window
+ ;; point, is within the replaced region.
+ ;; Markers pretend to be numbers, so we can
+ ;; run this in any of the three cases.
(when (and (< text-start p)
(< p text-end))
(let* ((old-text (buffer-substring-no-properties
@@ -191,31 +199,43 @@ contains the patch."
(apheleia--align-point
old-text new-text old-relative-point))))
(goto-char text-start)
- (push `((marker . ,(point-marker))
- (command . set-point)
- (window . ,w)
- (relative-point . ,new-relative-point))
- commands))))))))))))))
+ (push
+ `((command . move-cursor)
+ (cursor . ,pos-spec)
+ (offset . ,(- new-relative-point
+ old-relative-point)))
+ commands))))))))))))))
(with-current-buffer content-buffer
- (let ((move-to nil))
- (save-excursion
- (dolist (command (nreverse commands))
- (goto-char (alist-get 'marker command))
- (pcase (alist-get 'command command)
- (`addition
- (insert (alist-get 'text command)))
- (`deletion
- (let ((text-start (point)))
- (forward-line (alist-get 'lines command))
- (delete-region text-start (point))))
- (`set-point
- (let ((new-point
- (+ (point) (alist-get 'relative-point command))))
- (if-let ((w (alist-get 'window command)))
- (set-window-point w new-point)
- (setq move-to new-point)))))))
- (when move-to
- (goto-char move-to))))
+ ;; We run both `goto-char' and `set-window-point' to offset
+ ;; point and window point, don't want to chance that both
+ ;; changes will stack on top of each other.
+ (let ((orig-point (point)))
+ (dolist (command (nreverse commands))
+ (pcase (alist-get 'command command)
+ (`addition
+ (save-excursion
+ (goto-char (alist-get 'marker command))
+ (insert (alist-get 'text command))))
+ (`deletion
+ (save-excursion
+ (goto-char (alist-get 'marker command))
+ (forward-line (alist-get 'lines command))
+ (delete-region (alist-get 'marker command) (point))))
+ (`move-cursor
+ (let ((cursor (alist-get 'cursor command))
+ (offset (alist-get 'offset command)))
+ (pcase (plist-get cursor :type)
+ (`point
+ (goto-char
+ (+ orig-point offset)))
+ (`marker
+ (set-marker
+ (plist-get cursor :pos)
+ (+ (plist-get cursor :pos) offset)))
+ (`window-point
+ (set-window-point
+ (plist-get cursor :window)
+ (+ orig-point offset))))))))))
;; Restore the scroll position of each window displaying the
;; buffer.
(dolist (entry window-line-list)