Skip to content

Instantly share code, notes, and snippets.

@sosmo
Last active August 29, 2015 14:13
Show Gist options
  • Save sosmo/471ae1aa73cefd223b68 to your computer and use it in GitHub Desktop.
Save sosmo/471ae1aa73cefd223b68 to your computer and use it in GitHub Desktop.
Tools for searching and replacing text in Vim
" Tools for searching and replacing text in Vim
" Search for the current visual selection
fun! StarSearch(direction)
let old_reg = getreg('"')
let old_regtype = getregtype('"')
exe 'normal! gvy\<esc>gV'
let @/ = EscapeMagic(@")
call histadd("/", @/)
call setreg('"', old_reg, old_regtype)
let v:searchforward = a:direction
norm! n
endfun
" In visual mode: * to search forward for the selection, # to search backwards
vnoremap * :<c-u>call StarSearch(1)<cr>:set hlsearch<cr>
vnoremap # :<c-u>call StarSearch(0)<cr>:set hlsearch<cr>
" Operator for putting text into the search register
function! SearchYank(type, start, end)
let old_reg = getreg('"')
let old_regtype = getregtype('"')
let mode = 'v'
if a:type == 'line'
let mode = 'V'
endif
exe 'norm! `'.a:start.'y'.mode.'`'.a:end
let @/ = EscapeMagic(@")
call setreg('"', old_reg, old_regtype)
call histadd("/", @/)
call feedkeys(":set hlsearch\<cr>", 'n')
endfunction
function! SearchYankOp(type)
call SearchYank(a:type, '[', ']')
endfunction
" yx{motion} to higlight text
nnoremap <silent> yx <Esc>:set opfunc=SearchYankOp<CR>g@
" Format and paste text to your searches. Asks for register name and the type of format you wish to convert the register into.
" You can use any register
" Types 'v', 'V' and 'm' convert your register to magic expressions (see :h magic).
" Type 'r' converts your register so that it works in the replace part of substitute
" Register '/' converts your last search so that it works in the replace part of substitute
fun! PasteEscaped()
echo "Register: "
let reg = nr2char(getchar())
let reg_content = getreg(reg)
if reg ==# '/'
return EscapeForReplace(UnEscapeSearch(reg_content))
endif
echo "Type: "
let type = nr2char(getchar())
if type ==# 'V'
return EscapeNoMagic(reg_content)
elseif type ==# 'm'
return EscapeMagic(reg_content)
elseif type ==# 'r'
return EscapeForReplace(reg_content)
endif
return EscapeVeryMagic(reg_content)
endfun
" In insert mode or command line: ctrl-q to format and paste text into searches
cnoremap <c-q> <C-R><C-R>=PasteEscaped()<CR>
inoremap <c-q> <c-g>u<C-R><C-R>=PasteEscaped()<CR>
fun! ConvertSpecials(string)
let result = substitute(a:string, '\n', '\\n', "g")
let result = substitute(result, '\t', '\\t', "g")
return result
endfun
fun! EscapeVeryMagic(string)
let result = escape(a:string, '.?=%@*+&<>()[]{}^$~|/\')
return ConvertSpecials(result)
endfun
fun! EscapeNoMagic(string)
let result = escape(a:string, '/\')
return ConvertSpecials(result)
endfun
fun! EscapeMagic(string)
let result = escape(a:string, '.*[]^$/\')
return ConvertSpecials(result)
endfun
fun! UnEscapeSearch(str)
let result = substitute(a:str, '\v\C\\@<!(\\\\)*\zs\\(v|V|m|M)', '', 'g')
let result = substitute(result, '\v\C\\@<!(\\\\)*\zs\\n', '\r', 'g')
let result = substitute(result, '\v\C\\@<!(\\\\)*\zs\\t', '\t', 'g')
let result = substitute(result, '\v\\((\\\\)*(\\)@!)@=', '', 'g')
return result
endfun
fun! EscapeForReplace(string)
let result = escape(a:string, '/\&~')
let result = substitute(result, '\r\n\{0,1}\|\n', '\\r', "g")
let result = substitute(result, '\t', '\\t', 'g')
return result
endfun
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment