ps-aux
ps-aux

Reputation: 12136

How to imap a character in Vim based on previous character

I have created the following mapping to simulate behaviour in some IDEs where when you insert { after a function declaration like foo() a closing } and empty row is inserted automatically and cursor is set to the empty row on tabbed position.

:imap { {<CR><CR>} <up><Tab>     

This of course does this behavior when I insert { in any context. How do I do it based on the previously inserted character? Must be a vim script function involved? Note: I do not want to use external vim plugins.

Upvotes: 1

Views: 159

Answers (3)

Ingo Karkat
Ingo Karkat

Reputation: 172520

You'll find multiple approaches and a list of plugins on the Automatically append closing characters Vim Tips Wiki page. Note that though there are simplistic solutions, they usually have some downsides, and the whole approach is unfortunately broken in Vim 7.4 with regards to undo.

Upvotes: 0

romainl
romainl

Reputation: 196486

These code snippets give you the character just before and just after the cursor when in insert mode:

let previous_character = getline(".")[col(".")-2]
let next_character     = getline(".")[col(".")-1]

You can use them in an <expr> mapping:

:inoremap <expr> { getline(".")[col(".")-2] == " " ? "{^M}^OO" : "{"

The pointless mapping above checks if the character before the cursor is a space before deciding if it inserts a { or an expanded {}.

If you want a "smart" mapping you won't be able to avoid writing one or more functions. The one I use, for example, is 69 lines long.

Upvotes: 1

Luchs
Luchs

Reputation: 1183

IDEs usually do this expansion after typing {<CR>, which is easy to do in vimscript:

:imap {<CR> {<CR><CR>} <up><Tab>

This will not expand if you keep on typing other things on the same line.

The caveat is that there's a small delay when typing a { with this mapping. See the 'timeout' and 'timeoutlen' options for details.

Upvotes: 1

Related Questions