7

: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?

2 Answers 2

8

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
    endwhile
    call histdel('/', -1)
    let @/ = save
endfunction

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:

:g/func/#
:g/^#/#
:g/::/#
5
  • 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, 2016 at 21:38
  • 1
    Maybe, but you would trade portability for virtually no benefit.
    – romainl
    Jan 8, 2016 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, 2016 at 23:53
  • I'm curious: should that be histdel('/', -1) or histdel('search', -1)?
    – muru
    Jan 17, 2016 at 18:38
  • @muru, both values are correct, use the one you prefer. See :help hist-names.
    – romainl
    Jan 17, 2016 at 20:43
2

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
  endif
  if a:forward
    let direction = '/'
  else
    let direction = '?'
  endif
  execute 'silent normal! ' . direction . pattern . "\n"
endfunction

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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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