不知道怎么说起,先列一下起因的关键词:mac 键盘,iterm2,emacs。这里面的每一个词都是我要解决的问题起源,也是有这篇文章的原因。这里的环境是 Ventura 13.6.6,iterm2 3.5.0,后面软件有更新的话可能配置路径不一样。
注意这里修改的是默认的配置文件,就不一一强调了。
首先是一个很多人都会遇到的问题:在 iterm2 中用 emacs(或者说在 iterm2 的命令行中用 emacs-style key binding)的时候 meta 键的映射。这个在网上已经有很多人写过了,就是在 iterm2 的 Settings -> Profiles -> Keys -> General 中,把其中的 Left Option key 的选项改为 Esc+,这样在终端中 option 键的行为就和其它键盘的 meta 行为一样了。
但是因为 mac 键盘中左边 option 的位置比较靠左一点,导致用左手大拇指按起来很别扭,因此很多人都会把左边的 option 和 command 的位置交换一下。这个可以通过 iterm2 的 Settings -> Keys -> Remap Modifiers 页面来设置,交换一下这两个键的位置。这样改动了之后,在 iterm2 中的所有涉及到 command 键的操作,就和 iterm2 外的不一样了。例如在 iterm2 中想切换窗口,按键是 option+tab(这里的 option 指的是物理按键的位置,因为我们的设置把 option 和 command 的位置交换了,所以实际的效果是 command+tab),然后切到其它窗口后再想切回 iterm2,要按的键位则是 command+tab。又因为 mac 神奇的窗口焦点行为,我经常会按错,需要先看下当前是不是在 iterm2 中,极大地降低了工作效率;但是如果不交换位置的话,按键又很难受。
其实我真正的需求是在 iterm2 中能够把 某些 command 的组合键映射为对应的 meta 的组合键,而并不是需要修改 option 的行为,或者 option 的位置。因此我最终使用了如下的解决方法。
例如 command+f,如果不做任何配置改动的话在 iterm2 中的行为是弹出查找框,但是我们期望的行为是在用 emacs 的时候能够往后跳一个单词。为了实现这个功能,我们在 iterm2 的 Settings -> Profiles -> Keys -> Key Mappings 中,新添加一个选项,Keyboard Shortcut 设置的是 command+f,Action 选的是 Send Hex Code,在框里填入 0x1b 0x66 然后确认就可以了。其中 0x1b 是 Esc+ 的十六进制代码,0x66 是 f 的十六进制 ASCII。
那怎么获得对应按键的 hex code 呢?例如这里的 command+f,可以在终端运行 xxd,然后按 command+f,接着回车,接着 ctrl+d,会看到这样的输出:
$ xxd
^[f
00000000: 1b66 0a
其中第二行的 1b66 就是 command+f 的 hex code,0a 就是回车的 hex code。添加完这项之后,在 iterm2 的命令行或者 emacs 中,按 command+f 都会往后跳一个单词了。
如果需要映射其它按键的话,按照上面的方法一个个加就行,对于我来说这些映射并不多,所以也可以接受。下面是我的一些映射:
| key | hex code |
|---|---|
| cmd+, | 0x1b 0x2c |
| cmd+/ | 0x1b 0x2f |
| cmd+; | 0x1b 0x3b |
| cmd+< | 0x1b 0x3c |
| cmd+> | 0x1b 0x3e |
| cmd+b | 0x1b 0x62 |
| cmd+d | 0x1b 0x64 |
| cmd+f | 0x1b 0x66 |
| cmd+g | 0x1b 0x67 |
| cmd+m | 0x1b 0x6d |
| cmd+n | 0x1b 0x6e |
| cmd+o | 0x1b 0x6f |
| cmd+p | 0x1b 0x70 |
| cmd+r | 0x1b 0x72 |
| cmd+w | 0x1b 0x77 |
| cmd+x | 0x1b 0x78 |
| cmd+ctrl+b | 0x1b 0x02 |
| cmd+ctrl+f | 0x1b 0x06 |
| cmd+ctrl+k | 0x1b 0x0b |
| cmd+ctrl+o | 0x1b 0x0f |
| cmd+delete | 0x1b 0x7f |
其中 cmd+ctrl+o 是我自定义的一个按键组合,在 xxd 中不知道为啥不能正常显示,但是直接按 option+ctrl+o 能正常工作,也就是说 hex code 应该是存在的,只是通过 xxd 查不到。然后我观察了下 cmd+ctrl+f 的值(通过 xxd 获取的),发现 f 的 ASCII 是 0x66,加了 ctrl 之后变成 0x06 了,那 ctrl+o会不会也是类似的 mask 呢?试了下果然就可以了。
最后要说的是,这个是在用 mac 键盘才会有键位的问题。如果用的是外接的非 mac 键盘,只要在 mac 全局交换 option 和 command 的位置(因为通常左 win 键对应左 option 键的位置,而左 Alt 键对应左 command 的位置,所以用外接非 mac 键盘我都会全局交换这两个键的位置),然后在 iterm2 中修改本文开头说的 Esc+ 以及 key mapping,改完之后在 iterm2 中 command 就可以同时拥有 command 和 meta 的功能了。