If I am using IntelliJ and I hover over a close bracket for a scope that starts somewhere that is not currently visible, it shows a popup at the top of the window previewing the line where with the corresponding open bracket.

enter image description here

Is there some way to do this in Vim? I tried searching but I don't know what this is called so it is hard to find any useful results. I think it should be possible using balloons, but even if there is a way that just shows a preview as the top visible line of the buffer that would be great.


Yes- the plugin match-up has this feature: https://github.com/andymass/vim-matchup

enter image description here

enter image description here

Using the option

let g:matchup_matchparen_offscreen = { 'method': 'popup' }

There is also the ability to show the match in the statusline (the default):

let g:matchup_matchparen_offscreen = { 'method': 'status' }`
  • I reposted your answer here (community wiki); just FYI
    – D. Ben Knoble
    Apr 3 '20 at 19:04

I guess you should use Mass's plugin in his answer.

If you want to know how to do it, you can check this answer.

This is a small task, you can do it with :h popup window

The result looks like this:

|  1 hello bracket {
| 12
| 13
| 14
| 15
| 16
| 17
| 18
| 19
| 20 }

Read comment as explanation:

" show open pair on left top of current window if cursor on (, [ or {.
" close popup window if cursor moved in normal, visual, insert mode.
augroup pair_popup_group | au!
  autocmd CursorHold * call s:popup_open_pair()
augroup end

let s:pair_popup_winid = 0

function s:popup_open_pair() abort

  " check if already popped up
  if s:pair_popup_winid != 0

  " check if current character is close pair character
  let c = matchstr( getline('.'), printf('\%%%dc.', col('.') ) )
  if stridx(')]}', c) == -1

  " check if open pair in current window.
  " get matching pair line, add space padded line number to it.
    let win_top_buf_lnum = line('.') - winline() + 1
    let cview = winsaveview()
    keepjumps norm! %
    if line('.') >= win_top_buf_lnum

    let content = printf( ' %*d %s', len( line('$') ), line('.'), getline('.') )
    call winrestview(cview)

  " show matching pair line on first screen line of current window
  let wpos = win_screenpos( winnr() )
  let s:pair_popup_winid = popup_create(
        \ content, { 'line' : wpos[0], 'col' : wpos[1] })

  " close popup if cursor moved
  autocmd pair_popup_group CursorMoved,CursorMovedI * ++once
        \  call popup_close(s:pair_popup_winid)
        \| let s:pair_popup_winid = 0


You could probably mess around with the new popup features.

Or you might be able to do something with :ptag.

But your best bet is to learn the mighty % key.

To quote :help %:

%           Find the next item in this line after or under the
            cursor and jump to its match. |inclusive| motion.
            Items can be:
            ([{}])      parenthesis or (curly/square) brackets
                    (this can be changed with the
                    'matchpairs' option)
            /* */       start or end of C-style comment
            #if, #ifdef, #else, #elif, #endif
                    C preprocessor conditionals (when the
                    cursor is on the # or no ([{
            For other items the matchit plugin can be used, see
            |matchit-install|.  This plugin also helps to skip
            matches in comments.

What this means is that for almost any construct that has a concept of "matching," you can hit % to jump to the next "match."

In the case of your switch example, from

switch (var) {
  // lots of code...
} // <- cursor

Hitting % takes you to the switch line, and % takes you back. Easy-peasy.

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.