]> git.eshelyaron.com Git - emacs.git/commitdiff
New keymap tab-line-mode-map and new tab order on tab-line (bug#69993)
authorJuri Linkov <juri@linkov.net>
Wed, 17 Apr 2024 17:55:45 +0000 (20:55 +0300)
committerEshel Yaron <me@eshelyaron.com>
Sat, 20 Apr 2024 11:03:47 +0000 (14:03 +0300)
* lisp/tab-line.el (tab-line-new-button-functions): New variable.
(tab-line-tabs-function): Change the default value from
'tab-line-tabs-window-buffers' to the new option
'tab-line-tabs-fixed-window-buffers'.
(tab-line-tabs-buffer-group-sort-function): Change the default
value from nil to 'tab-line-tabs-buffer-group-sort-by-name'.
(tab-line-tabs-buffer-group-sort-by-name): New function.
(tab-line-tabs-fixed-window-buffers): New function.
(tab-line-format-template): Use 'tab-line-new-button-functions'.
(tab-line-mode-map, tab-line-switch-repeat-map): New keymaps.

(cherry picked from commit 230eecf12a688f87354ed2d360a7dfcd7e2dae6a)

etc/NEWS
lisp/tab-line.el

index d88314ddd3fc4140c615c42fbc369b6a4d860e4a..0c454d671dc3f429d2ddc91fd66783bb9554fe49 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -349,11 +349,33 @@ By default it contains a keybinding 'C-TAB' to switch tabs,
 but only when 'C-TAB' is not bound globally.  You can unbind it
 if it conflicts with 'C-TAB' in other modes.
 
+---
+*** New keymap 'tab-line-mode-map'.
+By default it contains keybindings for switching tabs:
+'C-x <left>', 'C-x <right>', 'C-x C-<left>', 'C-x C-<right>'.
+You can unbind them if you want to use these keys for the
+commands 'previous-buffer' and 'next-buffer'.
+
+---
+*** Default list of tabs is changed to support a fixed order.
+This means that the new default tabs function
+'tab-line-tabs-fixed-window-buffers' is like the previous
+'tab-line-tabs-window-buffers' where both of them show
+only buffers that were previously displayed in the window.
+But the difference is that the new function always keeps
+the original order of buffers on the tab line, even after
+switching between these buffers.
+
 ---
 *** New user option 'tab-line-tabs-buffer-group-function'.
 It provides two choices to group tab buffers by major mode
 and by project name.
 
+---
+*** Now buffers on group tabs are sorted alphabetically.
+This will keep the fixed order of tabs, even after
+switching between them.
+
 +++
 ** New optional argument for modifying directory-local variables.
 The commands 'add-dir-local-variable', 'delete-dir-local-variable' and
index 48272b7b4b38faab928bdffa722644003d6ddf67..090815017058b4475de49f3f71d239b204be43a1 100644 (file)
@@ -210,6 +210,11 @@ If the value is a function, call it with no arguments."
               'help-echo "Click to add tab")
   "Button for creating a new tab.")
 
+(defvar tab-line-new-button-functions
+  '(tab-line-tabs-window-buffers
+    tab-line-tabs-fixed-window-buffers)
+  "Functions of `tab-line-tabs-function' for which to show a new button.")
+
 (defcustom tab-line-close-button-show t
   "Defines where to show the close tab button.
 If t, show the close tab button on all tabs.
@@ -333,18 +338,21 @@ If truncated, append ellipsis per `tab-line-tab-name-ellipsis'."
                   'help-echo tab-name))))
 
 \f
-(defcustom tab-line-tabs-function #'tab-line-tabs-window-buffers
+(defcustom tab-line-tabs-function #'tab-line-tabs-fixed-window-buffers
   "Function to get a list of tabs to display in the tab line.
 This function should return either a list of buffers whose names will
 be displayed, or just a list of strings to display in the tab line.
-By default, use function `tab-line-tabs-window-buffers' that
-returns a list of buffers associated with the selected window.
+By default, use function `tab-line-tabs-fixed-window-buffers' that
+returns a list of buffers associated with the selected window where
+buffers always keep the original order after switching buffers.
 When `tab-line-tabs-mode-buffers', return a list of buffers
 with the same major mode as the current buffer.
 When `tab-line-tabs-buffer-groups', return a list of buffers
 grouped by `tab-line-tabs-buffer-group-function'."
   :type '(choice (const :tag "Window buffers"
                         tab-line-tabs-window-buffers)
+                 (const :tag "Window buffers with fixed order"
+                        tab-line-tabs-fixed-window-buffers)
                  (const :tag "Same mode buffers"
                         tab-line-tabs-mode-buffers)
                  (const :tag "Grouped buffers"
@@ -400,9 +408,13 @@ as a group name."
   :group 'tab-line
   :version "30.1")
 
-(defvar tab-line-tabs-buffer-group-sort-function nil
+(defvar tab-line-tabs-buffer-group-sort-function
+  #'tab-line-tabs-buffer-group-sort-by-name
   "Function to sort buffers in a group.")
 
+(defun tab-line-tabs-buffer-group-sort-by-name (a b)
+  (string< (buffer-name a) (buffer-name b)))
+
 (defvar tab-line-tabs-buffer-groups-sort-function #'string<
   "Function to sort group names.")
 
@@ -515,6 +527,21 @@ variable `tab-line-tabs-function'."
             (list buffer)
             next-buffers)))
 
+(defun tab-line-tabs-fixed-window-buffers ()
+  "Like `tab-line-tabs-window-buffers' but keep stable sorting order.
+This means that switching to a buffer previously shown in the same
+window will keep the same order of tabs that was before switching.
+And newly displayed buffers are added to the end of the tab line."
+  (let* ((old-buffers (window-parameter nil 'tab-line-fixed-window-buffers))
+         (new-buffers (sort (tab-line-tabs-window-buffers)
+                            (lambda (a b)
+                              (< (or (seq-position old-buffers a)
+                                     most-positive-fixnum)
+                                 (or (seq-position old-buffers b)
+                                     most-positive-fixnum))))))
+    (set-window-parameter nil 'tab-line-fixed-window-buffers new-buffers)
+    new-buffers))
+
 \f
 (defcustom tab-line-tab-name-format-function #'tab-line-tab-name-format-default
   "Function to format a tab name.
@@ -599,7 +626,7 @@ This is used by `tab-line-format'."
                tab-line-right-button)))
      (if hscroll (nthcdr (truncate hscroll) strings) strings)
      (list separator)
-     (when (and (eq tab-line-tabs-function #'tab-line-tabs-window-buffers)
+     (when (and (memq tab-line-tabs-function tab-line-new-button-functions)
                 tab-line-new-button-show
                 tab-line-new-button)
        (list tab-line-new-button)))))
@@ -940,7 +967,7 @@ buffers, which effectively hides the buffer's tab from the tab line.
 If `kill-buffer', kills the tab's buffer.
 When a function, it is called with the tab as its argument.
 This option is useful when `tab-line-tabs-function' has the value
-`tab-line-tabs-window-buffers'."
+`tab-line-tabs-window-buffers' or `tab-line-tabs-fixed-window-buffers'."
   :type '(choice (const :tag "Bury buffer" bury-buffer)
                  (const :tag "Kill buffer" kill-buffer)
                  (function :tag "Function"))
@@ -1033,6 +1060,19 @@ However, return the correct mouse position list if EVENT is a
       (event-start event)))
 
 \f
+(defvar-keymap tab-line-mode-map
+  :doc "Keymap for keys of `tab-line-mode'."
+  "C-x <left>"    #'tab-line-switch-to-prev-tab
+  "C-x C-<left>"  #'tab-line-switch-to-prev-tab
+  "C-x <right>"   #'tab-line-switch-to-next-tab
+  "C-x C-<right>" #'tab-line-switch-to-next-tab)
+
+(defvar-keymap tab-line-switch-repeat-map
+  :doc "Keymap to repeat tab/buffer cycling.  Used in `repeat-mode'."
+  :repeat t
+  "<left>"  #'tab-line-switch-to-prev-tab
+  "<right>" #'tab-line-switch-to-next-tab)
+
 ;;;###autoload
 (define-minor-mode tab-line-mode
   "Toggle display of tab line in the windows displaying the current buffer."