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.