Vim is my preferred text editor when I program, and thus I always run into a particularly annoying issue.
Frequently, when I quickly need to save the buffer and continue on to some other miscellaneous task, I do the typical
:w
However, I always — what seems to be like more than 50% of the time — manage to capitalize that :w
. Naturally, Vim yells at me because W
is an invalid command:
E492: Not an editor command: W
My question is how can one alias colon-commands in Vim. Particularly, could you exemplify how to alias W
to w
.
I am aware of the process to map keys to certain commands, but that is not what I’m looking for.
8 Answers 8
To leave completion untouched, try using
cnoreabbrev W w
It will replace W
in command line with w
, but only if it is neither followed nor preceded by word character, so :W<CR>
will be replaced with :w<CR>
, but :Write
won’t. (Note that this affects any commands that match, including ones that you might not expect. For example, the command :saveas W Z
will be replaced by :saveas w Z
, so be careful with this.)
Update
Here is how I would write it now:
cnoreabbrev <expr> W ((getcmdtype() is# ':' && getcmdline() is# 'W')?('w'):('W'))
As a function:
fun! SetupCommandAlias(from, to)
exec 'cnoreabbrev <expr> '.a:from
\ .' ((getcmdtype() is# ":" && getcmdline() is# "'.a:from.'")'
\ .'? ("'.a:to.'") : ("'.a:from.'"))'
endfun
call SetupCommandAlias("W","w")
This checks that the command type is :
and the command is W
, so it’s safer than just cnoreabbrev W w
.
-
3This answer is the safest and most reliable for me.Sean– Sean2010年10月13日 01:57:51 +00:00Commented Oct 13, 2010 at 1:57
-
2If you use the recommended solution, please, be aware both of the two below commands will work as the lower one which may present an unexpected result depending on the actual buffer content and VIM settings:
:%s/W/foo/g<CR>
:%s/w/foo/g<CR>
cprn– cprn2012年04月25日 02:00:26 +00:00Commented Apr 25, 2012 at 2:00 -
2Actually, this would mean W will be replaced anywhere in the command bar, including, for example, in searches, so s/W foo/bar/g would be turned into s/w foo/bar/g. this can get annoying really fast. see my answer for a comprehensive solution.airstrike– airstrike2012年05月22日 19:17:14 +00:00Commented May 22, 2012 at 19:17
-
4Absolutely; this is a horrible idea. You should never, ever, ever do this.Chris Morgan– Chris Morgan2012年05月23日 13:43:42 +00:00Commented May 23, 2012 at 13:43
-
4
:cnoreabbrev <expr> W getcmdtype()==':'&&getcmdline()=~#'^W'?'w':'W'
kev– kev2012年07月27日 13:32:50 +00:00Commented Jul 27, 2012 at 13:32
With supplementary searching, I've found that someone asked nearly the same question as I.
:command <AliasName> <string of command to be aliased>
will do the trick.
Please be aware that, as Richo points out, the user command must begin with a capital letter.
-
6Using :command is good solution. :cnoreabbrev doesn't understand cmd1|cmd2, :command does.Pavel Strakhov– Pavel Strakhov2011年04月14日 00:01:08 +00:00Commented Apr 14, 2011 at 0:01
-
1A less confusing way to write this is,
:command AliasName string of command to be aliased
Alec Jacobson– Alec Jacobson2013年08月21日 16:36:45 +00:00Commented Aug 21, 2013 at 16:36 -
9This won't handle/forward any
command
arguments, like-nargs
,-complete
etc.blueyed– blueyed2014年02月11日 10:21:28 +00:00Commented Feb 11, 2014 at 10:21 -
What about
:Q!
or:W!
?Jacklynn– Jacklynn2014年07月31日 18:56:11 +00:00Commented Jul 31, 2014 at 18:56 -
14Just to be very literal: put
:command W w
in the.vimrc
file.isomorphismes– isomorphismes2014年09月25日 19:54:21 +00:00Commented Sep 25, 2014 at 19:54
I find that mapping the ;
key to :
would be a better solution, and would make you more productive for typing other commands.
nnoremap ; :
vnoremap ; :
-
3This is the single best tip for vim. I'm so used to it now that every time I encounter the normal behavior, it takes me a few tried to get my mind retrained.airstrike– airstrike2015年02月24日 19:58:33 +00:00Commented Feb 24, 2015 at 19:58
-
4This is not an answer to the question.Flimm– Flimm2018年08月24日 11:45:28 +00:00Commented Aug 24, 2018 at 11:45
-
13@Flimm No, but it makes OP's issue go away.Dessa Simpson– Dessa Simpson2018年09月24日 18:02:30 +00:00Commented Sep 24, 2018 at 18:02
-
5When using
t
orf
, one can usually use;
to go to the next occurrence. One can safely map that the other way, even if you mapped semicolon to colon. There won't be an alias loop.nnoremap : ;
Luc– Luc2019年03月05日 08:27:17 +00:00Commented Mar 5, 2019 at 8:27 -
2@EricDuminil If you go from
:
to;
, then you're no longer using shift when typing;w
and therefore won't accidentally typeW
instead ofw
.Dessa Simpson– Dessa Simpson2024年03月10日 08:10:24 +00:00Commented Mar 10, 2024 at 8:10
The best solution involves writing a custom function for handling abbreviations that only take place in the beginning of the command bar.
For this, add the following your vimrc file or anywhere else.
" 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')
A few useful abbreviations from the source material where I found this stuff:
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")
-
3There is a built-in function
string()
that does the same thing as yoursSingle_quote()
.ZyX– ZyX2012年05月23日 00:57:08 +00:00Commented May 23, 2012 at 0:57 -
But don't you have to type
<c-]>
, space, or some other non-keyword character after abbreviations? So I'd end up typing:s/<c-]>
or:s/ <bs>
, which hardly seems faster.Jacktose– Jacktose2025年05月23日 23:38:12 +00:00Commented May 23 at 23:38
Suppose you want to add alias for tabnew command in gvim. you can simply type the following command in your .vimrc file (if not in home folder than create one)
cabbrev t tabnew
-
3This will cause a command like
:saveas t example
to be replaced with:saveas tabnew example
Flimm– Flimm2018年08月24日 11:56:48 +00:00Commented Aug 24, 2018 at 11:56
Maybe you would like to map one of your function keys (F1..F12) to :w ? Then put this into your .vimrc:
noremap <f1> :w<return>
inoremap <f1> <c-o>:w<return>
(ctrl-o in insert mode switches temporarily to normal mode).
Safest and easiest is a plugin such as cmdalias.vim or my recent update vim-alias of it that take into account
- preceding blanks or modifiers such as
:sil(ent)(!)
or:redi(r)
, - range modifiers such as
'<,'>
for the current visual selection, - escape special characters such as quotes, and
- check if the chosen alias is a valid command line abbreviation.
I think @ZyX's answer is great, but if you're using a newer version of neovim (0.5+), you might want to define the function using lua instead. Here's one way you could do it:
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
Then, you'd drop the call
from call SetupCommandAlias("pg", "postgres://")
and just use the function like this: SetupCommandAlias("pg", "postgres://")
.
n.b. If using it from a .vim
file instead of a .lua
file, you'd need to prefix the function call with lua
, i.e. lua SetupCommandAlias("pg", "postgres://")
.
:W
you could a map a key to perform the saving. If you are used to some program that saves with Ctrl-s, there are these mappings from $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>