mirror of
https://github.com/vale981/apheleia
synced 2025-03-04 09:01:42 -05:00
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>
This commit is contained in:
parent
49701675a8
commit
615b0f5591
2 changed files with 54 additions and 31 deletions
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
(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
|
||||
;; 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))
|
||||
(goto-char (alist-get 'marker command))
|
||||
(pcase (alist-get 'command command)
|
||||
(`addition
|
||||
(insert (alist-get 'text command)))
|
||||
(save-excursion
|
||||
(goto-char (alist-get 'marker command))
|
||||
(insert (alist-get 'text command))))
|
||||
(`deletion
|
||||
(let ((text-start (point)))
|
||||
(save-excursion
|
||||
(goto-char (alist-get 'marker command))
|
||||
(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))))
|
||||
(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)
|
||||
|
|
Loading…
Add table
Reference in a new issue