15

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?

muru
  • 24,838
  • 8
  • 82
  • 143
Andrew Ferrier
  • 6,729
  • 7
  • 28
  • 41

2 Answers2

10

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
statox
  • 49,782
  • 19
  • 148
  • 225
1

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.

Rich
  • 31,891
  • 3
  • 72
  • 139