1

I'm trying to implement a mapping for making the vim cursor jump to a pre-defined search pattern without overriding the current search, but it is falling short in multiple ways:

function! JumpToBlockEnd()
    let search = @/
    let @/ = '\%^\|^# ----------'   "predefined search pattern
    normal n
    let @/ = search
endfunction
noremap m] :call JumpToBlockEnd()<CR>

  1. It isn't accepting a count. I would like to be able to do something like 3m] to jump to the third occurrence of the pattern
  2. It exits visual mode. If I want to highlight text from the current position to the intended jump pattern position, I want to be able to do vm] to continue with visual highlighting
  3. This is a minor issue, but if there was a search pattern prior to executing the function that was called with reverse lookup ? instead of forward lookup /, it reassigns that pattern always to the forward lookup /.

I'm making the above specific mapping to enable block-like editing and execution in vim, sort of like jupyter notebook. Here's the file I'm testing this function on:


x = 3
y = 4

# ---------- [block] ----------:

hi = 'hi'

hi = 'hi'
# ---------- [end] ----------:

hey = 'hey'

Edit: Based on the accepted answer below, I created a function that takes the pattern as an input and can also be passed flags, enabling reverse search:

function! JumpToPattern(count, visual, pattern, flags)
    if a:visual
        normal! gv
    endif
    for _ in range(a:count)
        call search(a:pattern, a:flags)
    endfor
endfunction
nnoremap m] :<c-u>call JumpToPattern(v:count1, 0, '\%$\\|^# ----------', '')<cr>
xnoremap m] :<c-u>call JumpToPattern(v:count1, 1, '\%$\\|^# ----------', '')<cr>
nnoremap m[ :<c-u>call JumpToPattern(v:count1, 0, '\%^\\|^# ----------', 'b')<cr>
xnoremap m[ :<c-u>call JumpToPattern(v:count1, 1, '\%^\\|^# ----------', 'b')<cr>

1 Answer 1

3

You can use the search() function (see :help search())

function! JumpToBlockEnd(count, visual)
    if a:visual
        normal! gv
    endif
    for _ in range(a:count)
        call search('\%^\|^# ----------')
    endfor
endfunction

nnoremap m] :<c-u>call JumpToBlockEnd(v:count1, 0)<cr>
xnoremap m] :<c-u>call JumpToBlockEnd(v:count1, 1)<cr>

Here, we distinguish normal and visual maps because we need to re-enter visual mode upon calling the function (gv).

If your vim is new enough you can use <Cmd>, which is simpler

function! JumpToBlockEnd(count)
    for _ in range(a:count)
        call search('\%^\|^# ----------')
    endfor
endfunction

noremap m] <Cmd>call JumpToBlockEnd(v:count1)<cr>
2
  • Thanks, but this doesn't address the limitations 1. and 2 (it doesn't accept a count and it breaks visual mode). It does however address limitation 3
    – WalksB
    Sep 25, 2021 at 20:00
  • 1
    @ZaidGharaybeh please see the edits
    – Mass
    Sep 25, 2021 at 20:10

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.