Helix快速起步
helix-editor 是使用 Rust 编写的编辑器,并且借鉴了 Kakoune 和 neovim 的设计进行开发(主要是Kakoune的设计理念)。
为社么使用helix
对我来说,我一直使用 Vim 来完成 Linux / FreeBSD 上编辑和软件开发工作,但是vim作为上古神器,需要大量的"无谓"投入来实现一个基本的 NeoVim IDE ,而且配置方法繁杂多变,完全偏离了我"只是为了提高编程效率"的初始目标。
另外,虽然 NeoVim IDE 配置已经很简化了,但是一方面要依赖社区不断开发和修复配置方法,另一方面这种特定vim配置工具(方法)对Linux依赖极深,当我迁移到 FreeBSD 开发就遇到了无法完成基本的LSP配置(Mason不支持FreeBSD上clangd配置)。实在没有精力在折腾,所以转向内建支持LSP的Helix,尝试在FreeBSD上新的编辑器体验。
功能
类似vim的模式编辑
多种选择方式
通过
tree-setter
实现智能、增量型的语法高亮和代码编辑器
安装
FreebSD
FreebSD发行版已经提供了Helix,可以通过 pkg
安装:
pkg install helix
使用
配置vim键盘映射(放弃)
Helix虽然借鉴了 Kaboune
和 neovim 设计,但是主要偏向于 Kaboune
。所以默认的键盘模式采用了和 vim
略有差别的快捷键( Migrating from Vim )。由于多年使用vim形成的肌肉记忆,所以我依然希望helix能够采用vim的模式,所以采用 LGUG2Z/helix-vim/config.toml 更改默认配置:
备注
Vim keymap for Helix #4419 的讨论非常有启发: 0atman
提出了值得思考的设计理念:
工具的一致性 而不是片面追求更优雅的特例: 保留 HELIX 的先选择后执行默认设置。但允许为 emacs 和 vim 模式配置原生绑定
他提出理念其实是很好的产品设计理念:
标准化总是胜过技术正确性 : Colemak 和 Dvorak 的打字速度比 Qwerty 键盘快得多,也更符合人体工程学,但是Qwerty使用最广,为了能够保持一致体验,用户会依然选择Qwerty键盘
类似Qwerty键盘的商业案例,如果不作出一点让步,Helix就有可能被淘汰;而提供抵消的vim或emacs模式,可能会拥有1000倍的用户
不过Helix开发者拒绝了这个建议,以及一些用户从其他角度的分析也很有说服力:
Helix的目标是开发更好的编辑器,而不是取代vim/emacs
Helix的内部设计使得采用vim键盘模式会增加大量容易误导的开发工作
虽然vim用户会欢迎这种兼容模式,但是对于不使用vim/emacs的用户,例如 VS Code 和 Jetbrain 的用户,会带来困扰
虽然不能在每个地方都立即使用helix,但是跨平台支持安装,还是很容易确保自己的工作环境中具备相同的开箱即用的helix
有一个用户提到他不依赖vim插件,现在转为使用helix:
拒绝导入vim键盘绑定功能,因为类似vim这样不同的编辑器配置和文档存在严重的碎片化和歧义问题
vim/nvim大量插件存在相互冲突的配置,使得基本用户无所适从
我这个讨论非常有意思,就像拥有无数发行版的Linux和只有一个发行版的FreeBSD:
vim确实浪费了我大量的时间来探索研究如何配置一个可用的 NeoVim IDE 环境,并且眼花缭乱的社区配置充满了歧义和冲突,导致我每隔一段时间配置就要调整和重新研究
有点类似Linux,其实更应该研究统一的内核而不是不同发行版各不相同的包管理和配置差异;对于编辑器,不应该聚焦于程序开发而不是反复配置界面和编辑器功能
我现在更喜欢FreeBSD,就是为了能够更聚焦于核心的开发工作;类似helix,我或许应该尝试全新的编辑器
备注
使用 LGUG2Z/helix-vim/config.toml 和原本的vim还是有细微差别
修改
~/.config/helix/config.toml
:
~/.config/helix/config.toml
[keys.normal]
# Quick iteration on config changes
C-o = ":config-open"
C-r = ":config-reload"
# Some nice Helix stuff
C-h = "select_prev_sibling"
C-j = "shrink_selection"
C-k = "expand_selection"
C-l = "select_next_sibling"
# Personal preference
o = ["open_below", "normal_mode"]
O = ["open_above", "normal_mode"]
# Muscle memory
"{" = ["goto_prev_paragraph", "collapse_selection"]
"}" = ["goto_next_paragraph", "collapse_selection"]
0 = "goto_line_start"
"$" = "goto_line_end"
"^" = "goto_first_nonwhitespace"
G = "goto_file_end"
"%" = "match_brackets"
V = ["select_mode", "extend_to_line_bounds"]
C = ["extend_to_line_end", "yank_main_selection_to_clipboard", "delete_selection", "insert_mode"]
D = ["extend_to_line_end", "yank_main_selection_to_clipboard", "delete_selection"]
S = "surround_add" # Would be nice to be able to do something after this but it isn't chainable
# Clipboards over registers ye ye
x = "delete_selection"
p = ["paste_clipboard_after", "collapse_selection"]
P = ["paste_clipboard_before", "collapse_selection"]
# Would be nice to add ya and yi, but the surround commands can't be chained
Y = ["extend_to_line_end", "yank_main_selection_to_clipboard", "collapse_selection"]
# Uncanny valley stuff, this makes w and b behave as they do Vim
w = ["move_next_word_start", "move_char_right", "collapse_selection"]
W = ["move_next_long_word_start", "move_char_right", "collapse_selection"]
e = ["move_next_word_end", "collapse_selection"]
E = ["move_next_long_word_end", "collapse_selection"]
b = ["move_prev_word_start", "collapse_selection"]
B = ["move_prev_long_word_start", "collapse_selection"]
# If you want to keep the selection-while-moving behaviour of Helix, this two lines will help a lot,
# especially if you find having text remain selected while you have switched to insert or append mode
#
# There is no real difference if you have overridden the commands bound to 'w', 'e' and 'b' like above
# But if you really want to get familiar with the Helix way of selecting-while-moving, comment the
# bindings for 'w', 'e', and 'b' out and leave the bindings for 'i' and 'a' active below. A world of difference!
i = ["insert_mode", "collapse_selection"]
a = ["append_mode", "collapse_selection"]
# Undoing the 'd' + motion commands restores the selection which is annoying
u = ["undo", "collapse_selection"]
# Escape the madness! No more fighting with the cursor! Or with multiple cursors!
esc = ["collapse_selection", "keep_primary_selection"]
# Search for word under cursor
"*" = ["move_char_right", "move_prev_word_start", "move_next_word_end", "search_selection", "search_next"]
"#" = ["move_char_right", "move_prev_word_start", "move_next_word_end", "search_selection", "search_prev"]
# Make j and k behave as they do Vim when soft-wrap is enabled
j = "move_line_down"
k = "move_line_up"
# Extend and select commands that expect a manual input can't be chained
# I've kept d[X] commands here because it's better to at least have the stuff you want to delete
# selected so that it's just a keystroke away to delete
[keys.normal.d]
d = ["extend_to_line_bounds", "yank_main_selection_to_clipboard", "delete_selection"]
t = ["extend_till_char"]
s = ["surround_delete"]
i = ["select_textobject_inner"]
a = ["select_textobject_around"]
j = ["select_mode", "extend_to_line_bounds", "extend_line_below", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"]
down = ["select_mode", "extend_to_line_bounds", "extend_line_below", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"]
k = ["select_mode", "extend_to_line_bounds", "extend_line_above", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"]
up = ["select_mode", "extend_to_line_bounds", "extend_line_above", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"]
G = ["select_mode", "extend_to_line_bounds", "goto_last_line", "extend_to_line_bounds", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"]
w = ["move_next_word_start", "yank_main_selection_to_clipboard", "delete_selection"]
W = ["move_next_long_word_start", "yank_main_selection_to_clipboard", "delete_selection"]
g = { g = ["select_mode", "extend_to_line_bounds", "goto_file_start", "extend_to_line_bounds", "yank_main_selection_to_clipboard", "delete_selection", "normal_mode"] }
[keys.normal.y]
y = ["extend_to_line_bounds", "yank_main_selection_to_clipboard", "normal_mode", "collapse_selection"]
j = ["select_mode", "extend_to_line_bounds", "extend_line_below", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
down = ["select_mode", "extend_to_line_bounds", "extend_line_below", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
k = ["select_mode", "extend_to_line_bounds", "extend_line_above", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
up = ["select_mode", "extend_to_line_bounds", "extend_line_above", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
G = ["select_mode", "extend_to_line_bounds", "goto_last_line", "extend_to_line_bounds", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
w = ["move_next_word_start", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
W = ["move_next_long_word_start", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"]
g = { g = ["select_mode", "extend_to_line_bounds", "goto_file_start", "extend_to_line_bounds", "yank_main_selection_to_clipboard", "collapse_selection", "normal_mode"] }
[keys.insert]
# Escape the madness! No more fighting with the cursor! Or with multiple cursors!
esc = ["collapse_selection", "normal_mode"]
[keys.select]
# Muscle memory
"{" = ["extend_to_line_bounds", "goto_prev_paragraph"]
"}" = ["extend_to_line_bounds", "goto_next_paragraph"]
0 = "goto_line_start"
"$" = "goto_line_end"
"^" = "goto_first_nonwhitespace"
G = "goto_file_end"
D = ["extend_to_line_bounds", "delete_selection", "normal_mode"]
C = ["goto_line_start", "extend_to_line_bounds", "change_selection"]
"%" = "match_brackets"
S = "surround_add" # Basically 99% of what I use vim-surround for
u = ["switch_to_lowercase", "collapse_selection", "normal_mode"]
U = ["switch_to_uppercase", "collapse_selection", "normal_mode"]
# Visual-mode specific muscle memory
i = "select_textobject_inner"
a = "select_textobject_around"
# Some extra binds to allow us to insert/append in select mode because it's nice with multiple cursors
tab = ["insert_mode", "collapse_selection"] # tab is read by most terminal editors as "C-i"
C-a = ["append_mode", "collapse_selection"]
# Make selecting lines in visual mode behave sensibly
k = ["extend_line_up", "extend_to_line_bounds"]
j = ["extend_line_down", "extend_to_line_bounds"]
# Clipboards over registers ye ye
d = ["yank_main_selection_to_clipboard", "delete_selection"]
x = ["yank_main_selection_to_clipboard", "delete_selection"]
y = ["yank_main_selection_to_clipboard", "normal_mode", "flip_selections", "collapse_selection"]
Y = ["extend_to_line_bounds", "yank_main_selection_to_clipboard", "goto_line_start", "collapse_selection", "normal_mode"]
p = "replace_selections_with_clipboard" # No life without this
P = "paste_clipboard_before"
# Escape the madness! No more fighting with the cursor! Or with multiple cursors!
esc = ["collapse_selection", "keep_primary_selection", "normal_mode"]
helix编辑模式
待续...