In vim, is there a way to rebind "*" to highlight the current word, without advancing to the next? [duplicate] - vim

This question already has answers here:
Vim: search and highlight but do not jump
(14 answers)
Closed 4 years ago.
I often use * to highlight all instances of the current word, and the fact that it advances to the next word is pretty annoying. I'd like to disable this behavior, knowing that I can always use "n" if I actually need to advance.
Any insight?
EDIT: I should add that I'd like to avoid a screen redraw at all costs as it is visually distracting.

Try this:
nnoremap * :let #/ = "\\<<C-R><C-W>\\>"<CR>
(Assumes you have 'hlsearch' on). This just changes the current search pattern to the word under the cursor (surrounded by \< and \> to match word boundaries). If you have hlsearch enabled, it will highlight the word. n and N will then work as normal.
See:
:help :let-#
:help quote/
:help c_CTRL-R_CTRL-W

Try this Vim Tip. I find it very useful. The most interesting is that you can have more matches and every one in different color.

I cannot give an exact answer, but this Vim Tip tells you what you have to add to your .vimrc to simply highlight the word under the cursor when Vim is in idle state.
Works without any key-remapping...

You can remap it to return:
nnoremap * '*N'
(but this redraws the screen)

Related

Cycling and/or highlighting through a vim selection

The feature I am thinking of is kind of inspired by a feature that I really like about sublime text.
In sublime text, if you select a sequence of characters, it automatically puts a little box around it (to distinguish it from the word that you just highlighted). For me, this is very helpful because I can see and find specific things of the code much faster.
It would be awesome to have something similar to my vim environment. It does not have to be exactly the same as the one in sublime though, but it would be awesome if it were as similar as possible plus the additional feature to easy cycling through similar words.
Currently, what I am doing is highlight the work I want and then manually typing it to the search command /. It would be much better if I can just highlight it in visual mode and then automatically highlight similar words on the current screen with a different colour from the highlighting in visual mode and then have a quick key short cut to cycling through them, if I wished to do that.
I am not sure if a there exists a plugin or something that already does that, but that would cool! Ideally, I would want to to know as many details of the commands/changes to the vimrc file, so that I have the most control over this feature and be able to customize it as I wish.
You can get the highlighting you are looking for by enabling the hlsearch option:
:set hlsearch
It will highlight every occurrence of the last search pattern and thus work after all the following commands (and their relatives):
/foo<CR>
?bar<CR>
:s/fizz/buzz/g
*
#
You can use n to jump to the next occurrence in the direction of your search and N to do the same in the opposite direction.
To highlight every occurrence of the current word "without" moving the cursor, you can simply do:
*N
or:
*``
to jump to the next occurrence and jump back immediately.
Doing the same for visually selected text is a bit trickier but still possible…
either via a lightweight plugin like visualstar or The Search Party,
or with a tiny bit of crude vimscript in your ~/.vimrc:
" this function cleans up the search pattern
function! GetVisualSelection()
let old_reg = #v
normal! gv"vy
let raw_search = #v
let #v = old_reg
return substitute(escape(raw_search, '\/.*$^~[]'), "\n", '\\n', "g")
endfunction
" map * and # in visual mode so that they do the same as *N and #N in normal mode
xnoremap * :<C-u>/<C-r>=GetVisualSelection()<CR><CR>N
xnoremap # :<C-u>?<C-r>=GetVisualSelection()<CR><CR>N
My SearchHighlighting plugin changes the * command so that it just toggles the highlighting for the current word, without the movement to the next match (for which you can press n, or pass a count). This also works in visual mode, using the selection. I find this very handy for highlighting all matches.
There's also a mode that automatically highlights the current word / selection, like what many IDEs offer.
Other plugins
If you want more permanent highlighting, separate from searching, the Mark plugin offers that.
To get an orientation about the number of matches (without highlighting them), I have the SearchPosition plugin.

Highlight current search result in vim

In emacs, when you do a search, there will be one highlight color for all occurences in the buffer, and another color for the occurence that your cursor happens to be on. I was wondering if anyone knew about similar behavior in vim, a vim plugin, or even some ideas on how to accomplish it myself in vimscript.
(note, I already know about hl-IncSearch, which is close, but not what I am looking for)
It sounds like you want to highlight all results in the buffer. You can say
:set hls
Which will turn on hlsearch. Then you can say
:set nohls # turn off permanently
:noh # turn off until next time you search.
You can also search for / highlight the word under the cursor with * (forwards) or # (backwards).
As far as I know there isn't a built-in way to do what you want.
If I were to try to implement it myself... Well one way you could do it is by overriding *, n and p and combining it with something like this function:
noremap n n:call HighlightNearCursor()<CR>
noremap p p:call HighlightNearCursor()<CR>
noremap * *:call HighlightNearCursor()<CR>
function HighlightNearCursor()
if !exists("s:highlightcursor")
match Todo /\k*\%#\k*/
let s:highlightcursor=1
else
match None
unlet s:highlightcursor
endif
endfunction
I haven't tested it out, so this isn't a complete solution, but I think it is at least a viable approach.
EDIT : You will probably have to set some custom highlight colours. This vimwiki page gives some information about that, although I remember seeing a terser example somewhere.
EDIT AGAIN: Maybe a cleaner solution is to use Mark.vim in conjunction with the first technique. Then it would all boil down to something like:
noremap n \nn\m
noremap p \np\m
noremap * \n*\m
I just wrote a vim plugin that does what you requested.
https://github.com/timakro/vim-searchant
I don't have a real answer, but a simple way to get maybe 75% of what you want may be to just change the highlighting of the cursor. The default gray cursor block doesn't contrast well with the default yellow of search highlights. So just change cursor highlighting to (a) something that contrasts more with yellow and (2) also contrasts with other colors in your colorscheme. For me something like this works pretty well:
highlight Cursor guifg=green guibg=red
For me the blinking red cursor on first letter of current search match stands out pretty well. Not as good as a full-blown solution, but dead-simple. (I assume it works just as well in terminal Vim if you add those items to the highlight command but haven't tested it there.)

vim Editing - how to edit the highlighted segment of a search or convert to visual block

In vim, if I have the following text:
hello there
Say I search for hell in the text above.
/hell
and press n to move to the next instance.
hello
hell is now highlighted in vim and my cursor is on the 'h'.
What is the most efficient way to now yank/delete that highlighted text.
Is there a way to 'yank to the end of the highlighted text'?
Or 'create visual block from highlighted text'?
I know I can use %s/hell/whatever/gc to step through as an alternative.
TIA Tom
y//e, or d//e should do the trick.
:let #" = #/ as well, even if you have moved the cursor.
I don't know of a built in mapping (Edit: but see Luc Hermitte's answer below as that's a much better solution than my bodges End Edit), but you could do the yank or select with a couple of mappings:
nmap ,y y/<C-R>/\zs<CR>
nmap ,v v/<C-R>/<BS>\zs<CR>
The ,y mapping uses the '/' register to pull in the last search term search, adds \zs to make the search point be the end and the yank proceeds up to that point. The ,v mapping does a visual selection, but has to delete the last character of the search (with <BS>) to make it end at the right place.
For what it's worth, you can simplify the %s/hell/whatever/gc that you suggested by refining your search with / and then using a shortened form:
/hell
:%s//whatever/gc
This is because :s uses the last search term by default.

How to jump to the next tag in vim help file

I want to learn the vim documentation given in the standard help file. But I am stuck on a navigating issue - I just cannot go to the next tag without having to position the cursor manually. I think you would agree that it is more productive to:
go to the next tag with some
keystroke
press Ctrl-] to read corresponding
topic
press Ctrl-o to return
continue reading initial text
PS. while I was writing this question, I tried some ideas on how to resolve this. I found that searching pipe character with /| is pretty close to what I want. But the tag is surrounded with two pipe '|' characters, so it's still not really optimized to use.
Use the :tn and :tp sequences to navigate between tags.
If you want to look for the next tag on the same help page, try this search:
/|.\{-}|
This means to search for:
The character |
Any characters up to the next |, matching as few as possible (that's what \{-} does).
Another character |
This identifies the tags in the VIM help file.
If you want to browse tags occasionally only, without mapping the search string to keyboard,
/|.*|
also does the trick, which is slightly easier to type in than the suggested
/|.\{-}|
For the case, that the "|" signs for the links in the help file are not visible, you can enable them with
:set conceallevel=0
To establish this setting permanently, please refer to Defining the settings for the vim help file
Well, I don't really see the point. When I want to read everything, I simply use <pagedown> (or <c-f> with some terminals)
" .vim/ftplugin/help/navigate.vim
nnoremap <buffer> <tab> /\*\S\+\*/<cr>zt
?
Or do you mean:
nnoremap <buffer> <tab> /\|\zs\S\{-}\|/<cr><c-]>
?
You could simply remap something like:
nmap ^\ /<Bar><Bslash>zs<Bslash>k<Bslash>+<Bar><CR>
where ^\ is entered as (on my keyboard) Ctrl-V Ctrl-#: choose whatever shortcut you want.
This does a single key search for a | followed by one or more keyword characters and then a |. It puts the cursor on the first keyword character. The and bits are there due to the way map works, see
:help :map-special-chars
As an aside, I imagine that ctrl-t would make more sense than ctrl-o as it's a more direct opposite of ctrl-], but it's up to you. Having said that, ctrl-o will allow you to go back to before the search as well.

How to emulate Emacs’ transpose-words in Vim?

Emacs has a useful transpose-words command which lets one exchange the word before the cursor with the word after the cursor, preserving punctuation.
For example, ‘stack |overflow’ + M-t = ‘overflow stack|’ (‘|’ is the cursor position).
<a>|<p> becomes <p><a|>.
Is it possible to emulate it in Vim? I know I can use dwwP, but it doesn’t work well with punctuation.
Update: No, dwwP is really not a solution. Imagine:
SOME_BOOST_PP_BLACK_MAGIC( (a)(b)(c) )
// with cursor here ^
Emacs’ M-t would have exchanged b and c, resulting in (a)(c)(b).
What works is /\w
yiwNviwpnviwgp. But it spoils "" and "/. Is there a cleaner solution?
Update²:
Solved
:nmap gn :s,\v(\w+)(\W*%#\W*)(\w+),\3\2\1\r,<CR>kgJ:nohl<CR>
Imperfect, but works.
Thanks Camflan for bringing the %# item to my attention. Of course, it’s all on the wiki, but I didn’t realize it could solve the problem of exact (Emacs got it completely right) duplication of the transpose-words feature.
These are from my .vimrc and work well for me.
" swap two words
:vnoremap <C-X> <Esc>`.``gvP``P
" Swap word with next word
nmap <silent> gw "_yiw:s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<cr><c-o><c-l> *N*
Depending on the situation, you can use the W or B commands, as in dWwP. The "capital" versions skip to the next/previous space, including punctuation. The f and t commands can help, as well, for specifying the end of the deleted range.
There's also a discussion on the Vim Tips Wiki about various swapping techniques.
In the middle of a line, go to the first letter of the first word, then do
dw wP
At the end of a line (ie the last two words of the line), go to the space between the words and do
2dw bhP
From the handy Equivalence of VIM & Emacs commands
You could add shortcut keys for those by adding something like the following to your vimrc file:
map L dwwP
map M 2dwbhP
In that case, SHIFT-L (in command-mode) would switch words in the middle of the line and SHIFT-M would do it at the end.
NB: This works best with space-separated words and doesn't handle the OP's specific case very well.
There's a tip on http://vim.wikia.com/wiki/VimTip10. But I choose to roll my own.
My snippet has two obvious advantages over the method mentioned in the tip: 1) it works when the cursor isn't in a word. 2) it won't high-light the entire screen.
It works almost like emacs 'transpose-words', except that when transposition is impossible, it does nothing. (emacs 'transpose-words' would blink and change cursor position to the beginning of current word.)
"transpose words (like emacs `transpose-words')
function! TransposeWords()
if search('\w\+\%#\w*\W\+\w\+')
elseif search('\w\+\W\+\%#\W*\w\+')
endif
let l:pos = getpos('.')
exec 'silent! :s/\(\%#\w\+\)\(\W\+\)\(\w\+\)/\3\2\1/'
call setpos('.', l:pos)
let l:_ = search('\(\%#\w\+\W\+\)\#<=\w\+')
normal el
endfunction
nmap <silent> <M-right> :call TransposeWords()<CR>
imap <silent> <M-right> <C-O>:call TransposeWords()<CR>
You can use dwwP or dWwP as Mark and CapnNefarious have said, but I have a few notes of my own:
If the cursor is on the first letter of the second word, as in the example you gave, you can use dwbP (or dWbP to handle punctuation);
If the cursor is in the middle of the word, you can use dawbP/daWbP.
There's a transpose-words script on vim.org that works beautifully.

Resources