Skip to content

Commit

Permalink
Preserve marks as well as points (#198)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
SohumB and raxod502 authored Nov 18, 2023
1 parent 4970167 commit 615b0f5
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
82 changes: 51 additions & 31 deletions apheleia-rcs.el
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down

0 comments on commit 615b0f5

Please sign in to comment.