Subject: Re: bug#44611: Prefix arg for xref-goto-xref

From: Juri Linkov <[email-masked]>
Date: Fri, 11 Dec 2020 11:30:25 +0200

>>>> Like e.g. 'quit-window' allows using a prefix argument
>>>> to change its behavior by relying on (interactive "P"),
>>>> xref-goto-xref should do the same:
>>>
>>> The proposed change is not quite the same (bury instead of kill), but if it
>>> really helps, go ahead.
>> I don't know how important would be to kill *xref* instead of burying.
>
> Indeed, probably not at all important. I'm just saying the parallel seems
> very rough.
>
> Which might or might not be important from the standpoint of trying to
> unify different behaviors in Emacs, to make them more "regular".

What do you think about adding a prefix arg 'KILL' to xref-pop-marker-stack
that would behave exactly like the same arg 'KILL' in quit-window?

This is very useful when there is a need to quickly peek with 'M-.',
and to kill the temporary buffer when going back with 'C-u M-,'.

Here is the implementation:

diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 6e99e9d8ac..1bfd7be154 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -401,17 +401,23 @@ xref-push-marker-stack
   (ring-insert xref--marker-ring (or m (point-marker))))
 
 ;;;###autoload
-(defun xref-pop-marker-stack ()
-  "Pop back to where \\[xref-find-definitions] was last invoked."
-  (interactive)
+(defun xref-pop-marker-stack (&optional kill)
+  "Pop back to where \\[xref-find-definitions] was last invoked.
+With prefix argument KILL non-nil, kill the previous buffer instead of
+burying it."
+  (interactive "P")
   (let ((ring xref--marker-ring))
     (when (ring-empty-p ring)
       (user-error "Marker stack is empty"))
-    (let ((marker (ring-remove ring 0)))
-      (switch-to-buffer (or (marker-buffer marker)
-                            (user-error "The marked buffer has been deleted")))
+    (let* ((marker (ring-remove ring 0))
+           (new-buffer (or (marker-buffer marker)
+                           (user-error "The marked buffer has been deleted")))
+           (old-buffer (current-buffer)))
+      (switch-to-buffer new-buffer)
       (goto-char (marker-position marker))
       (set-marker marker nil nil)
+      (when (and kill (not (eq old-buffer new-buffer)))
+        (kill-buffer old-buffer))
       (run-hooks 'xref-after-return-hook))))
 
 (defvar xref--current-item nil)