参照 all-the-icons.el 写一个扩展:nerd-icons.el

:point_right: GitHub - twlz0ne/nerd-icons.el

缘起:

代码主要来自 All The Icons,字体用的是 Hack Nerd Fonts,终端和 GUI 兼顾。

(我之前还有个 nerd-fonts.el 扩展,是用来输入 icon 符号的,相当于速查表,功能跟现在这个还是有差异的,就让它继续存在了。)


我自己也还没开始用(之前也没用过 All The Icons :joy:),所以功能上难免会有出入,目前只是用测试代码简单覆盖一下几个接口:

  • test-nerd-insert
  • test-nerd-icons-icon-for-file
  • test-nerd-icons-icon-for-mode
  • test-nerd-icons-icon-for-buffer
  • test-nerd-icons-icon-for-buffer
  • test-nerd-icons-icon-for-dir
  • test-nerd-icons-icon-for-url
  • test-nerd-icons-icon-for-weather

已经添加的大部分 Icon 是批量转的,我没有逐一去核对。其中最坑爹的是 Material Design Icons 字体,两个项目分别用了 google 版和社区版,完全对不上:

不确定的 Icon 只能先留空(\xff)了,待以后慢慢补充。

7 个赞

老兄动作很快啊,我本地试试看。这个包只支持 Hack Nerd Fonts 吗?其他 nerd fonts 不行么?

如果换其它字体,需要在 nerd-icons-data.el 文件里的重设 icon 映射关系,接口函数可以通用。

Hack Nerd Fonts 用的是社区版的 Material Design Icons,感觉不如 google 版的美观和醒目,比如3D旋转图标:

mdi-3d-rotation-community 社区版 Icons_-_Material_Design google 版

社区版的要放很大才能看出箭头是立体的

其他 nerd fonts 的映射都不一样吗?不一样就有点麻烦了。

Material icons 没有研究过社区版和 google 版,all-the-icons内置的是哪个版本呢?google 版会不会有 license 问题啊

刚试用了下,接口很方便,但是是有些字体显示不正常:(Hack nerd font 已经安装)

其它 nerd fonts 我没试过,如果他们用的是同一套打包脚本,那么码表应该是一致的,可能 Icon 的样式设计会有所不同。

all-the-icons 用的是 google 版本的 mdi,跟社区版的不仅样式不同,映射也是不一样的,找不到对应关系 -_-!

23_PM

我这边也是,最后呈现的 family 依旧是 Noto。是不是存在优先级的问题?我对 GUI 字体的配置不熟。

这个确实有优先级问题。如果编码一样就会有冲突。之前看过一篇文章介绍,但一时找不到了。我记得@tumashu 研究过,

另外,发现两错误:

if: Unable to find icon with name ‘terminal’ in icon set ‘fileicon’
Invalid face attribute :family Hack\ Nerd\ Font
if: Unable to find icon with name ‘lisp’ in icon set ‘fileicon’
Invalid face attribute :family Hack\ Nerd\ Font

少了些 icon,family 也不知道怎么设置

是 GUI 字体 fallback 顺序出了问题,但我不知道该怎么设置 :sweat_smile:

写了个最小配置,字体设置只有以下一行,强制 \xf963 这个字符使用 Nerd Fonts,效果就出来了:

(set-fontset-font t '#xf963 "Hack Nerd Font")

03_AM

还是终端省心啊

终于破案了:

  ;; set english
  (set-face-attribute 'default frame :font ...)
  
  ;; set cjk
  (dolist (charset '(kana han symbol cjk-misc bopomofo))
    (set-fontset-font (frame-parameter nil 'font) charset
                      (font-spec :family ...)))
  
  ;; set emoji
  (set-fontset-font t 'unicode
                    (font-spec :family ...) nil 'prepend)
  
  ;; set nerd fonts
- (set-fontset-font t 'unicode
+ (set-fontset-font nil 'unicode
                  (font-spec :family ...) nil 'prepend)

符号顺序在前,汉字也不受影响:

31_AM

Good! 我正准备给你回这个解决方案。但是这个似乎会影响英文字体设置。

还有一个问题,nerd-icons-icon-spec 中都是从all-the-icons 移植过来的对吧?很多 icon 不存在,可能得清理下。nerd-icons-auto-mode-match? 函数也不存在,需要加上。

现在是这效果(还是有很多\377)

的确,我改的是当前 frame 的字体,但是我是在终端改,然后启动 GUI 检验,所以一时没有察觉到英文字体的变化。如果直接在 GUI 里面改,就可以立即看到变化了😅

那么应该怎么写才正确,符号字体应该 prepend/append 到哪个字符集?

奇怪,我这里用这两个都是正确的

(set-fontset-font t 'unicode "Hack Nerd Font")
(set-fontset-font t 'unicode "Hack Nerd Font" nil 'prepend)

我把在我电脑上显示异常的区段(正好是连续的)找出来了,保持以前的字体配置不变,末尾加上这句就正常了:

(set-fontset-font nil (cons #xf900  ;; mdi-pig
                            #xfa6d) ;; mdi-view-dashboard
                  "Hack Nerd Font")

头两个参数用t 和 nil呢?不一定非要指定字符区间

在我电脑上,t 无效,nil 如果不指定区间会覆盖英文字体

Good!这样最可靠了。我用的是这个没有问题:(set-fontset-font t (cons #xf900 #xfa6d) "Hack Nerd Font")

另外,我提交了一个 PR,你 review 下?

还有一些 icons 缺失或者不匹配,等我慢慢测试。这个\377 怎么处理呢?

\377 就是目前还没找到对应图标的(代码里写的是 "\xff"),主要集中在 material。在 weather 中也有一些,例如 moon-* 这些图标,应该是 all-the-icons 自定义的一些别名。

处理这些“缺失”的图标:

  1. 找到替代。主要是 mdi(material),两个版本虽然很多图标的名称不一样(比如前面提到的 3D 旋转图标,google 版的叫 rotate-3d,社区版的叫 3d-rotation),设计也有点差别,但还是可以通用的,只是要花时间逐一检视。

    weather 集合里也有一系列名称 moon-* 开头的月相图标,应该是 all-the-icons 自定义的别名,找到并不困难。

  2. 移除。确实找不到替代,又不打算自行扩展 nerd fonts,就只能移除了。

  3. 观望。空白图标先留着,等待 nerd fonts 支持 google 版 mdi:Consideration of other fonts · Issue #300 · ryanoasis/nerd-fonts · GitHub

明白了,\377 可以再观望观望。 刚才看了下nerd-icons-data.el,里面有 fileicon 的定义,而nerd-fonts好像并不包含 fileicon。

fileicon 这部分需要讨论一下。

all-the-icons 里面有个单独的 all-the-icons-alist,算是个杂集,里面也放了一些作者自定义的图标。我把它取消了,代码中一些用到 alltheicons 的都改为 fileicon,不知是否合适。

fileicon 目前也是比较缺的,需要从其它集合中挑选。

对,all-the-icons-icon-alist 是一个集合,创建了一个文件名和图标之间的映射表。这个主要是用于all-the-icons-icon-for-bufferall-the-icons-icon-for-file,可以根据文件名自动提取出相应文件类型的 icon。

fileicon是一个单独的字体,这里你是想保留吗?把alltheicons归到fileicon也没问题,就是重新选择图标并创建映射关系。这样fileicon就需要按照all-the-icons的方式挑选图标。还有一个方案就是完全去掉fileicon,用真正的字体去映射。

还有一个需要优化的是,需要加上memorize 优化性能。

我不知道你是怎么插入字符编码的,想提 PR 不知如何下手。