【分享】使用 svg 打造更 fancy 的 tab-bar

刚刚在 reddit 上看到 Rougier 的 svg-lib 包更新至 0.3 版本 时,突发奇想:是不是能够用 svg 来显示 tab-bar ?于是赶紧实验了一下,发现效果挺不错的:

Peek 2023-12-31 01-05

而且 tab-bar 本身使用了缓存(tab-bar--auto-width-hash),所以整体性能也没影响多少。

代码很简单 (需要 svg-tag-mode

(defface tab-bar-svg-active
  '((t (:foreground "#a1aeb5")))
  "Tab bar face for selected tab.")

(defface tab-bar-svg-inactive
  '((t (:foreground "#cad7de")))
  "Tab bar face for inactive tabs.")

(defun eli/tab-bar-svg-padding (width string)
  (let* ((style svg-lib-style-default)
         (margin      (plist-get style :margin))
         (txt-char-width  (window-font-width nil 'fixed-pitch))
         (tag-width (- width (* margin txt-char-width)))
         (padding (- (/ tag-width txt-char-width) (length string))))
    padding))

(defun eli/tab-bar-tab-name-with-svg (tab i)
  (let* ((current-p (eq (car tab) 'current-tab))
         (name (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)
                           "")))
         (padding (plist-get svg-lib-style-default :padding))
         (width))
    (when tab-bar-auto-width
      (setq width (/ (frame-inner-width)
                     (length (funcall tab-bar-tabs-function))))
      (when tab-bar-auto-width-min
        (setq width (max width (if (window-system)
                                   (nth 0 tab-bar-auto-width-min)
                                 (nth 1 tab-bar-auto-width-min)))))
      (when tab-bar-auto-width-max
        (setq width (min width (if (window-system)
                                   (nth 0 tab-bar-auto-width-max)
                                 (nth 1 tab-bar-auto-width-max)))))
      (setq padding (eli/tab-bar-svg-padding width name)))
    (propertize
     name
     'display
     (svg-tag-make
      name
      :face (if (eq (car tab) 'current-tab) 'tab-bar-svg-active 'tab-bar-svg-inactive)
      :inverse t :margin 0 :radius 6 :padding padding))))

(setq tab-bar-tab-name-format-function #'eli/tab-bar-tab-name-with-svg)

ps. 对于 svg-tag-mode ,可能需要自己适配,详见

15 个赞

不错! tab-bar的标签如何才能将org-roam 建的文件名的时间标签隐藏?

tab-bar 默认用的是文件或 buffer 名,可以修改 tab-bar-tab-name-function ,自定义一个函数

请教一下,这种svg该怎么改变大小啊?

重新修改了一下方案,应该更通用了。

创建的时候修改 image-scaling-factor

1 个赞