:help section states:

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.

Is it possible to change the [ and ] commands to jump to a different character or pattern. For example in Markdown, I would like sections defined as titles, lines beginning with # aka the pattern ^#. Similarly in Haskell, I would like it to jump to the next/previous type definition (line containing ::). Both would be set in their respective ftplugin files.

I have tried using map ]] /^#<CR>w but this does not seem to work as expected and leaves text highlighted. It seems like there would be a better way to achieve this.

Is this possible and if so, how would I achieve this?


I stole and renamed the function below from $VIMRUNTIME/ftplugin/python.vim :

function! CustomJump(motion) range
    let cnt = v:count1
    let save = @/
    mark '
    while cnt > 0
        silent! execute a:motion
        let cnt = cnt - 1
    call histdel('/', -1)
    let @/ = save

and I use it like this in after/ftplugin/javascript.vim to jump from function definition to function definition:

nnoremap <buffer> ]] :call CustomJump('/function')<cr>
nnoremap <buffer> [[ :call CustomJump('?function')<cr>

You could use it like this for markdown:

nnoremap <buffer> ]] :call CustomJump('/^#')<cr>
nnoremap <buffer> [[ :call CustomJump('?^#')<cr>

or like that for haskell:

nnoremap <buffer> ]] :call CustomJump('/::')<cr>
nnoremap <buffer> [[ :call CustomJump('?::')<cr>

But don't forget the awesome :global command:

  • 1
    If my Vim version has :keepjumps, could I remove mark ', and if I have :keeppatterns could I remove let save = @/ and call histdel('/', -1) let @/ = save and replace silent! execute a:motion with something like silent! execute 'keepjumps keeppatterns ' . a:motion? – saginaw Jan 8 '16 at 21:38
  • 1
    Maybe, but you would trade portability for virtually no benefit. – romainl Jan 8 '16 at 22:28
  • I completely misunderstood the purpose of mark ', I thought it was to prevent the jumplist to be modified. But in fact, I think it's the opposite, it's for adding an entry in the jumplist so that you can come back to where you were with '' or ``, sorry. Anyway this is some great code! With this, you can define with autocommands different type of sections for different filetypes. – saginaw Jan 8 '16 at 23:53
  • I'm curious: should that be histdel('/', -1) or histdel('search', -1)? – muru Jan 17 '16 at 18:38
  • @muru, both values are correct, use the one you prefer. See :help hist-names. – romainl Jan 17 '16 at 20:43

The vim-markdown plugin has a function for this in Markdown files:

function! s:JumpToHeader(forward, visual)
  let pattern = '\v^#{1,6}.*$|^.+\n%(\-+|\=+)$'
  if a:visual
    normal! gv
  if a:forward
    let direction = '/'
    let direction = '?'
  execute 'silent normal! ' . direction . pattern . "\n"

It matches both ATX and setext headers (# foo as well as foo with --- below it). The function is mapped by default to [[ and ]] by the plugin. However, it could benefit from a call to histdel() (as seen in romainl's answer).

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.