55

我在 gnome 终端上运行 Vim。但是 alt 键映射不起作用。
例如(这只是一个例子):

:imap <A-i> <Esc>

它在 GVim 中运行良好。但是当我在 gnome 终端中使用 Vim 运行相同的命令时,它就不起作用了。
所以我认为问题出在终端上,对吧?
我该如何解决?

谢谢

编辑:我在同一台机器上安装了 Windows 7,并且使用 Windows 终端它也可以正常工作。

4

6 回答 6

101

问题

终端仿真器有两种方法可以发送Alt密钥(通常称为元密钥,因为实际终端没有 Alt)。它可以发送 8 位字符并在使用 Alt 时设置高位,也可以使用转义序列,发送Alt-a<Esc>a. Vim 期望看到 8 位编码而不是转义序列。

某些终端仿真器(例如xterm )可以设置为使用任一模式,但Gnome 终端不提供任何此类设置。老实说,在 Unicode 编辑时代,8 位编码无论如何都不是一个好主意。但是转义序列也不是没有问题的。它们无法区分<Esc>j含义Alt-jEsc紧随其后的j.

在早期的终端使用中,键入Escj是在没有键的情况下在键盘上发送 Meta 的另一种方式Meta,但这并不适合 vi 使用 Esc 离开插入模式。

解决方案

可以通过配置 vim 将转义序列映射到它们的 Alt 组合来解决这个问题。

将此添加到您的 .vimrc 中:

let c='a'
while c <= 'z'
  exec "set <A-".c.">=\e".c
  exec "imap \e".c." <A-".c.">"
  let c = nr2char(1+char2nr(c))
endw

set timeout ttimeoutlen=50

现在,终端中的 vi 和 gvim 都可以识别 Alt 字母。这些timeout设置用于解决转义序列的歧义。 Escj在 50ms 内发送将被映射到<A-j>,大于 50ms 将被视为单独的键。那应该有足够的时间来区分元编码和敲击两个键。

如果您不喜欢设置 timout,它会为其他映射的键序列超时(默认为一秒后),那么您可以ttimeout改用它。ttimeout 仅适用于键码,不适用于其他映射。

set ttimeout ttimeoutlen=50
于 2012-04-18T19:23:36.570 回答
8

对于Gnome-terminal,请改用以下内容:

imap ^[i <Esc>

^[i应按键入Ctrl-v Alt-i

注意:当您想将其复制到其他地方时,您需要yankput输入。Vim如果您只是在编辑器中复制映射gedit,则映射可能会被破坏。

这里的编辑是一个例子,它Alt-k在光标上方添加一个空行,并Alt-j在当前行之后添加一个空行。

" Alt-j/k to add a blank line
if has('gui_running')
    " the following two lines do not work in vim, but work in Gvim
    nnoremap <silent><A-j> :set paste<CR>m`o<Esc>``:set nopaste<CR>
    nnoremap <silent><A-k> :set paste<CR>m`O<Esc>``:set nopaste<CR>
else
    " these two work in vim
    " shrtcut with alt key: press Ctrl-v then Alt-k
    " ATTENTION: the following two lines should not be 
    " edited under other editors like gedit. ^[k and ^[j will be broken!
    nnoremap ^[k :set paste<CR>m`O<Esc>``:set nopaste<CR>
    nnoremap ^[j :set paste<CR>m`o<Esc>``:set nopaste<CR>
endif
于 2012-05-17T09:32:34.060 回答
2

同样的事情也发生在我身上。我用“gnome terminal alt key”在谷歌上搜索,发现有人问了几乎相同的问题:“如何在 gnome 终端上禁用 alt-hotkey 行为? ”在找到的第一个链接中。(第二个链接就是这个问题)

所以,也许你可以试试:

Edit > Keyboard Shortcuts, and uncheck "Enable menu access keys"
于 2012-06-23T00:54:55.437 回答
2

尝试

<m-i>

或者,如果键入alti插入一个字符(如在我的情况下,它插入一个 carret: ˆ)只需映射到该字符:

:inoremap ˆ <esc>

小心,因为这个不起作用(至少在我的系统中,MacOS 10.6)。插入符号等待一个字母,因为它不完全是插入符号,它是一个抑扬符。

于 2011-07-21T16:00:14.470 回答
1

查看http://vimdoc.sourceforge.net/htmldoc/map.html的第 1.10 节。这似乎表明 gnome-terminal 自动转义了 Alt 修饰符,因此它不会以 Vim 期望的方式切换发送的字节。该文件似乎表明,除了使用不同的终端(例如 xterm)之外,实际上没有办法解决这个问题。

这当然令人沮丧,因为据我所知,Linux 机器也无法使用 D(Mac 的命令或 Linux 的超级)绑定,所以至少就终端而言,我们仅限于 Shift 和 Ctrl 修饰符,即如果我们想确保我们可以在终端 Vim 上使用我们在 Gvim 中使用的所有命令(至少不切换终端,我可能过于固执——gnome-terminal 就更漂亮了),这令人沮丧。我一直在寻找解决此问题的方法,但一直找不到任何东西。

于 2012-01-23T02:50:22.137 回答
1

可能快捷方式实际上来自 Gnome 桌面。尝试查看 Gnome 键盘快捷方式工具(系统菜单、首选项、键盘快捷方式),它可以让您查看和修改 Gnome 桌面上定义的快捷方式。如果组合键分配给 Gnome Desktop 上的功能,则将其删除,然后该组合键应正确过滤到 Vim。

或者你可能是对的,这是终端的问题。并非所有终端都支持所有按键组合。您的问题可能是 Vim 帮助文档中描述的问题:h map-alt-keys。文档提供了一种解决方法,但不是一个很好的解决方法。

于 2011-07-21T18:00:49.177 回答