Emacs 30.1 highlight - intuitive tab line
The first Emacs 30.0.91 pretest for what will be the 30.1 release of Emacs was announced on the mailing list a few days ago. I was going through the NEWS file, and found something that I've wanted in Emacs for a while now.
One of the niggles I had with Emacs was its tab behavior. It worked differently from how other applications that I'm used to work (firefox, kitty, etc).
In emacs, tab-per-buffer can be achieved by using the tab-line-mode. But, before now, it had the following problems:
- Since tab-line-mode listed buffers sorted by recently visited, so the order or tabs kept changing
- There was no wrap-around when trying to go to the next tab from the last tab
Here's a video showing the old behavior:
To solve this, there is package called intuitive-tab-line-mode that solves the above two problems. But, I had problems with it because it did not work well with the beframe package that I also use.
Now, with Emacs 30.1, this behavior is what comes out-of-the-box with Emacs. The only config needed is to enable global-tab-line-mode
. And because it's built-in, it works with other modes like beframe.
Here's my config for minimal intuitive per-buffer tabs in Emacs >= 30.0.91:
(use-package tab-line
:demand t
:bind
(("C-<iso-lefttab>" . tab-line-switch-to-prev-tab)
("C-<tab>" . tab-line-switch-to-next-tab))
:config
(global-tab-line-mode 1)
(setq
tab-line-new-button-show nil
tab-line-close-button-show nil))
Here, I've also added keybindings to switch to next/prev tab using C-TAB
and C-S-TAB
keys.
More details about this change can be found in it's bug report mail thread.
Aside: why show buffers as tabs
One of the common questions is the need to show buffers as tabs at all. After all, in a long running Emacs session, there might be hundreds of buffers, and showing all of them as tabs becomes useless.
For me, I find that I usually work on a 2 to 5 buffers for a "purpose" at a time. These might be some files on a project I'm working on, or org-agenda + a couple of org files, or mu4e-main + headers + one or two emails and a reply. When in this mode, I think looking at all of these buffers in the tab bar gives me a good understanding of where I am in the project and makes it easy to switch to the next or previous buffer easily.
I also use frames and beframe to make sure that only a single "project" is showing in a frame at a time. So, even if there are hundreds of buffers in my Emacs session, only a handful are shown as tabs. This makes it useful to me without overwhelming me with too many tabs.
Interactions
👍 10 likes
🔁 5 reposts
Tab is such an incompatible concept with buffers. you would end up with multiple tabs pointing to the same buffers no matter what.
I think multiple tabs can only point to the same buffer if opened in another window or frame, in which case it's not a problem.
Useful for those who use it/want tab line, I suppose. I wonder how many people will try using it now that it's more sensible.
The other alternative is to lean in to the reordering. I set up bindings to select the nth most recent buffer, and modified the display of the tab to have a indication of the binding that will bring it forward. Also I show only up to the most recent, ordered left to right, so the current buffer is always the left-most tab, if that makes sense. I actually sometimes end up using these bindings without even looking when it's one of the top 3 or 4. When I need an older one, I find its tab and bring it forward. It's a nice way to navigate among your most recently visited buffers quickly.
How can I hide a tab by default (e.g. scratch, Message)? Is there an equivalent of intuitive-tab-line-shift-tab-left and intuitive-tab-line-shift-tab-right?
To hide some tabs, you can define a function and set it as
tab-line-tabs-buffer-list-function
.From what I can see, there is no direct equivalent of
intuitive-tab-line-shift-tab-left
and right functions. But, functions for that can be good contributions to the code.There is the
tab-line-mouse-move-tab
function that is used to reorder tab positions using mouse drag and drop.I highly recommend the package tabgo: https://github.com/isamert/tabgo.el. It works as described: "Go to tab, avy style."
Tabgo presents a unified way of navigating among tabs on the tab-line AND the tab-bar. The way to keep many dozens of dozens of buffers under control is to separate your projects by tab-bar tabs. At a level down, tab-line tabs organize your project's buffers.
Thanks for the tip about intuitive-tab-line-mode. I had not heard of it.