How to jump between patterns when using :vimgrep (Quickfix list)? - vim

I am new to vim, and still exploring some features of it. I have a problem with vimgrep. I can search for a pattern like this vimgrep /define/ ** so that it finds and opens next file that contains a define. But I couldn't yet find out how to go to the next file/line that matches my pattern. Any pointers?

Useful commands for the quickfix list (brackets around omittable part of the commands):
:cn[ext] and :cp[revious] jump to next and previous entry
:cnf[ile] and :cpf[ile] jump to next and previous file (if the quickfix list is not sorted by file you could write a function that getqflist(), performs a sort and then setqflist()
:cr[ewind] and :cla[st] go to beginning or end of the quickfix list
:col[der] and :cnew[er] will iterate through historical quickfix lists.
Needless to say there are plenty of other commands and you can discover them at :help quickfix.
Personally I have the following maps :
| ΓΈ | SHIFT | CTRL
------+--------+---------+---------
<F11> | :cprev | :cpfile | :colder
<F12> | :cnext | :cnfile | :cnewer
Of course if you use the location list instead of the quickfix list (:lvimgrep) the same commands exist, just replace the initial c with an l and that's it.
Vim 8 Additions:
:cdo : perform a command on all entries of quickfix list. For example
:vim /foo/ *.cpp *.h *.hpp can be followed by
:cdo s/pattern/replacement/g
:cfdo: perform a command an all files in quickfix list. For example,
:vim /foo/ *.cpp *.h *.hpp can be followed by
:cfdo %s/2ndpattern/2ndreplacement/g

To jump to the next occurrence of the patter you can use :cnext. You can go in reverse with :cNext.
I'm not sure of a way to skip all occurrences until the next file automatically, but you could open the quickfix window with :cwindow to see a list of matches and navigate to those matches by hitting Enter on the entry in the list.

Related

Vim: See all instances on page and choose one

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.

How to navigate multiple ctags matches in Vim?

I'm using Ctrl-] in Vim to navigate using Ctags.
How do I navigate to alternate file if there are multiple matches?
Ex. something.publish in a codebase containing multiple occurrences of publish:
class Foo
def publish
end
end
class Bar
def publish
end
end
Use g] instead of C-] to get the list of all matches.
You might want to read :help g]
:tn[ext] goes to the next tag, :tp[revious] goes to the previous one. :ts[elect] gives you a list to choose from.
:help tag-matchlist for more fun and exciting things to try!
Adding the answer I was ultimately looking for in case it helps others:
g<C-]> will jump to the tag if there's only one match and will present a list if there are multiple matches.
I've added this mapping to my .vimrc to make it do what I want by default:
nnoremap <C-]> g<C-]>
ltag
ltag the_tag_name
lopen
opens a location window with the tag matches.
This is specially powerful with regular expression tag searches:
ltag /tag_na
lopen
which will list all tags that contain the string tag_na (thus including the_tag_name).
You can then further search inside the location list, before hitting enter to jump to the tag.
To use it for the word under the cursor, you might want to define the map:
nnoremap <leader>l exec("ltag ".expand("<cword>"))<CR>
Then, if you are a tab maniac like me:
command! -nargs=1 Ltag silent ltag <args> | execute "normal \<C-o>" | tab lopen
will open a new tab with the location list and all the matches, instead of jumping to the tab directly:
:Ltag /my_struct

jEdit Hypersearch like results in VIM?

In jEdit, you can do what is called a hyper search, which lists all of the search results in one pane, and allows you to click on them to jump to that place in the text.
Does vim have a similar functionality, using a plugin or otherwise?
That would be the quickfix list or the location list.
To search for foo in the current buffer and display a list of all the occurrences, do:
:vim foo % | copen <-- use the quickfix list
:lvim foo % | lopen <-- use the location list
To search for foo in the current buffer's directory and display a list of all the occurrences, do:
:vim foo .* | copen
See :h quickfix.

Vim search text in folder

Is there a way to search for some text in a folder and to display search results in a separate buffer in Vim? (Like Sublime Text Ctrl + Shift + F results)
No, you don't need any plugin. The default :vimgrep (or :vim) is all you need.
Search for foo in every file in the current directory:
:vim foo * | cw
Search for foo in every JavaScript file in the current directory:
:vim foo *.js | cw
Search for foo in every JavaScript file in the current directory recursively:
:vim foo **/*.js | cw
Search for the current word in every file in the current directory:
:vim <C-r><C-w> * | cw
:vim <cword> * | cw
(edit: use :cw[indow] instead of :copen)
Sounds like you need ack.vim:
This plugin is a front for the Perl module App::Ack. Ack can be used as a replacement for 99% of the uses of grep. This plugin will allow you to run ack from vim, and shows the results in a split window.
Usage:
:Ack [options] {pattern} [{directory}]
Search recursively in {directory} (which defaults to the current directory) for the {pattern}.
Files containing the search term will be listed in the split window, along with the line number of the occurrence, once for each occurrence. [Enter] on a line in this window will open the file, and place the cursor on the matching line.
The :grep Vim command delegates the searching to the external grep tool (or a compatible alternative like ack, set via 'grepprg'). Alternatively, you can use :vimgrep, which performs the searching inside Vim. This allows use to use the same Vim-style regular expressions and glob patterns (like **/), but it usually is slower because each file is read into a Vim buffer.
Both commands display the results in the quickfix window, from which you can navigate to the matches.
You don't need any plugins for this, though there are several available that try to make the handling simpler or support different search commands (e.g. the already mentioned ack.vim).

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