Vim Tips Wiki
Register
m (commented out some tips in the to-be-merged section that I already handled merging.)
(Propose minor changes to method (more to do, but removed 'review' since tip is good))
Line 1: Line 1:
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=171
 
|id=171
Line 46: Line 45:
 
*[[VimTip1151|1151 Search visually]]
 
*[[VimTip1151|1151 Search visually]]
 
<!-- *[[VimTip1387|1387 Standard editing shortcuts]] (contains info that should be here) -->
 
<!-- *[[VimTip1387|1387 Standard editing shortcuts]] (contains info that should be here) -->
  +
  +
----
  +
One thing I don't like about the tip is that using it to search for something fails to put that something in the search history. Therefore, I can't press <tt>/</tt> followed by some up arrows to find what I searched for a few minutes ago.
  +
  +
Some approaches do not use <tt>\V</tt> but prefer to escape all the magic characters (I think '\.*$^~[]'). I like the <tt>\V</tt> (seems more robust), but I wanted to avoid having the '\V' in search history for simple searches.
  +
  +
I think the following fixes these points. I'm going to try this for a while and will, if ok, use this to replace the tip. Please add any comments below.
  +
  +
<pre>
  +
function! s:VSetSearch()
  +
let temp = @@
  +
normal! gvy
  +
if @@ =~# '^[0-9A-Za-z ,_]*$'
  +
let @/ = @@ " keep simple cases simple in search history
  +
else
  +
" Escape both slash and backslash because we're using @/ as a
  +
" temp variable that will be inserted into a '/' command.
  +
let @/ = '\V' . substitute(escape(@@, '/\'), '\n', '\\n', 'g')
  +
endif
  +
let @@ = temp
  +
endfunction
  +
vnoremap * :<C-u>call <SID>VSetSearch()<CR>/<C-r>/<CR>
  +
vnoremap # :<C-u>call <SID>VSetSearch()<CR>?<C-r>/<CR>
  +
vmap <kMultiply> *
  +
</pre>

Revision as of 01:26, 11 August 2008

Tip 171 Printable Monobook Previous Next

created December 2, 2001 · complexity basic · author Raymond Li · version 5.7


With the following, you can use * (or #) to search forwards (or backwards) for the current visual selection from either characterwise visual mode or linewise visual mode (but not from blockwise visual mode). These visual searches behave like any other searches; the 'n' and 'N' commands work as they should, and the search history correctly records each search. This solution works for all characters, and even for searches that span multiple lines (that is, if you select "a" at the end of one line and "b" at the beginning of the next, we'll only find other lines that end in "a" and have "b" as the first character on the next line).

" vsearch.vim
" Visual mode search
function! s:VSetSearch()
  let temp = @@
  norm! gvy
  let @/ = '\V' . substitute(escape(@@, '\'), '\n', '\\n', 'g')
  let @@ = temp
endfunction

vnoremap * :<C-u>call <SID>VSetSearch()<CR>//<CR>
vnoremap # :<C-u>call <SID>VSetSearch()<CR>??<CR>

This code first defines a function, only accessible inside the script it's defined in (:help s:), which first backs up the unnamed register (:help expr-register) so it we can restore it, then yanks the visual selection into the unnamed register (:help :norm :help gv :help y). Then, it takes that string and escapes all \ to \\, and replaces every newline with a pattern that matches newlines (:help escape() :help substitute()), and finally stores the resulting string to the search pattern register (:help registers), prepended with \V to turn off the special meanings of all characters but \ (which we already escaped all instance of) (:help /\V). Finally, the function restores the unnamed register to the value it had when we started. The visual map for * presses : in visual mode, then <C-u> in command line mode to remove the '<,'> that : inserts in visual mode (:help c_CTRL-u). Then, it calls the function to set up the search pattern register (:help :call :help <SID>), and then searches forwards for the next instance of the pattern (:help /<CR>). The visual map for # does the same, but searches backwards instead (:help ?<CR>).

You can either put this code into a file in your plugins directory (make sure the filename ends in '.vim') or include it directly in your vimrc. To make the * key on the numeric keypad also trigger this mapping, you can add this line:

vmap <kMultiply> *

Comments

 TO DO 
Tips related to visual searching (need to merge):


One thing I don't like about the tip is that using it to search for something fails to put that something in the search history. Therefore, I can't press / followed by some up arrows to find what I searched for a few minutes ago.

Some approaches do not use \V but prefer to escape all the magic characters (I think '\.*$^~[]'). I like the \V (seems more robust), but I wanted to avoid having the '\V' in search history for simple searches.

I think the following fixes these points. I'm going to try this for a while and will, if ok, use this to replace the tip. Please add any comments below.

function! s:VSetSearch()
  let temp = @@
  normal! gvy
  if @@ =~# '^[0-9A-Za-z ,_]*$'
    let @/ = @@  " keep simple cases simple in search history
  else
    " Escape both slash and backslash because we're using @/ as a
    " temp variable that will be inserted into a '/' command.
    let @/ = '\V' . substitute(escape(@@, '/\'), '\n', '\\n', 'g')
  endif
  let @@ = temp
endfunction
vnoremap * :<C-u>call <SID>VSetSearch()<CR>/<C-r>/<CR>
vnoremap # :<C-u>call <SID>VSetSearch()<CR>?<C-r>/<CR>
vmap <kMultiply> *