Beautifying the Tab Bar

Screenshot of stylized tab bar

Emacs 27.1 introduced a tab bar and I finally got around to trying it out. I found it particularly useful for switching between a few buffers quickly, particularly because I have muscle memory for the Safari tab keybindings (which I set for Emacs tabs).

I must say, the implementation is really nice. Ultimately customizable (a la everything Emacs). It also has some nice interactions with the mouse (if that’s your jam). You can use drag-and-drop to change tab ordering!

Basic Key Bindings

This was the first thing I setup, especially since I knew exactly what I wanted. These mirror Safari’s tab keybindings.

(global-set-key (kbd "s-{") 'tab-bar-switch-to-prev-tab)
(global-set-key (kbd "s-}") 'tab-bar-switch-to-next-tab)
(global-set-key (kbd "s-t") 'tab-bar-new-tab)
(global-set-key (kbd "s-w") 'tab-bar-close-tab)

The s- prefix key is the “command ⌘” key on a Mac.

I think s-w is set to kill-emacs or delete-frame something similar by default. I personally never want that to happen so I’ve had those functions and keybinding disabled for years now. I also had s-{ and s-} bound to switch between frames (other-frame), but I usually use the Emacs GUI in full screen mode, so using these for tabs makes more sense. At least for right now.

Settings

Of course, the tab bar comes with a bunch of customizable settings. I’m using:

(when (< 26 emacs-major-version)
 (tab-bar-mode 1)                           ;; enable tab bar
 (setq tab-bar-show 1)                      ;; hide bar if <= 1 tabs open
 (setq tab-bar-close-button-show nil)       ;; hide tab close / X button
 (setq tab-bar-new-tab-choice "*dashboard*");; buffer to show in new tabs
 (setq tab-bar-tab-hints t)                 ;; show tab numbers
  (setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator)))
                                            ;; elements to include in bar

The when clause wrapping these settings ensures my configuration is maximally compatible with all modern Emacs versions. I figured out these settings through a combination of looking at the *Customize* menu for Tab Bar and reading the help documentation for each variable.

One setting I really like (but am not using right now), is the ability to have a “Menu” button in the tab bar. This is achieved by adding tab-bar-format-menu-bar at the beginning of the tab-bar-format value list.

Theme

I worked really hard on my modeline and I can reuse all that styling! This is the snippet from my personal dusk theme1:

;; modeline settings
'(mode-line ((t (:underline nil :overline nil :box (:line-width 8 :color "#353644" :style nil) :foreground "white" :background "#353644"))))
'(mode-line-buffer-id ((t (:weight bold))))
'(mode-line-emphasis ((t (:weight bold))))
'(mode-line-highlight ((((class color) (min-colors 88)) (:box (:line-width 2 :color "grey40" :style released-button))) (t (:inherit (highlight)))))
'(mode-line-inactive ((t (:weight light :underline nil :overline nil :box (:line-width 8 :color "#565063" :style nil) :foreground "white" :background "#565063" :inherit (mode-line)))))
;; tab bar settings
'(tab-bar ((t (:inherit mode-line))))
'(tab-bar-tab ((t (:inherit mode-line :foreground "white"))))
'(tab-bar-tab-inactive ((t (:inherit mode-line-inactive :foreground "black"))))

Binding the Tab Hint Numbers

I have a pretty wonky keybinding setup, where I create my own minor mode key map and use that by default (as recommended by this stackexchange post). Here I use (setq mac-command-modifier 'super).

The tab bar documentation indicates that to enable pressing ⌘-1 (or s-1 as Emacs sees it) to switch to tab number 1 I would need:

(setq tab-bar-select-tab-modifiers "super")

But this didn’t work for me. Instead, I bound each super-number combination (s-1 through s-0) to tab-bar-select-tab and it works!

Final Comments

As I mentioned above, the tab bar implementation is really nice. This reflects the high standards that the Emacs community and developers have, especially for anything that becomes built in. I was able to do all of this implementation and blogging while flying back from a semi-vacation in Greece (where I spent a lot of time improving my blog, if you didn’t notice). An editor with completely built-in documentation and an interface for configuring / customizing is really, really pleasant. Not needing the internet to do something productive feels increasingly rare.

Footnotes

1 Back when I wrote about package cl being deprecated, I noted that the way I define my theme was outdated. I finally got around to modernizing it, but never wrote about the process. I’m not sure a blog post would be useful, since I’m guessing most readers use existing theme packages. I did start with the customize-create-theme function, which made the process of porting my old color-theme definition to the modern customize format trivial.

You can view my theme in my dotfiles GitHub repo.


Comments

Comments are sent directly to me and may or may not be posted for display on this page.