我目前的开发环境是用Vagrant起一个虚拟机,然后用Putty连上去,用VIM做日常的开发工作。

但某一天更新了一些配置以后,我在VIM里用小键盘输入1的时候,VIM就会在前一行加了一个q字符,让我很是困惑。

后来谷歌了一下这个问题,得知只要把Putty的Application keypad mode给关了就行了。

奇怪的错误

当刚开始小键盘的输入和预期有差别的时候,其实我是很困惑的。

首先我在Bash里面小键盘一切正常,这说明我键盘没问题,应该是VIM哪里不对。

其次我按的是1,结果出来的是前一行的q,我再按一下2,出来的是前一行的r。
假如键盘没有问题,要自己在VIM里面实现一个这种“功能”,那也要加一行配置:
inoremap <Num1> <Esc>Oq

但是这也太奇怪了吧,VIM里面怎么可能把<Num1>给替换成<Esc>Oq这么奇怪的东西?

寻求答案

于是我找到了VIM wiki上的一篇解答

根据这篇解答,问题是出在Putty上。
Putty会默认启用“Application Keypad Mode”,这个选项被启用以后
所有小键盘上的按键(包括)都会输出一串按键序列:

| 原按键 | 生成序列 |
|———–|———–|
| <Num1> | <Esc>Oq |
| <Num2> | <Esc>Or |
| <Num3> | <Esc>Os |
| <Num4> | <Esc>Ot |
| <Num5> | <Esc>Ou |
| <Num6> | <Esc>Ov |
| <Num7> | <Esc>Ow |
| <Num8> | <Esc>Ox |
| <Num9> | <Esc>Oy |
| <Num0> | <Esc>Op |
| . | <Esc>On |
| / | <Esc>OQ |
| * | <Esc>OR |
| + | <Esc>Ol |
| - | <Esc>OS |
| <Enter> | <Esc>OM |

居然<Num1>真的变成了<Esc>Oq

再去翻Putty关于Application keypad mode的说明:

Application Keypad mode is a way for the server to change the behaviour of the numeric keypad

唔,好吧,是服务器端决定的配置。

所以在Putty下简单的解决方案就是关掉这个模式了:

  • 打开Putty配置
  • 选中左边的Terminal -> Features
  • 在”Disable application keypad mode”处打钩
  • 选中左边的Session
  • 保存Putty配置

关闭application keypad mode

更多奇怪的答案

VIM wiki页面的讨论板块,有人给出了一个看起来很蠢的解决方案:

:inoremap <Esc>Oq 1
:inoremap <Esc>Or 2
:inoremap <Esc>Os 3
:inoremap <Esc>Ot 4
:inoremap <Esc>Ou 5
:inoremap <Esc>Ov 6
:inoremap <Esc>Ow 7
:inoremap <Esc>Ox 8
:inoremap <Esc>Oy 9
:inoremap <Esc>Op 0
:inoremap <Esc>On .
:inoremap <Esc>OQ /
:inoremap <Esc>OR *
:inoremap <Esc>Ol +
:inoremap <Esc>OS -
:inoremap <Esc>OM <Enter>

刚开始看到这个答案我立刻想到了这张XKCD

workflow

我认为mapping不应该是一个合适的解决方案,但是下面又有人讲了他自己苦逼的故事:

After a while struggling with this very problem with vnc viewer 4.1.3 under XP with a Debian lenny vnc4server 4.1.1+X4.3.0-31, this vim remapping is the only solution which work.

好吧,至少他找到了解决方案。

solution