From ac9acc1864b02b92de4eb2e98db7b5b0cd03e019 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 10 Feb 2020 02:49:36 +0200 Subject: [PATCH] Use quit-restore-window to close tab (bug#39446) * lisp/tab-bar.el (display-buffer-in-new-tab): New function with code from display-buffer-in-tab. (display-buffer-in-tab): Call display-buffer-in-new-tab. (switch-to-buffer-other-tab): Instead of 'display-buffer-same-window' use '(reusable-frames . t)'. * lisp/windmove.el (windmove-display-in-direction): Set arg 'type' to 'tab' for window--display-buffer when creating a new tab. * lisp/window.el (quit-restore-window): Call tab-bar-close-tab when quit-restore type is 'tab'. (display-buffer-record-window): Set window-parameter 'quit-restore' to 'tab' for type 'tab'. (window--display-buffer): Set window-prev-buffers to nil for tab too. --- lisp/tab-bar.el | 56 ++++++++++++++++++++++++++++++++++++------------ lisp/windmove.el | 25 ++++++++++----------- lisp/window.el | 16 ++++++++++++-- 3 files changed, 69 insertions(+), 28 deletions(-) diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index fac27f41ba9..873f54a27db 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -1467,8 +1467,7 @@ This is an action function for buffer display, see Info node `(elisp) Buffer Display Action Functions'. It should be called only by `display-buffer' or a function directly or indirectly called by the latter." - (let* ((tab-name (alist-get 'tab-name alist)) - (reusable-frames (alist-get 'reusable-frames alist)) + (let* ((reusable-frames (alist-get 'reusable-frames alist)) (reusable-tab (when reusable-frames (tab-bar-get-buffer-tab buffer reusable-frames)))) (if reusable-tab @@ -1480,26 +1479,55 @@ indirectly called by the latter." (tab-bar-select-tab (1+ index))) (when (get-buffer-window buffer frame) (select-window (get-buffer-window buffer frame)))) + (let ((tab-name (alist-get 'tab-name alist))) + (when (functionp tab-name) + (setq tab-name (funcall tab-name buffer alist))) + (if tab-name + (let ((tab-index (tab-bar--tab-index-by-name tab-name))) + (if tab-index + (progn + (tab-bar-select-tab (1+ tab-index)) + (when (get-buffer-window buffer) + (select-window (get-buffer-window buffer)))) + (display-buffer-in-new-tab buffer alist))) + (display-buffer-in-new-tab buffer alist)))))) + +(defun display-buffer-in-new-tab (buffer alist) + "Display BUFFER in a new tab. +ALIST is an association list of action symbols and values. See +Info node `(elisp) Buffer Display Action Alists' for details of +such alists. + +Like `display-buffer-in-tab', but always creates a new tab unconditionally, +without checking if a suitable tab already exists. + +If ALIST contains a `tab-name' entry, it creates a new tab with that name +and displays BUFFER in a new tab. The `tab-name' entry can be a function, +then it is called with two arguments: BUFFER and ALIST, and should return +the tab name. When a `tab-name' entry is omitted, create a new tab without +an explicit name. + +This is an action function for buffer display, see Info +node `(elisp) Buffer Display Action Functions'. It should be +called only by `display-buffer' or a function directly or +indirectly called by the latter." + (let ((tab-bar-new-tab-choice t)) + (tab-bar-new-tab) + (let ((tab-name (alist-get 'tab-name alist))) (when (functionp tab-name) (setq tab-name (funcall tab-name buffer alist))) - (if tab-name - (let ((tab-index (tab-bar--tab-index-by-name tab-name))) - (if tab-index - (tab-bar-select-tab (1+ tab-index)) - (let ((tab-bar-new-tab-choice t)) - (tab-bar-new-tab) - (tab-bar-rename-tab tab-name)))) - (let ((tab-bar-new-tab-choice t)) - (tab-bar-new-tab)))))) + (when tab-name + (tab-bar-rename-tab tab-name))) + (window--display-buffer buffer (selected-window) 'tab alist))) (defun switch-to-buffer-other-tab (buffer-or-name &optional norecord) "Switch to buffer BUFFER-OR-NAME in another tab. Like \\[switch-to-buffer-other-frame] (which see), but creates a new tab." (interactive (list (read-buffer-to-switch "Switch to buffer in other tab: "))) - (display-buffer buffer-or-name '((display-buffer-in-tab - display-buffer-same-window) - (inhibit-same-window . nil)) + (display-buffer buffer-or-name '((display-buffer-in-tab) + (inhibit-same-window . nil) + (reusable-frames . t)) norecord)) (defun find-file-other-tab (filename &optional wildcards) diff --git a/lisp/windmove.el b/lisp/windmove.el index 6e62e161548..40adb49e20f 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -467,18 +467,19 @@ When `switch-to-buffer-obey-display-actions' is non-nil, (minibuffer-depth (minibuffer-depth)) (action (lambda (buffer alist) (unless (> (minibuffer-depth) minibuffer-depth) - (let ((window (cond - ((eq dir 'new-tab) - (let ((tab-bar-new-tab-choice t)) - (tab-bar-new-tab)) - (selected-window)) - ((eq dir 'same-window) - (selected-window)) - (t (window-in-direction - dir nil nil - (and arg (prefix-numeric-value arg)) - windmove-wrap-around)))) - (type 'reuse)) + (let* ((type 'reuse) + (window (cond + ((eq dir 'new-tab) + (let ((tab-bar-new-tab-choice t)) + (tab-bar-new-tab)) + (setq type 'tab) + (selected-window)) + ((eq dir 'same-window) + (selected-window)) + (t (window-in-direction + dir nil nil + (and arg (prefix-numeric-value arg)) + windmove-wrap-around))))) (unless window (setq window (split-window nil nil dir) type 'window)) (setq new-window (window--display-buffer buffer window diff --git a/lisp/window.el b/lisp/window.el index 40c4bf5ad47..bd825c09e16 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -5008,6 +5008,13 @@ nil means to not handle the buffer in a particular way. This prev-buffer))) quad entry) (cond + ((and (not prev-buffer) + (eq (nth 1 quit-restore) 'tab) + (eq (nth 3 quit-restore) buffer)) + (tab-bar-close-tab) + ;; If the previously selected window is still alive, select it. + (when (window-live-p (nth 2 quit-restore)) + (select-window (nth 2 quit-restore)))) ((and (not prev-buffer) (or (eq (nth 1 quit-restore) 'frame) (and (eq (nth 1 quit-restore) 'window) @@ -6367,7 +6374,12 @@ fourth element is BUFFER." ;; WINDOW has been created on a new frame. (set-window-parameter window 'quit-restore - (list 'frame 'frame (selected-window) buffer))))) + (list 'frame 'frame (selected-window) buffer))) + ((eq type 'tab) + ;; WINDOW has been created on a new tab. + (set-window-parameter + window 'quit-restore + (list 'tab 'tab (selected-window) buffer))))) (defcustom display-buffer-function nil "If non-nil, function to call to handle `display-buffer'. @@ -7034,7 +7046,7 @@ Return WINDOW if BUFFER and WINDOW are live." ;; use that. (display-buffer-mark-dedicated (set-window-dedicated-p window display-buffer-mark-dedicated)))) - (when (memq type '(window frame)) + (when (memq type '(window frame tab)) (set-window-prev-buffers window nil)) (let ((quit-restore (window-parameter window 'quit-restore)) (height (cdr (assq 'window-height alist)))