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

From: Juri Linkov <[email-masked]>
Date: Thu, 24 Dec 2020 22:19:16 +0200

> There's only one rule: not to make backward-incompatible changes
> without a very good reason.

With further development of the search commands based on xref, more
users perceive it as a grep replacement, that however is not based
on grep mode, so this is a good reason to make xref keybindings more
compatible with grep mode.

> Given the single precedent I found, I'm fine with declaring the
> current binding of TAB obsolete and providing a replacement for it
> ('b'? 'q'?), so that we could replace it in some future version after
> 28, if that is okay with you and Juri.

Thanks, this is surely okay.  So here is the patch that does this.
It binds 'xref-quit-and-goto-xref' to 'C-j' like in icomplete mode:

diff --git a/etc/NEWS b/etc/NEWS
index b155ff9d42..14dba83368 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1820,6 +1820,11 @@ first).
 
 * Incompatible Editing Changes in Emacs 28.1
 
+** In xref, 'TAB' now moves to the next xref instead of quitting *xref* buffer.
+Using 'TAB' / 'S-TAB' key bindings to navigate the search results
+is more in the line with other modes like grep mode.  The command
+'xref-quit-and-goto-xref' is now bound to 'C-j' like in icomplete.
+
 ** In 'nroff-mode', 'center-line' is now bound to 'M-o M-s'.
 The original key binding was 'M-s', which interfered with I-search,
 since the latter uses 'M-s' as a prefix key of the search prefix map.
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index 181f94b0bc..8b48396495 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -585,16 +585,26 @@ xref-show-location-at-point
     (when xref
       (xref--show-location (xref-item-location xref)))))
 
+(defun xref-next-line-no-select ()
+  "Move to the next xref but don't display its source."
+  (interactive)
+  (xref--search-property 'xref-item))
+
 (defun xref-next-line ()
   "Move to the next xref and display its source in the appropriate window."
   (interactive)
-  (xref--search-property 'xref-item)
+  (xref-next-line-no-select)
   (xref-show-location-at-point))
 
+(defun xref-prev-line-no-select ()
+  "Move to the previous xref but don't display its source."
+  (interactive)
+  (xref--search-property 'xref-item t))
+
 (defun xref-prev-line ()
   "Move to the previous xref and display its source in the appropriate window."
   (interactive)
-  (xref--search-property 'xref-item t)
+  (xref-prev-line-no-select)
   (xref-show-location-at-point))
 
 (defun xref-next-group ()
@@ -765,7 +775,9 @@ xref--xref-buffer-mode-map
     (define-key map (kbd "P") #'xref-prev-group)
     (define-key map (kbd "r") #'xref-query-replace-in-results)
     (define-key map (kbd "RET") #'xref-goto-xref)
-    (define-key map (kbd "TAB")  #'xref-quit-and-goto-xref)
+    (define-key map (kbd "C-j")  #'xref-quit-and-goto-xref)
+    (define-key map "\t" 'xref-next-line-no-select) ; like compilation-next-error
+    (define-key map [backtab] 'xref-prev-line-no-select) ; like compilation-previous-error
     (define-key map (kbd "C-o") #'xref-show-location-at-point)
     ;; suggested by Johan Claesson "to further reduce finger movement":
     (define-key map (kbd ".") #'xref-next-line)