bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#69578: 30.0.50; tab-bar-mode binding of (control tab) not always use


From: Juri Linkov
Subject: bug#69578: 30.0.50; tab-bar-mode binding of (control tab) not always useful
Date: Mon, 11 Mar 2024 19:50:20 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/30.0.50 (x86_64-pc-linux-gnu)

>> So, maybe these bindings should not be done?
>
> Too late for that now, but they should definitely be done in a way that
> users can customize, without having to advice tab-bar--define-keys (and
> tab-bar--undefine-keys).

Thanks for bringing up this issue.  Customization of keys was not supported
since no once asked for it, I guess because tab-bar--define-keys
respected the existing global keybindings before defining own.
But indeed this doesn't work for local keymaps.

> Maybe by using a mode map?  If there is some reason this cannot be
> done, then maybe a "dummy keymap" could be used?  (User could then
> manipulate the fake tab-bar-mode-map like any keymap, but the bindings
> it contains would then somehow be "transplanted" into the global map
> by tab-bar--define-keys.)

Just adding a simple mode map completely makes it customizable
since 'define-minor-mode' is able to pick it by naming convention:

  (defvar tab-bar-mode-map
    (let ((map (make-sparse-keymap)))
      (define-key map [(control tab)] #'tab-next)
      (define-key map [(control shift tab)] #'tab-previous)
      (define-key map [(control shift iso-lefttab)] #'tab-previous)
      map)
    "Tab Bar mode map.")

The rest of complexity in the following patch comes
from the need to address the customization of
'tab-bar-select-tab-modifiers'.

There is a slight backward incompatibility for users who have own
global keybindings for C-TAB.  They will need to unbind these keys
in the new map.  Then this change should be announced in NEWS:
diff --git a/etc/NEWS b/etc/NEWS
index 19cd170e5c7..0aab2d04ca2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -285,6 +285,11 @@ selected or deselected at the end of executing the current 
command.
 
 ** Tab Bars and Tab Lines
 
+---
+*** New keymap 'tab-bar-mode-map'.
+If you have global keybinding for 'C-TAB', then you might want
+to unbind the same keybinding in 'tab-bar-mode-map'.
+
 ---
 *** New user option 'tab-bar-tab-name-format-functions'.
 It can be used to add, remove and reorder functions that change
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 61efa332e0b..07470f072e1 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -104,10 +104,11 @@ tab-bar-select-tab-modifiers
               (const alt))
   :initialize #'custom-initialize-default
   :set (lambda (sym val)
+         (when tab-bar-mode
+           (tab-bar--undefine-keys))
          (set-default sym val)
          ;; Reenable the tab-bar with new keybindings
          (when tab-bar-mode
-           (tab-bar--undefine-keys)
            (tab-bar--define-keys)))
   :group 'tab-bar
   :version "27.1")
@@ -115,21 +116,17 @@ tab-bar-select-tab-modifiers
 (defun tab-bar--define-keys ()
   "Install key bindings to switch between tabs if so configured."
   (when tab-bar-select-tab-modifiers
-    (global-set-key (vector (append tab-bar-select-tab-modifiers (list ?0)))
-                    #'tab-recent)
+    (define-key tab-bar-mode-map
+                (vector (append tab-bar-select-tab-modifiers (list ?0)))
+                #'tab-recent)
     (dotimes (i 8)
-      (global-set-key (vector (append tab-bar-select-tab-modifiers
-                                      (list (+ i 1 ?0))))
-                      #'tab-bar-select-tab))
-    (global-set-key (vector (append tab-bar-select-tab-modifiers (list ?9)))
-                    #'tab-last))
-  ;; Don't override user customized key bindings
-  (unless (global-key-binding [(control tab)])
-    (global-set-key [(control tab)] #'tab-next))
-  (unless (global-key-binding [(control shift tab)])
-    (global-set-key [(control shift tab)] #'tab-previous))
-  (unless (global-key-binding [(control shift iso-lefttab)])
-    (global-set-key [(control shift iso-lefttab)] #'tab-previous))
+      (define-key tab-bar-mode-map
+                  (vector (append tab-bar-select-tab-modifiers
+                                  (list (+ i 1 ?0))))
+                  #'tab-bar-select-tab))
+    (define-key tab-bar-mode-map
+                (vector (append tab-bar-select-tab-modifiers (list ?9)))
+                #'tab-last))
 
   ;; Replace default value with a condition that supports displaying
   ;; global-mode-string in the tab bar instead of the mode line.
@@ -144,12 +141,18 @@ tab-bar--define-keys
 
 (defun tab-bar--undefine-keys ()
   "Uninstall key bindings previously bound by `tab-bar--define-keys'."
-  (when (eq (global-key-binding [(control tab)]) 'tab-next)
-    (global-unset-key [(control tab)]))
-  (when (eq (global-key-binding [(control shift tab)]) 'tab-previous)
-    (global-unset-key [(control shift tab)]))
-  (when (eq (global-key-binding [(control shift iso-lefttab)]) 'tab-previous)
-    (global-unset-key [(control shift iso-lefttab)])))
+  (when tab-bar-select-tab-modifiers
+    (define-key tab-bar-mode-map
+                (vector (append tab-bar-select-tab-modifiers (list ?0)))
+                nil)
+    (dotimes (i 8)
+      (define-key tab-bar-mode-map
+                  (vector (append tab-bar-select-tab-modifiers
+                                  (list (+ i 1 ?0))))
+                  nil))
+    (define-key tab-bar-mode-map
+                (vector (append tab-bar-select-tab-modifiers (list ?9)))
+                nil)))
 
 (defun tab-bar--load-buttons ()
   "Load the icons for the tab buttons."
@@ -239,6 +242,14 @@ tab-bar--update-tab-bar-lines
                       (if (and tab-bar-mode (eq tab-bar-show t)) 1 0))
                 (assq-delete-all 'tab-bar-lines default-frame-alist)))))
 
+(defvar tab-bar-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [(control tab)] #'tab-next)
+    (define-key map [(control shift tab)] #'tab-previous)
+    (define-key map [(control shift iso-lefttab)] #'tab-previous)
+    map)
+  "Tab Bar mode map.")
+
 (define-minor-mode tab-bar-mode
   "Toggle the tab bar in all graphical frames (Tab Bar mode)."
   :global t

reply via email to

[Prev in Thread] Current Thread [Next in Thread]