Vim <C-R><C-W> ignore current content of the line - vim

I have this script to search for the word under cursor in the current project:
nnoremap <leader>K :grep! "\b<C-R><C-W>\b"<CR>:cw<CR>
It works just fine except when the word starts with b.
This is due to <C-R><C-W> only completing the remaining of the word. For example, if I'm searching for "branch", my pattern gets something like this:
\branch\b
Which is equivalent to search for the work "ranch".
Any thoughts on how to figure this out?

Try this: nnoremap <leader>K :execute 'grep! "\b"'.expand("<cword>").'"\b"'<CR>:cw<CR>.
<cword> will expand to the current word under the cursor, as :help :<cword> explains, along with others:
<cword> is replaced with the word under the cursor (like |star|)
<cWORD> is replaced with the WORD under the cursor (see |WORD|)
<cfile> is replaced with the path name under the cursor (like what|gf| uses)
Check the help for more info.

Related

How can I pre-fill a substitute command with the result of the previous `*` search in the position where the {string} goes?

I currently use the following mapping to substitute the result of the last search pattern with a new word in the entire buffer:
nnoremap <Leader>sa :%s///g<left><left>
What I would like is to put the result of the last search pattern where the new word goes.
Example:
suppose my cursor is standing on the word "hello"
Then I press *
Then I invoke the mapping with <Leader>sa
At this point, my command line is filled with :%s///g. What I would like to have is :%s//hello/g.
I tried the mapping below, but it adds the whole word delimeters (\< and \>) which I don't want.
nnoremap <Leader>sa :%s///g<left><left><C-r>/
--- EDIT ---
After some much needed clarification, I think that the simplest approach is to use :help s/\& in the replacement part of your substitution:
nnoremap <key> :%s//&/g<left><left>
If you really need a more visually explicit method, you can trim the \< and the \>, like this:
nnoremap <key> :%s//<C-r>=substitute(#/,'\\<\\|\\>','','g')<CR>/g<left><left>
which should get you something like this:
:%s//hello/g
with the cursor after hello, ready for further editing.
--- ENDEDIT ---
In command-line mode, :help c_ctrl-r_ctrl-w inserts the word under the cursor:
nnoremap <key> :%s///g<left><left><C-r><C-w>
<cword> gets the word under the cursor, but you have to call expand and send a carriage return
nnoremap <Leader>sa :%s///g<left><left><C-r>=expand("<cword>")<CR>
One way to support visual selections and multiple words is to yank the text you want to replace then search for it with <C-r>"
nnoremap <Leader>sa :%s///g<left><left><C-r>"
You would make a visual selection, press y, then <leader>sa to replace, or /<C-r>" to search.
Edit
After reading the clarifications above, here is a different way to do (almost) the same thing:
Make a visual selection
Press *
Type cgn<C-r>"2 (e.g. change "ThisIsAVeryLongVariable" to "ThisIsAVeryLongVariable2")
Each press of . will repeat the substitution

When does expand need to be used when mapping a <cword> command in vim?

I can create a mapping that will search for the word under the cursor like so:
noremap <leader>/ :grep <cword> **<cr>
Why is it that unite mappings like unite (I doubt this is a unite specific issue) requires <C-r>=expand('<cword>')<CR> or <c-r><c-w> instead of <cword>?
nnoremap g/ :Unite -input=<C-r>=expand('<cword>')<CR> tag<CR>
The special characters like % and <cword> are explained under :help cmdline-special.
In Ex commands, at places where a file name can be used, the following
characters have a special meaning. These can also be used in the expression
function expand().
That explains why :edit <cword> works, but :echo "<cword>" does not: the latter does not take a file name. :grep just fuzzily refers to [arguments], but naturally some of them have to be files. The :Unite command is universal (and custom), so you need to use expand() there. When in doubt, just try it out :-)

How to display all results of a search in vim

When searching string with notepad++, new window opens and shows find
results. I want to use this feature in vim. After googling I found out some suggestions:
vimgrep /<pattern>/ %
copen
It is possible to create mapping which do those two commands. Pattern should be the current word: may be cword keyword in vim?
The requirement is actually easy. but to get user inputted pattern, you need a function.
function! FindAll()
call inputsave()
let p = input('Enter pattern:')
call inputrestore()
execute 'vimgrep "'.p.'" % |copen'
endfunction
if you want to have a mapping, add this line:
nnoremap <F8> :call FindAll()<cr>
but as I commented under your question. % may not work for unamed buffer.
I suggest lvimgrep (so you can use quickfix for :make)
:nnoremap <F6> :lvimgrep /\M\<<C-R><C-W>\m\>/ **/*.[ch]pp **/Makefile | lopen<CR>
Also, if you just wanted to find in the current file:
:g/<pattern>/
will invoke 'print' (default command) on each matching line.
:v// " non-matching lines
:g//-1 " lines preceding the matching line
:g//-1,+1 " lines around the matching line
etc.
:global is far more useful:
:g/foo/ join " join all lines containing foo
etc.
Those two commands can be shortened and chained: :vim foo %|co. You can pull the word under the cursor like this: :vim <C-r><C-w> %|co.
Here is a quick normal mode mapping that you can use to list all the occurrences of the word under your cursor in the quickfix window:
nnoremap <F6> :vimgrep /<C-r><C-w>/j % <bar> cwindow<cr>
You can also use :il[ist] foo to display a list of all the occurrences of foo or [I to display the same list for the word under your cursor.
When the list is displayed, use :{line number} to jump to the corresponding line.

Find number of occurrences of word under cursor

I've enjoyed using # to highlight and search for a word (variable) but I would love if I could hit a single command that would simply tell me how many occurrences are in the current file. I've found the following
:%s/dns_name_change_flag/&/gn
But that's too much typing. Is there anyway to maybe map the above one-liner to use the word under cursor?
I don't know how to do this without execute. The following maps F5 to count occurrences of the word under the cursor using <cword> and word boundary patterns (\\< and \\>):
:map <f5> :execute ":%s#\\<" . expand("<cword>") . "\\>\#&#gn"<CR>
:map <F2> "zyiw:exe "%s/".#z."//gn"<CR>
add this line (without the ":") to your .vimrc and F2 will be mapped every time you start vim.
It yanks the 'inner word' to the z register and then performs a search in the whole buffer outputting the number of appearances.
This approach differs to the one given by Thor in that way, that it also counts appearances of the word that are not a word themselves, but only part of a word. For example: looking for 'an' will also count 'and'.
This might be helpful too:
"A quick way to list all occurrences of the word under the cursor it to type [I (which displays each line containing the current keyword, in this file and in included files when using a language such as C)."
source: http://vim.wikia.com/wiki/Word_count
Map Execute to Grep
You can map a sequence to an external grep command. For example:
:nmap fg :execute '!fgrep --count <cword> %'<CR>
This maps a normal-mode command to fg. The command will run fgrep on the current file in an external process, counting the instances of the word under the cursor.
Minor Caveat
This operates on the current file, not the current buffer. You need to make sure the file is written to disk (e.g. :write) before the word count will be accurate.
I have written a plugin for that: SearchPosition; it provides mappings for the current search pattern and current word / selection, and also lists where the matches occur:
1 match after cursor in this line, 8 following, 2 in previous lines;
total 10 for /\<SearchPosition\>/
:nmap <Leader>* *<C-o>:%s///gn<CR><C-o>
I have a function that does not change search register #/
fun! CountWordFunction()
try
let l:win_view = winsaveview()
exec "%s/" . expand("<cword>") . "//gn"
finally
call winrestview(l:win_view)
endtry
endfun
command! -nargs=0 CountWord :call CountWordFunction()
nnoremap <F3> :CountWord<CR>
If you alredy have searched for the word you can just type
:%~n

how to highlight all occurrences of a word in vim on double clicking

When I'm on Windows, I use notepad++, and on Linux I use vim. I really like vim. But there is at least one thing I find really interesting in notepad++. You can double-click on a word and it highlights all occurrences of that word automatically. I was wondering if I could do something like that with vim? So the question is how to highlight all occurrences of a word when you double click on the word in vim.
Obviously, I don't want to search for that word, or change my cursor position, just highlighting. My :set hlsearch is also on.
probably you may want to avoid the mouse in vim, but I make an exception here :).
I know that * does the same job, but what about mouse?
If you want to highlight the word under the cursor like *, but do not want to move the cursor then I suggest the following:
nnoremap <silent> <2-LeftMouse> :let #/='\V\<'.escape(expand('<cword>'), '\').'\>'<cr>:set hls<cr>
Basically this command sets the search register (#/) to the current word and turns on 'hlsearch' so the results are highlighted. By setting #/ the cursor is not moved as it is with * or #.
Explanation:
<silent> - to not show the command once executed
<2-LeftMouse> - Double click w/ the left mouse button
#/ is the register used for searching with / and ?
expand('<cword>') get the current word under the cursor
escape(pattern, '\') escape the regex in case of meta characters
\V use very-non-magic mode so everything meta character must be escaped with /
\< and \> to ensure the current word is at a word boundary
set hls set 'hlsearch' on so highlighting appears
If setting the #/ register is not your cup of tea than you can use :match instead like so:
nnoremap <silent> <2-leftMouse> :exe 'highlight DoubleClick ctermbg=green guibg=green<bar>match DoubleClick /\V\<'.escape(expand('<cword>'), '\').'\>/'<cr>
To clear the matches just use:
:match none
You can map * to double-click by a simple mapping:
:map <2-LeftMouse> *
If you want to use said functionality in insert-mode you can use this mapping:
:imap <2-LeftMouse> <c-o>*
Without (Ctrl-o) the * would be printed
[EDIT]
As ZyX pointed out, it is always a good idea to use noremap respectively inoremap if you want to make sure that if * or <c-o> will be mapped to something else, that this recursive mapping won't be expanded.

Resources