Making the Emacs built-in tab-bar Look Like Vim’s Tab Bar

4.5/5

If you’re an Emacs user who appreciates the appearance of Vim, you might frequently attempt to incorporate some of Vim’s minimalist elements into Emacs. One such element is the color scheme, especially how Emacs built-in tab-bar tabs are displayed.

The Emacs built-in tab-bar feature, which enables users to manage multiple buffers through a visual interface at the top of the Emacs window, is available in Emacs version 27 or higher. In this article, you will discover a function I developed called my-tab-bar-vim-like-colors, designed to modify the appearance of the tab-bar in Emacs to mimic the color scheme of Vim.

This is how the tabs will appear if you execute the function below or add it to your init.el after the theme is loaded. More screenshots below.

The Emacs Lisp (Elisp) code below customizes the appearance of the tab bar and makes sure that its appearance remains consistent with the overall color scheme of the current theme.

;; Description: Making the Emacs Tab Bar Look Like Vim's Tab Bar
;; License: MIT
;; Author: James Cherti
;; URL: https://www.jamescherti.com/emacs-tab-bar-vim-style-colors/

(defun my-tab-bar-vim-name-format-function (tab i)
  "Add a space on the sides of every tab."
  (let ((current-p (eq (car tab) 'current-tab)))
    (propertize
     (concat " "
             (if tab-bar-tab-hints (format "%d " i) "")
             (alist-get 'name tab)
             (or (and tab-bar-close-button-show
                      (not (eq tab-bar-close-button-show
                               (if current-p 'non-selected 'selected)))
                      tab-bar-close-button)
                 "")
             " ")
     'face (funcall tab-bar-tab-face-function tab))))

(defun my-tab-bar-vim-like-colors ()
  "Apply Vim-like color themes to Emacs tab bars."
  (let* ((fallback-light "white")
         (fallback-dark "#333333")
         (bg-default (or (face-attribute 'default :background) fallback-light))
         (fg-default (or (face-attribute 'default :foreground) fallback-dark))
         (bg-modeline-inactive (or (face-attribute 'mode-line-inactive :background)
                                   fallback-dark))
         (fg-modeline-inactive (or (face-attribute 'mode-line-inactive :foreground)
                                   fallback-light))
         (bg-tab-inactive bg-modeline-inactive)
         (fg-tab-inactive fg-modeline-inactive)
         (fg-tab-active fg-default)
         (bg-tab-active bg-default))
    (setq tab-bar-tab-name-format-function #'my-tab-bar-vim-name-format-function)
    (setq tab-bar-format '(tab-bar-format-tabs tab-bar-separator))
    (setq tab-bar-separator "\u200B")  ;; Zero width space to fix color bleeding
    (setq tab-bar-tab-hints nil)  ;; Tab numbers of the left of the label
    (setq tab-bar-new-button-show nil)
    (setq tab-bar-close-button-show nil)
    (setq tab-bar-auto-width nil)
    (custom-set-faces
     ;; The tab bar's appearance
     `(tab-bar
       ((t (:background ,bg-tab-inactive
                        :foreground ,fg-tab-inactive
                        :box (:line-width 3 :color ,bg-tab-inactive :style nil)))))
     ;; Inactive tabs
     `(tab-bar-tab-inactive
       ((t (:background ,bg-tab-inactive
                        :foreground ,fg-tab-inactive
                        :box (:line-width 3 :color ,bg-tab-inactive :style nil)))))
     ;; Active tab
     `(tab-bar-tab
       ((t (:background ,bg-tab-active :foreground ,fg-tab-active
                        :box (:line-width 3 :color ,bg-tab-active :style nil))))))))

;; Customize the appearance of the tab bar
;; Make sure to load your theme using 'load-theme' before
;; calling 'my-tab-bar-vim-like-colors'.
(tab-bar-mode 1)
(my-tab-bar-vim-like-colors)
Code language: Lisp (lisp)

Here are a few more screenshots showing how the Elisp function above adapts Emacs tab-bar colors to any loaded theme:

The above theme is the Tomorrow Night Deepblue Emacs theme

For those who have never used Vim and are curious about the appearance of Vim tabs, here is a screenshot:

Leave a Reply

Your email address will not be published. Required fields are marked *