在控制台Vim中使用CMD映射 [英] Use CMD-mappings in console Vim

查看:88
本文介绍了在控制台Vim中使用CMD映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在终端中的Vim中使用Cmd键? MacVim可以做到.

Is there a way to use Cmd key for Vim in terminal? Something MacVim does.

我已经在iTerm2中重新映射了Cmd+S以发送Esc:w!<CR>以将文件保存在Vim中,但这听起来有些虚弱.

I have remapped Cmd+S in iTerm2 to send Esc:w!<CR> to save files in Vim, but this sounds a bit weak.

借助iTerm和Vim的全部功能,应该有一些方法可以正确执行此操作?

With all the power of iTerm and Vim there should be some way to do this right?

推荐答案

虽然可以,但是需要一些努力并且存在一些缺点.

It is possible, but it takes some doing and has some downsides.

第一组问题是:

  • 尽管iTerm2可以接受 Command 键并将其传递给终端程序,但只能通过将它们重新映射来实现,例如左选项 Control 键.
  • 它只能在iTerm2中重新映射每个修饰键"无处不在" ;您不能仅对某些窗口,窗格或配置文件执行此操作.
  • 为了在终端中重新映射修饰符,您需要允许iTerm2在安全性和安全性"中控制计算机.隐私首选项窗格;当您配置iTerm2进行重新映射时,它将自动将您定向到那里.
  • 重新映射 Left Command 后, Left Command + N 之类的东西无法打开新窗口.幸运的是,您可以重新映射例如向左命令向左选项,并且仍然具有可用于Mac快捷方式的向右命令键;或者您可以在 Command Option 键之间切换.
  • although iTerm2 can accept the Command keys and pass them on to terminal programs, it can only do so by remapping them as something else, e.g. the Left Option or Control keys.
  • it can only remap each modifier key everywhere in iTerm2; you can't do it just for certain windows, panes, or profiles.
  • in order to remap a modifier within the terminal, you need to allow iTerm2 to control the computer in the Security & Privacy preference pane; when you configure iTerm2 to do remapping, it will direct you there automatically.
  • once you've remapped Left Command, things like Left Command+N to open a new window no longer work. Luckily, though, you can remap e.g. Left Option to Left Command and still have your Right Command key available for Mac shortcuts; or you can switch around your Command and Option keys.

剩下的问题是,Vim没有像Mac那样的按键绑定进行开箱即用的配置.幸运的是,MacVim在/Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim中包含了大多数Mac风格的GUI绑定,而不是在Interface Builder或Objective-C源代码中进行编码;这样我就可以复制这些文件并将其用于终端设备.这是一个与MacVim(和其他Mac应用程序)非常接近的配置:

The remaining issue is that Vim isn't configured out of the box with Mac-like key bindings. Luckily, MacVim includes most of its Mac-style GUI bindings in /Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim rather than coding them in Interface Builder or Objective-C source; so I was able to copy those and adapt them for the terminal. Here is a config that works pretty closely to MacVim (and other Mac apps):

" Keybindings for terminal vim; mostly to emulate MacVim (somewhat)

" See /Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim (from
" which many of the following are taken); and menu.vim in the same directory.

" Since these all have native (Cmd-modified) versions in MacVim, don't bother
" defining them there.

" A utility function to help cover our bases when mapping.
"
" Example of use:
"   call NvicoMapMeta('n', ':new<CR>', 1)
" is equivalent to:
"   exec "set <M-n>=\<Esc>n"
"   nnoremap <special> <Esc>n :new<CR>
"   vnoremap <special> <Esc>n <Esc><Esc>ngv
"   inoremap <special> <Esc>n <C-o><Esc>n
"   cnoremap <special> <Esc>n <C-c><Esc>n
"   onoremap <special> <Esc>n <Esc><Esc>n
function! NvicoMapMeta(key, cmd, add_gv)
    " TODO: Make this detect whether key is something that has a Meta
    " equivalent.
    let l:keycode = "<M-" . a:key . ">"

    let l:set_line = "set " . l:keycode . "=\<Esc>" . a:key

    let l:nmap_line = 'nmap <silent> <special> ' . l:keycode . ' ' . a:cmd
    let l:vnoremap_line = 'vnoremap <silent> <special> ' . l:keycode . ' <Esc>' . l:keycode
    if(a:add_gv)
        let l:vnoremap_line.='gv'
    endif
    let l:inoremap_line = 'inoremap <silent> <special> ' . l:keycode . ' <C-o>' . l:keycode
    let l:cnoremap_line = 'cnoremap <special> ' . l:keycode . ' <C-c>' . l:keycode
    let l:onoremap_line = 'onoremap <silent> <special> ' . l:keycode . ' <Esc>' . l:keycode

    exec l:set_line
    exec l:nmap_line
    exec l:vnoremap_line
    exec l:inoremap_line
    exec l:cnoremap_line
    exec l:onoremap_line
endfunction

" I can't think of a good function to assign to Meta+n, since in MacVim Cmd+N
" opens a whole new editing session.

" Meta+Shift+N
" No equivalent to this in standard MacVim. Here " it just opens a window on a
" new buffer.
call NvicoMapMeta('N', ':new<CR>', 1)

" Meta+o
" Open netrw file browser
call NvicoMapMeta('o', ':split %:p:h<CR>', 1)

" Meta+w
" Close window
call NvicoMapMeta('w', ':confirm close<CR>', 1)

" Meta+s
" Save buffer
call NvicoMapMeta('s', ':confirm w<CR>', 1)

" Meta+Shift+S
" Save as
" TODO: This is silent, so you can't tell it's waiting for input. If anyone can
" fix this, please do!
call NvicoMapMeta('S', ':confirm saveas ', 1)

" Meta+z
" Undo
call NvicoMapMeta('z', 'u', 1)

" Meta+Shift+Z
" Redo
call NvicoMapMeta('Z', '<C-r>', 1)

" Meta+x
" Cut to system clipboard (requires register +")
exec "set <M-x>=\<Esc>x"
vnoremap <special> <M-x> "+x

" Meta+c
" Copy to system clipboard (requires register +")
exec "set <M-c>=\<Esc>c"
vnoremap <special> <M-c> "+y

" Meta+v
" Paste from system clipboard (requires register +")
exec "set <M-v>=\<Esc>v"
nnoremap <silent> <special> <M-v> "+gP
cnoremap <special> <M-v> <C-r>+
execute 'vnoremap <silent> <script> <special> <M-v>' paste#paste_cmd['v']
execute 'inoremap <silent> <script> <special> <M-v>' paste#paste_cmd['i']

" Meta+a
" Select all
call NvicoMapMeta('a', ':if &slm != ""<Bar>exe ":norm gggH<C-o>G"<Bar> else<Bar>exe ":norm ggVG"<Bar>endif<CR>', 0)

" Meta+f
" Find regexp. NOTE: MacVim's Cmd+f does a non-regexp search.
call NvicoMapMeta('f', '/', 0)

" Meta+g
" Find again
call NvicoMapMeta('g', 'n', 0)

" Meta+Shift+G
" Find again, reverse direction
call NvicoMapMeta('G', 'N', 0)

" Meta+q
" Quit Vim
" Not quite identical to MacVim default (which is actually coded in the app
" itself rather than in macmap.vim)
call NvicoMapMeta('q', ':confirm qa<CR>', 0)

" Meta+Shift+{
" Switch tab left
call NvicoMapMeta('{', ':tabN<CR>', 0)

" Meta+Shift+}
" Switch tab right
call NvicoMapMeta('}', ':tabn<CR>', 0)

" Meta+t
" Create new tab
call NvicoMapMeta('t', ':tabnew<CR>', 0)

" Meta+Shift+T
" Open netrw file browser in new tab
call NvicoMapMeta('T', ':tab split %:p:h<CR>', 0)

" Meta+b
" Call :make
call NvicoMapMeta('b', ':make<CR>', 1)

" Meta+l
" Open error list
call NvicoMapMeta('l', ':cl<CR>', 1)

" TODO: We need to configure iTerm2 to be able to send Cmd+Ctrl+arrow keys, so
" we can duplicate the :cnext/:cprevious/:colder/:cnewer bindings to those keys
" in MacVim.
" There may be a few others I've missed, too.

NvicoMakeMeta函数将传递给它的密钥的元密钥修改版本映射到指定的操作;这里的元密钥"只是 Command -或 Option -修改过的通用术语.名称中的"Nvico"表示它以常规,可视,插入,命令和操作员暂挂模式进行映射的事实.

The NvicoMakeMeta function maps a meta-key-modified version of the key passed into it to the specified action; "meta-key" here is just a generic term for Command- or Option-modified. The "Nvico" in its name represents the fact that it maps in normal, visual, insert, command, and operator pending modes.

由于Vim在解释ESC字符(这是所有元键序列以及箭头键等的开始)时的工作方式,如果我们简单地映射ESC的序列和另一个字符,在收到实际的 Esc 按键后,Vim会等待相当长的时间(例如,表示希望返回正常模式).我的函数避免这种情况的方法是使用:set设置键码(请参见:help :set-termcap).

Due to the way way Vim works when interpreting the ESC character (which is the beginning of all meta key sequences as well as arrow keys, etc.), if we simply mapped sequences of ESC plus another character, we would end up with Vim waiting a noticeable amount of time after receiving the actual Esc keypress (e.g. to signal a desire to return to normal mode). The way my function avoids this is by using :set to set a key code (see :help :set-termcap).

总而言之,这是您需要做的:

  • 将上述代码放入.vimrc中.
  • 转到常规iTerm2首选项(iTerm菜单> Preferences…);转到Keys标签;重新映射您想用作修饰符的任何键,以便它发送左选项右选项.遵循建议,以允许iTerm2控制计算机;它应该会打开右侧的首选项窗格,以便您执行此操作.您必须先单击锁并输入密码,然后才能选中iTerm旁边的框.
  • 打开您想要使用的终端配置文件的首选项(例如,通过在Profiles选项卡的应用程序范围内的Preferences对话框中将其打开),并确保已选中Left option key acts as旁边的+Esc (和/或Right option key acts as,具体取决于您是否已将元密钥发送给权利选项).
  • Put the above code in your .vimrc.
  • Go to the general iTerm2 preferences (iTerm menu > Preferences…); go to the Keys tab; remap your whatever key you'd like to use as a modifier so that it sends Left Option or Right Option. Follow the advice to allow iTerm2 to control the computer; it should open up the right preference pane for you to do that. You'll have to click the lock and type in your password before you can check the box next to iTerm.
  • Open the preferences for the terminal profile you'd like to use (e.g. by opening it in the app-wide Preferences dialog in the Profiles tab) and ensure that +Esc is checked next to Left option key acts as (and/or Right option key acts as, depending on whether you've made your meta key send Right Option).

这篇关于在控制台Vim中使用CMD映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆