]> git.eshelyaron.com Git - emacs.git/commitdiff
Honor window-switching intents in xref-find-definitions (bug#28814)
authorJoão Távora <joaotavora@gmail.com>
Fri, 13 Oct 2017 14:13:14 +0000 (15:13 +0100)
committerJoão Távora <joaotavora@gmail.com>
Fri, 3 Nov 2017 16:13:35 +0000 (16:13 +0000)
When there is more than one xref to jump to, and an *xref* window
appears to help the user choose, the original intent to open a
definition in another window or frame is remembered when the choice to
go to or show a reference is finally made.

* lisp/progmodes/xref.el (xref--show-pos-in-buf): Rewrite.
(xref--original-window-intent): New variable.
(xref--original-window): Rename from xref--window and move up
here for clarity.
(xref--show-pos-in-buf): Rewrite.  Don't take SELECT arg here.
(xref--show-location): Handle window selection decision here.
(xref--window): Rename to xref--original-window.
(xref-show-location-at-point): Don't attempt window management here.
(xref--show-xrefs): Ensure display-action intent is saved.

lisp/progmodes/xref.el

index 3dbf65ef6f524e7847ea042c42545cd1c9c210d8..ee23bc7a64efb6616e1a018c0264f521a9716b02 100644 (file)
@@ -448,43 +448,68 @@ If SELECT is non-nil, select the target window."
        (when xref-w
          (set-window-dedicated-p xref-w xref-w-dedicated)))))
 
-(defun xref--show-pos-in-buf (pos buf select)
-  (let ((xref-buf (current-buffer))
-        win)
+(defvar-local xref--original-window-intent nil
+  "Original window-switching intent before xref buffer creation.")
+
+(defvar-local xref--original-window nil
+  "The original window this xref buffer was created from.")
+
+(defun xref--show-pos-in-buf (pos buf)
+  "Goto and display position POS of buffer BUF in a window.
+Honor `xref--original-window-intent', run `xref-after-jump-hook'
+and finally return the window."
+  (let* ((xref-buf (current-buffer))
+         (pop-up-frames
+          (or (eq xref--original-window-intent 'frame)
+              pop-up-frames))
+         (action
+          (cond ((memq
+                  xref--original-window-intent
+                  '(window frame))
+                 t)
+                ((and
+                  (window-live-p xref--original-window)
+                  (or (not (window-dedicated-p xref--original-window))
+                      (eq (window-buffer xref--original-window) buf)))
+                 `(,(lambda (buf _alist)
+                      (set-window-buffer xref--original-window buf)
+                      xref--original-window))))))
     (with-selected-window
-        (xref--with-dedicated-window
-         (display-buffer buf))
+        (with-selected-window
+            ;; Just before `display-buffer', place ourselves in the
+            ;; original window to suggest preserving it. Of course, if
+            ;; user has deleted the original window, all bets are off,
+            ;; just use the selected one.
+            (or (and (window-live-p xref--original-window)
+                     xref--original-window)
+                (selected-window))
+          (display-buffer buf action))
       (xref--goto-char pos)
       (run-hooks 'xref-after-jump-hook)
       (let ((buf (current-buffer)))
-        (setq win (selected-window))
         (with-current-buffer xref-buf
-          (setq-local other-window-scroll-buffer buf))))
-    (when select
-      (select-window win))))
+          (setq-local other-window-scroll-buffer buf)))
+      (selected-window))))
 
 (defun xref--show-location (location &optional select)
   (condition-case err
       (let* ((marker (xref-location-marker location))
              (buf (marker-buffer marker)))
-        (xref--show-pos-in-buf marker buf select))
+        (cond (select
+               (select-window (xref--show-pos-in-buf marker buf)))
+              (t
+               (save-selected-window
+                 (xref--with-dedicated-window
+                  (xref--show-pos-in-buf marker buf))))))
     (user-error (message (error-message-string err)))))
 
-(defvar-local xref--window nil
-  "The original window this xref buffer was created from.")
-
 (defun xref-show-location-at-point ()
   "Display the source of xref at point in the appropriate window, if any."
   (interactive)
   (let* ((xref (xref--item-at-point))
          (xref--current-item xref))
     (when xref
-      ;; Try to avoid the window the current xref buffer was
-      ;; originally created from.
-      (if (window-live-p xref--window)
-          (with-selected-window xref--window
-            (xref--show-location (xref-item-location xref)))
-        (xref--show-location (xref-item-location xref))))))
+      (xref--show-location (xref-item-location xref)))))
 
 (defun xref-next-line ()
   "Move to the next xref and display its source in the appropriate window."
@@ -726,7 +751,8 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
         (xref--xref-buffer-mode)
         (pop-to-buffer (current-buffer))
         (goto-char (point-min))
-        (setq xref--window (assoc-default 'window alist))
+        (setq xref--original-window (assoc-default 'window alist)
+              xref--original-window-intent (assoc-default 'display-action alist))
         (current-buffer)))))
 
 \f
@@ -753,7 +779,8 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
    (t
     (xref-push-marker-stack)
     (funcall xref-show-xrefs-function xrefs
-             `((window . ,(selected-window)))))))
+             `((window . ,(selected-window))
+               (display-action . ,display-action))))))
 
 (defun xref--prompt-p (command)
   (or (eq xref-prompt-for-identifier t)