I'm trying to create an abbreviation with the command ab:

if I type if ( under INSERT mode, I want some piece of code to be printed immediately.

Here is what I've tried:

ab if<Space>( if<Space>()<Space>{<CR>}

But I always get an error: E474: Invalid argument. It seems that <Space> causes some error.

Is it possible to create an abbreviation with <Space>?


This is not directly possible.

See :help abbreviations which talks about the three types of abbreviations, but even the (least restrictive) "non-id" type mentions "the other characters may be of any type, excluding space and tab."

And also:

Examples of strings that cannot be abbreviations: a.b, #def, a b, _$r

You can work around this, by using an <expr> abbreviation that triggers a function that checks the words preceding the one currently being abbreviated and decide to expand it or not (not expanding it means expanding it to the same text.)

But even that doesn't really help much in your particular case, since "an abbreviation is only recognized when you type a non-keyword character." So you would have to expect a symbol or whitespace after the ( to trigger the abbreviation, but you're quite likely to find a variable name or function call there, which would be an alphanumeric character and would not expand and abbreviation.

Perhaps a more convenient way to handle this is to use an inoremap, since that will trigger when the key itself is pressed and not after the whole word is entered as a word. You could use an inoremap <expr> ( ... to trigger the mapping when the ( is typed, then check whether it's preceded by an if word and, in that case, expand the sequence you wanted.

See this answer for an iabbrev <expr> that inspects the preceding word when deciding whether to expand an abbreviation, and this answer for an advanced use of inoremap <expr> that might be somewhat similar to yours.

But if you're really serious about having Vim type your code for you, you should really look into a snippet engine such as UltiSnips.

UltiSnips allows you to define your snippets using a much higher level templating language and it takes care of the low-level details such as the Vim mappings needed to make the snippets work.

It also allows you to define "fields" through markers in your templates, which you'll find you really need for a template to an if or a for, since you typically want to enter one or more expressions before the cursor lands in the inner code block.

I'd seriously recommend that you'd take a look into it.

| improve this answer | |

The way to do it is to have a mapping on ( that detects its context: if, while, for... and expands depending on this context.

What I've chosen in my lh-cpp plugin is instead to have an abbreviation on if that expands into the full control-statement snippet if, and only if, we are not in the context of a comment or of a string. I also provide snippets not based on abbreviations but on a snippet/template engine. Plus abbreviations and snippets that surround with control statements. Bracket placement... can be tuned through lh-style options that lh-cpp depends upon.

| improve this answer | |

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.