Elliot Nelson
Elliot Nelson

Reputation: 11557

Best way to create substitution macros in vim

I'd like to set up some custom auto-complete macros in vim. I'm thinking something like this (| represents the cursor position):

it<TAB>|

immediately becomes:

it("|", function () {
});

Is this possible using straight vim, or would I need a plugin? If so, is there a preferred plugin out there?

Upvotes: 3

Views: 458

Answers (2)

dlmeetei
dlmeetei

Reputation: 10391

Here is a abbreviation that you can use for your particular example

:inoreabbrev it it("", function () {<cr>});<esc>kf"a

Typing it followed by ctrl + ] in insert mode will render

it("|", function () {
});

and keep you in insert mode.

But I would definitely go for ultisnips and there is a screencast for creating snippets on the same page. That's why I am omitting the snippet here as you can do it yourself.

Upvotes: 2

user852573
user852573

Reputation: 1750

Using an abbreviation you could write something like this:

inorea it it("", function () {<cr>});<c-o>k<c-o>f"

The purpose of <c-o>k<c-o>f" at the end is to reposition your cursor inside the double quotes, but it may not work all the time.


Using a mapping, you could try this:

ino <expr> <tab> <sid>expand_last_word()

let s:your_expansions = {
                        \ 'it': '\<c-w>it(\"\", function () {\<cr>});\<c-o>k\<right>',
                        \ }

fu! s:expand_last_word() abort
    let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
    return has_key(s:your_expansions, last_word)
                \ ? eval('"'.s:your_expansions[last_word].'"')
                \ : "\<tab>"
endfu

You would have to add your abbreviations and their expansions inside the dictionary s:your_expansions.


Using the :read command, you could define larger snippets of code, and split them across several files:

ino <expr> <tab> <sid>expand_last_word()

fu! s:expand_last_word() abort
    let last_word = matchstr(getline('.'), '\v<\k+%'.col('.').'c')
    if last_word ==# 'it'
        return "\<c-w>\<c-o>:r /path/to/some_file\<cr>\<c-o>f\"\<right>"
    endif
    return "\<tab>"
endfu

Here /path/to/some_file should contain your snippet:

it("", function () {
});

They are very simple solutions, if you want something more robust, you probably need a snippets plugin. One of them is UltiSnips, which requires that your Vim version has been compiled with Python support (:echo has('python') or :echo has('python3') returns 1).

With UltiSnips, you would write your snippet like this:

snippet it "your description" b
it("$0", function () {
});
endsnippet

Here the definition is included between the keywords snippet and endsnippet. On the 1st line, you can describe the purpose of your snippet, inside the string in double quotes. It will be displayed by UltiSnips inside a list, if you've defined several snippets with the same tab trigger, and there's an ambiguity.

The ending b is an option to prevent the tab trigger it from being expanded anywhere else than the beginning of a line.

$0 is a tabstop, it stands for the position in which you want the cursor to be, once the snippet has been fully expanded.

The readme page on github gives a quick start, and some links to videos.

If you want to have a look at the snippets written by other people, you can install vim-snippets.

There are other snippet managers but I don't know them well enough to describe the syntax of their snippets. If you want a comparison, here's one, and here are links for some of them:

Upvotes: 3

Related Questions