Honor window-switching intents in xref-find-definitions (bug#28814)

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.
This commit is contained in:
João Távora 2017-10-13 15:13:14 +01:00
parent 78e9065e9f
commit 2a973edeac

View file

@ -448,43 +448,68 @@ If SELECT is non-nil, select the target window."
(when xref-w (when xref-w
(set-window-dedicated-p xref-w xref-w-dedicated))))) (set-window-dedicated-p xref-w xref-w-dedicated)))))
(defun xref--show-pos-in-buf (pos buf select) (defvar-local xref--original-window-intent nil
(let ((xref-buf (current-buffer)) "Original window-switching intent before xref buffer creation.")
win)
(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 (with-selected-window
(xref--with-dedicated-window (with-selected-window
(display-buffer buf)) ;; 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) (xref--goto-char pos)
(run-hooks 'xref-after-jump-hook) (run-hooks 'xref-after-jump-hook)
(let ((buf (current-buffer))) (let ((buf (current-buffer)))
(setq win (selected-window))
(with-current-buffer xref-buf (with-current-buffer xref-buf
(setq-local other-window-scroll-buffer buf)))) (setq-local other-window-scroll-buffer buf)))
(when select (selected-window))))
(select-window win))))
(defun xref--show-location (location &optional select) (defun xref--show-location (location &optional select)
(condition-case err (condition-case err
(let* ((marker (xref-location-marker location)) (let* ((marker (xref-location-marker location))
(buf (marker-buffer marker))) (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))))) (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 () (defun xref-show-location-at-point ()
"Display the source of xref at point in the appropriate window, if any." "Display the source of xref at point in the appropriate window, if any."
(interactive) (interactive)
(let* ((xref (xref--item-at-point)) (let* ((xref (xref--item-at-point))
(xref--current-item xref)) (xref--current-item xref))
(when xref (when xref
;; Try to avoid the window the current xref buffer was (xref--show-location (xref-item-location xref)))))
;; 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))))))
(defun xref-next-line () (defun xref-next-line ()
"Move to the next xref and display its source in the appropriate window." "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) (xref--xref-buffer-mode)
(pop-to-buffer (current-buffer)) (pop-to-buffer (current-buffer))
(goto-char (point-min)) (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))))) (current-buffer)))))
@ -753,7 +779,8 @@ Return an alist of the form ((FILENAME . (XREF ...)) ...)."
(t (t
(xref-push-marker-stack) (xref-push-marker-stack)
(funcall xref-show-xrefs-function xrefs (funcall xref-show-xrefs-function xrefs
`((window . ,(selected-window))))))) `((window . ,(selected-window))
(display-action . ,display-action))))))
(defun xref--prompt-p (command) (defun xref--prompt-p (command)
(or (eq xref-prompt-for-identifier t) (or (eq xref-prompt-for-identifier t)