diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 76e7f8c33a..dd9d520ed9 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -1575,6 +1575,21 @@ find-file-other-tab value) (switch-to-buffer-other-tab value)))) +(defun other-tab-prefix () + "Display the next buffer 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. +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 (let ((tab-bar-new-tab-choice t)) + (tab-bar-new-tab) + (selected-window)) + '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 +1600,7 @@ tab-prefix-map (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/window.el b/lisp/window.el index d658cb81f6..3f851c86f4 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -10069,6 +10069,46 @@ window--adjust-process-windows (set-process-window-size process (cdr size) (car size)))))))))) (add-hook 'window-configuration-change-hook 'window--adjust-process-windows) + + +(defun display-buffer-override-next-command (action-function &optional exit-function) + "Override `display-buffer-overriding-action' for the next command. +`action-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 type. See argument +meaning in `window--display-buffer'. `exit-function' is called after the +buffer is displayed in the window. The function takes one argument `window'." + (let* ((new-window) + (minibuffer-depth (minibuffer-depth)) + (action (lambda (buffer alist) + (unless (> (minibuffer-depth) minibuffer-depth) + (let* ((ret (funcall action-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)) + (when (functionp exit-function) + (funcall exit-function 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))) + ;; Some of these are in tutorial--default-keys, so update that if you ;; change these. diff --git a/lisp/windmove.el b/lisp/windmove.el index f96383197b..38e3fee83a 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -462,59 +462,38 @@ windmove-display-in-direction 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))) + (old-window (or (minibuffer-selected-window) (selected-window)))) + (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 (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)