Is it possible to grep the quickfix window in Vim? - vim

Let’s say I use the ag.vim plugin to search for the string disabled through multiple files. It returns me some results in the quickfix window:
1 first_file.rb|1 col 1| disabled something something
2 second_file.rb|1 col 2| disabled another something
Is it possible to pick the quickfix results as an input, grep through them, and open results in new quickfix window? In other words, if I would enter :quickfix_grep first_file, new quickfix would pop up with only one entry:
1 first_file.rb|1 col 1| disabled something something

Update
A vim plugin has been written for this requirement: https://github.com/sk1418/QFGrep
Original Answer:
My understanding of your goal is:
Your grep result is somehow huge in your quickfix, you want to narrow
your view of it. by entering a command with regex, filter the grep
result. The filtered result should also be displayed in QuickFix
window, so that you could open/jump to the file.
If the above is what you want, check out the following:
source this function and the command line:
function! GrepQuickFix(pat)
let all = getqflist()
for d in all
if bufname(d['bufnr']) !~ a:pat && d['text'] !~ a:pat
call remove(all, index(all,d))
endif
endfor
call setqflist(all)
endfunction
command! -nargs=* GrepQF call GrepQuickFix(<q-args>)
then after your grep/ack/whatever show stuffs in your quickfix, you could type
:GrepQF <regex>
to do filtering in your quickfix.
Here I add an GIF animation. I am using Ack instead of grep, but it makes no difference. The given regex will match filename and the text showing in quickfix. I did filtering twice to show that.
hope it helps.

New official vim plugin cfilter
Since 21.8.2018 (patch: 8.1.0311) the plugin cfilter is distributed with vim in $VIMRUNTIME. It is documented under :h cfilter-plugin.
Load plugin cfilter when needed or load it always in your vimrc
:packadd cfilter
Filter quickfix list with
:Cfilter DPUST

My solution to this problem has always been to make the quickfix
buffer modifiable by default:
:autocmd BufReadPost quickfix set modifiable
(The above command is to be put in the .vimrc file.)
Doing this opens a whole range of possibilities for any appropriate
edits of the grepping results, such as removing unrelated entries
manually or by filtering using the :global and :vglobal commands
(which provide the functionality desired in the question for free);
grouping and reordering related entries; adding blank lines or
comments in free form; etc.

Here's a shorter & neater version of #Kent's answer:
function! GrepQuickFix(pat)
call setqflist(filter(getqflist(), "bufname(v:val['bufnr']) !~# a:pat"))
endfunction
command! -nargs=* GrepQF call GrepQuickFix(<q-args>)
It is the same code, just neater and shorter, I don't believe it deserves a separate plugin.

Related

How to search through vim keymaps?

I often forget infrequently used keymappings, but i roughly remember the command name like make or PlugInstall.
When i open :nmap i have to scroll through a long list of mappings to find the one i look for.
As suggested in https://stackoverflow.com/a/2240892/4936725 i currently export the keybindings into a file and grep through that.
:redir >> ~/mymaps.txt
:map
:redir END
Is there a more convenient way to search or grep through the keymaps list?
Vim 8 has introduced the :help :filter command that allows you to directly grep the output of a :map command:
:filter /make/ nmap
This is good for a quick-and-dirty lookup. You still get annoying false positives like <Plug> mappings, though. For a robust solution, you'd probably still capture the output with :redir, then split() it into lines and filter() (via multiple passes) for matching output.

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.

Selecting resulting files from grep in vim

After I run a grep search in vim with :grep, I get a list of files. Is there a way to select one of those files and open it in a new tab at that particular line?
Just for completeness, as well as the :copen command, there's also :cw, which only opens the "quickfix" window if there are entries (so if your grep has no results, it won't appear).
I think the easiest way (without defining a mapping) of making the files open in a new tab would be to do:
:cw " Open the quickfix window
Ctrl-W T " Switch the window into a new tab
<ENTER> " Open the file/line
Alternatively, you could do:
:cw " Open the quick fix window
Ctrl-W <ENTER> " Open the file/line in a new window
Ctrl-W T " Move the new window to a new tab
If you want to do it by default, you could probably use the BufEnter and BufLeave autocmds to create and remove a mapping when entering and leaving the quickfix window; however, this is probably not trivial.
:help :cw
:help :copen
:help quickfix
For achieving what you want you have to open the quickfix/error window after calling grep:
:copen
I have a script that makes it for me every time i use grep.
I came upon this thread looking for an answer to a very similar question. The answer presented above, though correct, failed to describe a convenient way to open ALL the files in the QuickFix window at once ... into either buffers or tabs.
There doesn't seem to be a built in command to do it, but it's trivial as a VIM plugin ... somebody has done it here
http://pastebin.com/J9RwciFQ
It's 12 lines of code (one function) ... pasted here to save you a click during your analysis. Do follow the pastebin link if you are going to try to implement this though ... my plugin is installed in pathogen directory and I modified the plugin from the original slightly (details after code).
~/.v/b/v/p/quickfixopenall.vim
" Create command
command! QuickFixOpenAll :call StartQuickFixOpenAll()
function! StartQuickFixOpenAll()
if empty(getqflist())
return
endif
let s:prev_val = ""
for d in getqflist()
let s:curr_val = bufname(d.bufnr)
if (s:curr_val != s:prev_val)
exec "edit " . s:curr_val
endif
let s:prev_val = s:curr_val
endfor
endfunction
So once I have a grep result I'm satisfied with ... the plugin has a function :QuickFixOpenAll ... I had to modify the plugin as given (added the following line to the quickfixplugin.vim). And I renamed his given function StartQuickFixOpenAll ...
" Create command
command! QuickFixOpenAll :call StartQuickFixOpenAll()
Then you have all the files in the grep result open as buffers ... if you want to run any commeon operations such as find/replace you can prefix the regular command with the "bufdo" command which will perform your command in all ... in VIM type "help bufdo"
You can fairly trivially modify this plugin if you wan to use tabs ... it uses the commaned "edit" ... just replace that with "tabe" and :QuickFixOpenAll will open each result buffer in a new tab.
If you get a list of files you can browse them in a tree-like manner via
:cn
:colder
For more information
:help grep
and scroll to the bottom of the entry

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)

View a list of recent documents in Vim

Is there a way to view the list of recent documents you've opened in Vim?
I realize I could view the cursor jump list, :ju, and then go to a cursor position in the list but this is not ideal because there will be multiple listings of the same document in the list.
Is there another command which would do what I'm looking for?
Don't use a plugin, unless you want a nice menu. From Vim Documentation: Starting (or :help old):
:ol[dfiles]
Then to open one of the listed files, use: '0, '1, '2, ... '9
List the files that have marks stored in the viminfo file.
:bro[wse] ol[dfiles][!]
List file names as with :oldfiles, and then prompt for a number. When the number is valid that file from the list is edited. Use ! to abandon a modified buffer.
The Most Recently Used (MRU) plugin provides an easy access to a list of
recently opened/edited files in Vim. This plugin automatically stores the
file names as you open/edit them in Vim.
http://www.vim.org/scripts/script.php?script_id=521
Besides :oldfiles, fzf.vim has :History.
Start Vim and hit Ctrl-o-o to open previously edited file. Keep hitting o (while still pressing the Ctrl key) to cycle back through earlier files. See https://dev.to/jovica/3-little-known-but-useful-vim-tips-1pbg
vim plugin: minibufexpl may help you.
the opened file list is displayed on the top or bottom of the screen:
in vim normal mode, type :b${bufid} to jump to the ${bufid}_th buffer, for example: type :b13 to jump to the 13th buffer, ie. ngx_mail_ssl_module.c.
besidies, you can map some convenient bindings in your vimrc, such as:
" ------------------------------- minibufexpl mappings -----------------------------------
"let g:miniBufExplSplitBelow=1
nnoremap <silent> <leader>bn :bn<cr>
nnoremap <silent> <leader>bp :bp<cr>
nnoremap <silent> <leader>bf :bf<cr>
nnoremap <silent> <leader>bl :bl<cr>
nnoremap <silent> <leader>bt :TMiniBufExplorer<cr>
Get the plugin from here: https://github.com/fholgado/minibufexpl.vim
In addition to oldfiles there's a nice thing called tinyMRU.
Vim-tinyMRU's only purpose is to provide an intuitive alternative to the built-in :oldfile command. Nothing more, nothing less.
It's very simple:
https://github.com/romainl/vim-tinyMRU/blob/master/plugin/tinymru.vim
A good plugin is https://github.com/Shougo/denite.nvim
You can call :Denite file_old in order to have fuzzy search on the list of old files. In particular, just hitting Enter will re-open the last opened file. Assigning a shortcut to this is useful:
nnoremap <leader>o :Denite<space>file_old<CR>
This saves few keystrokes compared to :browse oldfiles, q, 1, Enter
The easiest way for me to access recent files is to add the following to one's .gvimrc file:
let g:netrw_sort_by = 'time'
let g:netrw_sort_direction = 'r'
These lines get netrw to sort files by those most recently modified. Then one simply calls :e. and selects the file one wants.
This solution presupposes files are saved in one main directory so specified in .gvimrc. E.g.
cd ~/vim
No directly the answer but related.
you can define aliases to open the last opened file(s) by vim:
alias vil='vim -c "normal! '\''0"' # open the last file
alias vil1='vim -c "normal! '\''1"' # open the second last file ...
alias vil2='vim -c "normal! '\''2"'
:ol works, but why not use fuzzy search to get the exact match quickly from a long list of file?
There's a very handy plugin, ctrlp which allows you to use :CtrlPMRU, and you can quickly get what you looking for.
For many many years, ctrlp is one of the first thing I would install for vim!
https://github.com/ctrlpvim/ctrlp.vim

Resources