【分享】vscode 风格的 Corfu 图标(通过 kind-icon 使用)

已经从 Company 迁移到 Corfu有一段时间了,对 kind-icon 的默认图标一直不怎么满意。虽然通过 svg-lib 可以从 Templarian/MaterialDesign 下载海量的图标,但要挑选合适对补全进行分类的并不容易,反而是 vscode 的图示显得更好看,更加易于识别。

于是将 company-mode 的图标根据 kind-icon 的 kind-icon-mapping规则重新命名,就可以使用和 company/vscode一样的图标了。 效果如下:

深色主题:

浅色主题:

需要的可以克隆 icons-vscode 这个仓库到 .emacs.d/.cache/svg-lib/icons,然后执行 M-x kind-icon-preview-all 就可看到预览效果。

4 个赞

赞👍🏻 楼主用corfu和company有什么感受分享下?

用下来感觉从以下几点说说:

  1. 由于使用了childframe,界面更加好看。可惜childframe还不支持终端,终端用户要安装corfu-terminal,不过我基本不在终端下用Emacs。用childframe 实现还有个好处是,候选框可以超出窗口外,在候选项比较长时很有用。
  2. 更加方便和orderless配合使用。Company也支持,但不怎么了解。
  3. Corfu支持的后端比Company要少,但我也可以通过 cape 来扩展。
  4. 流畅性方面,Corfu 和 company 一样,我个人主要配合 eglot 用,很顺滑。
  5. Corfu 使用 Tab-and-Go 的方式,感觉更舒服。Company也有Tab-and-Go,但没用过。这是用 Tab 选择候选项,其实这时 orderless 用的少了,2 的优势不明显了。

这是我的 Corfu Tab-and-Go 配置:

提醒下,我这在 Emacs 29 下使用 kind-icon,需要下面的配置调整 margin 或者 height,图标才能正常显示,不然会过小或者显示不全。

(when (eq system-type 'windows-nt)
  (custom-set-variables
   '(kind-icon-default-style
     '(:padding 0 :stroke 0 :margin 0 :radius 0 :height 0.8 :scale 1.0))))

(when (eq system-type 'darwin)
  (custom-set-variables
   '(kind-icon-default-style
     '(:padding 0 :stroke 0 :margin 1.5 :radius 0 :height 2.0 :scale 1.0))))

这么看来两者并没有多大差别。我在GUI下用company-box,也是基于childframe的。自己定制了下显示效果如下:

1 个赞

是的,从普通用户的角度来看 Corfu 确实没多大优势。Company 依然是 Emacs 最成熟的。

如果是高级用户,可能还会看中 Corfu 的另一点是,他的代码比较少,更容易理解。

我用 coofu 只是单纯的喜新厌旧 :rofl:

1 个赞

corfu代码是少, 但是写的很脏, 并不容易理解。

原来是这样,我还没完全去读完 Corfu 的代码,只是之前听子龙说 Corfu 好懂 :smile:

回头有需求再去研究下 Corfu 的源码。

但 Company 实在太长了,我一般就挑感兴趣的去看看。

人之常情。

那只是功能少吧, 我认真读过两边的代码, company 要更清晰点, 当然代码少功能更容易理解是好事情(比如 eglot), 但是 corfu 不是这样的, 大量坐标手动转换代码, 大量逻辑绕过去绕过来 (我今年6月1日阅读代码有感)。

对于 corfu, 我不认为它代码少是一个更优秀的 company 替代品。

1 个赞

确实,从我在三楼列出那几点就看出来了,Corfu 有的 Company 基本基本都有,Company 也流畅。 Corfu 的定位就是一个更加轻量的框架,更多的功能都是仓库目录下的插件中,或者通过其他的包来实现。Company 用的好好的,其实没必要换过来。

我当时是因为在 haskell-mode 的 REPL 中如果有 IO action的话用不了 company-mode,会卡死,但是 Corfu 能用。但是现在 Corfu 也不能用了。2016年的老 Bug,现在都没修复。

corfu 纯粹是因为它是一个新的包, 大家喜新厌旧, 大部分Emacser都喜欢折腾, 所以会觉得 corfu 更好, 我是研究 lsp-bridge 的时候, company和corfu代码都阅读过, 也深入改造过。

我的个人感受是:

  • company也许代码更多, 但是代码更清晰, 代码多有时候不代表臃肿, 而是历史的沉淀, 更稳定

  • corfu 的代码少是因为功能更少, 插件更少, 兼容 capf 的代码都不可能少, 作者README说更简洁更轻量, 我觉得不实, 我反而觉得代码质量一般(相对于 eglot 这种明星项目而言)

有时候corfu快, 可能都只是喜新厌旧带来的错觉, company和corfu的代码性能受 capf 接口封印, 不会有本质的性能差距的。

1 个赞

:smile: 太真实,说不定我哪天玩厌了 Corfu,又会滚回 company。

感谢大佬分享关于 corfu 和 company 的体验。

2 个赞

我也是试用了两次corfu没感觉到任何优势,还是用回了company。我还以为是使用时间太短没有深刻体会到。现在看来,无论从功能、稳定性还是从生态上来讲company还是略胜一筹。唯一遗憾是company-box维护慢了点,但是胜在稳定,到最后就自己优化了,体验基本和vscode一样。尤其是company-box-doc的显示方式费了点心思。暂时就不折腾了。

2 个赞

Corfu在variable-pitch-mode一直存在对齐问题,手动修改corfu-default的face还会出现补全栏与补全项的高度不一致。估计Corfu 代码里有很多hard-coded东西

这个原来是 Emacs 29 在 svg 方面的 bug,现在最新版本的已经修复了。

corfu 比 company 有个优势就是,有人帮它实现了 corfu-teminalcorfu-doc-terminal,对终端用户是件好事。

但 corfu-doc (已合并到 corfu) 有个严重影的问题,就是它采用 *Help* 来渲染文档。除了我在 corfu-doc 已被合并进了 corfu - #6,来自 twlz0ne 提到的问题之外,还会严重拖慢速度。

因为在 *Help* 查看变量的时候,是要把变量值列出来的。当遇到一个超大列表(例如 glboal-mapobarry) 的时候,就会卡住。

1 个赞

company自带的那个原生ui要比 corfu-terminal 健壮。corfu-terminal在 org-indent-mode 开启的时候会出现对齐混乱的问题 (应该是overlay计算的时候要考虑到缩进太多corner case了)。但是company不会有这个问题。但是company的那个原生ui确实没有corfu和corfu-terminal好看。

现在可以通过下面的设置就会自动下载 vscode 的图标了,可以没有直接集成到 kind-icon中。

(setq kind-icon-mapping
      '((array          "a"   :icon "symbol-array"       :face font-lock-type-face              :collection "vscode")
        (boolean        "b"   :icon "symbol-boolean"     :face font-lock-builtin-face           :collection "vscode")
        (color          "#"   :icon "symbol-color"       :face success                          :collection "vscode")
        (command        "cm"  :icon "chevron-right"      :face default                          :collection "vscode")
        (constant       "co"  :icon "symbol-constant"    :face font-lock-constant-face          :collection "vscode")
        (class          "c"   :icon "symbol-class"       :face font-lock-type-face              :collection "vscode")
        (constructor    "cn"  :icon "symbol-method"      :face font-lock-function-name-face     :collection "vscode")
        (enum           "e"   :icon "symbol-enum"        :face font-lock-builtin-face           :collection "vscode")
        (enummember     "em"  :icon "symbol-enum-member" :face font-lock-builtin-face           :collection "vscode")
        (enum-member    "em"  :icon "symbol-enum-member" :face font-lock-builtin-face           :collection "vscode")
        (event          "ev"  :icon "symbol-event"       :face font-lock-warning-face           :collection "vscode")
        (field          "fd"  :icon "symbol-field"       :face font-lock-variable-name-face     :collection "vscode")
        (file           "f"   :icon "symbol-file"        :face font-lock-string-face            :collection "vscode")
        (folder         "d"   :icon "folder"             :face font-lock-doc-face               :collection "vscode")
        (function       "f"   :icon "symbol-method"      :face font-lock-function-name-face     :collection "vscode")
        (interface      "if"  :icon "symbol-interface"   :face font-lock-type-face              :collection "vscode")
        (keyword        "kw"  :icon "symbol-keyword"     :face font-lock-keyword-face           :collection "vscode")
        (macro          "mc"  :icon "lambda"             :face font-lock-keyword-face)
        (magic          "ma"  :icon "lightbulb-autofix"  :face font-lock-builtin-face           :collection "vscode")
        (method         "m"   :icon "symbol-method"      :face font-lock-function-name-face     :collection "vscode")
        (module         "{"   :icon "file-code-outline"  :face font-lock-preprocessor-face)
        (numeric        "nu"  :icon "symbol-numeric"     :face font-lock-builtin-face           :collection "vscode")
        (operator       "op"  :icon "symbol-operator"    :face font-lock-comment-delimiter-face :collection "vscode")
        (param          "pa"  :icon "gear"               :face default                          :collection "vscode")
        (property       "pr"  :icon "symbol-property"    :face font-lock-variable-name-face     :collection "vscode")
        (reference      "rf"  :icon "library"            :face font-lock-variable-name-face     :collection "vscode")
        (snippet        "S"   :icon "symbol-snippet"     :face font-lock-string-face            :collection "vscode")
        (string         "s"   :icon "symbol-string"      :face font-lock-string-face            :collection "vscode")
        (struct         "%"   :icon "symbol-structure"   :face font-lock-variable-name-face     :collection "vscode")
        (text           "tx"  :icon "symbol-key"         :face font-lock-doc-face               :collection "vscode")
        (typeparameter  "tp"  :icon "symbol-parameter"   :face font-lock-type-face              :collection "vscode")
        (type-parameter "tp"  :icon "symbol-parameter"   :face font-lock-type-face              :collection "vscode")
        (unit           "u"   :icon "symbol-ruler"       :face font-lock-constant-face          :collection "vscode")
        (value          "v"   :icon "symbol-enum"        :face font-lock-builtin-face           :collection "vscode")
        (variable       "va"  :icon "symbol-variable"    :face font-lock-variable-name-face     :collection "vscode")
        (t              "."   :icon "question"           :face font-lock-warning-face           :collection "vscode")))

Windows 用户可能还要调整下大小:

(when (eq system-type 'windows-nt)
    (plist-put kind-icon-default-style :height 0.8))

效果:

sanityinc-tomorrow-day ------------------------------ sanityinc-tomorrow-bright

详细见 Wiki:

相关的 issue:

  1. Make svg-lib optional · Issue #13 · jdtsmith/kind-icon · GitHub
  2. VSCode icons support · Issue #27 · rougier/svg-lib · GitHub
1 个赞