2

I often type :w< instead of :wq, so I wanted to redefine it (in order to avoid the creation of a < file) as following:

command! w< w

But it seems to not be allowed:

Error detected while processing /home/mevimrc:
line  222:
E182: Invalid command name
Press ENTER or type command to continue

Any workaround to avoid this typing mistake?

Thanks in advance.

2
  • 2
    Welcome to Vi and Vim!
    – filbranden
    Nov 2 '20 at 22:26
  • 2
    Filbranden has already given you a detailed answer regarding the problems of your attempt and how to circumvent them. I just feel the duty to remember you that :x is almost always equal to :wq.
    – Quasímodo
    Nov 3 '20 at 13:03
5

The reason why the approach using user commands (with :command!) does not work is that user commands are quite restricted in how they are allowed. They must always start with an uppercase letter (so they don't clash with Vim native commands) and their names may not include special characters (such as <.)

Instead of user commands, you can use :cabbrev to create an abbreviation that turns w< into wq in the command-line.

A naive approach using cabbrev is:

cabbrev w< wq

The problem with this approach is that it will trigger if the word w< is found in later parts of the command-line (not just at the beginning, as a command.) It will also trigger for other features that use the last line for input and also expand cabbrev. One significant example of the latter is search, so if you search for w< Vim might expand it to wq (if it appears on its own, since abbreviations only trigger when the left-hand expression is a word on its own.)

In order to prevent those, you can use an <expr> mapping, together with the getcmdtype() and getcmdpos(), to ensure the w< abbreviation only triggers when typed on an Ex command-line (entered through :) and when it's typed at the beginning of the command (cursor position will be 3 after typing it, which is one more than the length of the expression.)

You can accomplish that with:

cabbrev <expr> w< getcmdtype() == ':' && getcmdpos() == 3 ? 'wq' : 'w<'

Note that the expression expands to w< when the conditions don't hold. That's so that w< will have no effect (by mapping to itself) in those cases.

6
  • Thanks for your answer but it does not work in ViM :/
    – GlinesMome
    Nov 3 '20 at 18:50
  • @GlinesMome Yes this should work in VIM, that's where I tested it... I have Vim 8.2.1885, but none of these features are actually new, so I'd expect it would work on an older version of Vim as well... Can you expand on how it does not work for you? Does the simpler version of cabbrev w< wq work as expected?
    – filbranden
    Nov 3 '20 at 19:23
  • Actually I use ViM 8.2.1704, and it still creates a < file, even with the simple expression. They is no substitution.
    – GlinesMome
    Nov 4 '20 at 17:38
  • Does it expand if you type :w< followed by a "space"?
    – filbranden
    Nov 4 '20 at 18:10
  • Ah, yes, it works with a space, but not when I hit Enter.
    – GlinesMome
    Nov 4 '20 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.