使用 tmux 时如何在 vim 中创建 CTRL 键绑定?

使用 tmux 时如何在 vim 中创建 CTRL 键绑定?

我在 tmux 中使用 Vim,最近将以下内容添加到我的.vimrc文件中:

" easy navigation
nnoremap <C-Left> :tabprevious
nnoremap <C-Right> :tabnext

但这似乎没有效果(我按下CTRL+lCTRL+Right,我的光标只是移动,就像我CTRL根本没有按下一样)。我猜 tmux 在某种程度上对此负责。

我尝试将以下每一行(而不是同时)添加到我的代码中,但.tmux.conf无济于事:

set -g default-terminal "xterm"
set-window-option -g xterm-keys on

肯定有一种简单的方法可以将这些命令传递给 vim?

我读了这篇文章:

如何让 tmux 中的 Vim 中的 shift+箭头和 ctrl+箭头起作用?

并尝试将以下内容添加到我的.vimrc,但也没有明显的效果:

if &term =~ '^screen'
    " tmux will send xterm-style keys when its xterm-keys option is on
    execute "set <xUp>=\e[1;*A"
    execute "set <xDown>=\e[1;*B"
    execute "set <xRight>=\e[1;*C"
    execute "set <xLeft>=\e[1;*D"
endif

我正在运行 vim 版本 7.4

答案1

TERMtmux 的推荐设置是screen-256color,并且您添加到作品中的代码片段vimrc仅适用于以TERM开头的,screen因此您可以确保如果您的代码块TERM是,那么该代码块将永远不会被执行xterm

我之前在这台机器上成功使用过这个代码片段,没有set-window-option -g xterm-keys on但不知为何,它似乎不再对我有用了(过去三个月我都没有使用 tmux)。我想知道发生了什么。iTerm 升级?tmux 升级?

添加set-window-option -g xterm-keys on到我的~/.tmux.conf修复程序中即可解决问题。

<C-Left>无论如何,您可以直接映射由和生成的原始序列<C-Right>作为临时解决方法。

nnoremap <C-v><C-Left> :tabprevious<CR>

应该会给你类似这样的结果:

nnoremap ^[[D :tabprevious<CR>

答案2

除非你看到你使用的代码(例如<C-Left>)在“终端键”部分:set termcap,您不能立即使用它。

文档列出了映射特殊键的 3 种方法。第一种方法是插入或者命令行模式按下Ctrl-K,然后按下要映射的键序列(例如Ctrl-K Ctrl-Left)。如果它打印<...>,则可以将其用作映射的左侧。否则,在其前面加上<Esc>( Ctrl-V Esc) ,或使用Ctrl-V Ctrl-Left。例如,在 下,tmux我得到[1;5DCtrl-Left并且<Left>Left这意味着对于Left我可以使用<Left>,并且对于Ctrl-Left我需要^[[1;5D^[应该是一个字符,,Ctrl-V Esc请注意后面的<CR>):

nnoremap ^[[1;5D <Cmd>tabprevious<CR>

或者 (:h :set-termcap):

set <C-Left>=^[[1;5D
nnoremap <C-Left> <Cmd>tabprevious<CR>

如果您在不同的终端下工作,您可能需要第二种方法:

if &term =~ '^screen'
    set <C-Left>=...
elseif &term =~ '^tmux'
    set <C-Left>=...
endif
nnoremap <C-Left> <Cmd>tabprevious<CR>

某些键适用于某些终端,但不能适用于其他终端(当它们在相应的 terminfo 条目中没有字段时)。让我们<S-Left>以 为例。从( ):set termcap下的 not中,我可以看到它位于字段中:tmuxTERM=rxvt-unicode-256colort_#4 termcap

t_#4 <S-Left>    ^[[d

man terminfo说:

key_sleft                   kLFT      #4     shifted left-arrow
                                             key

这意味着名称terminfo是。现在让我们看看(not under )、(under ) 和(我们稍后可能需要)kLFT的此字段的值:TERM=rxvt-unicode-256colortmuxTERM=screentmuxTERM=tmux

$ infocmp rxvt-unicode-256color | grep kLFT
    kLFT=\E[d, kNXT=\E[6$, kPRV=\E[5$, kRIT=\E[c, ka1=\EOw,

$ infocmp screen | grep kLFT

$ infocmp tmux | grep kLFT
    kHOM=\E[1;2H, kIC=\E[2;2~, kLFT=\E[1;2D, kNXT=\E[6;2~,

条目中缺少该screen terminfo内容。要解决此问题:

if &term =~ '^screen'
    set <S-Left>=...
endif
nnoremap <S-Left> <Cmd>tabprevious<CR>

或者(vim我们必须使用termcap名称):

if &term =~ '^screen'
    set t_#4=...
endif
nnoremap <S-Left> <Cmd>tabprevious<CR>

或者你可以告诉tmux使用它自己的 terminfo入口:

set -g default-terminal tmux

附注:<Esc>如果可能,请避免在配置中(或通常在文本文件中)使用该字符。它是一个看起来像 2 的字符。如果您使用鼠标复制它,它^[会变成 2 个字符,这样它就不起作用了。特别是在文档中,您可以找到^[2 个字符的示例,您不能直接复制。这种事情很容易被忽视。

顺便说一下xterm-keys无法使用自从2.4

如果仍然不起作用,请告诉我您按下了什么以及它产生的转义序列(使用Ctrl-V)。

答案3

另一种解决方案如下:

" Note:  Move to the next tab! By Questor
nnoremap <silent> <C-Up> :tabnext<cr>
inoremap <silent> <C-Up> <C-O>:tabnext<cr>
vnoremap <silent> <C-Up> :<C-U>tabnext<cr>v

" Note:  Move to the previous tab! By Questor
nnoremap <silent> <C-Down> :tabprevious<cr>
inoremap <silent> <C-Down> <C-O>:tabprevious<cr>
vnoremap <silent> <C-Down> :<C-U>tabprevious<cr>v

对我来说非常有用!

参见使用示例https://github.com/eduardolucioac/groovim/blob/master/.vimrc

相关内容