feat(lib): sudo-{find,this}-file: invoke save-place

After switching to the sudo-ed tramp buffer, this restores the point and
scroll position of the window to match the source buffer.

I exploit save-place here instead of simply saving/restoring (point)
and (window-start), because I believe it's better UX that save-place
treat the two buffers as effectively the same now and in the future, and
record the last cursor position equally between them, even if the
implementation is messier. This *could* be generalized into an advice
for save-place-find-file-hook and save-place-to-alist, but that's an
experiment for another day.

This is an experimental implementation and may change later.

Close: #7181
Co-authored-by: YourFin <YourFin@users.noreply.github.com>
This commit is contained in:
Henrik Lissner 2024-04-05 18:07:45 -04:00
parent cf6d44d82d
commit f18603e66a
No known key found for this signature in database
GPG Key ID: B60957CA074D39A3

View File

@ -484,17 +484,50 @@ If FORCE-P, overwrite the destination file if it exists, without confirmation."
file))))
;;;###autoload
(defun doom/sudo-find-file (file)
"Open FILE as root."
(interactive "FOpen file as root: ")
;; HACK: Disable auto-save in temporary tramp buffers because it could trigger
;; processes that hang silently in the background, making those buffers
;; inoperable for the rest of that session (Tramp caches them).
(let ((auto-save-default nil)
;; REVIEW: use only these when we drop 28 support
(remote-file-name-inhibit-auto-save t)
(remote-file-name-inhibit-auto-save-visited t))
(find-file (doom--sudo-file-path (expand-file-name file)))))
(defun doom/sudo-find-file (file &optional arg)
"Open FILE as root.
This will prompt you to save the current buffer, unless prefix ARG is given, in
which case it will save it without prompting."
(interactive
(list (read-file-name "Open file as root: ")
current-prefix-arg))
;; HACK: Teach `save-place' to treat the new "remote" buffer as if it were
;; visiting the same local file (because it is), and preserve the cursor
;; position as usual.
(letf! ((defun remote-local-name (path)
(if path (or (file-remote-p path 'localname) path)))
(defmacro with-local-name (&rest body)
`(when save-place-mode
(let ((buffer-file-name (remote-local-name buffer-file-name))
(default-directory (remote-local-name default-directory)))
,@body))))
(let ((window-start (window-start))
(buffer (current-buffer)))
(when (and buffer-file-name (file-equal-p buffer-file-name file))
(when (buffer-modified-p)
(save-some-buffers arg (lambda () (eq (current-buffer) buffer))))
(with-local-name (save-place-to-alist)))
(prog1
;; HACK: Disable auto-save in temporary tramp buffers because it could
;; trigger processes that hang silently in the background, making
;; those buffers inoperable for the rest of that session (Tramp
;; caches them).
(let ((auto-save-default nil)
;; REVIEW: use only these when we drop 28 support
(remote-file-name-inhibit-auto-save t)
(remote-file-name-inhibit-auto-save-visited t)
;; Prevent redundant work
save-place-mode)
(find-file (doom--sudo-file-path (expand-file-name file))))
;; Record of the cursor's old position if it isn't at BOB (indicating
;; this buffer was already open), in case the user wishes to go to it.
(unless (bobp)
(doom-set-jump-h)
;; save-place-find-file-hook requires point be a BOB to do its thang.
(goto-char (point-min)))
(with-local-name (save-place-find-file-hook))
(set-window-start nil window-start)))))
;;;###autoload
(defun doom/sudo-this-file ()