Vim search text in folder - vim

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

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:

VIM search multiple closed files

One thing that I like to do from time to time is do a quick search on the directory I am working on and find all the references to a specific string, specially when debugging code from some one else. Is it still not possible for VIM to do such search? Is there an alternative to do it directly with plain terminal?
ATM (since I'm still learning VIM) I do the search in TextMate and find the string that way.
You can use the vim command :vimgrep. This will search for a pattern in the specified files and puts the results in the quickfix window which you can then use to jump to a specific match. So for example to search for foo recursively in every .php file in your current directory you would do
:vimgrep "foo" **/*.php
Another option is the command :grep which actually calls the grep program (or whatever grepprg is set to). It also puts the results in the quickfix window for easy navigation. However this requires that you have grep on your system.
vim's an editor, not really a file searcher. It's trivially simple to call out to a shell and run 'grep', however. Assuming you're on a Unix-ish environment (TextMate - MacOs?) While in command mode, hit ctrl-z and you'll be at the shell prompt, then do
grep somestring *.c
and you'll get all matches for 'somestring' in any C source files.
Once done grepping, just do a fg (foreground) command and boom - back to VIM.
vimgrep will work, but if the source happens to be in Git then you can use tpope's excellent https://github.com/tpope/vim-fugitive plugin, which exposes :Ggrep which hangs off git grep for more flexibility.
If it's specific entities you're looking for (functions, variables, etc) the integration with ctags is probably of interest to you as well.
Sounds like you might like to have a look at vim tag search functionality combined with ctags. ctags is an utility that can be used to generate an index (a tags file) of various language objects for source code (full project tree, not just a directory). In vim a tag is sort of identifier that can be jumped to or searched for.
See vim documentation:
:help tagsrch
Or:
http://vimdoc.sourceforge.net/htmldoc/tagsrch.html#ctags

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)

Shortcut to open file in Vim

I want to open a file in Vim like in Eclipse using Ctrl + Shift + R, or via the Ctrl + N option of autofill. Invoke a keyboard shortcut, type the file name/pattern, and choose from all the matching files names.
I know opening it normally like:
:tabe <filepath>
:new <filepath>
:edit <filepath>
The problem here is that I have to specify the whole file path in these cases.
What I normally do is e . (e-space-dot) which gives me a browsable current directory - then I can / - search for name fragments, just like finding a word in a text file. I find that generally good enough, simple and quick.
I recently fell in love with fuzzyfinder.vim
... :-)
:FuzzyFinderFile will let you open files by typing partial names or patterns.
:find is another option.
I open vim from the root of my project and have the path set to there.
Then, I can open files located anywhere in the tree using:
:find **/filena< tab >
Tab will autocomplete through various matches. (** tells it to search recursively through the path).
You can search for a file in the current path by using **:
:tabe **/header.h
Hit tab to see various completions if there is more than one match.
Consider using CtrlP plug-in.
It is included in Janus Distributive.
Allows you to find files in the current directory, open buffers or most recently used files using "fuzzy matching" or regular expression.
unless I'm missing something, :e filename is the fastest way I've found.
You can use tab to autocomplete the filename as well.
I like the :FuzzyFinderTextMate (or Ctrl + F) on my setup.
See http://weblog.jamisbuck.org/2008/10/10/coming-home-to-vim
I use a couple of shortcuts in my .vimrc file (exact syntax below).
They are based on the fact that in 90% of the cases, I want to open another file in the same directory as the file that I am currently editing, or in a directory that is very close in the hierarchy to that edited file.
Here's what the commands do do:
,cd : Change the current working directory to the directory that the current file you are editing is in.
,e : Opens a file with the current working directory already filled in so you have to specify only the filename.
Put these into your .vimrc:
map ,e :e <C-R>=expand("%:p:h") . "/" <CR>
map ,cd :cd %:p:h <CR>
Here's a sequence of events:
You are editing a file called test.java in "/home/prog"
,cd -> Current working directory now
becomes "/home/prog"
,e -> Expands to ":e /home/prog" so
that you can just fill in the file
name, say test.h.
,e -> Expands to ":e /home"
tab -> Cycle through subdirectories of /home
enter -> cd to the directory you
want say /home/prog
,e -> Expands to ":e /home/prog"
There's also command-t which I find to be the best of the bunch (and I've tried them all). It's a minor hassle to install it but, once it's installed, it's a dream to use.
https://wincent.com/products/command-t/
Use tabs, they work when inputting file paths in vim escape mode!
If you've got tags (and you should), you can open a file from the command line just by the name of the class or method or c function, with "vim -t DBPlaylist", and within vim with ":tag ShowList".
If you're editing files in a common directory, you can :cd to that directory, then use :e on just the filename.
For example, rather than:
:e /big/long/path/that/takes/a/while/to/type/or/tab/complete/thingy.rb
:sp /big/long/path/that/takes/a/while/to/type/or/tab/complete/other_thingy.c
:vs /big/long/path/that/takes/a/while/to/type/or/tab/complete/one_more_thingy.java
You can do:
:cd /big/long/path/that/takes/a/while/to/type/or/tab/complete/
:e thingy.rb
:sp other_thingy.c
:vs one_more_thingy.java
Or, if you already have a file in the desired directory open, you can use the % shorthand for the current filename, and trim it to the current directory with the :h modifier (:help :_%:) :
:e /big/long/path/that/takes/a/while/to/type/or/tab/complete/thingy.rb
:cd %:h
:sp other_thingy.c
:vs one_more_thingy.java
And, like others have said, you can tab-complete file names on the ex-line (see :help cmdline-completion for more).
This isn't exactly what you're looking for, but it's good in many cases (though not all).
If you VIM open and there's a name of a file in the buffer, you can put the cursor on that filename and type gf. This opens the file whose name is under the cursor in the same buffer. It's the same as
:e CTRL+r CTRL+w
I know three plugins that permit to open files, support auto-completion, and don't require to enter the full path name of the file(s) to open (as long as the files are under one of the directories from &path vim option):
searchInRuntime that I'm maintaining (the completion is not on :e/:find, but on split actions)
fuzzy finder as it has been already pointed out,
lookupfile.
Lately, I've seen another plugin with a similar feature, but I don't remember the name.
Soon, :find is likely support auto-completion -- patches on this topic are circulating on vim_dev mailing-list these days.
you can use (set wildmenu)
you can use tab to autocomplete filenames
you can also use matching, for example :e p*.dat or something like that (like in old' dos)
you could also :browse confirm e (for a graphical window)
but you should also probably specify what vim version you're using, and how that thing in emacs works. Maybe we could find you an exact vim alternative.
FuzzyFinder has been mentioned, however I love the textmate like behaviour of the FuzzyFinderTextmate plugin which extends the behaviour to include all subdirs.
Make sure you are using version 2.16 of fuzzyfinder.vim - The higher versions break the plugin.
With Exuberant ctags, you can create tag files with file information:
ctags --extra=+f -R *
Then, open file from VIM with
:tag filename
You can also use <tab> to autocomplete file name.
In GVIM, The file can be browsed using open / read / write dialog;
:browse {command}
{command} - open / read / write
open - Opens the file
read - Appends the file
write - SaveAs dialog
I installed FuzzyFinder. However, the limitation is that it only finds files in the current dir. One workaround to that is to add FuzzyFinderTextmate. However, based on the docs and commentary, that doesn't work reliably. You need the right version of FuzzyFinder and you need your copy of Vim to be compiled with Ruby support.
A different workaround I'm trying out now is to open all the files I'm likely to need at the beginning of the editing session. E.g., open all the files in key directories...
:args app/**
:args config/**
:args test/**
etc...
(This means I would have possibly scores of files open, however so far it still seems to work OK.)
After that, I can use FuzzyFinder in buffer mode and it will act somewhat like TextMate's command-o shortcut...
:FuzzyFinderBuffer

Resources