如何在 Vim 中为命令创建别名?
Posted
技术标签:
【中文标题】如何在 Vim 中为命令创建别名?【英文标题】:How to create an alias for a command in Vim? 【发布时间】:2011-04-22 04:15:37 【问题描述】:Vim 是我编程时首选的文本编辑器,因此我总是遇到一个特别烦人的问题。
通常,当我需要快速保存缓冲区并继续执行其他杂项任务时,我会做典型的
:w
但是,我总是——似乎超过 50% 的时间——设法利用:w
。很自然,Vim 会对我大喊大叫,因为 W
是一个无效命令:
E492: Not an editor command: W
我的问题是如何在 Vim 中为冒号命令别名。特别是,您能否举例说明如何将W
别名为w
。
我知道将键映射到某些命令的过程,但这不是我想要的。
【问题讨论】:
Can I (re-) map commands in vim?的可能重复 为了避免: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>
关于 Vi Stack 交换的类似问题:vi.stackexchange.com/q/2665/7244
【参考方案1】:
要保持完成不变,请尝试使用
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
,所以它比cnoreabbrev W w
更安全。
【讨论】:
这个答案对我来说是最安全最可靠的。 如果您使用推荐的解决方案,请注意以下两个命令都将作为较低的命令工作,根据实际缓冲区内容和 VIM 设置可能会出现意外结果::%s/W/foo/g<CR>
:%s/w/foo/g<CR>
实际上,这意味着 W 将被替换 anywhere 在命令栏中,包括例如在搜索中,因此 s/W foo/bar/g 将被替换进入 s/w foo/bar/g。这会很快变得烦人。请参阅我的答案以获得全面的解决方案。
绝对的;这是一个可怕的想法。您应该永远、永远、永远这样做。
:cnoreabbrev <expr> W getcmdtype()==':'&&getcmdline()=~#'^W'?'w':'W'
【参考方案2】:
通过补充搜索,我发现有人问的question和我几乎一样。
:command <AliasName> <string of command to be aliased>
会成功的。
请注意,正如Richo 指出的那样,用户命令必须以大写字母开头。
【讨论】:
使用 :command 是很好的解决方案。 :cnoreabbrev 不理解 cmd1|cmd2,:command 可以。 一个不那么容易混淆的写法是:command AliasName string of command to be aliased
这不会处理/转发任何command
参数,例如-nargs
、-complete
等。
:Q!
或 :W!
怎么样?
直言不讳:将:command W w
放入.vimrc
文件中。【参考方案3】:
我发现将;
键映射到:
会是一个更好的解决方案,并且可以提高您键入其他命令的效率。
nnoremap ; :
vnoremap ; :
【讨论】:
这是 vim 的最佳技巧。我现在已经习惯了,每次遇到正常行为时,我都需要尝试几次才能重新训练自己的思想。 这不是问题的答案。 @Flimm 不,但它使 OP 的问题消失了。 当使用t
或f
时,通常可以使用;
转到下一个匹配项。即使您将分号映射到冒号,也可以安全地映射另一种方式。不会有别名循环。 nnoremap : ;
【参考方案4】:
最好的解决方案是使用writing a custom function 处理仅出现在命令栏开头的缩写。
为此,请在您的 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')
一些useful abbreviations from the source material 我在哪里找到了这些东西:
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")
【讨论】:
有一个内置函数string()
和你的 Single_quote()
做同样的事情。【参考方案5】:
假设你想在 gvim 中为 tabnew 命令添加别名。您只需在 .vimrc 文件中键入以下命令(如果不在主文件夹中,则创建一个)
cabbrev t tabnew
【讨论】:
这将导致:saveas t example
之类的命令被:saveas tabnew example
替换【参考方案6】:
也许您想将您的一个功能键 (F1..F12) 映射到 :w ?然后把它放到你的 .vimrc 中:
noremap <f1> :w<return>
inoremap <f1> <c-o>:w<return>
(插入模式下的 ctrl-o 暂时切换到普通模式)。
【讨论】:
【参考方案7】:最安全和最简单的是插件,例如cmdalias.vim 或我最近更新的vim-alias 考虑到
前面的空格或修饰符,例如:sil(ent)(!)
或:redi(r)
,
用于当前视觉选择的范围修饰符,例如 '<,'>
,
转义特殊字符,例如引号和
检查所选别名是否为有效的命令行缩写。
【讨论】:
【参考方案8】:我认为@ZyX 的回答很棒,但是如果您使用的是新版本的 neovim (0.5+),您可能希望使用 lua 来定义函数。这是您可以做到的一种方法:
function _G.abbreviate_or_noop(input, output)
local cmdtype = vim.fn.getcmdtype()
local cmdline = vim.fn.getcmdline()
if (cmdtype == ":" and cmdline == input) then
return output
else
return input
end
end
function SetupCommandAlias(input, output)
vim.api.nvim_command("cabbrev <expr> " .. input .. " " .. "v:lua.abbreviate_or_noop('" .. input .. "', '" .. output .. "')")
end
然后,您可以从 call SetupCommandAlias("pg", "postgres://")
中删除 call
并使用如下函数:SetupCommandAlias("pg", "postgres://")
。
n.b.如果从.vim
文件而不是.lua
文件中使用它,则需要在函数调用前加上lua
,即lua SetupCommandAlias("pg", "postgres://")
。
【讨论】:
以上是关于如何在 Vim 中为命令创建别名?的主要内容,如果未能解决你的问题,请参考以下文章
在 pipenv 项目中为 python 文件创建命令行别名
如何分别创建多个 Flutter 版本别名以在 Windows PC 的命令提示符中使用 [关闭]