Say I have 10 lines in quickfix coming from 3 files: 1.txt, 2.txt, and 3.txt.
1.txt - 3 lines
2.txt - 3 lines
3.txt - 4 lines
What I'd like to do is to set up a binding that would remove all entries from file under cursor from quickfix. I use Cfilter plugin, but it requires more typing, so at first I'd have to yank needed file name, and then run :Cfilter! <filename>, which is not very convenient.
Any ideas on how better to achieve this?
Thanks
You can use :help c_ctrl-r_ctrl-f to insert the filename under the cursor.
With it, your command:
:Cfilter! foo/bar/baz.txt<CR>
can become:
:Cfilter! <C-r><C-f><CR>
which can be mapped for convenience:
" in after/ftplugin/qf.vim
nnoremap <buffer> <key> :Cfilter! <C-r><C-f><CR>
All you have to do is move the cursor on an entry from the file you don't want and press <key>.
I want to open file with modifiable buffer set noma ON by default for this specific file.
for example something like this:
vi file1.txt noma
vi file2.txt ma , # default
OR at least inside vim:
:tabnew file1.txt noma
Thanks
You can add that to your .vimrc, which will set the flag if the file has that name:
augroup ReadOnly
autocmd!
autocmd BufReadPost file1.txt set noma
augroup END
That will set it both if the file exists (BufReadPost).
Edit: The view command allows you to open a file in readonly mode.
For reference: :help autocmd-groups and :help autocmd-define
You can use the -R command-line option to open a file in 'readonly' mode (which includes 'nomodifiable' and also other options that are useful when viewing files.)
$ vim -R file1.txt
The view command is usually available as a shortcut to vim -R, so this is often also possible:
$ view file1.txt
If you already have a Vim running and want to use it to open a file in read-only mode in a new tab, you can use this sequence:
:tab sview file1.txt
The :view command opens a file in read-only mode, the :sview command does so in a split and the :tab modifier has Vim do so in a new tab instead.
Is there a way to move a file within Vim? E.g. I opened a file foo/bar.txt in Vim. I know 2 ways to move this file:
First solution:
Delete the buffer with :bd bar.txt
Perform the move on the shell with mv foo/bar.txt foo/bar2.txt
Load the file in vim with :e foo/bar2.txt
Second solution:
Close Vim, so all buffer where closed.
Perform the move on the shell...
Start Vim and load the file.
But these two solutions are embarrassing. I know, there is a plugin for renaming files vim-enuch, but isn't there a Vim way for performing such basic functionality?
You could also use netrw (the default file explorer) rename functionality.
Open netrw with :E
Move your cursor to the line with the file you intend to rename, in this case bar.txt . You move to the file in question using h,j,k,l or you can search for it with / (e.g. /bar.txt)
Hit R. You will then be prompted for a new filepath. When done entering the filepath hit <CR>
Move your cursor to the new file and open it with <CR>
While this solution may not be as quick as using vim-eunch, it does allow you to see the project's structure as you rename the file. This will also allow you to move multiple files at once.
For further reading run :help netrw-move
There is no atomic way to move a file like that, but this should be close:
function! MoveFile(newspec)
let old = expand('%')
" could be improved:
if (old == a:newspec)
return 0
endif
exe 'sav' fnameescape(a:newspec)
call delete(old)
endfunction
command! -nargs=1 -complete=file -bar MoveFile call MoveFile('<args>')
Now you could say:
:MoveFile file2.txt
To rename to file2.txt
:MoveFile %.0
to move file2.txt to file2.txt.0
if you're in the bar.txt buffer:
:w bar2.txt
:!rm bar.txt
If bar2.txt already exists in the current directory, use :w!.
Is there any way to search a directory recursively for a file (using wildcards when needed) in Vim? If not natively, is there a plugin that can handle this?
You can use wildcards with the :edit command. So,
:e **/test/Suite.java
will open test/Suite.java no matter where it is in the current directory hierarchy. This works with tab-completion so you can use [tab] to expand the wildcards before opening the file. See also the wildmode option for a way to browse through all possible extensions instead.
Another trick is to use
:r! find . -type f
to load a list of all files in the current directory into a buffer. Then you can use all the usual vim text manipulation tools to navigate/sort/trim the list, and CTRL+W gf to open the file under the cursor in a new pane.
There is a find command. If you add ** (see :help starstar) to your 'path' then you can search recursively:
:set path
will show you your current path, add ** by doing something like
:set path+=**
then you can just type
:find myfile.txt
and it opens magically!
If you add the set command to your .vimrc it'll make sure you can do recursive search in future. It doesn't seem to search dot directories (.ssh for example)
I'd recommend ctrlp.vim. It's a very good plugin, ideal to work inside large projects. It has search by file name or full path, regexp search, automatic detection of the project root (the one with the .git|hg|svn|bzr|_darcs folder), personalized file name exclusions, and many more.
Just press <c-p> and it will open a very intuitive pane where you can search what you want:
It's possible to select and open several files at once. It also accepts additional arbitrary commands, like jump to a certain line, string occurrence or any other Vim command.
Repo: https://github.com/kien/ctrlp.vim
vim as a builtin find command (:help find) but only open the first found file. However you can use this amazing plugin : FuzzyFinder which does everything you want and even more
You can browse the file system with :ex ., but I do not know how to search recursively (I am a Vim novice — I have been using it only ten years).
There are a few popular file browsers plug-ins:
NERD tree
Lusty explorer
vtreexplorer
See also this thread on SuperUser.
Command-T lets you find a file very fast just by typing some letters. You can also open the file in a new tab, but it need vim compiled with ruby support.
You can use ! to run shell commands :
:! find . -name *.xml
vim has bild in commands named grep, lgrep, vimgrep or lvimgrep that can do this
here is a tutorial on how to use them
http://vim.wikia.com/wiki/Find_in_files_within_Vim#Recursive_Search
you can also use an external command like find or grep from vim by executing it like this
:!find ...
Quickfix-like result browsing
Usage:
Find my.regex
Outcome:
a new tab opens
each line contains a relative path that matches a grep -E regex
hit:
<enter> or <C-w>gf to open the file on the current line in a new tab
gf to open the file on the current tab and lose the file list
Find all files instead:
Find
Alternative methods:
Gfind my.regex: only search for Git tracked files (git ls-files). Fugitive request: https://github.com/tpope/vim-fugitive/issues/132#issuecomment-200749743
Gtfind my.regex: like Gfind, but search from the git Top level instead of current directory
Locate somefile: locate version
Code:
function! Find(cmd)
let l:files = system(a:cmd)
if (l:files =~ '^\s*$')
echomsg 'No matching files.'
return
endif
tabedit
set filetype=filelist
set buftype=nofile
" TODO cannot open two such file lists with this. How to get a nice tab label then?
" http://superuser.com/questions/715928/vim-change-label-for-specific-tab
"file [filelist]
put =l:files
normal ggdd
nnoremap <buffer> <Enter> <C-W>gf
execute 'autocmd BufEnter <buffer> lcd ' . getcwd()
endfunction
command! -nargs=1 Find call Find("find . -iname '*'" . shellescape('<args>') . "'*'")
command! -nargs=1 Gfind call Find('git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Gtfind call Find('git rev-parse --show-toplevel && git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Locate call Find('locate ' . shellescape('<args>'))
Depending on your situation (that is, assuming the following command will find just a single file), perhaps use a command like:
:e `locate SomeUniqueFileName.java`
This will cause Vim to open, in the current tab (the e command) a file that is the result of running (in this example),
locate SomeUniqueFileName.java
Note that the magic here is the backticks around the command, which will convert the output from the shell command into text usable in the Vim command.
You don't need a plugin only for this function, below code snippet is enough.
function! FindFiles()
call inputsave()
let l:dir = input("Find file in: ", expand("%:p:h"), "dir")
call inputrestore()
if l:dir != ""
call inputsave()
let l:file = input("File name: ")
call inputrestore()
let l:nf = 'find '.l:dir.' -type f -iname '.l:file.' -exec grep -nH -m 1 ".*" {} \;'
lexpr system(l:nf)
endif
endfunction
nnoremap <silent> <leader>fo :call FindFiles()<CR>
Run:
:args `find . -name '*xml'`
Vim will run the shell command in backticks, put the list of files to arglist and open the first file.
Then you can use :args to view the arglist (i.e. list the files found) and :n and :N to navigate forward and bacwards through the files in arglist.
See https://vimhelp.org/editing.txt.html#%7Barglist%7D and https://vimhelp.org/editing.txt.html#backtick-expansion
You can find files recursively in your "path" with this plugin. It supports tab completion for the filename as well.
I am surprised no one mentioned Unite.vim yet.
Finding files (fuzzily or otherwise) is just the very tip of the iceberg of what it can do for a developer. It has built in support for ag, git, and a myriad of other programs/utilities/vim plugins. The learning curve can be a bit steep, but i cannot imagine my life without it. User base is big, and bugs are fixed immediately.
ag tool and corresponding Ag vim plugin solves this problem perfectly:
To find a file using some pattern use:
AgFile! pattern
It will open quickfix window with results where you can choose.
You can add vim keybinding to call this command using selected word as a pattern.
nnoremap <silent> <C-h> :AgFile! '<C-R><C-W>'<CR>
vnoremap <silent> <C-h> y :AgFile! '<C-R>"'<CR>
In a given working directory, if I do
:tabe **/test*.py
vim complains with E77: Too many file names. What if I want it to open every matching file in a separate tab? There must be a way to do it, but I can't find it.
You could use the args list and argdo like so:
:args **/test*.py
:argdo tabe %
However, the syntax event is turned off by argdo (to speed up the normal use case), so the files will be loaded without syntax at first. You could follow it up with a :syntax on to force the syntax event on all loaded buffers. Compressed into one line (need to wrap argdo in execute so it doesn't absorb the following |):
:args **/test*.py | execute 'argdo tabe %' | syntax on
Alternately, you can open vim from the command line via:
vim -p **/test*.py
But that will max out at 10 tabs.
You can use the following:
:next **/test*.py
It opens all the files.
To map it
nmap <c-d> :args **/*.tpl<bar>execute 'argdo tabe %'<bar>syntax on<cr>
But still it displays list of files, you have to press enter few times (depending of number of files).
This functionality can be included as a command in your .vimrc file:
"open all files in seperate tabs
command -nargs=1 OpenAll call <SID>openAll(<f-args>)
function! s:openAll(dir)
execute 'args ' . a:dir
silent argdo tabe %
syntax on
endfunction
With this function running :OpenAll **/*.py from vim will quickly open all files into new tabs
None of the other answers works for me, but this is fine:
find <path> -iname <pattrn> | xargs -o vim -p
all files are visible in different tabs
file lookup is recursive
Note, vim can limit tabs - to be changed by set tabpagemax=42.
Also, if you wonder how to close all tabs at once, use :qa