I'm trying to improve my ability to move around inside files in vim, especially using built-in mappings/commands. I edit a lot of different types, including shell, markdown, Python, etc. I'm familiar with the { and } keys, which move between paragraphs (in fact, anything with a blank lines separating them, which is useful even when writing code), as well as other keys of course.

However, I'm reading about the [[, [], ][, and ]] keys, which seem designed for moving between 'sections'. However, reading about sections in the vim documentation doesn't really help much; it seems to be written in terms of 'nroff', which I'm vaguely familiar with but isn't a file format I really know much about, or use. None of the filetypes I deal with seem to recognise those mappings/keys.

This makes me think that it would be useful to repurpose/rebind them. However, is there some non-nroff-specific meaning to a section? If so, how do I exploit/use it/turn it on?


2 Answers 2


The initial usage of these mapping is to navigate between functions in C files as said in :h section (note it's not the same topic as :h 'sections' that you linked in your question)

The "]" and "[" commands stop at the '{' or '}' in the first column.  This is
useful to find the start or end of a function in a C program.

So this is the definition of the section as Vim understands it: An arbitrary number of lines delimited by curvy brackets on the first column of a line.

Note that it is only if the curvy bracket characters are on the first column like in this code:

int main()
   printf("Hello, World!");
   return 0;

If your code doesn't follow this convention the help advises to remap the keys so that they look for curvy brackets anywhere in the line:

If your '{' or '}' are not in the first column, and you would like to use "[["
and "]]" anyway, try these mappings: 

   :map [[ ?{<CR>w99[{
   :map ][ /}<CR>b99]}
   :map ]] j0[[%/{<CR>
   :map [] k$][%?}<CR>

This is better but not ideal so it is sometimes a good idea to remap them to achieve the same purpose (e.g. navigate between functions) but for different filetypes. An example is in the standard vim ftplugin shipped with vim and neovim:

nnoremap <silent><buffer> [[ m':call search('^\s*fu\%[nction]\>', "bW")<CR>
vnoremap <silent><buffer> [[ m':<C-U>exe "normal! gv"<Bar>call search('^\s*fu\%[nction]\>', "bW")<CR>
nnoremap <silent><buffer> ]] m':call search('^\s*fu\%[nction]\>', "W")<CR>
vnoremap <silent><buffer> ]] m':<C-U>exe "normal! gv"<Bar>call search('^\s*fu\%[nction]\>', "W")<CR>
nnoremap <silent><buffer> [] m':call search('^\s*endf\%[unction]\>', "bW")<CR>
vnoremap <silent><buffer> [] m':<C-U>exe "normal! gv"<Bar>call search('^\s*endf\%[unction]\>', "bW")<CR>
nnoremap <silent><buffer> ][ m':call search('^\s*endf\%[unction]\>', "W")<CR>
vnoremap <silent><buffer> ][ m':<C-U>exe "normal! gv"<Bar>call search('^\s*endf\%[unction]\>', "W")<CR>

In any buffer with a filetype vim the mappings will navigate through the function thanks to searches based on the keywords function and endfunction (and their short version).

Several other plugins do this but you can also do it by yourself for your favorite filetypes.

After a quick search in the standard runtime files I found that Vim remaps these keys for the following filetypes:

  • abaqus
  • cobol
  • context
  • eiffel
  • hamster
  • j
  • mf
  • mp
  • python
  • ruby
  • rust
  • vim
  • zimbu
  • 3
    Hm i thought only [{ and friends handled curly braces. [[ also seemed more for .SH macros in nroff. Learned something today.
    – D. Ben Knoble
    Jun 4, 2020 at 20:00
  • This is great, thanks, much clearer! This is very helpful. Probably worth pointing out that [ and ] are not commands, though, as that help page says. [[ and ]] are the actual keymappings. [ and ] are prefix keys for a family of keybindings, where [ and ] move by sections. Jun 5, 2020 at 20:15
  • 4
    I wrote a little plugin to map [[/]] for a bunch of filetypes (and also make it behave more consistent) which may be of interest @AndrewFerrier Jun 6, 2020 at 1:25
  • @MartinTournoij thanks, that looks great! Jun 7, 2020 at 10:02
  • @AndrewFerrier While you are at it, you may also have a look at gbgar/pandoc-sections.vim (not me!) for some more inspiration. It provides i]] i][ a]] a][ I][ and A][. The plugin is currently not being maintained. Oct 12, 2020 at 11:40

The accepted answer by statox already covers what these days must be the main use case for ]] and [[: jumping to lines that start with a curly brace character.

I thought I'd just clarify the rest of their behaviour, which is described in :help section.

It's actually simpler than you might be presuming. You don't really need to know anything about nroff markup* to understand it: it just means that ]] and [[ will jump to any lines that start with a dot followed by any of the pairs of characters in the 'sections' option. Try pasting the following into a buffer and using ]] and [[:

.SH The
.NH cursor
.H stops
.HU here,
.nh here,
.XX here if you :set sections+=XX
.sh and here.

The commands will also stop at a line that begins with a CTRL-L character. This is slightly harder to include in an answer, but you can add such a line to your buffer by typing oCtrl-VCtrl-LEsc, starting from normal mode.

This last one is probably the only part of the above that isn't nroff-specific: I've seen CTRL-L characters used to divide C/C++ files into sections, and this character also appears to be ignored by the Python interpreters I have installed. I suspect it's safe to use it for this purpose in a fair number of file formats.

* nroff is a text-formatting program which is used for writing man pages. It takes marked-up text as input and outputs formatted text. You can think of an "nroff macro" as being similar to an HTML tag.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.