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.
Related
I am learning vim recently as i have to use vim in some restricted machines. As i am a vscode user, I would like to find ctrl+f and ctrl+shift+f equivalent to do string search
Ctrl+f will search within the file
ctrl+shift+f will search in all the files in the folder tree.
I added ripgrep , It search :Rg! ,it always search in all files like Ctrl+shift+f
Whether Rg can be used to search with the files? (like ctrl+f).
Also how to add ctrl+f and ctrl+shift+f mapping in vim
I agree with romainl, vim already has these function without any plugins. Just want to add some details.
Search string in current file is done by / in normal mode, see :h /, :h pattern.txt.
Search string in many files may be done by vimgrep command, see :h :vimgrep.
Also you may find useful vim fzf plugin, it uses ripgrep you already installed and does much more.
Of course you can do mappings on Ctrl-F and Ctrl-Shift-F, but it will override builtin vim command, so I don't recommend to do it.
map <C-F> /
map <CS-F> :vimgrep /
See :h map.txt
In Zsh, I can use filename completion with slashes to target a file deep in my source tree. For instance if I type:
vim s/w/t/u/f >TAB<
zsh replaces the pattern with:
vim src/wp-contents/themes/us/functions.php
What I'd like is to be able to target files the same way at the Vim command line, so that typing
:vi s/w/t/u/f >TAB<
will autocomplete to:
:vi src/wp-contents/themes/us/functions.php
I'm trying to parse the Vim docs for wildmode, but I don't see what settings would give me this. It's doing autocompletion for individual filenames, but not file paths. Does Vim support this natively? Or how can I customize the autocomplete algorithm for files?
Thanks for any advice!
-mykle-
I couldn't find a plugin to do this, so I wrote one. It's called vim-zsh-path-completion. It does what you're looking for, although via <C-s> rather than <Tab>. You can use it with <Tab> for even more control over what matches, though.
It's got bugs, but for basic paths without spaces/special characters, it should work. I think it's useful enough in its current state to be helpful. I hope to iron out the bugs and clean up the code, but I figured I'd start soliciting feedback now.
Thanks for the idea!
Original (wrong) answer, but with some useful information about Vim's wildmode.
Put the following in your .vimrc:
set wildmenu
set wildmode=list:longest
That will complete to the longest unique match on <Tab>, including appending a / and descending into directories where appropriate. If there are multiple matches, it will show a list of matches for what you've entered so far. Then you can type more characters and <Tab> again to complete.
I prefer the following setting, which completes to the first unique match on <Tab>, and then pops up a menu if you hit <Tab> again, which you can navigate with the arrow keys and hit enter to select from:
set wildmode=list:longest,list:full
Check out :help wildmenu and :help wildmode. You might also want to set wildignore to a list of patterns to ignore when completing. I have mine as:
set wildignore=.git,*.swp,*/tmp/*
Vim doesn't have such a feature by default. The closest buil-in feature is the wildmenu/wildmode combo but it's still very different.
A quick look at the script section of vim.org didn't return anything but I didn't look too far: you should dig further. Maybe it's there, somewhere.
Did you try Command-T, LustyExplorer, FuzzyFinder, CtrlP or one of the many similar plugins?
I use CtrlP and fuzzy matching can be done on filepath or filename. When done on filepath, I can use the keysequence below to open src/wp-contents/themes/us/functions.php (assuming functions.php is the only file under us that starts with a f):
,f " my custom mapping for the :CtrlP command
swtuf<CR>
edit
In thinking about a possible solution I'm afraid I was a little myopic. I was focused on your exact requirements but Vim has cool tricks when it comes to opening files!
The :e[dit] command accepts two types of wildcards: * is like the * you would use in your shell and ** means "any subdirectory".
So it's entirely possible to do:
:e s*/w*/t*/u*/f*<Tab>
or something like:
:e **/us/f<Tab>
or even:
:e **/fun<Tab>
Combined with the wildmode settings in Jim's answer, I think you have got a pretty powerful file navigation tool, here.
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
I'm looking for a way to make Vim have the ability to open a file by fuzzy-searching its name.
Basically, I want to be able to define a project once, and then have a shortcut which will give me a place to type a file name, and will match if any letters match up.
This kind of functionality exists in most editors I've seen, but for the life of me I can't understand how to get Vim to do this.
Note that I'm looking for something that won't require me to have any idea where in my directory tree a file is. I just want to be able to open it by the filename, regardless of what directory it's in.
Thanks
There are two great vim plugins for this.
ctrlp:
Written in pure VimL
Works pretty much everywhere
Supports custom finders for improved performance
Most popular fuzzy search plugin for Vim
Command-T:
Written in C, VimL and Ruby
Fast out of the box
Requires +ruby support in Vim
Recommends Vim version >= 7.3
EDIT:
I use CtrlP with ag as my custom finder and it's incredibly quick (even on massive projects) and very portable.
An example of using ag with CtrlP:
if executable('ag')
" Use Ag over Grep
set grepprg=ag\ --nogroup\ --nocolor
" Use ag in CtrlP for listing files. Lightning fast and respects .gitignore
let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'
endif
CommandT for Vim is very much the comparable feature as in TextMate. My work flow is now
1) open up MacVim
2) :cd ~/my_project
3) (I have this mapped as described in the installation help)
4) C-v the file to open the file in a vertical split, or CR to open a new horizontal split.
5) to close the split, use :bd (buffer delete)
6) to switch to another buffer, I have BufferExplorer installed, so just \be and select
This workflow is comparable to TextMate, it takes a while to get used to, and I'm still learning.
Basic solution
Simply add this to your .vimrc
nnoremap <C-p> :find ./**/*
Pressing Ctrl+p will now allow you to fuzzyfind files in your current working directory and sub-directories thereof. Use the tab key to cycle through options.
Related solution
For those who want to keep it basic i.e. no plugins, this entertaining video shows another way to achieve fuzzy file find in vim.
They actually use
set path+=**
set wildmenu
in their .vimrc to find files in current sub-directories.
For example, with :find *Murph followd by tab, I would find the files KilianMurphy2012Why.R and KilianMurphy2014ROLE.R in subdir code which I can cycle through with the tab key. The first solution above has the advantage that the relative path is also shown.
Note that your current working directory will matter and that other files on your path (:set path?) will also be found with the this type of solution. The wildmenu option adds visual information and is not essential.
For a keyboard shortcut, add
nnoremap <C-p> :find *
to your .vimrc. Now you will be able to quickly search for files inside your project/current dir with Ctrl+p in normal mode.
What about http://www.vim.org/scripts/script.php?script_id=1984 Then there is http://github.com/jamis/fuzzy_file_finder .
Also see these blog posts: http://weblog.jamisbuck.org/2008/10/10/coming-home-to-vim and http://weblog.jamisbuck.org/2009/1/28/the-future-of-fuzzyfinder-textmate
HTH
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