I can't reproduce your exact issue. The
ev<cr> mapping works fine for me. I don't see the
E492: Not an editor command: ev error you're seeing.
But I wanted to write an answer to recommend that you don't use
cnoremap for this purpose.
There are many limitations to the way
cnoremap works that make it really inconvenient for this purpose:
- It will expand anywhere in the command line, not only at the beginning of the line, where an Ex command is expected.
- It will expand not only in command mode (for Ex commands) but for search strings as well (so now
/ev will search for
vsplit $MYVIMRC instead!)
- It will "eat" keystrokes and not display them in full trying to match a mapping. Feels funny to start typing and not seeing the characters in feedback as you expect.
There's a way to accomplish something very close to what you want (see solution #3 below.)
But I have two suggestions that accomplish something similar to what you're asking for, not exactly the same, that I think are superior.
1. User-defined Command
You can define user commands in Vim, which is really close to what you seem to want here.
The main constraint is that user commands need to start with a capital letter, so you can't really use
ev exactly, you'd have to use
Ev instead. (I tend to find the former easier to type, by holding down the shift key while typing the "E" and "V".)
Having said that, it's pretty straightforward to define a user command for this purpose:
command! -bar EV vsplit $MYVIMRC<cr>
Once that's defined, you can use it with:
One advantage of user commands is that they support a whole range of features, you can have commands that use arguments, ranges, completion (for example, filenames), a second version with a bang (
2. Normal mode Mapping
Another option is to use a normal mode mapping. An advantage of that approach is that it's usually quicker to access it than using the command-line. (You need the
: to enter command mode, plus the "Enter" at the end. Plus, if you're using user commands, you need uppercase, which means holding the "Shift" key.)
You could simply use
<Leader>ev in Normal mode (three keystrokes) to accomplish the same.
<Leader> defaults to backslash, but many use
<Space> to make it even easier to access.
To use a normal mapping with
<Leader>, this is all you need:
nnoremap <Leader>ev :vsplit $MYVIMRC<cr>
You could also define a similar
xnoremap mapping so it also works in Visual mode, in which case use
<c-u> to delete the range first.
Access it with
\ev from Normal mode.
3. Command-mode abbreviation
You can use a command-line abbreviation (instead of mapping) to get closer to the intended result of making
:ev<cr> work. The abbreviation will not have the unintended side-effect of "eating" keystrokes while finding a match, since it only looks for matches when whole words were typed.
Additionally, by using an
<expr> abbreviation, you can only make it trigger for commands (not when typing a search pattern) and only trigger when it's typed as the command.
This is a start:
cabbrev <expr> ev getcmdtype() ==# ':' && getcmdline() ==# 'ev' ? 'vsplit $MYVIMRC' : 'ev'
This checks whether it's in command-line mode (see
:help getcmdtype() for more details) and whether the whole command-line matches
ev exactly (which means it's the command, since it's the first item) and only then expands it to the
vsplit command. Otherwise, expands to
ev itself, to keep no changes.
Note that this will produce a slightly weird behavior if you press a key other than "Enter" after
:ev. If you press "Space", it will show the expansion with the space at the end. Even more odd if you type some other non-word character like
There's a way for you to only expand the abbreviation if an "Enter" was typed by looking at
getchar(0) from the abbreviation. But it's not enough to test it, you'll have to save it to include it in the abbreviation, since you'll have consumed the character... You'll need a function:
if getcmdtype() ==# ':' && getcmdline() ==# 'ev'
let c = nr2char(getchar(0))
if c ==# "\r"
return "vsplit $VIMRC\r"
return 'ev' . c
cabbrev <expr> ev EditVimrc()
This seems to do exactly what you wanted. It even works if you mistype a character and go back to correct it. It won't work if you have additional spaces in the line though. And the implementation is pretty complex...
So I'd really recommend you go with #1 or #2 instead. But if you want the exact interface you described, this is the closest you'll get.