有没有办法使用Cmd
终端中 Vim 的键? MacVim 做的事情。
我已重新映射 Cmd+S
在 iTerm2 中发送 Esc:w!<CR>
在 Vim 中保存文件,但这听起来有点弱。
凭借 iTerm 和 Vim 的所有功能,应该有一些方法可以做到这一点吗?
最佳答案
这是可能的,但需要做一些事情并且有一些缺点。
第一组问题是:
剩下的问题是 Vim 没有开箱即用地配置类似 Mac 的键绑定(bind)。幸运的是,MacVim 在/Applications/MacVim.app/Contents/Resources/vim/runtime/macmap.vim 中包含了大部分 Mac 风格的 GUI 绑定(bind),而不是在 Interface Builder 或 Objective-C 源代码中编码它们;所以我能够复制这些并将它们改编为终端。这是一个与 MacVim(和其他 Mac 应用程序)非常接近的配置:
" 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-modified 的通用术语。其名称中的“Nvico”表示它以正常、可视、插入、命令和运算符(operator)挂起模式映射的事实。由于 Vim 在解释
ESC
时的工作方式字符(这是所有元键序列以及箭头键等的开始),如果我们简单地映射 ESC
的序列加上另一个字符,我们最终会在 Vim 收到实际的 Esc 按键后等待相当长的时间(例如,表示希望返回正常模式)。我的函数避免这种情况的方法是使用 :set
设置 key 代码(见 :help :set-termcap
)。总而言之,您需要执行以下操作:
iTerm
菜单 > Preferences…
);转至Keys
标签;重新映射您想用作修饰符的任何键,以便它发送左选项或右选项。按照建议允许 iTerm2 控制计算机;它应该为您打开正确的首选项 Pane 。您必须先单击锁并输入密码,然后才能选中 iTerm 旁边的框。 Preferences
对话框中的 Profiles
选项卡中打开它)并确保 +Esc
在 Left option key acts as
旁边选中(和/或 Right option key acts as
,取决于您是否让元 key 发送正确的选项)。 关于macos - 在控制台 Vim 中使用 CMD 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26310077/