From 59126587d419b5f57c79a970919894f6e91b5c91 Mon Sep 17 00:00:00 2001 From: Robert Cochran Date: Mon, 7 Oct 2019 13:41:47 -0700 Subject: [PATCH] Allow tabs to have consistent given names * lisp/tab-bar.el (tab-bar--tab): Pull automatic name information from current tab (tab-bar--current-tab): Pull automatic name information from current tab, or from new optional template argument (tab-bar-select-tab): Pass the target tab as a template when setting current tab (tab-bar-rename-tab, tab-bar-rename-tab-by-name): New functions --- lisp/tab-bar.el | 80 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 14 deletions(-) diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index 91bc589ae2..1a1d5ab2b8 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -301,9 +301,13 @@ tab-bar-make-keymap-1 (let* ((separator (or tab-bar-separator (if window-system " " "|"))) (i 0) (tabs (funcall tab-bar-tabs-function)) - (current-tab-name (assq 'name (assq 'current-tab tabs)))) - (when current-tab-name - (setf (cdr current-tab-name) (funcall tab-bar-tab-name-function))) + (current-tab-name (assq 'name (assq 'current-tab tabs))) + (current-tab-no-auto-name (assq 'no-auto-name (assq 'current-tab tabs)))) + (when (and current-tab-name + current-tab-no-auto-name + (not (cdr current-tab-no-auto-name))) + (setf (cdr current-tab-name) + (funcall tab-bar-tab-name-function))) (append '(keymap (mouse-1 . tab-bar-handle-mouse)) (mapcan @@ -355,16 +359,29 @@ tab-bar-make-keymap-1 (defun tab-bar--tab () - `(tab - (name . ,(funcall tab-bar-tab-name-function)) - (time . ,(time-convert nil 'integer)) - (wc . ,(current-window-configuration)) - (ws . ,(window-state-get - (frame-root-window (selected-frame)) 'writable)))) - -(defun tab-bar--current-tab () - `(current-tab - (name . ,(funcall tab-bar-tab-name-function)))) + (let* ((tab (assq 'current-tab (frame-parameter nil 'tabs))) + (tab-no-auto-name (cdr (assq 'no-auto-name tab)))) + `(tab + (name . ,(if tab-no-auto-name + (cdr (assq 'name tab)) + (funcall tab-bar-tab-name-function))) + (no-auto-name . ,tab-no-auto-name) + (time . ,(time-convert nil 'integer)) + (wc . ,(current-window-configuration)) + (ws . ,(window-state-get + (frame-root-window (selected-frame)) 'writable))))) + +(defun tab-bar--current-tab (&optional tab) + ;; `tab` here is an argument meaning 'use tab as template'. This is + ;; necessary when switching tabs, otherwise the destination tab + ;; inherent the current tab's `no-auto-name` parameter. + (let* ((tab (or tab (assq 'current-tab (frame-parameter nil 'tabs)))) + (tab-no-auto-name (cdr (assq 'no-auto-name tab)))) + `(current-tab + (name . ,(if tab-no-auto-name + (cdr (assq 'name tab)) + (funcall tab-bar-tab-name-function))) + (no-auto-name . ,tab-no-auto-name)))) (defun tab-bar--current-tab-index (&optional tabs) ;; FIXME: could be replaced with 1-liner using seq-position @@ -433,7 +450,7 @@ tab-bar-select-tab (when from-index (setf (nth from-index tabs) from-tab)) - (setf (nth to-index tabs) (tab-bar--current-tab))) + (setf (nth to-index tabs) (tab-bar--current-tab (nth to-index tabs)))) (when tab-bar-mode (force-mode-line-update))))) @@ -587,6 +604,40 @@ tab-close-other (force-mode-line-update) (message "Deleted all other tabs"))))) +(defun tab-bar-rename-tab (name &optional arg) + "Rename the tab specified by its absolute position ARG. +If no ARG is specified, then rename the current tab. +ARG counts from 1. +If NAME is the empty string, then use the automatic name +function `tab-bar-tab-name-function'." + (interactive "sNew name for tab (leave blank for automatic naming): \nP") + (let* ((tabs (tab-bar-tabs)) + (tab-index (if arg + (1- (max 0 (min arg (length tabs)))) + (tab-bar--current-tab-index tabs))) + (tab-to-rename (nth tab-index tabs)) + (tab-no-auto-name (> (length name) 0)) + (tab-new-name (if tab-no-auto-name + name + (funcall tab-bar-tab-name-function)))) + (setf (cdr (assq 'name tab-to-rename)) tab-new-name + (cdr (assq 'no-auto-name tab-to-rename)) tab-no-auto-name + (frame-parameter nil 'tabs) tabs) + (if (tab-bar-mode) + (force-mode-line-update) + (message "Renamed tab to '%s'" tab-new-name)))) + +(defun tab-bar-rename-tab-by-name (tab-name new-name) + "Rename the tab named TAB-NAME. +If NEW-NAME is the empty string, then use the automatic name +function `tab-bar-tab-name-function'." + (interactive (list (completing-read "Rename tab by name: " + (mapcar (lambda (tab) + (cdr (assq 'name tab))) + (tab-bar-tabs))) + (read-from-minibuffer "New name for tab (leave blank for automatic naming): "))) + (tab-bar-rename-tab new-name (tab-bar--tab-index-by-name tab-name))) + ;;; Short aliases @@ -595,6 +646,7 @@ 'tab-close (defalias 'tab-select 'tab-bar-select-tab) (defalias 'tab-next 'tab-bar-switch-to-next-tab) (defalias 'tab-previous 'tab-bar-switch-to-prev-tab) +(defalias 'tab-rename 'tab-bar-rename-tab) (defalias 'tab-list 'tab-bar-list) -- 2.21.0