3

I am using tabbar-mode and I love it. I have only one thing which is irritating me: the sorting order of tabs of fired windows.

As in other modes, they seem to be sorted by time opened. But in case of the dired buffers, I would prefer a sorting based on the directory structure, so that lower directories are further left, an directories higher in the directory structure further to the right. As an example, the tabs could be sorted like this:

/ | home | Username | DirectoryInUsernamesHomeDirectory | SecondUsername | ...

I am aware, that it is not possible to project a two-dimensional tree structure into a one dimensional tab-bar, but any logical sorting based on the tree structure would be favourable to a time-of-opening sorting as it is now.

Is there any way (sure there is - but my elisp knowledge is not sufficient to write it) to achieve this? I guess a custom function tab-bar-add-tab needs to be defines as here?

Rainer
  • 897
  • 10
  • 16

1 Answers1

5

Conveniently enough, sorting dired buffers alphabetically (by full path) results in exactly the behaviour you describe. So it turns out to be quite achievable.

Simply add the following snippet to your init file and everything should work.

(require 'tabbar)

(defun tabbar-add-tab (tabset object &optional append)
  "Add to TABSET a tab with value OBJECT if there isn't one there yet.
If the tab is added, it is added at the beginning of the tab list,
unless the optional argument APPEND is non-nil, in which case it is
added at the end."
  (let ((tabs (tabbar-tabs tabset)))
    (if (tabbar-get-tab object tabset)
        tabs
      (let ((tab (tabbar-make-tab object tabset)))
        (tabbar-set-template tabset nil)
        (set tabset
             (if (tabbar-tab-derived-mode-p 'dired-mode tab)
                 (sort (cons tab tabs) #'tabbar-default-directory<)
               (if append
                   (append tabs (list tab))
                 (cons tab tabs))))))))

(defun tabbar-default-directory< (a b)
  "Is the `default-directory' of tab A `string<' than that of B?"
  (string<
   (expand-file-name (buffer-local-value 'default-directory (car a)))
   (expand-file-name (buffer-local-value 'default-directory (car b)))))

(defun tabbar-tab-derived-mode-p (mode tab)
  "Is the major mode of TAB derived from MODE?"
  (with-current-buffer (car tab)
    (derived-mode-p mode)))

All the magic happens on the line (sort (cons tab tabs) #'tabbar-dired<) which sorts the dired tab list whenever a new tab is added.

Malabarba
  • 22,878
  • 6
  • 78
  • 163
  • Perfect - works like a charm. If I want to use the same for other modes, i.g. org-mode files, I assume I have to use (if (tabbar-tab-derived-mode-p 'org-mode tab) - but what do I have to use instead of "#'tabbar-dired<"? – Rainer Sep 25 '14 at 09:37
  • @Rainer _Now that you ask, that was a bad name for the function, so I renamed it._ On your question, do you want to sort your org-mode files in exactly the same way (by the directory structure)? If so, you can use the exact same function. – Malabarba Sep 25 '14 at 09:44
  • 1
    OK - understood - didn't realise it was a function. Thanks again. – Rainer Sep 25 '14 at 09:47
  • 1
    For the record: I replaced `(tabbar-tab-derived-mode-p 'dired-mode tab)` with `(or (tabbar-tab-derived-mode-p 'dired-mode tab) (tabbar-tab-derived-mode-p 'org-mode tab))` to get the same behaviour for org-mode. This can be extended for other modes as well. – Rainer Sep 25 '14 at 10:01