刚刚在 reddit 上看到 Rougier 的 svg-lib 包更新至 0.3 版本 时,突发奇想:是不是能够用 svg 来显示 tab-bar ?于是赶紧实验了一下,发现效果挺不错的:
而且 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 ,可能需要自己适配,详见