Matched pairs and friends

March 05, 2021

Let's talk about the matched pairs: parenthesis, brackets, quotes, any symbols that come in pairs.

If we put the cursor on an opening parenthesis ( and press %, it will jump to the corresponding closing one ).

Which symbols are considered to be matched?

Run set matchpairs?. This global variable contains all the paired symbols Vim knows about.

By default, it looks something like (:),{:},[:],<:>.

We can easily override it if we want. Say, set matchpairs+=a:b. Now % can take us between a and b.

Matchit

There's a Vim plugin that nowadays is a part of the Vim distribution, which means you already have it installed. It enhances the % operator functionality in several ways.

It significantly extends the number of matched pairs that % operator knows about. They are stored in a different variable :echo b:match_words. As the name suggests, the matched pairs can also be words, and even regular expressions are supported.

Many of the filetype plugins override this list to make it useful for a specific language.

For example, in a ruby, file I can jump between def and end keywords as they are added to the list as matching pairs.

Matchup

Even though matchit is quite solid, there's a plugin that takes it to the next level. It's called andymass/vim-matchup, and it adds some more niceties like highlighting the matched symbol/keyword when the cursor is on it.

Now we can see exactly where's it's going to jump when we press %.

Auto-closing plugins

Almost any IDE nowadays has this behaviour that if you put an opening parenthesis, ( it will automatically add a closing one ). Vim can't do that out-of-the-box, but there's a plugin for that.

Meet jiangmiao/auto-pairs. I can't live without that one. The default list can be extended, see g:AutoPairs variable.

For Rubyists out there, there's a cool tpope/vim-endwise plugin that ends the language-specific constructs like def...end, if...else, etc. It also supports Elixir, and some other languages.

Finally, for HTML there's alvan/vim-closetag that automatically closes tags.

To make it work properly with JSX/TSX:

" add file extensions
let g:closetag_filenames = '*.html,*.tsx,*.jsx'

" make sure it only works for the JSX region
let g:closetag_regions = {
    \ 'typescript.tsx': 'jsxRegion,tsxRegion',
    \ 'javascript.jsx': 'jsxRegion',
    \ }

Vim-sandwich

Here's a handy plugin that allows to easily surround any word, sentence, any text object with something.

It's called machakann/vim-sandwich, and it works like this.

The basic mechanics is sa<text object><wrapper>.

For example, put the cursors on a word hello and press saiw" it will wrap that word with quotes: "hello".

Similarly, sri"' replaces double quotes with single ones, and sd) deletes the parenthesis.

What makes this plugin stand out compared to a similar and more popular tpope/vim-surround, is that it actually highlights the object before you press that last key, so it's clear what you're going to change.

What's next?

Vim For Developers

Vim For Developers

❄️ 35% off this Christmas season! ❄️

Learn Vim and upgrade your productivity to the next level by building the IDE of your dreams.

LEARN MORE