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
Related
There are a couple of things I do not yet understand the VIM way.
One of these is searching in a project like so (using VIM in Atom):
I use CtrlP currently for file names, but what about the contents?
How can I search with a string, and then look through a list of all occurrences using VIM and/or VIM plugins?
I've found an even better solution for this: FZF
It simply searches through everything in your project asynchronously using the :Ag command.
Use :grep or :vimgrep to search file contents. The results are put onto the "location list" which you can open by typing :cw Enter.
Syntax for :grep is, by default, the same as the grep(1) command:
:grep 'my pattern.*' /path/to/dir
By default it will search the current directory (:pwd). I added set autochdir to my .vimrc so my PWD always follows the file I'm editing.
The major difference between :grep and :vimgrep is that :vimgrep (:vim for short) uses Vim-compatible regular expressions, whereas :grep uses whatever regular expressions your &grepprg uses.
You can use a custom program by setting &grepprg to something different. I personally like ack which uses Perl-compatible regex.
Apart from fzf, there are also other excellent plugins for fuzzy finding.
telescope.nvim (neovim only): after install, just use Telescope live_grep to search through your project.
Leaderf: another fuzzy finder with good performance. After install, use Leaderf rg to search through your project.
To open a file, I highlight the row (Shift-v) in the location list and hit Enter.
In particular, I'm editing files in Verilog and would like to see other instances of a word under the cursor in other files. Ideally, it'd bring up a list like the auto-complete list. I can then select the line entry and vim would open the file (either in the same window or a new tab).
I've seen this feature in Emacs. I have to think it exists in Vim somewhere.
This would be really fun to write in vimscript, but I don't exactly have time at the moment. Hopefully this will get you going in the right direction:
There is a vim plugin called Fugitive
It allows you to do things like git grep, or git blame right from you vim console. https://github.com/tpope/vim-fugitive
Their git grep command, Ggrep, should get you a list of local files with whatever word you want to grep for. Possibly check out this Q/A for getting it to work nicely: Getting 'git grep' to work effectively in vim
Last thing I would do is write a little vimscript function and a keystroke alias that would call Ggrep with the word under the cursor.
(hopefully I'll have time to write a better answer later)
If you have a tags file available, you might be able to use :tselect identifier for that purpose.
Vimgrep is your friend.
:vimgrep /pattern/ <path>/**
This will add lines to the quickfix window. Each line is the text from the line in a file that matches the pattern. The ** is shorthand for recurse into subdirectories.
I work with multiple fairly large projects with 1600+ files across 125+ directories each, but those files are interspersed with larger projects with many times that number of files and directories, which make recursive searching from the top of the project too slow and unwieldy. And I'd rather not preemptively load all those files into vim's buffers.
Fortunately, these projects have fairly good filelists that I've can parse to setup project-specific vimrc files (project.vimrc) that right now just contain a lot of "set path+=/path/to/dir" which works great for enabling stuff like "gf" to work quickly.
I'd like to find a grep solution to search for a string in the given filelist or in the directories in vim's path variable, and have it list results in the quickfix window. Is there a way to do this?
Most of the existing grep solutions seem to want you to specify the top directory and recurse, or let you grep through the files already loaded into the buffers.
If your 'path' option already contains a list of interesting directories, you can pass that on to :vimgrep, like this:
:execute 'vimgrep /pattern/' join(map(split(&path, ','), 'v:val . "/*"'))
This appends /* to each path, so that any files inside that directory are searched.
grep can take multiple directories to search recursively like via grep -r foo/ bar/ (See man grep and :h :grep for more information). However grep can be a bit slow with many files. There are some nice alternatives:
Ack is faster than regular grep because it skips VCS directories, binary files, and can search for specific type of filetypes like --perl. For Vim integration see Ack.vim
Ag the Silver Surfer is a code-searching tool similar to ack, but faster. Vim plugin: Ag.vim
git grep searches a repository very quickly. Fugitive.vim provides :Ggrep.
I recommend both Ag and git grep as they are both super fast. I have searched over 4700+ in less than a 1 second.
To test out one of these alternatives without a plugin or you simply don't want a plugin you can set your 'grepprg' option accordingly. e.g. set grepprg=ack. See :h 'grepprg' for more information.
If you really need to search a specific list of files Ack has --files-from=FILE and -x options which take a list of files in the form of file or stdin respectively.
Other tools which may be of some help for some programming languages are:
ctags builds a symbol database and allows you to jump to symbols. See :h tags-and-searches
Cscope is a tool like ctags, but think of it as ctags on steroids since it
does a lot more than what ctags provides.
locate unix tool much like find except it uses a prebuilt database. See man locate and Tim Pope's vim-eunuch.
GNU global is another symbol database that provides ctag/cscope like options as well.
As a final fallback you can use :vimgrep as it is available on all systems that Vim is available. See :h :vimg for more help.
As most of these options use the quickfix list I suggest you use some more friendly mappings to transverse the quickfix list. I use Tim Pope's unimpaired plugin which uses ]q and [q for :cnext and :cprev respectively. Some people like the quickfix to open after a search is performed then add the following to your ~/.vimrc file: autocmd QuickFixCmdPost *grep* cwindow
In conclusion you have many options however I personally doubt you can beat git grep or Ag in for general searching needs. I also use GNU Global for my symbol needs.
For example, when I encounter:
funcMiracle (argMagic);
I want to press a button, and woosh, I immediately jump to the definition of funcMiracle, regardless of it is in the current file or not.
Install exuberant ctags on your machine. Then, from the command line, in your project root:
ctags -R
Pressing ctrl-[ in Vim will then jump to the definition of the symbol. After the jump, ctrl-T will take you back where you just came from.
Updated
Since I read your comment:
The question is, though it can help me find any function in my project, it won't automatically find the external functions that I probably linked from a header file, for example, the definition of fgets() in stdio.h
Have a look at
C-[C-I for include file search
C-[d for and definition lookup
Shift-K opens up the man page for the identifier under the cursor (e.g. fgets :)
With the man.vim script you can also summon the manpage inside a Vim buffer for easy copy/paste, highlighting, crossreference like with helptags etc. Key: Leader-K
Once again, :he ^[^I etc. are good pointers for more help/details
Tags on external projects
You can generate tags for an external project (say, linux headers) using ctags as shown earlier (below). It then a matter of letting Vim know where your tags are:
:se tags+=/usr/src/linux/tags
Note the +=: Vim can handle multiple tags files at once
The standard approach
install (if you haven't), ctags
:!ctags % (or for recursive whole folder etc :!ctags -R %:h or :!ctags **/*.c etc)
use tags (C-] or Ctrl-MouseButton, see :help tags for complete reference)
You can integrate the building of tags in your makefile if you have one. Exuberant ctags is highly configurable; I routinely use
ctags --exclude=packagedir -R --c++-kinds=+p --fields=+iaS --extra=+q
for use with C++, but it supports many many languages out of the box with zero configuration.
When using Vim, and given a directory filled with code (e.g. ~/trunk/) with a number of sub-directories, is there a way to grep/search for instances of text/regexes across the entire source code?
At the moment I use:
:lcd ~/trunk
:grep "pattern" *.py */*.py */*/*.py */*/*/*.py
(Obviously I'm limiting this to Python files, which is a different issue, but it's noteworthy that ideally I'd like to limit the searches to files with specific extensions.)
:vimgrep "pattern" ~/trunk/**/*.py
:copen 20
If you have quite a big project I'd recommend to you to use cscope and vim plugins. Here is one designed to handle big projects: SourceCodeObedience
There is a brief description of how to grep text using SourceCodeObedience.
I use grep directly for that.
grep -IirlZ "pattern" .|xargs -0 vim
-I: ignore binary
-i: ignore case
-r: recursive
-l: print file name only
-Z: print \0 after each file name
You may want to check out :vimgrep and :grep in the vim documentation. :vimgrep uses vim's own pattern searching functionality and reads all files into vim buffers. :grep by default links to an external grep utlity on your system, but you can change the behavior by setting the grepprg option. Here's a link to the online docs:
http://vimdoc.sourceforge.net/htmldoc/quickfix.html#grep
There's more info on that and also some other options in the tip on "Find in files within Vim" at the Vim Tips Wiki:
http://vim.wikia.com/wiki/Find_in_files_within_Vim
Set grepprg to Ack, then use :grep to search with Ack.
Or use ctags.
Ag is good option to search the pattern recursively.
https://github.com/rking/ag.vim
You could use :vimgrep i.e.:
:vimgrep /pattern/ **/*.py
Check this Vim Tip:
Find in files within Vim
Also give a look to grep.vim, it's a plugin that integrates the grep, fgrep, egrep, and agrep tools with Vim and allows you to search for a pattern in one or more files and jump
to them...
You can generate a source code index using ctags and then VIM can use this to navigate seamlessly through your code base. It's source code aware in that you can jump directly to method declarations etc.
You need to regenerate the ctags files every so often, but you can do that as part of your make process. It should be pretty fast unless your code base is sizeable.
Nobody's mentioned it, but I use tend nowadays to use ripgrep