Not highlighting search in vim if it is a part of a command - vim

In my .vimrc I've enabled highlighting the searched text (which I find to be a handy feature and wouldn't want to disable it).
set hlsearch
And, following answers to this question, I've made a mapping to be able to clear the highlight:
nmap <silent> ,/ :nohlsearch<CR>
The problem comes with commands which include search. For example, delete to next character 'x':
d/x
This will automatically highlight all the instances of 'x'. To remove this highlight I have to punch ,/ to clear it, which is quite annoying.
The question. Is it possible to enforce :nohl if the search is a part of a preceding command? Maybe, it is possible at least for a selected list of commands (say, d, y and c) before / character is hit?

d/x does not work for me as you describe. (I'm on vim 7.3 here and it can't make sense of the / following d in normal mode, so disregards the d and starts a regular / search.)
If you want to delete to the next x, then dfx or dtx are what I would use (depending on whether you want to also delete the x itself or not).
No highlighting involved.
Hope that helps.
[Following some clarification in the comments.]
I'm thinking that it should be possible to write a custom function to do what you want, and then assign a custom key sequence to call that function.
I played around a little, but am not very well versed in vim functions and couldn't make it work.
Here's what I tried:
function! g:DeleteToSearchAndNohls(term)
:normal d/a:term
:nohlsearch
endfunc

If 'x' is on the same line than the cursor, you can use dtx (meaning delete to x).

Related

Vim function to find pattern, replace, and visual mode

So I use Vim to write reports at work, reports are basically a bunch of "common issues" that we write over and over, so they are templated. These templates have placeholder blocks {==BLOCK==} to ensure people modify things as/when needed, so this is an example:
The test revealed that it was possible to access {==sensitive data==},
as shown in the examples below...
That block may need to be modified, or not. So the idea is, I am editing the common issue, and I see there are 3 or 4 blocks like the one in the example, I'd like to press let's say [leader]b and then end up having the template text for the first block selected in visual mode without the {== and ==} that are around it.
I have tried a few things but I didn't get too far, any suggestions?
Thanks!
You could define the following function:
function! VisualSelect()
call search("==}")
norm hvT=
endfunction
nnoremap <leader>b :call VisualSelect()<cr>
vnoremap <leader>b Ol<esc>:call VisualSelect()<cr>
This will visually select the contents between {== and ==}. Typing <leader>b repeatedly will select the next occurrence.
Most template/snippet expand plugins support this.
With my lh-brackets plugin, you can execute
:SetMarkers {== ==}
and then jump from one placeholder to the next with CTRL+J with vim, or META-DEL with gvim. lh-brackets doesn't take care of loading/expanding templates. mu-template will add this layer.
If instead you choose to use one of the more popular snippet plugin, there will certainly be an option to change the syntax of the placeholders, but I don't know it.
The poor man's solution would look like:
nnoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr><c-g>
snoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr><c-g>
but it won't take care of restoring the search pattern, of the cases where the cursor is already within a placeholder, and so on...
EDIT: the version that automatically deletes the placeholder marks is
nnoremap <c-j> <c-\><c-n>/{==.*==}<cr>v/==}/e<cr>s<c-r>=matchstr(#", '{==\zs.*\ze==}')<cr><esc>gv6h<c-g>
the same in snoremap
In short:
nnoremap <leader>b /{==.*==}<cr>xxxvt=<esc>/==}<cr>xxxgv
What it does:
1.) find the pattern
/{==.*==}<cr>
2.) Remove the first "{=="
xxx
3.) Visual select your text until the first = (maybe this could be also optimized for using a regex instead of simple searching for the next =)
vt=
4.) Go to the end sequence
/==}<cr>
5.) Remove it
xxx
6.) Select again your last selection
gv
I have figured out a way based on what #snap said, I ended up adding the code to a Python plugin to run it through it, as that fits better with what I am trying to do, snippet below:
#neovim.command('VimisEditTemplateBlock')
def urlify(self):
"""Search next codify block and prepare for editing"""
[...]
self.nvim.command('call search("{==")') # Find beginning of codify block
self.nvim.command('norm xxx') # Delete {==
self.nvim.command('norm vf=') # Select the inner text
self.nvim.command('norm v')
self.nvim.command('norm xxxgvh') #Delete ==} and leave the inner text selected in Visual Mode

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.

Vim: Vertical "f" and "t"

One tiny piece of functionality I find myself missing increasingly often is the ability to move vertically in a similar fashion to f and t. Usually what I want is to move to the top or bottom of a paragraph without losing my column position, and while I "could" just write a script for it, I wondered if there is any known way around this problem that you guys know of.
Example ( [ ] = current position, < > = destination ):
set tabstop=4
set shiftwidth=4
set <s>ofttabstop=4
set gfn=Source\ Code\ Pro:h14
set encoding=utf-8
set [t]_Co=256
set number
Like a vertical fs, or t<space>.
Again, this is usually useful when working with blocks of code. Any ideas?
vim regex provides \%nc (n is col idx) to match only in certain column.
so without installing plugin, what you could do is :
nnoremap <leader>f :<c-u>exe line('.').'/\%'.col('.').'c'.nr2char(getchar())<cr>
in this way, you press <leader>f, then press a key, vim will search that char in the same col. next, you press n/N
If you want to have the same but search backwards, use ?.
The most basic way is to use forward search, /t_<CR> and backward search, ?so<CR>, ideally with set incsearch.
But there are quite a lot of plugins designed around that idea:
EasyMotion,
Sneak,
Fanfingtastic,
and a few othersā€¦
For moving vertically without changing columns, you can use <n>j or <n>k. That doesn't completely help with "top of paragraph" or "bottom of paragraph" without counting the lines. There's also '{' and '}' for jumping between paragraphs. Not sure there's a single command to do exactly what you want...
I recently implemented the JumpToVerticalOccurrence plugin (just published), which implements an f{char} equivalent as ]V{char}. It also has related mappings that jump to the same character the cursor is under, or to non-whitespace in the same column.
I have a mapping that might be useful in visual selection.
To extend the selection downwards (<leader>j) or upwards (<leader>k) from the current column, but not beyond the block of text:
vnoremap <leader>j <Esc>m`:let b:ss=#/<CR>:let b:zz=col('.') - 1<CR>/\%<C-r>=b:zz<CR>c.\zs.\+\n.\{,<C-r>=b:zz<CR>}$<CR>:let #/=b:ss<CR><C-v>``o
vnoremap <leader>k <Esc>m`:let b:ss=#/<CR>:let b:zz=col('.') - 1<CR>?^.\{,<C-r>=b:zz<CR>}\n.*\%<C-r>=b:zz<CR>c.\zs.<CR>:let #/=b:ss<CR><C-v>``o
It also avoids clobbering the search register. At least, that's how I avoid clobbering the search register.

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.)

Is there a way to emulate ReSharper's "extend selection" feature in Vim?

ReSharper has a nice feature called "extend selection": by pressing CTRL+W (I think this is the default) repeatedly, you select more and more from your current caret location. First it's a word, then more and more words, a line, inner then outer block of lines (for example an if-block), then a function, etc...
Basically, by pressing the key combination repeatedly, you can end up selecting the entire file. I'm sure at least some of you will be familiar with it.
I have just started learning all the intricacies of vim and I don't have enough experience to see how something like this could be implemented in Vim (although I assume it's possible). So my question is meant for Vim gurus out there: can this be done and how?
Update: a bit of a background story. I've been talking to my ex-boss about all the benefits of Vim, and he thinks it's all great. His only question/problem was: does it have "extend selection"? My question so far has been no. So, if someone knows the answer, I'll finally win a discussion :P (and maybe create a new Vim convert:-))
I had a quick go at this problem. It doesn't work as is. Feel Free to make edits and post on the vim wiki or as a plugin if you get it refined.
chances are you'd want to make a g:resharp_list for each language (eg. one for paranthesised languages, etc.)
All that is needed is a marker for the original cursor position :he markers and a timeout autocommand that resets the index.
"resharp emulator
"TODO this needs a marker
"also c-w is bad mapping as it has a lag with all the other-
"window mappings
"
let g:resharp_index = 0
let g:resharp_select = ['iw', 'is', 'ip', 'ggVG']
func! ResharpSelect()
if g:resharp_index >= len (g:resharp_select)
let g:resharp_index = 0
endif
exe "norm \<esc>v" . g:resharp_select[g:resharp_index]
let g:resharp_index = g:resharp_index + 1
endfun
nnoremap <c-w> :call ResharpSelect()<cr>
vnoremap <c-w> :call ResharpSelect()<cr>
"Something to reset on timeout. TODO this doesn't work
au CursorHold :let g:resharp_index = 0<cr>
The answer is yes. Once in Visual mode you can use all the regular navigation methods as well as some extra ones.
Some of my favourites? First hit v while in normal mode to get to visual mode then hit:
iw - to select the inner word. Great for selecting a word while excluding surrounding braces or quotes
w - hit multiple times to keep selecting each subsequent word.
b - select wordwise backwords
^ - select all from current position to beginning of text on line
$ - select all from current position to end of line
I'm sure others here could add to this list as well. Oh and don't forget Visual Block mode C-v try it out in vim with the above commands it works in two dimensions :-)
If you're talking about Vim (and you should be :-), you can start marking text with the v command, then you have all the standard cursor movement commands (and, as you know, there are a lot of them) which will extend the selection, as well as moving the cursor.
Then you just do whatever you want with the selected text.
See here for the gory details.
One would need to write a function that would save the current selection, then try increasingly wide selections, until the new selection exceeds the saved one or selects all text. Some possible selections are:
viW - select word
vis - select sentence
vip - select paragraph
viB - select text within the innermost brackets
v2iB - select text within the next most innermost brackets
ggVG - select all text
I think Jeremy Wall's heading in the right direction. And to get a little further in that direction, you might look at the "surround.vim" script from Tim Pope. A good description is available on github. Or, if you'd rather, get it from vim.org. It'll probably help you do some of the things you'd like to do, though it doesn't seem to have a feature for say, simply selecting within a tag. Let me know if I'm wrong.
Ultimately, what you'd really like is a hierarchy of enclosing text-objects. You should read up on text-objects if you haven't. A nice overview is here. Note that you can grab multiple objects in one go using counts, or do this iteratively (try vawasap}}} from normal mode).
You can also get scripts which define other text-objects, like this one that uses indentation to define a text-object. It'll work for many languages if you're formatting according to common standards, and guaranteed for python.
One annoyance is that the cursor ends up at the end of the visual block, so, for example, you can't easily select everything between some ()'s, then get the function name that precedes them...
...BUT, I just found in this post that you can change this behavior with o. Cool!
I suspect you'll find yourself more efficient being able to skip over intermediate selections in the long run.
Anyway, I'll be curious to see if anyone else comes up with a more general solution as well!
In Rider [on a Mac with VS Mac bindings with IdeaVim], I bind:
Ctrl+= to Extend Selection
Ctrl+- to Shrink Selection
Doesn't clash with any other bindings of consequence and doesn't require a v for mode switching, and easier than Cmd+Option+-> and Cmd+Option+<-
Putting it here as I always hit this question with any Rider Vim selection searches. If I get enough harassment, I'll create a self-answered "How to use Extend Selection with Rider Vim mode".

Resources