在工作的十来年内,我使用过各种各样的文本编辑器,从最开始的nodepad以及网页三剑客,到sublime2,sublime3,vim, neovim, atom, vscode, 特别是在使用 vscode 的时候, vim 键盘布局的兼容,加上逐渐丰富的插件系统,使用起来非常的好,可以说是我近年来使用过最好编辑器了。但是随着使用时间的加深,vscode 使用 electron 在我的电脑上也开始出现了隔上一段时间就会出现一次小小的卡顿,最开始的时候还能够忍受,当你的输入被打断的时候,就变得非常的不爽了,然后重新回到了 neovim 编辑器。

Neovim 和 vim 相同,初始仅提供了模态编辑功能,优秀的键盘布局通过练习后会形成一套肌肉记忆,让编辑文本变得更加的有效率,这也是近年来多数商业的编辑器也都支持了vim mode 的原因。

Neovim 支持 lua 来配置,这比之前的vim配置有效率的多,也诞生了不少框架,比如NvChad,有这些框架的支持,最少也不用重新开始配置了,然后就是查询 neovim 的最优插件,tree-sitter 语法支持,lsp 支持,为使用到的语言配置。然后更新,修改配置。然后就是维护这套配置。这无疑会话费大量的时间。

去年五月份的时候,我在github上发现了Helix编辑器项目,当时已经有 10K STAR 了,下载后自己编译了文件,发现编辑器和 vim 非常的类似,仅仅是部分操作有所差别,官方提供了更加现代化的提示,可以说非常的友好,可以看出它融合了很多现代编辑器以及vim插件的特性,这些我们下面再说。

Vim 的操作模式是多数是 动作 --> 对象, 默认情况下除了编辑器下方的动词,你没有任何的提示,需要我们自己来确认需要处理的选择对象。

而 Helix 是 选择操作的对象 --> 动作, 是先要明确要操作的对象,然后才是输入动作,这样在多光标多个选区的时候是非常有效和明确的。Helix 编辑器和 Kakoune 相同是以多光标操作为核心,允许多个选区同时操作的编辑器。而 Vim 则需要通过插件实现多光标模式,所以操作上也有一定的差异。

在使用了 Helix 的几个月内,一定程度上变成了我主要编辑器,因为 Debugger (DAP) 还不成熟,Debug 我还在用 Vscode。下面让我快速的介绍下这款编辑器吧。

Helix 宣称

官方制作组称 Helix 为一款后现代文本模态编辑器。

  • 零配置

    真的不需要任何配置就可以完全使用功能,不过想要好的体验还是需要配置一些快捷键之类的。

  • 受 Neovim 和 Kakoune 启发

    按键布局和动作都有受 vim 的影响,而编辑核心则更加偏向 Kakoune 。

  • 非常的快

    这点还是有保证的,在和 alacritty 配合使用的时候,几乎CPU功耗和内存低的发指。 有的时候 LSP 的关闭速度会导致 hx 关闭的时候要等待lsp服务结束(这个好像已 经异步解决了)。

  • 基于终端的模态编辑

    支持 true-color theme

  • 多光标,多选区
  • vim-style 键盘布局

    官方提供了键盘布局sheet, 有中文文档可以阅读。

  • 内置语言支持 Tree-Sitter

    查看项目的 languages.toml 可以看到支持的语言。

  • LSP支持

    wiki 中可以查询下载需要的 语言服务器

Helix 内置功能

Helix 零配置下提供了大量的 vim 插件实现的功能。

  • Virtual Text 虚拟文本
  • Fuzz File finder,文件选择器,一种文件过滤器
  • Minor modes 微模态
    • Goto Mode: Goto模式,提供了光标操作和lsp跳转操作
    • View Mode, 预览模式下优化了阅读操作体验
    • Match Mode 匹配模式
      • Autopairs / Surround 自动匹配符号对,可以对选区追加,改变包括的符号。
      • Textobject Select,利用 treesitter textobject 快速选择函数,类,段落等文字块。
    • Window Mode 窗口模式,窗口分割,切换,跳转功能。暂时不支持窗口大小的变更。
    • Space Mode 命令映射窗口
    • Popup 弹窗
    • Unimpaired 代码导航
  • LSP (Language Server Protocol) 语言服务
    • Completion 自动不全。
    • Diagnostics 错误提示。
    • Action 服务器提供各种代码重构,纠错功能。
    • File/Workspace symbol 代码结构。
    • Rename symbol 重命名重构语法。
  • Formatter 代码格式化
  • Treesitter
    • Hightlight 语法高亮。
    • Indent 自动缩进。
    • Textobject 文本选择,比如 maf 选择 function
  • Debuger (DAP) 调试机制支持的还是不太好,建议使用cli调试或者其他的编辑器。

    已经有改进的 issues 里程碑计划,后续可能会有更好的调试模式。

  • 多重光标,这个模式下对比vscode和vim,功能完善的非常多。
  • Buffer Manger
  • Git Gutter
  • Indent Guides
  • Themes
  • 其他

Helix 提供了大量的内置功能来达到用户可以开箱使用,而无需在配置和寻求功能上话费大量的时间。但这并不意味着所有的功能都会加入到 helix 本身。插件系统在讨论版(discussions)上置顶,基于性能的嵌入式还是RPC协议以及其他?想要了解的可以移步到插件系统查看讨论。其中也提到了另外一个编辑器 Lapce 使用PSP 协议创建服务器插件。

Lapce 和 Helix 相同,也是使用Rust开发的一款文本 文本编辑器,不同的是 lapce 一开始就走了类似 vscode 的道路,有不错的GUI界面,已经有了 基于 PSP 基于服务器插件协议的插件系统。当前 star 比 helix 要多谢,但是开发者活跃度 和PR 与helix 却有上不少的差距。

我在用功能PR

  • Explorer V3 这个分支已经被 人迭代了3个版本,已经进行了多轮测试,但是核心团队仍没有合并,原因是UI的操作倒退,需要设计更加合理的组件,还有就是核心成员更喜欢使用fuzz。

  • LSP Inlay Hints PR#5934 基于虚拟文本(virtual Text) 利用 LSP 提供的嵌入式提示文本可以在不影响操作和 正确的字符索引处理下提供非常好的代码提示体验。默认情况下支持rust,其他的语言 需要根据各自语言的lsp是否支持 Inlay Hints配置。

    issues#2070 中我有贴出 gopls, lua, typescript 的 Inlay Hints 的配置。

    img

  • Icon 图标系统,图标系统默 认使用 NerdFonts 图标字体, 可以通过自定义 runtime/icons 或者 .config/helix/icons/ 配置文件夹下配置图标主题来实现自定义图标。现在图标支持 bufferline, picker, statusline, 部分 symobl .

现在仍有大量的功能型 PR 提交未合并,相信 22.12 的下一个版本中看到更好的功能。

快速入门

移动命令

移动即选择光标贯穿的选区。

  • h j k l 光标单字符选区移动
  • w e b W E B 光标单词移动选区
  • t f T F 光标移动到匹配字符并选择
  • % 全选,光标会移动到文档最后一个字符
  • x 选择当前行,延伸向下选择行

操作命令

  • d 删除
  • c,C 复制/不复制 修改所选的内容
  • | 执行 shell 命令
  • y 复制内容到寄存器
  • p P 在所选内容 后方|前方 粘贴
  • r 替换
  • ~ 切换大小写
  • J 合并行
  • Ctrl-c 注释切换
  • & 多光标下对齐选择
  • ; 取消选区到光标
  • : 执行命令

insert 插入模式

  • i o a I O A 进入插入模式
  • c 修改选的内容会进入插入模式

多光标

  • C
  • Alt-C

    这里是大写的 C ,实际按键应为 Alt-Shift-c, 其他的也是一样,注意按键 字母的大小写。

  • Alt-s 多行选区中对非空行的末尾追加光标。
  • , 只保留主选区

常用的微模式命令

Space Mode 目录

  • space f 文件选择器
  • space k lsp 提示
  • space w 窗口模式
  • 其他的基本都是常用的 ^_^

Goto Mode 跳转

  • gh 行首 gl 行末
  • gg 首行 ge 末行
  • gc 窗口中间 gt 窗口顶部 gb 窗口中间
  • LSP
    • gd 定义 gy 类型定义 gr 引用 gi 实现
  • ga 上次选择的文件

Match mode 匹配模式

  • ms 用来为选区追加括号引号等符号
  • ma 选择定义选区

Window mode 窗口

space w 或者 ctrl-w 进入模式

  • s 水平底部拆分窗口
  • v 垂直向右拆分窗口
  • q 关闭窗口
  • o 仅保留当前窗口

Unimpaired

] 向下匹配 [ 向上匹配,然后选择

需要 tree-sitter 的 textobject 支持。

  • d diagnostics 错误诊断
  • f function 函数
  • t type definition 类型定义
  • a parameter 参数
  • c comment 注释
  • p paragraph 段落

配置

即使 Helix 在零配置下也可以使用,如果想要更加符合自己的习惯还是需要一些配置。 erasin/helix-config 是我自己正在使用的配置文件。

在 Helix 中,加载配置的顺序是 默认配置 -->> .config/helix/中自定义配置 --> self-project/.helix/ 项目文件夹下自定义配置。在三层配置这种常规设计基本上可以满足各种使用的情况了。

配置文件结构主要有:

  • config.toml <-- 编辑器配置
  • language.toml <-- 语言支持配置
  • themes/ &lt-- 自定义主题
    • self-theme1.toml
  • icons/ &lt-- 自定义图标
    • self-icons.toml

config.toml

配置主要提供 true-color 支持,自定义显示,以及自定义键盘布局。在编辑器器中使用 :set-option 可以看到配置选项,或者阅读官方文档配置。

theme = "onedark"
# icons = "nerd"

# editor 编辑器
[editor]

# 真彩支持
true-color = true
auto-completion = true
# auto-save = false
auto-info = true
# cursorcolumn = true # 光标列高亮
cursorline = true # 光标 行高亮
color-modes = true
idle-timeout = 40
# mouse = true
# scrolloff = 5 # 滚动时上下边缘填充行数
# scroll-lines = 3
# line-number = "relative"  # 行号类型 absolute / relative 
# rulers = [80, 120]   # 标尺

# bufferline = "multiple"  # always | multiple | nerver
# gutters = ["diagnostics", "spacer", "line-numbers", "spacer", "diff"]

[editor.lsp]
display-messages = true # 服务器语言信息提示 
# display-signature-help-docs = false
display-inlay-hints = true # 默认 false 

[editor.whitespace.render]
space = "all"
tab = "all"
newline = "all"

[editor.whitespace.characters]
space = "·"
nbsp = "⍽"
tab = "→"
newline = "⏎"
tabpad = "·"

[editor.soft-wrap]
enable = true
# max-wrap = 20 
# max-indent-retain = 40
# wrap-indicator = "↪ "

# 光标样式
[editor.cursor-shape]
insert = "bar"
normal = "block"
select = "underline"

# 状态栏定义
[editor.statusline]
# [#2869] file-type-icon
left = ["mode", "spacer", "spinner", "spacer", "file-type-icon", "file-name", "file-modification-indicator"]
center = ["diagnostics","workspace-diagnostics"]
right = [ "selections", "position", "position-percentage", "file-encoding", "file-line-ending", "file-type", ]

# 键盘布局
[keys.normal]
# use `li` or remap `after insert`
a = ["move_char_right","insert_mode"]
"C-s" = ":write"  # 原保存跳转列表位置,修改为 C-j
"C-j" = ["save_selection"]
"C-r" = ":reload"
"C-z" = "normal_mode"     # replace suspend
"C-q" = ":quit"
"A-/" = "toggle_comments"
"\\" = ":reflow" # |
"X" = "extend_line_above"
"Z" = { "Z" = [":quit"] }

# macos 自动切换到英文环境
"esc" = [":sh macism com.apple.keylayout.ABC", "normal_mode"]

# space mode
[keys.normal.space]
"x" = ":buffer-close"
"w" = { "r" = ":config-reload" }
"." = "file_picker_in_current_buffer_directory"

[keys.insert]
"esc" = [":sh macism com.apple.keylayout.ABC", "normal_mode"]

# [keys.select]

Helix 提供 keymapcommands 命令, 这些命令在自定义键盘布局中自由组合,命令组会顺序处理。比如 a = ["move_char_right","insert_mode"] Helix 中 a 默认为选区追加, 将其覆盖为字符向后移动一位编辑模式。 详细的请参看 配置文档

自定义语言支持

如果有自定义的特殊语言支持,一种是提交issues到官方项目寻求帮助,另外一种是自己动手处理,具体可以分解以下步骤:

  1. languages.toml 中追加语言和语言的 tree-sitter 实现。
  2. runtime/queries/ 下对语言 hightlights.scm 高亮支持 , textobjects.scm 文本选择支持, indents.scm 缩进支持。
  3. 如果是在 helix 项目中提交代码,需要执行 cargo xtask docgen 来生成文档支持, 自定义的则不需要这一步。
  4. hx -g fetch & hx -g build 会自动拉去配置 tree-sitter 并编译。之后就可以测试了。

结语

如果有 Vim 基础的同学,可以通过上面的简单的介绍,在自己测试的情况下应该能够对 Helix 有基本的了解了。 如果想要更加深入的了解,请移步到官方站点或者Github项目地址。

Helix 现在还不是很完善,但无疑是非常具有潜力的编辑器,活跃的开发社区注定了编辑器会变得更好。