Vim: See all instances on page and choose one - search

I seem to recall a vim plugin that will allow you to, essentially, execute ":g/pattern/p" and then prompt you to select one. Does anyone know of this plugin? Or is it a built-in function?
Basically, I want to perform a search, see all instances on the current page (or even in open buffers), and then be able to select which one to go to.
Thanks!
EDIT:
I want it to actually take me to the line number when I make my selection, and I want it to be a fairly simple solution. I'm pretty sure I've seen a plugin for this, but I can't remember what it was. Any thoughts?
PS. Thank you to all who are answering. They're great answers.

You can use :vim[grep] or :gr[ep].
:vim foo % | cw
See :help quickfix.
If you want a plugin, you'll have to search vim.org.

This might get you close. Its not an interactive menu but it does tell you the line number for the match
:g/<regex>/#
The # tell global to print the line numbers. Take a look at :h :number (# is a synonym for :number)

You could populate the result into the quickfix window via the :vimgrep command
:vimgrep/regex/ %
% represents the current buffer's filename. Note: buffer must be a file and not a scratch buffer.
Then use quickfix commands like :cnext and :cprev to move through the list. Or open the list via :copen and press <cr> to jump to the match.
You can :vimgrep any number of files:
All *.c files e.g. :vimgrep/regex/ *.c.
Use ** to search down into deep directories e.g. :vimgrep/regex/ **/*.c.
You can also use vimgrep with the args list via :vimgrep/regex/ ##.
For more help see:
:h :vimgrep
:h quickfix
:h c_%
:h arglist

:g/regex/p
:g executes :p by default, so it can be omitted; the trailing slash can also be dropped:
:g/regex
Note that :g jumps to the last occurrence in the file, so you can then execute N/ (in normal mode) to jump to the Nth occurrence. Or, if there are many matches and you don't care to count which one you want, you can at least jump to its line, L, with LG or Lgg or :L.
If you don't use :set number but want line numbers in the output of :p, append nu[mber] or # as #FDinoff suggests:
:g/regex/nu
:g/regex/#

You can confirm one change after another in all open buffers with:
:bufdo %s;<pattern>;<replace>;c | update
The :bufdo goes through all buffers. The c is the flag to confirm all changes. The update writes the current buffer which allows going to the next.

Related

Find and replace all instances of specific string in multiple files in vim

I'm still relatively new to Vim and can't figure out how to replace all instances of a specific string in multiple files (from a specific project directory). Ideally I want to do this without any additional plugins; was looking into :vimgrep and :arg options but can't work it out.
Thanks for your time in advance!
The general workflow is:
Search for your pattern across the project.
Operate on each match (safer, slower) or on each file with matches (riskier, faster).
Write your changes.
The first step can be done with any command that populates the quickfix list: :help :vimgrep, :help :grep, something from a third-party plugin, etc.
Taking :grep as an example:
:grep foo **/*.js
will populate the quickfix list with an entry for every foo found in *.js files in the current directory and subcategories. You can see the list with :cwindow.
The second step involves :help :cdo or :help :cfdo:
:cdo s/foo/bar/gc
which will substitute every foo with bar on each line in the quickfix list and ask for confirmation. With :cfdo it would look like that:
:cfdo %s/foo/bar/gc
If you are super confident, you can drop the c at the end. See :help :s_flags.
The third step involves :help :update:
:cfdo update
which will write every file in the quickfix list to disk if they have been changed.
In short:
:gr foo **/*.js
:cdo s/foo/bar/gc
:cfdo up
You can run a standard substitute command on all lines of all files of the arg
list like so:
:argdo %s/pattern/replacement/ge
And if you want to add all files from a particular directory to the arg list,
you can use:
argadd `path/to/dir/*.py`
Notice the backticks in the above example.
See a good series of screen casts about how to do more
here and see this
episode in
particular.

gvim - jumplist to functions within a file

I'm using VIM to work with Powershell files. How do I make gvim:
show full list of strings that match some regex? (either in new buffer or in command window)
go to a line selected in the found list?
The following command will get you all the matching lines into the command window.
:vimgrep /INSERT_EXPRESSION_HERE/ % | cw
You can then use normal vim navigation to find the line inside the command window, and hit Enter to jump to that line in the file. To return to the list again, you can use the normal vim Window movement commands C-w,j in normal mode.
For a non-persistent list of search results, you can use the built-in :ilist command to list and :ijump to jump. My FindOccurrence plugin has extended mappings ([/ to query for a pattern, list all occurrences, and query for a number to jump to, and [N which uses the current search pattern). Here's a little demo:
To persist the list of search results, :vimgrep with the quickfix list can be used (as shown in #merlin2011's answer). My GrepHere plugin makes this even easier. Again, a short demo:

how to edit highlight text in vim after searching

I like to use "*" to search text in vim. after hight light the target text, I want to edit all of them, is there any way I can do it in vim? for example, after highlight text, I just need to press ctrl+i then the highlight text can be edited simultaneously
Simultaneous editing (like seen in other editors) is not built into Vim (but there are plugins). You don't need them, though. After *, the text is stored in the last search pattern register, and you can just :substitute// without repeating what you're searching for:
:%s//replacement/g
The % is a range and applies this to the whole buffer; the /g is a flag that replaces all (globally) instances, not just the first in each line. Read :help :s for details.
You can check out the vim-multiple-cursors plugin.
Personally, I like #Ingo's solution. The less plugins the better.
As a nice alternative. You can use gn and the . command.
Set your search pattern i.e. * or /foo
Change your highlighted pattern via c operator over the gn motion
cgnbar<esc> will change the highlighted area to bar.
Now you can use . too repeat this change. You can also use n to skip places.
Note: This requires at least 7.4
For more help see:
:h gn
:h .
If you wish to edit the word with another you can use the substitute command. (e.g. :%s/hi/hello/g)
This will change all occurrences of hi to hello in the file.

Vim searching through all existing buffers

When dealing with a single file, I'm used to:
/blah
do some work
n
do some work
n
do some work
Suppose now I want to search for some pattern over all buffers loaded in Vim, do some work on them, and move on. What commands do I use for this work flow?
Use the bufdo command.
:bufdo command
:bufdo command is roughly equivalent to iterating over each buffer and executing command. For example, let's say you want to do a find and replace throughout all buffers:
:bufdo! %s/FIND/REPLACE/g
Or let's say we want to delete all lines of text that match the regex "SQL" from all buffers:
:bufdo! g/SQL/del
Or maybe we want to set the file encoding to UTF-8 on all the buffers:
:bufdo! set fenc=utf-8
The above can be extrapolated for Windows (:windo), Tabs (:tabdo), and arguments (:argdo). See help on :bufdo for more information.
We can do this using vimgrep and searching across the argslist. But first let's populate our argslist with all our buffers:
:bufdo :args ## %
Now we can search in our argslist
:vimgrep /blah/ ##
Where % == the current filepath and ## == the arglist.
I recommend watching these vimcasts if you want to learn more: Populate the arglist, Search multiple files with vimgrep
I have the following mappings (inspired by Vimperator) that make switching previous/next buffer easier.
nmap <C-P> :bp<CR>
nmap <C-N> :bn<CR>
This works really well with 'n'. When you're done working with your file, just hit CTRL-n before hitting n again and you're searching in the next buffer. Redo until you're through all buffers.
Another way of working with many files is the argument list.
It contains any files passed as parameters when you started vim (e.g: vim someFile.txt someOtherFile.py). The file within [brackets] is the current file.
:args
[someFile.txt] someOtherFile.py
:n will bring you to the next file in the list and :N will bring you back. You can also add to the argslist with :argadd, or create a new args list with
:n some.py files.py you.py want.py to.py work.py with.py
or to open all *.py files recursively from some project.
:n ~/MyProjects/TimeMachine/**/*.py
The args list work well with macros too (see :help q), if you have similar changes to your files. Just record your macro on the first file, finish with :n to move to the next file, and stop recording.
qq/searchForSomethingAndDoStuffOrWhatever:nq
Then run your macro through all files (6#q), have a look to make sure everything went well, and finish with a :wall.
It kinda depends on what you want to do. If you just have one change that is exactly the same across many files (and those are the only ones you have loaded), I also like the :ba (:tabdo sp) command. It's very quick and you can see what's happening.
And if you have a bunch of buffers open, you can load up the files you want to work within, each in a window, and do a regexp on all of them.
CTRL-w v :b someFile
:sp anotherFile
...
:windo :%s/foo/bar/g
I really recommend FuzzyFinder, it makes your life a lot easier when opening files.
http://www.vim.org/scripts/script.php?script_id=1984
MMmMmmmm VIM IS NICE! SO SEXY! : )
Anytime you want to switch to another buffer try this.
:b + <any part of file in buffer> + tab
For an example. I have this in my buffer
77 "/var/www/html/TopMenuAlertAlert.vue" line 65
78 "/var/www/html/MainSidebar.vue" line 29
79 "/var/www/html/FullScreenSearch.vue" line 26
80 "/var/www/html/Menu.vue" line 93
81 "/var/www/html/layouts/RightSidebar.vue" line 195
As I want to change to another buffer, I probably remember some detail about the file like 'Alert'
So I just go
:b Alert + tab
if the file given is not the one I want, I just keep on pressing tab.
Vim will keep on giving the next file close to it.
Once you got it. Press Enter.
Here is your gospel:
https://github.com/jeetsukumaran/vim-buffersaurus
This lovely plugin shows you all the files that match your query in a separate window, from which you can choose. It support regex.
I don't believe it's possible to extend the 'n' functionanly across files or buffers. You could use
:grep blah *
And then do
:cn
To move to the next line with blah on it. That will switch between files but it's not quite as neat. It's more cumbersome to type the colon all the time, and it will only take you to the line, not the word.
What I usually do is either to open the files I want to searched in tabs and then use 'n' and 'gt' to jump to next tab when I reach the end of the file, or list the files on the command line to I can skip to the next file with ':wn' when I'm done editing it.
Hope it helps!
Another approach:
:call setqflist([]) " clear quickfix list
:silent bufdo grepadd! foo % " edit foo in command-line history window
:cw " view search results
Or mapped:
cmap bbb call setqflist([]) \| silent bufdo grepadd! %<C-F>$hha
I would open all the buffers in a new tab using the following two commands:
:tab sp
:bufdo sp
Then search through each file one by one and close its window when you are done (use :q or :close). Use CTRL+W_ to maximize each window as you are working in it. When you're finished and you close the last window, the tab page will close and you'll be dropped back wherever you were before you decided to do the search.

Hide all (not)matching lines in Vim

Is it possible to show/hide all matching lines in vi or Vim? Not highlight but just show only those lines.
For example I have a text with word the word ERROR. How do I make it show only lines containing ERROR and how to show only lines without ERROR?
Is there a solution without deleting all matching lines and then just undoing it?
Do you know about the :global command? Does this do what you want?
:g/ERROR
and for the opposite:
:g!/Error
or equivalently:
:v/Error
Another approach depending on your use case would be using vimgrep and its results in quickfix. You can do the following:
:vimgrep pattern % will search the current file and take you to the first search result. More importantly it also puts the results in the "quickfix list".
:copen will then open the quickfix list in a separate quickfix-window. So you will have a separate window with all lines from your last vimgrep. Inside the quickfix-window you can then hit Enter or double-click on a line to jump to the corresponding line in your original file.
:colder will let you go back to older quickfix lists (older vimgrep results). And :cnewer goes forward to newer search results.
Note that the quickfix list is also updated when running :make (which is why its called quickfix for fixing errors). Because of this there also is an alterative to the quickfix list called the "location list". To use it instead you use :lvimgrep, then use l-prefixed commands rather than c-prefixed commands - :lopen, :lolder, :lnewer.
There is, of course, a lot more you can do. See :help quickfix for more info.
PS, You said you didn't want an approach that deletes lines and then undoing them. But since you marked g/ERRORas the answer I thought I would point out a quick and dirty way is to do g!/ERROR/d. You can then easily undo it using u. Also FYI, you can do :set hlsearch to highlight patterns matched with :g commands.
You can use
:g/ERROR/
to print all the lines with ERROR
Also there is a Vim plugin which I saw many times but didn't use:
foldsearch : fold away lines that don't match a given pattern
The best way to do this is->
:vimgrep /something/g % | copen
This will open the list of matches for your keyword and also will show only the matched lines in quickfix window.
Replace % with path to file if not considering the current file.
:vimgrep /something/g % | copen works awesome. Also :g/<pattern>/d can be used to delete lines with the pattern
in case you happen to use fzf you could use:
:Lines in all open files
:BLines only in open buffer
:Rg [pattern] using ripgrep
You probably mean command in less vi vim
& /pattern/
which shows lines containing /pattern/ (like grep).
Some hackish dirty way to do this:
:w (save)
ggdG (deletes everything)
:.!grep something % (replace current line with grep output)

Resources