2

Currently, I have the following map for cpp files: inoremap ;;f for<Space>()<Space>{<Enter>}<Esc>kkf)i

Which essentially allows me to quickly setup a c-style for loop. However, I have been wondering for the longest time whether one could supply arguments to an inoremap command, so that typing: var bound ;;f would automatically end up as:

for (int var = 0; i < bound; var++) {

}
5

TL;DR: Yes, you can find simple ways to pass arguments to mappings (in particular inoremap), but they tend to be somewhat awkward or limited in some ways.

For the particular case you mentioned, using a snippet manager, such as UltiSnips.


Having said that, there are a few ways to make your mappings take parameters.

For instance, you could prompt the user for the variable and bound, using the input() function. An example of that would be:

function! ForLoop()
  let var = input('Variable name? ')
  let bound = input('Bound? ')
  return "for (int ".var." = 0; ".
      \ var." < ".bound."; ".
      \ var."++) {\n}\eO"
endfunction
inoremap <expr> ;;f ForLoop()

This mapping uses <expr> to call a function and have it return the keystrokes that will get expanded. As it's an inoremap, the keystrokes will happen in insert mode.

The function composes a string with the expansion, starting with the "for" statement. At the end, the \n inserts a line break, then the \e exits insert mode and the O normal mode command begins a new line above the current one, putting you back in insert mode in between the curly braces.

One issue with this approach is that prompting might break the editing flow. You also don't get access to most of Vim's editing commands while answering the prompts. That makes this method somewhat awkward and limited.

Another possibility is to have the mapping consume the text you typed on the current line before the mapping was invoked. For example:

function! ForLoop()
  let [var, bound] = matchlist(getline('.'), '\v\s*(.*);(.*)')[1:2]
  return "\<C-u>for (int ".
      \ var." = 0; ".
      \ var." < ".bound."; ".
      \ var."++) {\n}\eO"
endfunction
inoremap <expr> ;;f ForLoop()

The \<C-u> at the start issues a Ctrl-U in order to delete the beginning of the line, that was used as arguments to the mapping.

You can invoke this mapping with i;100;;f, which will expand to a for loop going from 0 to 99 over the variable i.

This approach has some advantages, in that you get access to Vim's editing commands when entering the parameters. But it's somewhat intuitive that you enter the arguments first, use a somewhat ad-hoc separator (;, in this case) and the arguments disappear.

So, in short, while some approaches are possible, they're far from what a snippet manager can do.

A snippet manager exposes a much friendlier UI, typically showing you the expansion at first, then allowing you to fill in the fields in the order you specify, repeating them when they're needed in more than one place, and allowing you to skip to the next field by pressing "Tab" or a similar keystroke.

Furthermore, snippet managers implement a generic engine, so you can define your own snippets using a simple templating language and they'll expand them correctly for you.

So while you can get something fairly simple done in a few lines of Vimscript, it's probably worth investing into setting up and learning to use a snippet manager, particularly if you expect to use many similar templates.

  • But of the methods you give are not convenient and not elegant(especially the second one). Why reinventing the wheel when you have Snippets? – eyal karni Aug 22 at 21:05
  • 1
    @eyalkarni That was exactly my point! It can be done, but using Snippets is much better and much easier. Re-read my first paragraph and you'll see that's what I'm saying. As for why describe these methods: while they're not appropriate for this exact use case (expanding a for), they might be good in other situations where Snippets are not the best answer. So describing these might help others with similar question but different use case. Also, it explains why Snippets are much better (by contrasting with the alternative.) – filbranden Aug 22 at 21:45

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.