summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuri Linkov <juri@linkov.net>2020-06-07 02:42:24 +0300
committerJuri Linkov <juri@linkov.net>2020-06-07 02:42:24 +0300
commit788cd6d8b98c0e7750e478ae84e580f29576b5ff (patch)
tree46c566e2e9e89003d4ba2555c3c8e6c56151cdcf
parent7ac79872aed63110c0d26c1e62e1838d6101c9bd (diff)
downloademacs-788cd6d8b98c0e7750e478ae84e580f29576b5ff.tar.gz
The key prefix 'C-x t t' displays next command buffer in a new tab (bug#41691)
* lisp/tab-bar.el (other-tab-prefix): New command. (tab-prefix-map): Bind key 'C-x t t' to other-tab-prefix. * lisp/windmove.el (windmove-display-in-direction): Use display-buffer-override-next-command. * lisp/window.el (display-buffer-override-next-command): New function refactored from windmove-display-in-direction.
-rw-r--r--etc/NEWS4
-rw-r--r--lisp/tab-bar.el20
-rw-r--r--lisp/windmove.el86
-rw-r--r--lisp/window.el41
4 files changed, 97 insertions, 54 deletions
diff --git a/etc/NEWS b/etc/NEWS
index edad5b37d6c..6e94d4a91ba 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -109,6 +109,10 @@ setting the variable 'auto-save-visited-mode' buffer-locally to nil.
* Changes in Specialized Modes and Packages in Emacs 28.1
+** Tab Bars
+
+*** The key prefix 'C-x t t' displays next command buffer in a new tab.
+
** New bindings in occur-mode, 'next-error-no-select' bound to 'n' and
'previous-error-no-select' bound to 'p'.
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 76e7f8c33a2..eb3ad72db43 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -1575,6 +1575,25 @@ Like \\[find-file-other-frame] (which see), but creates a new tab."
value)
(switch-to-buffer-other-tab value))))
+(defun other-tab-prefix ()
+ "Display the buffer of the next command in a new tab.
+The next buffer is the buffer displayed by the next command invoked
+immediately after this command (ignoring reading from the minibuffer).
+Creates a new tab before displaying the buffer, or switches to the tab
+that already contains that buffer.
+When `switch-to-buffer-obey-display-actions' is non-nil,
+`switch-to-buffer' commands are also supported."
+ (interactive)
+ (display-buffer-override-next-command
+ (lambda (buffer alist)
+ (cons (progn
+ (display-buffer-in-tab
+ buffer (append alist '((inhibit-same-window . nil)
+ (reusable-frames . t))))
+ (selected-window))
+ 'tab)))
+ (message "Display next command buffer in a new tab..."))
+
(define-key tab-prefix-map "2" 'tab-new)
(define-key tab-prefix-map "1" 'tab-close-other)
(define-key tab-prefix-map "0" 'tab-close)
@@ -1585,6 +1604,7 @@ Like \\[find-file-other-frame] (which see), but creates a new tab."
(define-key tab-prefix-map "b" 'switch-to-buffer-other-tab)
(define-key tab-prefix-map "f" 'find-file-other-tab)
(define-key tab-prefix-map "\C-f" 'find-file-other-tab)
+(define-key tab-prefix-map "t" 'other-tab-prefix)
(provide 'tab-bar)
diff --git a/lisp/windmove.el b/lisp/windmove.el
index f96383197bd..341c739d924 100644
--- a/lisp/windmove.el
+++ b/lisp/windmove.el
@@ -461,60 +461,38 @@ select the window with a displayed buffer, and the meaning of
the prefix argument is reversed.
When `switch-to-buffer-obey-display-actions' is non-nil,
`switch-to-buffer' commands are also supported."
- (let* ((no-select (xor (consp arg) windmove-display-no-select))
- (old-window (or (minibuffer-selected-window) (selected-window)))
- (new-window)
- (minibuffer-depth (minibuffer-depth))
- (action (lambda (buffer alist)
- (unless (> (minibuffer-depth) minibuffer-depth)
- (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 'new-frame)
- (let* ((params (cdr (assq 'pop-up-frame-parameters alist)))
- (pop-up-frame-alist (append params pop-up-frame-alist))
- (frame (make-frame-on-current-monitor
- pop-up-frame-alist)))
- (unless (cdr (assq 'inhibit-switch-frame alist))
- (window--maybe-raise-frame frame))
- (setq type 'frame)
- (frame-selected-window frame)))
- ((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
- type alist))))))
- (command this-command)
- (clearfun (make-symbol "clear-display-buffer-overriding-action"))
- (exitfun
- (lambda ()
- (setq display-buffer-overriding-action
- (delq action display-buffer-overriding-action))
- (when (window-live-p (if no-select old-window new-window))
- (select-window (if no-select old-window new-window)))
- (remove-hook 'post-command-hook clearfun))))
- (fset clearfun
- (lambda ()
- (unless (or
- ;; Remove the hook immediately
- ;; after exiting the minibuffer.
- (> (minibuffer-depth) minibuffer-depth)
- ;; But don't remove immediately after
- ;; adding the hook by the same command below.
- (eq this-command command))
- (funcall exitfun))))
- (add-hook 'post-command-hook clearfun)
- (push action display-buffer-overriding-action)
- (message "[display-%s]" dir)))
+ (let ((no-select (xor (consp arg) windmove-display-no-select)))
+ (display-buffer-override-next-command
+ (lambda (_buffer alist)
+ (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 'new-frame)
+ (let* ((params (cdr (assq 'pop-up-frame-parameters alist)))
+ (pop-up-frame-alist (append params pop-up-frame-alist))
+ (frame (make-frame-on-current-monitor
+ pop-up-frame-alist)))
+ (unless (cdr (assq 'inhibit-switch-frame alist))
+ (window--maybe-raise-frame frame))
+ (setq type 'frame)
+ (frame-selected-window frame)))
+ ((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))
+ (cons window type)))
+ (lambda (old-window new-window)
+ (when (window-live-p (if no-select old-window new-window))
+ (select-window (if no-select old-window new-window))))))
+ (message "[display-%s]" dir))
;;;###autoload
(defun windmove-display-left (&optional arg)
diff --git a/lisp/window.el b/lisp/window.el
index d658cb81f65..998568e7b82 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -8578,6 +8578,47 @@ documentation for additional customization information."
(interactive
(list (read-buffer-to-switch "Switch to buffer in other frame: ")))
(pop-to-buffer buffer-or-name display-buffer--other-frame-action norecord))
+
+(defun display-buffer-override-next-command (pre-function &optional post-function)
+ "Set `display-buffer-overriding-action' for the next command.
+`pre-function' is called to prepare the window where the buffer should be
+displayed. This function takes two arguments `buffer' and `alist', and
+should return a cons with the displayed window and its type. See the
+meaning of these values in `window--display-buffer'.
+Optional `post-function' is called after the buffer is displayed in the
+window; the function takes two arguments: an old and new window."
+ (let* ((old-window (or (minibuffer-selected-window) (selected-window)))
+ (new-window nil)
+ (minibuffer-depth (minibuffer-depth))
+ (action (lambda (buffer alist)
+ (unless (> (minibuffer-depth) minibuffer-depth)
+ (let* ((ret (funcall pre-function buffer alist))
+ (window (car ret))
+ (type (cdr ret)))
+ (setq new-window (window--display-buffer buffer window
+ type alist))))))
+ (command this-command)
+ (clearfun (make-symbol "clear-display-buffer-overriding-action"))
+ (exitfun
+ (lambda ()
+ (setq display-buffer-overriding-action
+ (delq action display-buffer-overriding-action))
+ (remove-hook 'post-command-hook clearfun)
+ (when (functionp post-function)
+ (funcall post-function old-window new-window)))))
+ (fset clearfun
+ (lambda ()
+ (unless (or
+ ;; Remove the hook immediately
+ ;; after exiting the minibuffer.
+ (> (minibuffer-depth) minibuffer-depth)
+ ;; But don't remove immediately after
+ ;; adding the hook by the same command below.
+ (eq this-command command))
+ (funcall exitfun))))
+ (add-hook 'post-command-hook clearfun)
+ (push action display-buffer-overriding-action)))
+
(defun set-window-text-height (window height)
"Set the height in lines of the text display area of WINDOW to HEIGHT.