关于modal editing

使用emacs以来,我一直都是把caps_lock键映射成ctrl,这么用貌似也不错。

但是最近有一股转换到modal editing 的冲动,各位如何看待modal editing?主要是我觉得现在用modifiers组合键的方式不太优雅,有时候还要同时按shift和alt。

希望网友们可以分享下自己用的modal editing方案,以及对各种插件的兼容性;或者聊聊对modal editing 的看法。

1 个赞

重度 vim/evil 用户 + 重度 meow keypad 用户

这俩也不冲突哇~我的 evil insert 模式下会全用 emacs 快捷键,normal 下再用 evil 快捷键

我还在使用一个自己修改过的god-mode,这个是属于比较轻量级的方案了,好处是不需要记忆额外的快捷键。

自己maintain 的话好处可以加自己喜欢的功能(比如我有sticky modifier,按了G之后默认的modifier就变成 C-M- )坏处是我在这上面花的时间远远超过用它省的时间 :person_shrugging:

1 个赞

借这个帖子 介绍下 最近两周 在deepseek 的帮助下 撸的 helixel , 功能还不完善,只包含了基本的编辑功能(包括 texobj surround “.” repeat register ),与各种mode 的集成 还没时间做。 代曾经用过 evil/meow/meep ,借鉴了其中一些觉得还不错的功能,下面要介绍的 几个特点自我感觉还不错。

helixel-mode — Emacs 上的 Helix 风格模态编辑

Emacs 实现 Helix 先选后操作范式。选几个突出优点介绍。

安装

(use-package helixel
  :vc (:url "https://github.com/jixiuf/helixel-mode")
  :config (helixel-mode))

目前 0 依赖 (有1个可选的evil-textobj-tree-sitter 依赖 用于textobj 支持 tree-sitter) 下载后直接可以体验,keybinding 基本是vim 那套 大同小异

emacs -Q -L . -l helixel.el --eval '(helixel-mode)' 

下面提一下觉得还不错的几处用法:

主要特点

1. Session Mark(;helixel-action-cycle

; 把 mark 设回到当前移动序列的起点,一眼看到你从哪过来的。不同操作类型独立维护 session,不会互相干扰。 连续相同类别的movement 视为一个session,此处的 “;” 及 C-i C-o 的 helixel-jump-backward helixel-jump-forward 都可以自定义 哪些类型的命令会被考虑。

(defcustom helixel-action-cycle-categories
  '(movement textobj search find-char edit)

(defcustom helixel-jump-cycle-categories
  '(movement textobj search find-char edit goto user jump)

w w         ← 前进两个词
;           ← mark 回到 w w 起点,看到选区覆盖来的路径 (注意是 mark 移动,不是point 移动,point 移动的在 `C-i` `C-o` 上。

j j         ← 下移两行
;           ← 回到 j j 起点(不是上面 w w 的起点!)
;           ← 再按一次,回到 w w 起点

C-u ;       ← 反方向回跳
C-g         ← 取消当前 session,下次操作用新 session

包括 /  f F t T  search find 相关的 都支持此种方式快速选中 的选中
比如 fx n n n 查找"x" ,3 次 next 后 ";" 直接将 执行f时的起始位置到当前光标的位置选中。
search 也是一样。 

2. Dot-Repeat(.)支持丰富前缀

不只是 3.. 支持多种前缀。搜索触发的编辑自动前进到下一匹配,手感格外流畅。

/foo<RET>      ← 搜索 foo
cbar<ESC>      ← 改成 bar
.              ← 下一个 foo 也改成 bar
.              ← 再下一个
3.             ← 接下来 3 个一起改
0.             ← 剩余所有匹配全部改掉(沿搜索方向)
C-u - 3 .      ← 反方向改 3 个
C-u .          ← 整个 buffer 从头发改完

/$<RET>    搜索行尾
afoo<ESC> 在行尾添加 foo (这里只是演示 支持  $ ^ 这样搜索后插入。
.       repeat insert foo at next line

还有一个 ‘,’ (helixel-repeat-selection) 如果你不确定下一个 “.” 会 repeat 哪个,可以先 用","选中它 ,然后再 “.”

非搜索场景也行操作自动前进,如:

x              ← 选中当前行
>   > >      ← 缩进 3次
.              ← 下一行自动缩进3次
.              ← 再下一行
3.             ← 接下来 3 行

x             select line
ihello<ESC>   insert "hello" at bol
.             insert "hello" on next line (auto-advance)
.             insert "hello" on next line

x x       select two line
ahello<ESC>   每两行在末尾添加hello


3. Search & Repeat 历史共用

/ 搜索和 f/F/t/T 查字符的历史环是共用的。C-u n 弹出列表 /foo/f→x 混排,选哪个执行哪个。

fb             ← 找下一个 b
n              ← 再找下一个 b
N              ← 反向找上一个 b
n              ← 继续反向找

/hello<RET>    ← 搜索 hello
n              ← 下一个
N              ← 反向
C-u n          ← 弹出历史,可看到前面 fb 和 /hello/ 混在一起,选一条执行

4. Swap 位置感知交换(S

选一段文本 y 复制,再选另一段 S,两者交换——不只是粘贴到目标、删除源文本,而是真正的两端位置感知交换。

基本用法

vw y           ← 选一个词,复制(自动标记为 swap source)
vw             ← 选另一个词
S              ← 两者交换

隐含选区:没选文本时按 S,根据 swap source 的维度自动推算目标:字符级按同列宽、行级按同行数、矩形按同行列。

x x x y        ← 选 3 行,复制
(移动到别处)
S              ← 从当前行起,隐含选 3 行,交换

跨 buffer 交换:在两个 buffer 各选一段,y 在一边复制,切换到另一边 S,交换完成。源 buffer 中的文本被目标文本原位替换。

矩形交换:矩形选区逐行交换,自动跳过每行首尾公共字符保留对齐。

C-v 选矩形 → y → 另选一个矩形 → S
C-u S          ← 行数不同时截短到 min(N,M),而非扩展

4. 其他亮点

  • Surround 零输入识别m d/m r 从前一个 text object 自动获知括号还是引号,无需再输字符。

  • C-o/C-i 跨 buffer 跳转:每次移动、编辑、搜索自动记点,跳到其它 buffer 也能原路返回。

  • 扩写简单helixel-define-command 一行宏出带 session + dot-repeat 的新命令;helixel-define-regex-textobj 一行定义正则块选区;tree-sitter text object 也支持。


欢迎试用、提 issue 和 PR!

3 个赞

我曾是十多年 Vim 用户,转 Emacs 后就放弃了模态编辑,改用 Emacs 原生键位。我不用模态编辑,有以下几点理由:

  1. 中英切换。之前用 Vim,几乎不输入中文,没什么感觉。转 Emacs 后要用 org-mode,难免要输入中文。模态编辑和中英切换兼容性不佳。有不少自动化控制中英切换的工具,但自动切换只要不能读心,就不可能 100% 准确。不如用 Emacs 原生按键,一了百了。

  2. 普适性。Vim 按键确实舒服,但只在 Vim 中有效。在我还在用 Vim 时,经常想尽办法把其他应用的按键也配置成 Vim,但不可能所有程序都完美还原 Vim 按键。用 Emacs 后,反倒在普适性上比 Vim 还有进步,比如 terminal 里支持 C-f/b/a/e,M-f/b 等(我无法习惯 terminal 里的 vi mode),macOS 系统全局支持许多光标移动按键。

  3. 效率神话。刚入门 Vim 的用户喜欢标榜模态编辑效率多高,经常举 ci(da" 之类的例子。殊不知 Emacs 中的基于 sexp 的光标移动和编辑命令,效率一点不比 Vim 低,甚至功能更强。比如:Vim 移动到函数首/尾的原生按键 [[]] 等,默认只能识别行首大括号,而 Emacs 的同类功能 C-M-aC-M-e 等,要强大得多。Vim 默认没有提供「函数」这个文本对象,而 Emacs 可以直接 C-M-h 选中一个函数。况且,效率高低和按键次数多少的关系并不大。Vim 按键的优势,与其说效率高,不如说更舒服,更易记忆。

  4. 维护成本。尽管 evil-mode 可能已经是天下最还原 Vim 按键的 Emacs 包,但它仍然无法覆盖所有情况,不是每个 Emacs 内置功能和第三方包都是奔着兼容 evil 的目标开发的。用了 evil,就总是需要调整按键。而且我个人感觉,Vim 默认按键确实简洁易记,但它的按键空间已经几乎被占满了,而 Emacs 的功能又如此庞杂,光 org 家族就有数不清的默认按键。要么为它们全部找到合理映射,要么就得舍弃一些「用不着」的按键。无论哪种,都是痛苦的抉择。

另外,关于用 modifier 优雅与否的问题,我也有些感想。

  1. Home row mods。我在工作时间会用某款分体键盘,通过 zmk 实现 home row mods。像 C-M-% 之类的组合键,按起来不但不别扭,甚至还有点弹钢琴的感觉——瞬间明白了为什么叫 key chords。也有纯软件实现的 home row mods,如 kanata、kmonad 等,我都尝试过,但感觉会让输入有延迟,没有长期使用。

  2. M-x。可能是从 Vim 时期延续下来的习惯,每次新写一个小函数,就迫不及待地给它安上一个快捷键——然后再也不用。实际上,有时候通过 M-x 调用命令就挺好,既能缓解紧张的按键空间,也能释放疲劳的大脑记忆空间。

希望以上内容能有所帮助。

7 个赞

我基本上也是跟题主一样的需求,才从修饰键位转到了模式编辑,最后选择了 Meow。

作为一个专门为 Emacs 开发的模式编辑插件,Meow 基本上解决了大部分题主提到的问题:比如说中英文切换,meow 和 emacs-rime 可以非常智能的解决这个问题,进入 normal 的时候是英文,进入 insert 后恢复上次的输入法(好像是,要不就是根据当前字符判断输入法);插件兼容性也非常棒,因为 meow 有一套将原生按键自动映射成模式编辑按键的功能,所以基本上其他插件的快捷键不需要怎么动。

但是不可否认,我自己对 meow 也有一些不舒适(并不是 meow 的问题),其中最大的不舒适就是 meow 是一套专有的模式编辑概念,和 vim 相似但不完全一致,而且 meow 基本上就只有 emacs 可用。相当于每次打开 emacs 我就需要换一下脑子,告诉自己“我要用另一套模式编辑思路了”,这就很割裂。尤其是现在的 TUI APP 往往是 vim 键位的,经常使我误操作。

这个世界要是 meow 的模式编辑思路占主流就好了哈哈哈哈。

1 个赞

我是选择了改键盘方式, 将字母 a/s/d/f/j/k/l/' 长按改成 super/alt/ctrl/shift 这样既能左右按快捷键, 也能使用 Emacs 原生按键, 并且防止手指问题.
Kmonad 改按键软件(全平台):

基于相同的理由,Centaur Emacs 默认只提供了原生按键。任何魔改的方案,换一台机器那可痛苦了 :joy:

Emacs 默认键位对小指来说负担比较大,但我又不喜欢模态编辑,所以我目前采用两种方案结合使用:

  1. 调教过的 god-mode。基本上类似粘滞键,学习成本很低,自己慢慢调教之后用起来还是比较舒服的。
  2. 脚踏板。弥补有些 god-mode 不太方便的情景,彻底解放双手。你有两只脚,好好利用上吧!
2 个赞

也可以試試這个方案:

ctrl, alt, shfit, comand 映射到 asdf / hjkl,用有力的手指去按修饰鍵。

就先不说要改肌肉记忆,改到别的手指按一样要按,一样会疲劳。而 god-mode 或者其它模态编辑是真正的减少按键。

换 corne,这个键盘上我切层键(两个空格键),修饰键全部在大拇指这里。至于在内置键盘中有时候用到上下左右和page down/up,我是用 ; 做了新的一层,这样标准键位下,小拇指自然押住;后hjkl为上下左右,nm为 page down/up。

买个原厂高度的机械键盘,Ctrl用手掌按,neovim里面我在用readline.nvim,减少了很多的模式切换,Emacs那就更不用说了。

1 个赞

你用meow的话,会两种键位混着用吗?也就是同时用emacs原生键位和meow的键位?

会,尤其是在 insert 模式的时候,如果我希望回到行首,要是先退出 insert 进入 normal 在到行首再进入 insert 实在是太慢了,我就直接 Ctrl-A 了。此外还有一些键位,我用原生键习惯了,而且也不是什么频率很高的,就会直接用。

不过这也导致我的 Meow 在 Normal 格式下的风格也是 N/P/F/B/A/E 这种,甚至都没有模仿 vim ,这进一步加重了我在不同应用切换时的成本,唉。但是 Meow 是真舒服。

1 个赞

如果你没有RSI的话,换modal editing收益不大,如果你有或者想预防,我觉得最好的办法还是硬件,换一个人体工程学键盘,我推荐diy一个ergo-s-1,全套成本应该只有500左右,难度更低一点的有sofle和lily58,成本能再低个100左右。但是如果你换不了键盘,或者用不了自己的键盘,那我首推evil,因为vim key是最流行的方案,如果你只用Emacs的话再考虑用Emacs社区自己捣鼓的各种方案。

粘滞键听起来不错,我打算尝试一下

粘滞键很有用。如果你熟悉vim,那么粘滞键可以给你一种类似vim的体验。我前段时间换到了evil模式后发现其实最重要的还是粘滞键。evil对于手指确实比较友好,但是emacs加上粘滞键看来也是一个不错的选择。我现在换回emacs原生按键再看看是否也不错。当然ctrl键必须交换,我现在用的caps当ctrl

确实不一样的键盘也是一种解决emacs按键问题的方法。前几天我发现system76自家的键盘看起来对emacs会比较友好。不知道有人用过那个键盘没有