How do I turn on search highlighting from a vim script? - vim

If I do either of the following two:
call search("searchString")
exec "/ searchString"
From a script, then vim does the search but does not highlight the results, even though hlsearch. Doing the same searches from outside a script highlights the results.

Just found out the answer myself:
call search(l:searchString)
call matchadd('Search', l:searchString)

The
feedkeys()
function is the key (pun intended):
call feedkeys("/pattern\<CR>")
or cleaner:
" highlights – or doesn’t – according to 'hlsearch' option
function SearcH(pattern)
let #/ = a:pattern
call feedkeys("/\<CR>")
endfunction

I know this is late. However when I searched for the answer to this problem this page came up. So I feel compelled to help fix it.
call search(l:searchString)
call matchadd('Search', l:searchString)
Did not work for me. (when run from inside a function) It did higlight the words I wanted to search for but n/N wouldn't cycle between them. Also when I performed a new search the "l:serachStirng" pattern still remained highlighted. This answer on this link worked much better
Vim search and highlighting control from a script
Which gave me:
let #/ = l:searchString
then run
normal n
outside the funciton (so the highlighting is done immediately without the user needing to press n)

To turn on, press ESC type :set hls
To turn off, press ESC type :set nohls

Found answer here:
http://vim.1045645.n5.nabble.com/highlighting-search-results-from-within-a-function-tt5709191.html#a5709193
```
One solution would be
function! XXXX()
execute '/this'
return #/
endfunction
and to use the following instead of ":call XXXX()".
:let #/ = XXXX()
```

I believe this works from inside a function
(to just enable highlighting and nothing more):
call feedkeys(":\<C-u>set hlsearch \<enter>")

You need to put this in your .vimrc file
" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
syntax on
set hlsearch
endif
The .vimrc file is usually located in your home directory, or you can find it using "locate .vimrc"

Related

VimScript execute search does not work anymore

I don't know since when, but my visual selection search function is not working anymore. I broke the problem down to this minimal example.
Assume the following buffer:
word
word
word
When I run /word, I find all results and can jump between them.
When I run :execute '/word' this works the same as before.
When I write a short autoload function just doing the same it does not work the same:
~/.config/nvim/autoload/utils/search.vim:
function! utils#search#visual_selection() abort
execute '/word'
endfunction
Executing :call utils#search#visual_selection() makes the cursor land on the first result, but no results are highlighted. Moreover it is using the old search pattern instead of the new one. So if I search first for something non existing like foo and then execute this function, pressing n give me the error message Pattern not found: foo.
What has changed. What is the difference here?
This is actually documented behavior of Vim and NeoVim. It's not really related to the use of :execute (you can reproduce it with a direct use of /word), but with how search (and redo) work in a function.
See :help function-search-undo, which states:
The last used search pattern and the redo command "." will not be changed by the function. This also implies that the effect of :nohlsearch is undone when the function returns.
You can work around that by explicitly setting the search pattern register, which you can do with a let command.
function! utils#search#visual_selection()
let #/ = 'word'
execute "normal /\<cr>"
endfunction
The second command executes a simple / from normal mode, that is enough to search for word, since it will look for the last search pattern which is now set to what you wanted.
After the function is finished, the search pattern will keep its value, which means highlighting through 'hlsearch' will work, and so will the n command to find the next match.
A restriction from the approach above is that you can't really set search direction for repeats with n. Even though there is v:searchforward, which can be set, that variable is also reset after a function as part of the :help function-search-undo effects. There doesn't seem to be anything you can do about that one...
If the purpose of this function is for use in a key mapping, you might consider a completely different approach, using nnoremap <expr> and having the function return the normal mode command for the search as a string, that way the actual search happens outside of the function and the restrictions from function-search-undo won't apply.
For example:
function! utils#search#visual_selection(searchforward)
let pattern = 'word'
if a:searchforward
let dir = '?'
else
let dir = '/'
endif
return dir.pattern."\<cr>"
endfunction
And then:
" Mappings for next-word and previous-word
nnoremap <expr> <leader>nw utils#search#visual_selection(1)
nnoremap <expr> <leader>pw utils#search#visual_selection(0)
This avoids the issue with :help function-search-undo altogether, so consider something like this approach, if possible in your case.

How do you know what VIM help keyword to search?

I was trying to google how to search within a scope in VIM and found this link. Limiting search scope for code in Vim
I wouldn't imagine to come up with the keyword "/\%V" to search help in VIM help. So, I'm wondering how most people get help from VIM help, like in this case.
You did the right thing. Google is probably going to be your best bet. You can also use the vim help site, it has a search function built in: http://vimdoc.sourceforge.net/htmldoc/
General:
:help help-summary is a great document explaining how to search
effectively.
Using wildcard expansion
I've had the same frustration, but I just realised that you can use wildcard
expansion when searching.
In your case it wouldn't have helped, but possibly if you'd started with :h pattern and then searched in that page for key words related to what you were
trying to achieve you might have found it.
In my case I was looking for a page I'd been on before only the other night,
:h ex-cmd-index, (on a different machine, so I couldn't search my command
history) but I could only remember than it had to do with ex commands, and had
the word index in there. I spent 20 mins trying to find it unsuccessfully (I
eventually googled it just so I could then return to vim and look it up...). I
was trying ex + Tab and being shown hundreds of possibilities...
But with wildcard expansion, I can just do :h ex*index* and hit Tab and I
get a shortlist of two possibilities, ('ex-cmd-index' and 'ex-edit-index') one
of which was the one I wanted!
So as long as you have an idea of the order that things should appear in the
help topic, you should be able to narrow down the possibilities much faster.
Using :helpgrep
There is a in-built command :helpgrep which puts every line matching a
pattern into a quickfix list. Then you can jump through each line with the
:cnext and cprev commands.
Fuzzy search the help with fzf (and optionally ag-silver-searcher)
The fzf plugin has the command :Helptags to do a fuzzy search on... the
help tags. This is very nice.
In case all the above fails, I added a few functions to search the entire
contents (not just help-tags) of all the files in the vim's help doc directory
using ag-silver-searcher and fzf.
First is a function that I found on an issue on the fzf github repo. I have no
idea how it works, but the command that calls this function allows me to search
the contents of a directory using ag, which pumps the results into fzf:
" Ag: Start ag in the specified directory e.g. :Ag ~/foo
function! s:ag_in(bang, ...)
if !isdirectory(a:1)
throw 'not a valid directory: ' .. a:1
endif
" Press `?' to enable preview window.
call fzf#vim#ag(join(a:000[1:], ' '),
\ fzf#vim#with_preview({'dir': a:1}, 'right:50%', '?'), a:bang)
endfunction
" Ag call a modified version of Ag where first arg is directory to search
command! -bang -nargs=+ -complete=dir Ag call s:ag_in(<bang>0, <f-args>)
So I wrote a function (Help_Ag) that calls the above command, and supplies
the directory containing the vim help docs (141 .txt files, plus a handful of
other files (a README, the tag files themselves etc).
If we select a help page to open, we set it to non-nomodifiable. I noticed that
not all the tags worked, and some redirected to the wrong page (e.g. a tag like
*help-topic* would take me to a page called help if the cursor was on that
word, and take me to topic if the cursor was on that word, whereas the in
real help, I would be taken to help-topic). I found that if I opened the real
help, the tags would start behaving normally in files selected with ag+fzf. So
I simply open and close the real help to trigger this behaviour (it's too quick
to even see, so I'm happy enough with this hack):
function! Help_Ag()
let orig_file = expand(#%)
let v1 = v:version[0]
let v2 = v:version[2]
" search in the help docs with ag-silver-search and fzf and open file
execute "normal! :Ag /usr/share/vim/vim".v1.v2."/doc/\<cr>"
" if we opened a help doc
if orig_file != expand(#%)
set nomodifiable
" for some reason not all the tags work unless I open the real help
" so get whichever help was found and opened through Ag
let help_doc=expand("%:t")
" open and close that help doc - now the tags will work
execute "normal! :tab :help " help_doc "\<cr>:q\<cr>"
endif
endfunction
" get some help
command! H :call Help_Ag()

Vim functions for cleaning up hidden characters

Currently in my .vimrc file I have a function which clears all trailing white spaces on save, while retaining my mouse position.
fun! <SID>StripTrailingWhitespaces()
let l = line(".")
let c = col(".")
%s/\s\+$//e
call cursor(l, c)
endfun
autocmd BufWritePre *.sql,*.php :call <SID>StripTrailingWhitespaces()
This works great. But I would like to add a few more things to it like:
* Remove carriage returns
* Fix indent SP followed by a TAB
I tried adding
%s/^M//e
to my StripTailingWhitespaces() function, but when I save now vim tells me
Press ENTER or type command to continue
So I think I did something wrong or am forgetting something. Any help figuring this out? Thanks
UPDATE: Still working on this problem. I've tried adding a <CR> at the end of my searches in the StripTrailingWhitespaces function as well as at the end of the BufWritePre command. No luck. In fact, adding it gives me lots of "Trailing Spaces" errors. Any more suggestions?
If not one for fixing the need to press enter problem, what about a search to fix indent SP followed by a TAB?
I have tested it with
fun! S()
let l = line(".")
let c = col(".")
%s/\s\+$//e
%s/^M//e
call cursor(l, c)
endfun
and it worked perfectly with Vim 7.3 (Note: the ^M is entered with CTRL-V CTRL-M)
So, it looks like you don't do anything wrong, and haven't forgotten anything.
Now, that doesn't help you going further, does it?
If you have this message, try :messages, maybe this will give you a hint.
Also, :help messages reads
Press ENTER or type command to continue
This message is given when there is something on the screen for you to read,
and the screen is about to be redrawn:
- After executing an external command (e.g., ":!ls" and "=").
- Something is displayed on the status line that is longer than the width of
the window, or runs into the 'showcmd' or 'ruler' output.
So, this section might be worth reading (it's longer than the one I pasted).

How to detect a function in Vim?

If the cursor is in somewhere within a very long function, is there a way to let Vim tell the user in which function he/she is editing?
By the way, I use taglist but seems that taglist does not auto update where you are even if you have moved the cursor to a different function.
The taglist plugin provides this feature. The function in which
the cursor is currently positioned is highlighted automatically in the list of
functions of taglist.
Make sure that Tlist_Auto_Highlight_Tag is not equal 0 to enable this feature.
'updatetime' defines the time of no activity which must elapse before
taglist highlights the current function. Default is 4 seconds.
:help taglist.txt See section "Highlighting the current tag"
As a quick test:
Type :TlistHighlightTag to force taglist to highlight the current function.
If this works I suppose that you have disabled the automatic highlighting in any
way (see Tlist_Auto_Highlight_Tag).
As an addition to Habi's answer, if you want to do it without using taglist, you can quite easily define a function that will work it out. It depends what language you're programming in, but for C-like languages, you can do this:
nmap ,f call ShowFuncName()
" Show the name of the current function (designed for C/C++, Perl, Java etc)
fun! ShowFuncName()
let lnum = line(".")
let col = col(".")
echohl ModeMsg
echo getline(search("^[^ \t#/]\\{2}.*[^:]\s*$", 'bW'))
echohl None
call search("\\%" . lnum . "l" . "\\%" . col . "c")
endfun
Put that it in your vimrc and then press ,f to see the current function.
Taken from here.

Vim: NERD_tree Plugin. Need help understanding a bloggers .vimrc addition to streamline this plugin

So I'm basically a beginner when it comes to Vim, nonetheless I do know the basic things (open files, edit, move around, basic grep, .vimrc, etc)
I would submit this link first
http://weblog.jamisbuck.org/2008/11/17/vim-follow-up
If you scroll down to where it says "NERD___tree", it explains what it is and gives a link to the home page. I have already gotten NERD_tree installed, so far so good.
Only thing is, this guy (JamisBuck) adds a line to the .vimrc file to streamline it's usage (I'm guessing to toggle between NERD_tree and the actual file, because as far as I can tell, there is no quick way to do it other than typing in:
:NERDTree
Every time which is less than desirable. The follwing is the code he adds to the .vimrc file:
map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>
He doesn't explain exactly what is is and/or how to use it, so If someone could give me a short explanation and/or point me towards a resource to learn more about this, that would be appreciated.
I'd say :help leader will give you what you need, is an anti-slash by default.
Thus, map <leader>d will be launched when you do \d.
According to the vim documentation, the
<Leader>
Is a special variable that is replaced with the value of "mapleader" at the time the mapping is defined. So:
map <leader>d :execute 'NERDTreeToggle ' . getcwd()<CR>
Is mapping the mapleader and "d" to the toggle. If you look at the page you linked, earlier in the page he says:
I’ve got my <Leader> character (:h mapleader) mapped to the comma
(since it’s easier to reach than the backspace character).
let mapleader = ","
So the toggle should be ",d" as far as I can tell.
In addition to what others have said (d mapped to the command), the command, itself:
:execute 'NERDTreeToggle ' . getcwd()<CR>
Is simply executing the NERDTreeToggle command with the first argument as the current working directory. The at the end is a carriage return, and is just simulating a press of the enter key.
This means that when NERD tree opens, it will be in the current working directory.

Resources