别名化Vim中的命令


151

Vim 是我编程时首选的文本编辑器,因此我总是遇到一个特别烦人的问题。

通常,当我快速需要保存缓冲区并继续执行其他任务时,我通常

:w

但是,我(似乎有50%的时间都喜欢)总是设法将其资本化:w。自然,vim对我大喊,因为这W是无效的命令

E492: Not an editor command: W

我的问题是在vim中如何使用一个别名冒号命令。尤其是,你能举例说明如何别名Ww

我知道将键映射到某些命令的过程。不幸的是,这不是我想要的。



1
为了避免这种情况,:W您可以映射一个键来执行保存。如果您习惯使用Ctrl-s保存的某些程序,则这些映射来自$ VIM / mswin.vim:" Use CTRL-S for saving, also in Insert mode noremap <C-S> :update<CR> vnoremap <C-S> <C-C>:update<CR> inoremap <C-S> <C-O>:update<CR>
mMontu 2012年

在六堆栈交换类似的问题:vi.stackexchange.com/q/2665/7244
Flimm

Answers:


127

要保持完成状态不变,请尝试使用

cnoreabbrev W w

,它将W在命令行中替换为w,但前提是该字符既不跟随也不在其前面,因此:W<CR>将替换为:w<CR>,但:Write不会替换。(请注意,这会影响所有匹配的命令,包括您可能不希望看到的命令,例如,该命令:saveas W Z将替换为:saveas w Z,因此请谨慎操作。)

更新资料

这是我怎么会写现在

cnoreabbrev <expr> W ((getcmdtype() is# ':' && getcmdline() is# 'W')?('w'):('W'))

作为功​​能:

fun! SetupCommandAlias(from, to)
  exec 'cnoreabbrev <expr> '.a:from
        \ .' ((getcmdtype() is# ":" && getcmdline() is# "'.a:from.'")'
        \ .'? ("'.a:to.'") : ("'.a:from.'"))'
endfun
call SetupCommandAlias("W","w")

这会检查命令类型为:和命令为W,因此它比just更安全cnoreabbrev W w


2
对于我来说,这个答案是最安全,最可靠的。
肖恩(Sean)2010年

2
如果您使用推荐的解决方案,请注意,以下两个命令都将作为较低的命令工作,根据实际的缓冲区内容和VIM设置,这两个命令可能会出现意外的结果::%s/W/foo/g<CR> :%s/w/foo/g<CR>
cprn 2012年

2
实际上,这意味着W将在命令栏中的任何位置被替换,包括例如在搜索中,因此s / W foo / bar / g将被转换为s / w foo / bar / g。这会变得非常烦人。查看我的答案以获取全面的解决方案。
空袭2012年

4
绝对; 这是一个可怕的想法。你应该永远永远永远做到这一点。
克里斯·摩根

4
:cnoreabbrev <expr> W getcmdtype()==':'&&getcmdline()=~#'^W'?'w':'W'
2012年

97

通过补充搜索,我发现有人问了几乎与我相同的问题

:command <AliasName> <string of command to be aliased>

会成功的

请注意,正如Richo指出的那样,用户命令必须以大写字母开头。


5
使用:command是一个很好的解决方案。:cnoreabbrev不了解cmd1 | cmd2,:command可以。
Pavel Strakhov 2011年

1
一种不太容易混淆的写法是,:command AliasName string of command to be aliased
Alec Jacobson

8
这不会处理/转发的任何command参数,比如-nargs-complete
blueyed

怎么样:Q!还是:W!
杰克

5
只要是非常字面:把:command W w.vimrc文件。
同构

20

我发现将;键映射到:会是更好的解决方案,并使您在键入其他命令时效率更高。

nnoremap ; :
vnoremap ; :

这是vim的最佳建议。我现在已经习惯了,每次遇到正常的行为时,都需要尝试一些重新训练自己的头脑。
空袭2015年

这不是问题的答案。
Flimm

5
@Flimm不,但是这使OP的问题消失了。
Duncan X Simpson

1
使用t或时f,通常可以使用;转到下一个出现的位置。即使您将分号映射到冒号,也可以用另一种方式安全地映射它。不会有别名循环。nnoremap : ;
卢克,

9

最好的解决方案包括编写一个自定义函数来处理仅在命令栏开头出现的缩写。

为此,在您的vimrc文件或其他任何位置添加以下内容。

" cabs - less stupidity                                                      {{{
fu! Single_quote(str)
  return "'" . substitute(copy(a:str), "'", "''", 'g') . "'"
endfu
fu! Cabbrev(key, value)
  exe printf('cabbrev <expr> %s (getcmdtype() == ":" && getcmdpos() <= %d) ? %s : %s',
    \ a:key, 1+len(a:key), Single_quote(a:value), Single_quote(a:key))
endfu
"}}}

 

" use this custom function for cabbrevations. This makes sure that they only
" apply in the beginning of a command. Else we might end up with stuff like
"   :%s/\vfoo/\v/\vbar/
" if we happen to move backwards in the pattern.

" For example:
call Cabbrev('W', 'w')

我在其中找到这些东西的原始资料中的一些有用缩写

call Cabbrev('/',   '/\v')
call Cabbrev('?',   '?\v')

call Cabbrev('s/',  's/\v')
call Cabbrev('%s/', '%s/\v')

call Cabbrev('s#',  's#\v')
call Cabbrev('%s#', '%s#\v')

call Cabbrev('s@',  's@\v')
call Cabbrev('%s@', '%s@\v')

call Cabbrev('s!',  's!\v')
call Cabbrev('%s!', '%s!\v')

call Cabbrev('s%',  's%\v')
call Cabbrev('%s%', '%s%\v')

call Cabbrev("'<,'>s/", "'<,'>s/\v")
call Cabbrev("'<,'>s#", "'<,'>s#\v")
call Cabbrev("'<,'>s@", "'<,'>s@\v")
call Cabbrev("'<,'>s!", "'<,'>s!\v")

1
有一个内置功能string()与您的功能相同Single_quote()
ZyX 2012年

6

也许您想将一个功能键(F1..F12)映射到:w?然后将其放入您的.vimrc中:

noremap  <f1> :w<return>
inoremap <f1> <c-o>:w<return>

(插入模式下的ctrl-o暂时切换到普通模式)。


6

假设您要在gvim中为tabnew命令添加别名。您只需在.vimrc文件中键入以下命令(如果不在主文件夹中而不是创建一个)

cabbrev t tabnew

1
这将导致命令:saveas t example替换为:saveas tabnew example
Flimm 18'Aug

5

最安全,最简单的是一个插件,例如cmdalias.vim或我最近考虑到的更新vim-alias

  • 前面的空白或修饰符,例如:sil(ent)(!):redi(r)
  • 范围修饰符,例如'<,'>当前的视觉选择,
  • 转义引号等特殊字符,以及
  • 检查所选别名是否为有效的命令行缩写。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.