By Sean


2010-10-07 04:31:47 8 Comments

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 – what seems to be like more than 50% of the time – always manage to capitalise 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. Unfortunately, that is not what I'm looking for.

7 comments

@ZyX 2010-10-07 08:03:16

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 which 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.

@Sean 2010-10-13 01:57:51

This answer is the safest and most reliable for me.

@cprn 2012-04-25 02:00:26

If 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>

@Andy Terra 2012-05-22 19:17:14

Actually, 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.

@Chris Morgan 2012-05-23 13:43:42

Absolutely; this is a horrible idea. You should never, ever, ever do this.

@kev 2012-07-27 13:32:50

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

@ZyX 2012-07-27 14:02:05

@kev Strange manner of saying “you’ve case problems here”. And an abbreviation with another problem: type :W<C-v> W<Space> But thanks, that was fixed. // I had two errors: getcmdline() is# 'w' which is impossible and swapped 'w' and 'W' in result.

@ZyX 2012-07-27 14:05:46

@kev By the way, using regular expressions where they are not needed is bad for performance. This is not perl, getcmdline()[0] is# 'W' serves the same purpose.

@kev 2012-07-27 14:07:04

My PC is not very slow. :)

@ZyX 2013-04-26 19:44:11

@CelsoDantas Replace cnoreabbrev with cnoremap then. With getcmdtype() … condition it should not be too intrusive. Or define two abbreviations.

@Kyle Strand 2013-06-20 18:02:34

@CelsoDantas Altering a file with some kind of custom command and then immediately quitting is dangerous anyway....

@idbrii 2013-12-13 19:09:02

You can use cmdalias to simplify this to :Alias W w and it will do the getcmdline magic for you.

@SeldomNeedy 2015-03-20 22:22:45

With regards to your edit, my only regret is that the fun! had to eventually come to an end.

@user14416 2016-06-06 16:32:47

I have a command without any arguments and to get it expanded I need to hit space. Is it possible to avoid this?

@ZyX 2016-06-07 00:57:19

@user14416 To verify that it gets expanded, not to get it expanded. <Enter> expands abbreviations just as good as a space, just you are unable to check or react if expansion is unwanted.

@user14416 2016-06-07 10:12:59

@ZyX Sorry, I have not fully understand your answer. I am using :Alias q qall. And :q<Enter> only does q, but not :qall<Enter>, am I missing something?

@ZyX 2016-06-07 14:35:52

@user14416 What is “:Alias”? If I use cnoreabbrev <expr> q ((getcmdtype() is# ':' && getcmdline() is# 'q')?('echo 1'):('echo 2')) I get 1 when typing :q<Enter> as expected. If I use call SetupCommandAlias('q', 'echo 1') (with function from my answer) I get 1 as expected. If you got buggy command somewhere not from this answer why are you asking here?

@user14416 2016-06-10 15:00:25

@ZyX The reason was that I had mapping cmap <Cr> <Cr>. Why it is not supposed to work when I have this kind of mapping?

@ZyX 2016-06-10 18:16:04

@user14416 cmap <CR> <CR> is not interferring with such aliases. What is is cnoremap. Check what is the difference in the help.

@Enno 2016-04-11 17:45:57

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.

@fent 2014-02-13 17:50:41

I find that mapping the ; key to : would be a better solution, and would make you more productive for typing other commands.

nnoremap ; :
vnoremap ; :

@Andy Terra 2015-02-24 19:58:33

This 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.

@Flimm 2018-08-24 11:45:28

This is not an answer to the question.

@Duncan X Simpson 2018-09-24 18:02:30

@Flimm No, but it makes OP's issue go away.

@Luc 2019-03-05 08:27:17

When using t or f, 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 : ;

@Sean 2010-10-07 04:34:56

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.

@Pavel Strakhov 2011-04-14 00:01:08

Using :command is good solution. :cnoreabbrev doesn't understand cmd1|cmd2, :command does.

@Sebastián Grignoli 2012-09-24 21:07:47

The OP was asking to map :W to :w, so it does work.

@Alec Jacobson 2013-08-21 16:36:45

A less confusing way to write this is, :command AliasName string of command to be aliased

@blueyed 2014-02-11 10:21:28

This won't handle/forward any command arguments, like -nargs, -complete etc.

@Jack 2014-07-31 18:56:11

What about :Q! or :W!?

@isomorphismes 2014-09-25 19:54:21

Just to be very literal: put :command W w in the .vimrc file.

@Sandip 2013-02-27 03:46:58

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

@Flimm 2018-08-24 11:56:48

This will cause a command like :saveas t example to be replaced with :saveas tabnew example

@Andy Terra 2012-05-22 19:22:13

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('[email protected]',  '[email protected]\v')
call Cabbrev('%[email protected]', '%[email protected]\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("'<,'>[email protected]", "'<,'>[email protected]\v")
call Cabbrev("'<,'>s!", "'<,'>s!\v")

@ZyX 2012-05-23 00:57:08

There is a built-in function string() that does the same thing as yours Single_quote().

@Benoit 2010-10-07 06:36:10

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).

Related Questions

Sponsored Content

19 Answered Questions

[SOLVED] Duplicate a whole line in Vim

63 Answered Questions

[SOLVED] Calling an external command from Python

29 Answered Questions

[SOLVED] Vim clear last search highlighting

  • 2009-03-18 09:00:32
  • Gabriel Solomon
  • 464076 View
  • 1829 Score
  • 29 Answer
  • Tags:   vim highlight

11 Answered Questions

[SOLVED] How to replace a character by a newline in Vim

11 Answered Questions

[SOLVED] How do I exit the Vim editor?

  • 2012-08-06 12:25:47
  • jclancy
  • 2012358 View
  • 3566 Score
  • 11 Answer
  • Tags:   vim vi

46 Answered Questions

[SOLVED] What's a quick way to comment/uncomment lines in Vim?

  • 2009-11-04 21:06:32
  • Ethan
  • 831183 View
  • 1082 Score
  • 46 Answer
  • Tags:   vim comments

7 Answered Questions

[SOLVED] How does the vim "write with sudo" trick work?

  • 2010-04-08 14:36:50
  • Doppelganger
  • 346680 View
  • 1351 Score
  • 7 Answer
  • Tags:   vim sudo

3 Answered Questions

13 Answered Questions

[SOLVED] How to do case insensitive search in Vim

50 Answered Questions

[SOLVED] What is your most productive shortcut with Vim?

  • 2009-08-02 08:08:28
  • Olivier Pons
  • 761144 View
  • 1126 Score
  • 50 Answer
  • Tags:   vim vi

Sponsored Content