From d07ed6dfee9338b0d715f8181703252c99e5133a Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Wed, 10 Mar 2021 20:09:23 +0200 Subject: [PATCH] * lisp/tab-bar.el (tab-bar-close-group-tabs): New command. (tab-close-group): New alias. (tab-bar-close-other-tabs): Rewrite to fix old bug where regardless of the returned value from tab-bar-tab-prevent-close-functions, only one tab was retained. --- etc/NEWS | 1 + lisp/tab-bar.el | 48 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index b5ee78893ce..b48f7c36167 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -542,6 +542,7 @@ It also supports a negative argument. --- *** 'C-x t G' assigns a group name to the tab. +'tab-close-group' can close all tabs that belong to the selected group. --- *** New user option 'tab-bar-tab-name-format-function'. diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index bc89a114228..66f8ccae472 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -1148,22 +1148,25 @@ for the last tab on a frame is determined by "Close all tabs on the selected frame, except the selected one." (interactive) (let* ((tabs (funcall tab-bar-tabs-function)) - (current-index (tab-bar--current-tab-index tabs))) - (when current-index - (dotimes (index (length tabs)) - (unless (or (eq index current-index) + (current-index (tab-bar--current-tab-index tabs)) + (current-tab (and current-index (nth current-index tabs))) + (index 0)) + (when current-tab + (dolist (tab tabs) + (unless (or (eq tab current-tab) (run-hook-with-args-until-success - 'tab-bar-tab-prevent-close-functions - (nth index tabs) + 'tab-bar-tab-prevent-close-functions tab ;; `last-tab-p' logically can't ever be true ;; if we make it this far nil)) (push `((frame . ,(selected-frame)) (index . ,index) - (tab . ,(nth index tabs))) + (tab . ,tab)) tab-bar-closed-tabs) - (run-hook-with-args 'tab-bar-tab-pre-close-functions (nth index tabs) nil))) - (set-frame-parameter nil 'tabs (list (nth current-index tabs))) + (run-hook-with-args 'tab-bar-tab-pre-close-functions tab nil) + (setq tabs (delq tab tabs))) + (setq index (1+ index))) + (set-frame-parameter nil 'tabs tabs) ;; Recalculate tab-bar-lines and update frames (tab-bar--update-tab-bar-lines) @@ -1277,6 +1280,32 @@ If GROUP-NAME is the empty string, then remove the tab from any group." (unless tab-bar-mode (message "Set tab group to '%s'" group-new-name)))) +(defun tab-bar-close-group-tabs (group-name) + "Close all tabs that belong to GROUP-NAME on the selected frame." + (interactive + (let* ((tabs (funcall tab-bar-tabs-function)) + (tab-index (1+ (tab-bar--current-tab-index tabs))) + (group-name (alist-get 'group (nth (1- tab-index) tabs)))) + (list (completing-read + "Close all tabs with group name: " + (delete-dups (delq nil (cons group-name + (mapcar (lambda (tab) + (alist-get 'group tab)) + (funcall tab-bar-tabs-function))))))))) + (let* ((close-group (and (> (length group-name) 0) group-name)) + (tab-bar-tab-prevent-close-functions + (cons (lambda (tab _last-tab-p) + (not (equal (alist-get 'group tab) close-group))) + tab-bar-tab-prevent-close-functions))) + (tab-bar-close-other-tabs) + + (let* ((tabs (funcall tab-bar-tabs-function)) + (current-index (tab-bar--current-tab-index tabs)) + (current-tab (and current-index (nth current-index tabs)))) + (when (and current-tab (equal (alist-get 'group current-tab) + close-group)) + (tab-bar-close-tab))))) + ;;; Tab history mode @@ -1807,6 +1836,7 @@ When `switch-to-buffer-obey-display-actions' is non-nil, (defalias 'tab-duplicate 'tab-bar-duplicate-tab) (defalias 'tab-close 'tab-bar-close-tab) (defalias 'tab-close-other 'tab-bar-close-other-tabs) +(defalias 'tab-close-group 'tab-bar-close-group-tabs) (defalias 'tab-undo 'tab-bar-undo-close-tab) (defalias 'tab-select 'tab-bar-select-tab) (defalias 'tab-switch 'tab-bar-switch-to-tab) -- 2.39.2