Vim Tips Wiki
Advertisement

Proposed tip Please edit this page to improve it, or add your comments below (do not use the discussion page).

Please use new tips to discuss whether this page should be a permanent tip, or whether it should be merged to an existing tip.
created January 17, 2012 · complexity basic · author Dinshaw H Dastoor · version 6.0

Very often, we want to search for a symbol (say a local variable) only in a specified range of lines that are visually selected for example a function or in general any visual region so as to confine our search.

Already exists[]

A tip of this nature already exists: Search only over a visual range.

This tip is slightly different than the above because, here you visually select a range of lines, then press Esc and run a shortcut to search.

How to install[]

Please source the following lines into your .vimrc file:

let g:sbr = 1
let g:sbc = 1
let g:ser = line("G")
let g:sec = col("G")
let g:searchstr = "searchfirst"
let g:sdir = "f"

function GetBlockInput()
  let g:searchstr = input('find what?:')
  let g:sbr = line("'<")
  let g:sbc = col("'<")
  let g:ser = line("'>")
  let g:sec = col("'>")
endfunction

function FindFirstRegion()
  call GetBlockInput()
  call FindNextRegion()
endfunction

function FindFirstRegionBack()
  call GetBlockInput()
  call FindNextRegionBack()
endfunction

function FindNextRegionWork()
  let l:fout = 0
  let l:fin = 0
  let l:crw = line(".")
  let l:ccl = col(".")
  let l:frw = -1
  let l:fcl = -1
  if g:sdir == "f"
    let l:flags = "w"
  else
    let l:flags = "wb"
  endif
  call search(g:searchstr, l:flags)
  let l:srw = line(".")
  let l:scl = col(".")
  while l:srw != 0 && (l:srw != l:frw || l:scl != l:fcl)
    if (l:srw == g:sbr && l:scl >= g:sbc) || (l:srw == g:ser && l:scl <= g:sec) || (l:srw > g:sbr && l:srw < g:ser)
      let l:fin = 1
      break
    else
      if l:fout == 0
        let l:fout = 1
        let l:frw = l:srw
        let l:fcl = l:scl
      endif
    endif
    call search(g:searchstr, l:flags)
    let l:srw = line(".")
    let l:scl = col(".")
  endwhile
  if l:fout == 1 && l:fin == 0
    execute "normal " . l:crw . "G"
    execute "normal " . l:ccl . "|"
  endif
endfunction

function FindNextRegion()
  let g:sdir = "f"
  call FindNextRegionWork()
endfunction

function FindNextRegionBack()
  let g:sdir = "b"
  call FindNextRegionWork()
endfunction

nnoremap <Leader>/ :call FindFirstRegion()<CR>
nnoremap <Leader>? :call FindFirstRegionBack()<CR>
nnoremap <Leader>n :call FindNextRegion()<CR>
nnoremap <Leader>p :call FindNextRegionBack()<CR>

Sample usage[]

After visually selecting a range, press <Esc> and then press:

  • <Leader>/ to search forward for a string
  • <Leader>? to search backward for a string
  • <Leader>n for the next occurence
  • <Leader>p for the previous occurence of the search

where the Leader key by default is backslash.

Advantages[]

  • Remembers the visually slected region so can do a <Leader>n or <Leader>p again at any time in normal mode.
  • Keeps your regular "/" search different from the visually selected one, so can mix your n/p and <Leader>n and <Leader>p shortcuts.

Disadvantage[]

If you want normal searches ("/") and visually selected searches to use the same key ('/', 'n', 'p'), then you will not be able to use this script.

Comments[]

Advertisement