Vim Tips Wiki
Register
(Add gV to function)
(Add a simple, one-liner solution to the problem, to accommodate anyone looking for a hassle-free snippet.)
Tag: Visual edit
(13 intermediate revisions by 8 users not shown)
Line 1: Line 1:
 
{{TipImported
 
{{TipImported
 
|id=171
 
|id=171
|previous=170
+
|previous=168
 
|next=172
 
|next=172
|created=December 2, 2001
+
|created=2001
 
|complexity=basic
 
|complexity=basic
 
|author=Raymond Li
 
|author=Raymond Li
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
With this tip, you can visually select some text, then press a key to search for the next occurrence of the text. Two alternative methods are presented.
+
With this tip, you can select some text, then press a key to search for the next occurrence of the text. Two alternative methods are presented.
  +
  +
== '''Simple''' ==
  +
The simplest solution is:
  +
vnorem // y/<c-r>"<cr>
  +
  +
== Advanced ==
  +
The following is a more advanced implementation, with more robust functionality than the above keymap.
   
 
'''Features'''
 
'''Features'''
*Press <tt>*</tt> to search forwards for selected text, or <tt>#</tt> to search backwards.
+
*Press <code>*</code> to search forwards for selected text, or <code>#</code> to search backwards.
*As normal, press <tt>n</tt> for next search, or <tt>N</tt> for previous.
+
*As normal, press <code>n</code> for next search, or <code>N</code> for previous.
 
*Handles multiline selection and search.
 
*Handles multiline selection and search.
 
*Whitespace in the selection matches ''any'' whitespace when searching (searching for "hello world" will also find "hello" at the end of a line, with "world" at the start of the next line).
 
*Whitespace in the selection matches ''any'' whitespace when searching (searching for "hello world" will also find "hello" at the end of a line, with "world" at the start of the next line).
Line 24: Line 31:
 
<pre>
 
<pre>
 
" Search for selected text, forwards or backwards.
 
" Search for selected text, forwards or backwards.
vnoremap <silent> * :<C-U>let old_reg=@"<CR>
+
vnoremap <silent> * :<C-U>
  +
\let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
 
\gvy/<C-R><C-R>=substitute(
 
\gvy/<C-R><C-R>=substitute(
\escape(@", '/\.*$^~[]'), '\_s\+', '\\_s\\+', 'g')<CR><CR>
+
\escape(@", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
\gV:let @"=old_reg<CR>
+
\gV:call setreg('"', old_reg, old_regtype)<CR>
vnoremap <silent> # :<C-U>let old_reg=@"<CR>
+
vnoremap <silent> # :<C-U>
  +
\let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
 
\gvy?<C-R><C-R>=substitute(
 
\gvy?<C-R><C-R>=substitute(
\escape(@", '?\.*$^~[]'), '\_s\+', '\\_s\\+', 'g')<CR><CR>
+
\escape(@", '?\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
\gV:let @"=old_reg<CR>
+
\gV:call setreg('"', old_reg, old_regtype)<CR>
 
</pre>
 
</pre>
 
The <tt>gV</tt> allows the mappings to work in <tt>--SELECT--</tt> mode as well as <tt>--VISUAL--</tt>. Without <tt>gV</tt>, searching for text in select mode does not move the cursor because the selection is automatically reselected after the mapping.
 
   
 
Following is an alternative version with some extra features:
 
Following is an alternative version with some extra features:
*A global variable (<tt>g:VeryLiteral</tt>) controls whether selected whitespace matches any whitespace (by default, VeryLiteral is off, so any whitespace is found).
+
*A global variable (<code>g:VeryLiteral</code>) controls whether selected whitespace matches any whitespace (by default, VeryLiteral is off, so any whitespace is found).
*Type <tt>\vl</tt> to toggle VeryLiteral to turn whitespace matching off/on (assuming the default backslash leader key).
+
*Type <code>\vl</code> to toggle VeryLiteral to turn whitespace matching off/on (assuming the default backslash leader key).
 
*When VeryLiteral is off, any selected leading or trailing whitespace will not match newlines, which is more convenient, and avoids false search hits.
 
*When VeryLiteral is off, any selected leading or trailing whitespace will not match newlines, which is more convenient, and avoids false search hits.
   
Create file (for example) <tt>~/.vim/plugin/vsearch.vim</tt> (Unix) or <tt>$HOME/vimfiles/plugin/vsearch.vim</tt> (Windows) with contents:
+
Create file (for example) <code>~/.vim/plugin/vsearch.vim</code> (Unix) or <code>$HOME/vimfiles/plugin/vsearch.vim</code> (Windows) with contents:
 
<pre>
 
<pre>
" Search for visually selected text.
+
" Search for selected text.
 
" http://vim.wikia.com/wiki/VimTip171
 
" http://vim.wikia.com/wiki/VimTip171
let s:save_cpo = &cpo | set cpoptions&
+
let s:save_cpo = &cpo | set cpo&vim
 
if !exists('g:VeryLiteral')
 
if !exists('g:VeryLiteral')
 
let g:VeryLiteral = 0
 
let g:VeryLiteral = 0
 
endif
 
endif
 
 
function! s:VSetSearch(cmd)
 
function! s:VSetSearch(cmd)
let temp = @@
+
let old_reg = getreg('"')
  +
let old_regtype = getregtype('"')
 
normal! gvy
 
normal! gvy
 
if @@ =~? '^[0-9a-z,_]*$' || @@ =~? '^[0-9a-z ,_]*$' && g:VeryLiteral
 
if @@ =~? '^[0-9a-z,_]*$' || @@ =~? '^[0-9a-z ,_]*$' && g:VeryLiteral
Line 67: Line 74:
 
endif
 
endif
 
normal! gV
 
normal! gV
  +
call setreg('"', old_reg, old_regtype)
let @@ = temp
 
 
endfunction
 
endfunction
 
 
vnoremap <silent> * :<C-U>call <SID>VSetSearch('/')<CR>/<C-R>/<CR>
 
vnoremap <silent> * :<C-U>call <SID>VSetSearch('/')<CR>/<C-R>/<CR>
 
vnoremap <silent> # :<C-U>call <SID>VSetSearch('?')<CR>?<C-R>/<CR>
 
vnoremap <silent> # :<C-U>call <SID>VSetSearch('?')<CR>?<C-R>/<CR>
 
vmap <kMultiply> *
 
vmap <kMultiply> *
 
 
nmap <silent> <Plug>VLToggle :let g:VeryLiteral = !g:VeryLiteral
 
nmap <silent> <Plug>VLToggle :let g:VeryLiteral = !g:VeryLiteral
 
\\| echo "VeryLiteral " . (g:VeryLiteral ? "On" : "Off")<CR>
 
\\| echo "VeryLiteral " . (g:VeryLiteral ? "On" : "Off")<CR>
 
if !hasmapto("<Plug>VLToggle")
 
if !hasmapto("<Plug>VLToggle")
nmap <unique> <leader>vl <Plug>VLToggle
+
nmap <unique> <Leader>vl <Plug>VLToggle
 
endif
 
endif
let &cpoptions = s:save_cpo | unlet s:save_cpo
+
let &cpo = s:save_cpo | unlet s:save_cpo
 
</pre>
 
</pre>
   
==Comments==
+
==Explanation==
  +
The first suggested mapping was:
{{Todo}}
 
 
<pre>
Tips related to visual searching (need to merge):
 
  +
vnoremap <silent> * :<C-U>
*[[VimTip1011|1011 Mappings and commands for visual mode]]
 
  +
\let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
*[[VimTip1151|1151 Search visually]]
 
  +
\gvy/<C-R><C-R>=substitute(
 
 
\escape(@", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
----
 
  +
\gV:call setreg('"', old_reg, old_regtype)<CR>
'''See current comments after the following box (the archived conversation in the box can be deleted soon).'''
 
 
</pre>
 
<div style="background:#FFEEDD; margin-top:0.5em; padding:0 10px 0 10px; border:1px solid #888888;">
 
<big>'''''Please don't change text in this box.'''''</big><br />
 
'''''Add any additional comments below the box (if wanted, copy anything relevant from here to your comment).'''''
 
 
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.
 
   
  +
When in visual mode, pressing <code>*</code> will then perform these commands:
 
<pre>
 
<pre>
  +
:<C-U>
function! s:VSetSearch()
 
  +
let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
let temp = @@
 
normal! gvy
+
gvy
  +
/<C-R><C-R>=
if @@ =~# '^[0-9A-Za-z ,_]*$'
 
  +
substitute(
let @/ = @@ " keep simple cases simple in search history
 
  +
escape(@", '/\.*$^~['),
else
 
  +
'\_s\+',
" Escape both slash and backslash because we're using @/ as a
 
  +
'\\_s\\+',
" temp variable that will be inserted into a '/' command.
 
  +
'g')<CR><CR>
let @/ = '\V' . substitute(escape(@@, '/\'), '\n', '\\n', 'g')
 
  +
gV
endif
 
  +
:call setreg('"', old_reg, old_regtype)<CR>
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>
 
</pre>
   
  +
<code>:<C-U></code> enters command mode and deletes (Ctrl-u) the <code>'<,'></code> range automatically inserted due to the visual selection. The unnamed register (<code>@"</code>) is saved and later restored.
----
 
Definitely not ok. That breaks pretty easily; try doing # after selecting "a?b" and you'll see that only "a" was searched for.
 
   
  +
<code>gvy</code> reselects then yanks the visual selection (copy to <code>@"</code>).
This works a little better:
 
<pre>
 
function! s:VSetSearch()
 
let temp = @@
 
norm! gvy
 
if @@ =~# '^[0-9A-Za-z ,_]*$'
 
let @/ = @@
 
else
 
let @/ = '\V' . substitute(escape(@@, '\'), '\n', '\\n', 'g')
 
endif
 
let @@ = temp
 
call histadd('/', @/)
 
endfunction
 
   
  +
<code>/<C-R><C-R>=</code> starts a search, then substitutes the expression register (<code>@=</code>) literally {{help|c_CTRL-R_CTRL-R}}. The result of the following expression is inserted into the command line.
vnoremap * :<C-u>call <SID>VSetSearch()<CR>//<CR>
 
vnoremap # :<C-u>call <SID>VSetSearch()<CR>??<CR>
 
</pre>
 
   
  +
<code>escape()</code> inserts a backslash before each <code>/\.*$^~[</code> character found in <code>@"</code>. The <code>/</code> must be escaped because we are using a <code>/</code> command. The other characters need to be escaped because they have a special meaning in a regular expression.
but it still has some quirks with handling / and ?... Consider, for example, selecting "a?b", pressing * (searches for "a?b"), pressing ?<Up><CR> (uses search "\Va\?b"; so matches "a?b"), then pressing /<Up><CR> (searches for "\Va\?b"; and \? behaves differently in a / search than a ? search - it now matches either "ab" or "b").
 
   
  +
<code>substitute()</code> replaces every sequence of one or more whitespace characters (space, tab, newline) with an escaped regular expression that will search for any similar sequence.
Changing the histadd() call to the following seems to work, but it yields an uglier pattern...
 
<pre>
 
call histadd('/', substitute(@/, '[?/]', '\="\\%d".char2nr(submatch(0))', 'g'))
 
</pre>
 
   
 
<code>gV</code> allows the mappings to work in <code>--SELECT--</code> mode as well as <code>--VISUAL--</code>. Without <code>gV</code>, searching for text in select mode would not move the cursor because the selection is automatically reselected after the mapping.
With that, we when searching on "a?b" or "a/b" we insert into the search history /\Va\%d63b/ and /\Va\%d47b/, respectively, which matches correctly but isn't terribly readable.
 
   
Any thoughts, John?
 
   
  +
==Paste matching text of last search==
----
 
  +
When using <code>^r/</code> in INSERT mode what one most of the time wants is to paste the matched text not the regex used to search the text. Example: after using * on a word, <code>^r/</code> will paste the word with <code>\<</code> prepended and <code>\></code> appended, not what we want. Similarly after a visual search we don't want the <code>\V</code> prepended. The following map takes care of these issues:
Thanks for pointing out the problem. Sorry, but somehow I missed seeing your edit, so my reply is delayed.
 
  +
<source lang="vim">
 
function! Del_word_delims()
  +
let reg = getreg('/')
  +
" After * i^r/ will give me pattern instead of \<pattern\>
  +
let res = substitute(reg, '^\\<\(.*\)\\>$', '\1', '' )
  +
if res != reg
  +
return res
 
endif
  +
" After * on a selection i^r/ will give me pattern instead of \Vpattern
 
let res = substitute(reg, '^\\V' , '' , '' )
  +
let res = substitute(res, '\\\\' , '\\', 'g')
 
let res = substitute(res, '\\n' , '\n', 'g')
  +
return res
 
endfunction
  +
inoremap <silent> <c-r>/ <c-r>=Del_word_delims()<cr>
  +
cnoremap <c-r>/ <c-r>=Del_word_delims()<cr>
  +
</source>
   
  +
For more complicated patterns, it's better to act on the text matched with the last search, using the {{help|prefix=no|gn}} object.
When I tried your new solution, I find that selecting 'something' and pressing * puts two items in the search history: 'something' (or '\Vsomething') and '//'. I don't like the resulting confusion, for example, when using /<Up> to locate the item-before-last that I searched for.
 
   
  +
So, you could also accomplish insertion of a search match using <code>maygn`ap</code> in normal mode. I.e. <code>ma</code> to drop a mark to return to later, <code>y</code> to yank the <code>gn</code> object, then <code>`a</code> to jump back where you were (because the yank will leave you on the text copied), finally <code>p</code> to paste.
The char2nr code is sensational, but as you say, the search history is too unreadable for my preference.
 
   
  +
When starting from insert mode, you don't even need a mark: you can use the <code>gi</code> command to start again from where you left off. For example:
There are some quirks I wouldn't worry about, for example, Vim itself has a quirk:
 
<pre>
 
/a?b<CR> (search forwards for 'a?b' -- good)
 
?<Up><CR> (search backwards for 'a\?b' -- good)
 
/<Up><CR> (search forwards for 'a\?b' -- bad, finds 'b' or 'ab')
 
</pre>
 
   
So, here is what I an currently trying:
 
 
<pre>
 
<pre>
  +
:inoremap <F3> <Esc>ygngi<C-R>0
function! s:VSetSearch(cmd)
 
let temp = @@
 
normal! gvy
 
if @@ =~# '^[0-9A-Za-z ,_]*$'
 
let @/ = @@ " keep simple cases simple in search history
 
else
 
" Escape both cmd and backslash because we're using @/ as a
 
" temp variable that will be inserted into a '/' or '?' command.
 
let @/ = '\V' . substitute(escape(@@, a:cmd.'\'), '\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>
 
</pre>
   
  +
Here, <code>ygn</code> is as before, but <code>gi</code> is used to go back to insert mode in the same place you left off, then <code><C-R>0</code> inserts the copied text.
Please tell me what you think. --[[User:JohnBeckett|JohnBeckett]] 09:11, 16 August 2008 (UTC)
 
</div>
 
   
  +
==See also==
'''The following box contains the version of the tip from 13 July by godlygeek.'''
 
  +
* [[Script:2944|visualstar.vim]]
   
  +
==Comments==
<div style="background:#FFEEDD; margin-top:0.5em; padding:0 10px 0 10px; border:1px solid #888888;">
 
 
{{Todo}}
<big>'''''Please don't change text in this box.'''''</big>
 
 
Tips related to visual searching (need to merge):
 
 
*[[VimTip1011|1011 Mappings and commands for visual mode]]
With the following, you can use <tt>*</tt> (or <tt>#</tt>) 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).
 
 
*[[VimTip1151|1151 Search visually]]
   
  +
This mapping forms a substitute command with the selected text:
 
<pre>
 
<pre>
  +
vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>
" 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>
 
 
</pre>
 
</pre>
  +
Found on [http://stackoverflow.com/questions/676600/vim-replace-selected-text Stack Overflow: Vim replace selected text].
   
  +
To auto escape certain characters (e.g. slash and backslash), one can use:
This code first defines a function, only accessible inside the script it's defined in ({{help|id=script-variable|label=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 <tt>\</tt> to <tt>\\</tt>, 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 <tt>\V</tt> to turn off the special meanings of all characters but <tt>\</tt> (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 <tt>*</tt> presses <tt>:</tt> 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|id=<SID>|label=<SID>}}), and then searches forwards for the next instance of the pattern ({{help|/<CR>}}). The visual map for <tt>#</tt> does the same, but searches backwards instead ({{help|?<CR>}}).
 
 
You can either put this code into a file in your <tt>plugins</tt> directory (make sure the filename ends in '.vim') or include it directly in your [[vimrc]]. To make the <tt>*</tt> key on the numeric keypad also trigger this mapping, you can add this line:
 
 
<pre>
 
<pre>
 
vnoremap <C-h> ""y:%s/<C-R>=escape(@", '/\')<CR>//g<Left><Left>
vmap <kMultiply> *
 
 
</pre>
 
</pre>
</div>
 
 
I have replaced the body of the tip with a version by Bill McCarthy from the vim_use mailing list (2008-08-19 15:43). I have edited the code in an attempt to clarify its function. I hope I haven't changed its meaning (except I changed the mapping to toggle VeryLiteral from '\dv' to '\vl'). The new code is quite a bit more complex, but I think that is justified by its functionality.
 
 
I need to add some explanations to the tip, but first let's decide what version to use, and finalise it.
 
 
Please check the current tip and add any comments below. --[[User:JohnBeckett|JohnBeckett]] 11:03, 19 August 2008 (UTC)
 
 
----
 

Revision as of 20:02, 6 June 2014

Tip 171 Printable Monobook Previous Next

created 2001 · complexity basic · author Raymond Li · version 6.0


With this tip, you can select some text, then press a key to search for the next occurrence of the text. Two alternative methods are presented.

Simple

The simplest solution is:

vnorem // y/<c-r>"<cr>

Advanced

The following is a more advanced implementation, with more robust functionality than the above keymap.

Features

  • Press * to search forwards for selected text, or # to search backwards.
  • As normal, press n for next search, or N for previous.
  • Handles multiline selection and search.
  • Whitespace in the selection matches any whitespace when searching (searching for "hello world" will also find "hello" at the end of a line, with "world" at the start of the next line).
  • Each search is placed in the search history allowing you to easily repeat previous searches.
  • No registers are changed.

Place the following mappings in your vimrc:

" Search for selected text, forwards or backwards.
vnoremap <silent> * :<C-U>
  \let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
  \gvy/<C-R><C-R>=substitute(
  \escape(@", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
  \gV:call setreg('"', old_reg, old_regtype)<CR>
vnoremap <silent> # :<C-U>
  \let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
  \gvy?<C-R><C-R>=substitute(
  \escape(@", '?\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
  \gV:call setreg('"', old_reg, old_regtype)<CR>

Following is an alternative version with some extra features:

  • A global variable (g:VeryLiteral) controls whether selected whitespace matches any whitespace (by default, VeryLiteral is off, so any whitespace is found).
  • Type \vl to toggle VeryLiteral to turn whitespace matching off/on (assuming the default backslash leader key).
  • When VeryLiteral is off, any selected leading or trailing whitespace will not match newlines, which is more convenient, and avoids false search hits.

Create file (for example) ~/.vim/plugin/vsearch.vim (Unix) or $HOME/vimfiles/plugin/vsearch.vim (Windows) with contents:

" Search for selected text.
" http://vim.wikia.com/wiki/VimTip171
let s:save_cpo = &cpo | set cpo&vim
if !exists('g:VeryLiteral')
  let g:VeryLiteral = 0
endif
function! s:VSetSearch(cmd)
  let old_reg = getreg('"')
  let old_regtype = getregtype('"')
  normal! gvy
  if @@ =~? '^[0-9a-z,_]*$' || @@ =~? '^[0-9a-z ,_]*$' && g:VeryLiteral
    let @/ = @@
  else
    let pat = escape(@@, a:cmd.'\')
    if g:VeryLiteral
      let pat = substitute(pat, '\n', '\\n', 'g')
    else
      let pat = substitute(pat, '^\_s\+', '\\s\\+', '')
      let pat = substitute(pat, '\_s\+$', '\\s\\*', '')
      let pat = substitute(pat, '\_s\+', '\\_s\\+', 'g')
    endif
    let @/ = '\V'.pat
  endif
  normal! gV
  call setreg('"', old_reg, old_regtype)
endfunction
vnoremap <silent> * :<C-U>call <SID>VSetSearch('/')<CR>/<C-R>/<CR>
vnoremap <silent> # :<C-U>call <SID>VSetSearch('?')<CR>?<C-R>/<CR>
vmap <kMultiply> *
nmap <silent> <Plug>VLToggle :let g:VeryLiteral = !g:VeryLiteral
  \\| echo "VeryLiteral " . (g:VeryLiteral ? "On" : "Off")<CR>
if !hasmapto("<Plug>VLToggle")
  nmap <unique> <Leader>vl <Plug>VLToggle
endif
let &cpo = s:save_cpo | unlet s:save_cpo

Explanation

The first suggested mapping was:

vnoremap <silent> * :<C-U>
  \let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
  \gvy/<C-R><C-R>=substitute(
  \escape(@", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
  \gV:call setreg('"', old_reg, old_regtype)<CR>

When in visual mode, pressing * will then perform these commands:

:<C-U>
let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
gvy
/<C-R><C-R>=
substitute(
  escape(@", '/\.*$^~['),
  '\_s\+',
  '\\_s\\+',
  'g')<CR><CR>
gV
:call setreg('"', old_reg, old_regtype)<CR>

:<C-U> enters command mode and deletes (Ctrl-u) the '<,'> range automatically inserted due to the visual selection. The unnamed register (@") is saved and later restored.

gvy reselects then yanks the visual selection (copy to @").

/<C-R><C-R>= starts a search, then substitutes the expression register (@=) literally :help c_CTRL-R_CTRL-R. The result of the following expression is inserted into the command line.

escape() inserts a backslash before each /\.*$^~[ character found in @". The / must be escaped because we are using a / command. The other characters need to be escaped because they have a special meaning in a regular expression.

substitute() replaces every sequence of one or more whitespace characters (space, tab, newline) with an escaped regular expression that will search for any similar sequence.

gV allows the mappings to work in --SELECT-- mode as well as --VISUAL--. Without gV, searching for text in select mode would not move the cursor because the selection is automatically reselected after the mapping.


Paste matching text of last search

When using ^r/ in INSERT mode what one most of the time wants is to paste the matched text not the regex used to search the text. Example: after using * on a word, ^r/ will paste the word with \< prepended and \> appended, not what we want. Similarly after a visual search we don't want the \V prepended. The following map takes care of these issues:

function! Del_word_delims()
   let reg = getreg('/')
   " After *                i^r/ will give me pattern instead of \<pattern\>
   let res = substitute(reg, '^\\<\(.*\)\\>$', '\1', '' )
   if res != reg
      return res
   endif
   " After * on a selection i^r/ will give me pattern instead of \Vpattern
   let res = substitute(reg, '^\\V'          , ''  , '' )
   let res = substitute(res, '\\\\'          , '\\', 'g')
   let res = substitute(res, '\\n'           , '\n', 'g')
   return res
endfunction
inoremap <silent> <c-r>/ <c-r>=Del_word_delims()<cr>
cnoremap          <c-r>/ <c-r>=Del_word_delims()<cr>

For more complicated patterns, it's better to act on the text matched with the last search, using the gn object.

So, you could also accomplish insertion of a search match using maygn`ap in normal mode. I.e. ma to drop a mark to return to later, y to yank the gn object, then `a to jump back where you were (because the yank will leave you on the text copied), finally p to paste.

When starting from insert mode, you don't even need a mark: you can use the gi command to start again from where you left off. For example:

:inoremap <F3> <Esc>ygngi<C-R>0

Here, ygn is as before, but gi is used to go back to insert mode in the same place you left off, then <C-R>0 inserts the copied text.

See also

Comments

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

This mapping forms a substitute command with the selected text:

vnoremap <C-r> "hy:%s/<C-r>h//gc<left><left><left>

Found on Stack Overflow: Vim replace selected text.

To auto escape certain characters (e.g. slash and backslash), one can use:

vnoremap <C-h> ""y:%s/<C-R>=escape(@", '/\')<CR>//g<Left><Left>