设置当前 buffer 字体时遇到的问题

我想通过设置 buffer-face-mode-face 的值来修改当前 buffer 的字体,参考了@casouri 大神的方法后解决方案是这样的:

(defvar my-font-alist
  '((sarasa-mono-slab-sc-16 . (:family "Sarasa Mono Slab SC" :size 16))
    (monaco-14              . (:family "Monaco" :size 14)))
  "An alist of all the fonts you can switch.
Key is a symbol as the name, value is a plist specifying the font spec.
More info about spec in `font-spec'.")

(defun my/load-buffer-font (&optional font-name)
  "Prompt for a FONT-NAME and set it for current buffer.
Fonts are specified in `my-font-alist'."
  (interactive (list
                 (completing-read "Choose a font for current buffer: "
                   (mapcar #'car my-font-alist))))
  (let* ((font-name (or font-name my-font))
         (font (apply #'font-spec
                 (if font-name
                     (alist-get (intern font-name) my-font-alist
                       nil nil #'equal)
                   (cdar my-font-alist)))))
    (setq buffer-face-mode-face `(:font ,font))
    (buffer-face-mode +1)))

但是遇到一个问题,也就是新的字体会遵循默认字体的字体大小;即使 monaco 已经设置成了 14 号字体,将当前 buffer 字体设置为 14 号字体的 monaco-14 时还是 16 号字体。

所以我又参考了下 @tumashu 大神的 cnfonts 的做法,(:font (font-spec :family ... :size ...))。不过这个做法的实际作用在我看跟上述效果应该是一致的,结果的确也没什么区别。

想问下大家这种问题该怎么解决呢?

1 个赞

根本没有:size这个face attribute,只有:height,14号是:height 140

File: elisp.info,  Node: Face Attributes,  Next: Defining Faces,  Up: Faces

39.12.1 Face Attributes
-----------------------
...
‘:family’
...
‘:foundry’
...
‘:family’
...
‘:width’
...
‘:height’
...
‘:weight’
...
‘:slant’
...
‘:foreground’
...
‘:distant-foreground’
...
‘:background’
...
‘:underline’
...
‘:overline’
...
‘:strike-through’
...
‘:box’
...
‘:inverse-video’
...
‘:stipple’
...
‘:font’
...
‘:inherit’
...
‘:extend’
...

是的,所以对于 :font 这个属性使用了 font-spec 这个函数。

针对全局修改字体大小能生效,只针对当前 buffer 就无法生效了

不清楚是什么原因

face-remapping-alist 最适合对 buffer local设置单独字体和单独的face。

1 个赞

谢谢,我回家后看一下

(defface vmacs-minibuffer-font
  `((t :inherit default :height 1.2))
  "The default font for minibuffer buffer.
Monospaced font whihc is fixed idth and height is recommended."
  :group 'minibuffer)

(defun vmacs-minibuffer-hook()
  (set (make-local-variable 'buffer-face-mode-face) 'vmacs-minibuffer-font)
  (buffer-face-mode t))

(add-hook 'minibuffer-setup-hook #'vmacs-minibuffer-hook)

我调整minibuffer 的字体大小是这样做的, 不知道有没有参考价值

1 个赞

今天抽空看了看,问题应该是出在设置当前 buffer 字体时会继承 default 的 :height 属性,这样即使设置了字体大小,行高还是不会变。解决办法是获取 :size 值然后乘以十?有什么函数可以做到这一点吗? :rofl:

@Angelaneia 想问下,最适合体现在什么地方呢?是因为这个是用 c 实现的吗?但是用 buffer-face-mode 的话,改变当前 buffer 字体后,想改回原有的 face 只需要关掉 buffer-face-mode 就可以了。

发现了,这玩意不是 buffer-local的,在其他 buffer 使用会影响到之前的结果;如果想要 buffer-local 需要使用 buffer-face-set,感谢指出这么个变量


搞了个非常丑陋的实现,如果有更好的实现方法请告诉我🐶

(defun my/load-buffer-font (&optional font-name)
  "Prompt for a FONT-NAME and set it for current buffer.
Fonts are specified in `my-font-alist'."
  (interactive (list
                 (completing-read "Choose a font for current buffer: "
                   (mapcar #'car my-font-alist))))
  (let* ((font-name (or font-name my-font))
         (font (apply #'font-spec
                 (if font-name
                     (alist-get (intern font-name) my-font-alist
                       nil nil #'equal)
                   (cdar my-font-alist)))))
    (set (make-local-variable 'face-remapping-alist)
      (copy-tree `((default :font ,font :height ,(* 10 (font-get `,font ':size))))))))