views:

86

answers:

3

In Vim, you can make it so each time you write "FF" on insert mode changes to some code by using:

:iab FF for ( int i = 0 ; i < n ; i++ )

But is there any way to use this with arguments? Something like C's #defines, so if I write

FF(e, 10)

It becomes

for ( int e = 0 ; e < 10 ; e++ )

+1  A: 

You can include function definitions in abbreviations, but they cannot take arguments. This is an example from the vimdocs:

func Eatchar(pat)
   let c = nr2char(getchar(0))
   return (c =~ a:pat) ? '' : c
endfunc
iabbr <silent> if if ()<Left><C-R>=Eatchar('\s')<CR>

I guess you could maybe parse the abbreviation expression in the function, but I'm not sure if you can also include characters like parenthesis in the abbreviation. Maybe something here will give you an idea.

Edit: You can always do something like this:

:iab for() for(int i = 0; i < ; i++)<C-o>T<

Which lacks the argument autocompletion of course but lets you start typing it immediately.

kprobst
Using `<C-o>T<` is much better understandable and editable then a sequence of `<Left>`.
ZyX
@ZyX, obviously better, thanks. Edited.
kprobst
+5  A: 

Take a look at SnipMate (a vim plugin). You won't get arguments, but upon expansion of an abbreviation, it allows you to tab through modifiable areas. In the for example, you'll be brought to the i first, can edit it to be e, and it will change it to e in all areas of the for declaration. Then simply tab to the next area you'd like to change.

From the docs:

snipMate.vim aims to be an unobtrusive, concise vim script that implements some of TextMate's snippets features in Vim. A snippet is a piece of often-typed text that you can insert into your document using a trigger word followed by a .

For instance, in a C file using the default installation of snipMate.vim, if you type "for" in insert mode, it will expand a typical for loop in C:

for (i = 0; i < count; i++) {

}

To go to the next item in the loop, simply over to it; if there is repeated code, such as the "i" variable in this example, you can simply start typing once it's highlighted and all the matches specified in the snippet will be updated.

The following is a nice helpful change to remap tab and s-tab to c-d and c-a, in case you don't want to lose the functionality of tab (in ~/.vim/after/plugin/snipMate.vim):

"""ino <silent> <tab> <c-r>=TriggerSnippet()<cr>
"""snor <silent> <tab> <esc>i<right><c-r>=TriggerSnippet()<cr>
"""ino <silent> <s-tab> <c-r>=BackwardsSnippet()<cr>
"""snor <silent> <s-tab> <esc>i<right><c-r>=BackwardsSnippet()<cr>
"""ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
ino <silent> <c-d> <c-r>=TriggerSnippet()<cr>
snor <silent> <c-d> <esc>i<right><c-r>=TriggerSnippet()<cr>
ino <silent> <c-a> <c-r>=BackwardsSnippet()<cr>
snor <silent> <c-a> <esc>i<right><c-r>=BackwardsSnippet()<cr>
ino <silent> <c-r><tab> <c-r>=ShowAvailableSnips()<cr>
nearlymonolith
Thanks! This is awesome!
Martín Fixman
I agree. I also made some changes to the ~/.vim/after/plugin/snipMate.vim file to remap away from `<tab>` since that was causing problems for me. I edited them in above - basically just changed `<tab>` and `<s-tab>` to `<c-d>` and `<c-a>`.
nearlymonolith
A: 

mu-template support interactive templates. With it, you can either ask something to the user, or reuse any variable, apply computation on it if you which (detecting that i is already use in the current scope is doable), and use the result in the text you will expand.

Luc Hermitte