I am searching through a large codebase and find vimgrep unusably slow, so I'm using :grep from within vim, which displays a list of files, then says Press ENTER or type command to continue.
After I press Enter I can then type :copen to get to the list of results. But I'm wondering if I could automate this process? Adding the -q flag to grep seems to have the effect of causing grep to do nothing and then copen to be blank, which, unless I'm doing something wrong here, isn't really desirable.
I am using vim 7.4
You could define such a command :
command! -bar -nargs=1 Grep silent grep <q-args> | redraw! | cw
This will allow you to call it like Grep pattern, and :cw which opens the quickfix list only if it isn't empty.
Use an autocommand. Here is the one suggested by Tim Pope for :Ggrep. It will work for your case as well:
autocmd QuickFixCmdPost *grep* cwindow
For more information see:
:h :au
:h QuickFixCmdPost
:h :cwindow
Related
How to autoupdate search vimgrep results from quickfix window after file is autoudpated due to change?
I use :vim/pattern/% to search and put result in quickfix window.
You can always do <up> on the command line with a prefix of :vimgrep to make searching history easier. You may also want to check out q: and the use ?// to search for the command to re-execute.
Assuming the quickfix title is set correctly, you can use following the command:
:execute get(getqflist({'title':1}), 'title')
This however I am not certain this will work with all :grep/:make commands. You also need a newer Vim version to get the Quckfix list title (Vim 8+ I think).
If you find yourself doing this often you may want to bind a mapping or command.
command! -nargs=0 -bar QFRefresh execute get(getqflist({'title':1}), 'title')
Now how to add do this automatically? We can use FileChangedShellPost autocmd to run our QFRefresh command once a file change has been detected. Add the following to you vimrc file:
augroup QFRefresh
autocmd!
autocmd FileChangedShellPost * if get(b:, 'qfrefresh_auto', 0) | QFRefresh | endif
augroup END
command! -nargs=0 -bar QFAutoRefreshToggle let b:qfrefresh_auto = !get(b:, 'qfrefresh_auto', 0) | echo b:qfrefresh_auto ? 'Auto Refresh' : 'No Auto Refresh'
Now you can use :QFAutoRefreshToggle to toggle refreshing a file.
Note: As stated before QFRefresh uses the quickfix's title to get the quickfix command. If the title is not set correctly a refresh may not work correctly. Also I am not sure what guarantees Vim has on triggering FileChangedShellPost. You can force a check via :checktime command.
For more help see:
:h getqflist()
:h :execute
:h :get
:h q:
:h cmdwin
:h c_Up
:h FileChangedShellPost
:h :checktime
Rather than having vim print the output of the :make command, I want to read the output in a file (which gets updated automatically in vim); so that my compiled file can run right away without having to see the output of the :make command.
I'm using the following makefile
all: compile run
compile: file.cc
g++ -o file file.cc
run: file
./file
How does one redirect the output of the :make command in a way that it isn't also printed to the screen by vim?
First of all we have https://vi.stackexchange.com/ , you can get better answers about Vim in there.
Second, I'll argue that a Makefile is no place to run a program, the idea behind make is to catch compilation errors. But assuming you have your reasons (e.g. ./file opens a graphical display) there are a couple of ways to perform this in Vim:
For a start you can set makeprg to perform the redirection:
:set makeprg=make\ >/dev/null\ 2>&1
(You can change /dev/null to an actual file)
But that still leaves the line:
Press ENTER or type command to continue
And asks for confirmation, which may be annoying when you know that there is no output.
To get rid of the confirmation line you can use silent as follows:
set makeprg=make\ >/dev/null\ 2>&1
function! MyMake()
silent make
redraw!
endfunction
command Mm call MyMake()
And now you can do:
:Mm
To perform the make and go back to straight to Vim. (the redraw! is needed only in some terminals)
You can execute this command:
:silent exec "!make >Output" | :redraw!
The file Output contains the last output of the executed make command.
Use :silent to remove the output and "press enter" prompt. I suggest a nice mapping or command:
command! -nargs=* Smake silent make <args>
nnoremap <f5> :silent make<cr>
:make will populate the quickfix list with the results from :make. Use :copen to open the quickfix window.
For more help see:
:h :command
:h silent
:h :make
:h 'makeprg'
:h quickfix
I want to :make and display output from it only if it fails.
I map to
:wa<cr>:make<cr><cr>
and only when it fails I want to see the results. Notice the
<cr><cr>
sequence, which closes the output because usually it's success and nothing to read. And it's much faster.
You want to use :silent to stop the output and use :cwindow to open the quickfix window when there is something to see.
:wa|silent make|cwindow<cr>
Note: you will want to use <bar> instead of | if this is inside a mapping. Example of a mapping below:
nnoremap <f9> :wa<bar>silent make<bar>cwindow<cr>
See the following for more information:
:h :silent
:h :cw
I'd like to run some $RANDOM_COMMAND, and have the results opened in ("piped to") the quickfix window (:copen/:cfile). Is this possible, without having to define some commands in vimrc? (Hopefully in some "simple way", i.e. I'd like to be able to memorize this so I can run this on any new random box with vanilla vim that I'll have to login to.)
edit: initially didn't know how to express "simple way" more precisely, but now I know at least partially: I'd much prefer an answer of 1, max 2 lines.
edit2: tried something like below (from this and this):
:call setqflist(split(system('RANDOM_COMMAND'), '\n'))
:copen
but didn't seem to work anyway :/ (and mucho ugly too)
Hmh, found the simplest solution in the end, by reading through the regular vimdoc for quickfix window:
:cex system('$RANDOM_COMMAND') | copen
(the | copen part is optional).
Still, Ingo Karkat's solution can have usability advantage, as on consecutive runs it's enough to run shorter :grep there.
One way to do this:
:set makeprg=$RANDOM_COMMAND
:make
:copen
Or, execute the command and capture the output in a temporary file:
:! $RANDOM_COMMAND > out
:cfile out
:copen
In any way, the output must match with the 'errorformat' setting, so that Vim can parse the file name and line numbers (if you need those; but otherwise, you could just use a scratch buffer as well the quickfix list).
[edit] Some improvements
To make this a oneliner, then somewhat shortened, you can:
:set mp=RANDOM_COMMAND | make | copen
Whitespaces in command must be escaped with backslash; also, the make command can take arguments, which get expanded in place of a $*; a more full-blown example thus:
:set mp=mycommand\ -d\ $PWD\ $* | make myarg | copen
Alternatively, similar thing can be done with :set grepprg and :grep, giving even shorter line:
:set gp=mycommand\ -d\ $PWD\ $* | gr myarg | copen
My problem is simple. I search a specific pattern in a file (let's say label in a Tex file)
:g/label/#
but there are lots of occurrences. So I'd like to redirect this output to another file to be able to work easily with it.
Do you have a trick or a command that I don't know?
it's not clear from the original post what you mean by "work easily with it" but it's often useful to see and quickly jump between all of the matches in a buffer without "extracting" the matches to a separate buffer.
vim has an internal grep built in. your example would be something like this (in vim, % denotes the current file)
:vimgrep /label/ %
This will take you to the first occurrence and report how many matches there were. What's cool is that you can look at all of the matches listed by opening up the quickfix error list using
:cope
Now you can just scroll around and press enter on a line to jump to the exact position of the match.
The quickfix error list is exactly the same buffer you use if you run make from inside vim and your compiler throws errors: it gives you a list of what and where the errors are.
After you've jumped to one location pointed by quickfix, you can go to forwards and backwards in the list via :cn and :cp. :ccl closes the error list.
You can also expand your "error" list via :vimgrepa /newpattern/ % or :vimgrepadd
The (documented) caveat is that vim's internal grep is slower than most native grep implementations (but you do get it "for free" in windows, for example). If you do have a grep installed, you can use :grep instead of :vimgrep for similar results.
quoting :help grep
Vim has two ways to find matches for a
pattern: Internal and external. The
advantage of the internal grep is that
it works on all systems and uses the
powerful Vim search patterns. An
external grep program can be used when
the Vim grep does not do what you
want.
The internal method will be slower,
because files are read into memory.
The advantages are:
- Line separators and encoding are automatically recognized, as if a file
is being edited.
- Uses Vim search patterns. Multi-line patterns can be used.
- When plugins are enabled: compressed and remote files can be searched.
You can also use the location list if you're already using the error list for dealing with compilation errors. just add l (for location) to the beginning of the grep command (:lvimgrep,:lvimgrepa :lgrep, :lgrepa) and use :lopen :ln :lp :lcl instead of the :c* ones.
For more commands consult
:help grep
:help quickfix-window
:help quickfix
:help quickfix-error-lists
:redir > matches.txt|execute 'g/foo/#'|redir END
See :h :redir, you can also redirect to registers, variables, the clipboard etc.
What you're doing is essentially 'grep -n label file' from command line. So you can run that command and > it into a file easily enough.
The derivation of 'grep' is even from basically the same source.
I've gotten this of the net at some point:
function GoToLine(mainbuffer)
let linenumber = expand("<cword>")
silent bd!
silent execute "buffer" a:mainbuffer
silent execute ":"linenumber
silent nunmap <Enter>
endfunction
command -nargs=1 GoToLine :call GoToLine(<f-args>)
function GrepToBuffer(pattern)
let mainbuffer = bufnr("%")
silent %yank g
enew
silent put! g
execute "%!egrep -n" a:pattern "| cut -b1-80 | sed 's/:/ /'"
silent 1s/^/\="# Press Enter on a line to view it\n"/
silent :2
silent execute "nmap <Enter> 0:silent GoToLine" mainbuffer "<Enter>"
" silent nmap <C-G> <C-O>:bd!<Enter>
endfunction
command -nargs=+ Grep :call GrepToBuffer(<q-args>)
Put it in your .vimrc, then :Grep Foo
Requires external grep program to work properly.
(Just an idea -- untested.)
You can delete all the lines with your pattern in it, write to another file, and undo the delete.
:g/label/d
:w matches
u