I want to perform a number of substitutions of the following kind across several files:
"\includegraphics{all.png}" → "\includegraphics[width=\linewidth]{all.png}"
I would like to do that without Sed, using only Vim. However, when I do it, I always replace the buffer by accident with something like space so wasting a lot of keys. How can I do it fast?
Smallest amount of keys wins!
Start inside Vim: getting the matches to buffers
:grep -r "includegraphics" Sections/*
A flexible way of performing some actions in a group of files using
Vim is to collect the list of their names into the argument list (see
:help arglist), and then iterate through it executing the desired
command.
In order to do the first step, use commands :args, :argadd, and
:argdelete. For instance, to set the argument list to the names of
all files that have the .tex extension in the current directory and
its subdirectories, run:
:args ./**/*.tex
To perform the second step, use the :argdo command:
:argdo %s/\\includegraphics\zs\ze{all.png}/[width=\\linewidth]/g
Replace in all buffers
:bufdo %s/\\includegraphics\{all\.png\}/\includegraphics[width=\linewidth]{all.png}/ge
Related
Say I had opened vim with no arguments, then from within vim opened 10 .txt
files and 10 .py files. Also, let's say the files are scattered around my file
system. The buffer list contains all 20 files.
Now I want to add the 10 .py files to the arguments list. I want to do
something like :argadd *.py, but this just creates a new file called '*.py'
and adds it to the arguments list.
I see from the help that argd[elete] can use a pattern, so I could delete all
the .py files with :argd *.py. Is there a way to do something similar for
:arga[dd]?
:[count]arga[dd] {name} ..
Add the {name}s to the argument list.
:argd[elete] {pattern} ..
Delete files from the argument list that match the
{pattern}s.
Surely there's a better way than navigating to each .py file and running
:argadd?
You can go through all your buffers and add them to the argument list based on some discriminant with a single easy command:
:bufdo if &ft == 'python' | argadd | endif
or, if you really don't like typing:
:bufdo if&ft=='python'|arga|en
See :help :bufdo.
Well, it's sort of a "made up" question, I think. One rarely needs so many buffers/args at the same time that naive :argadd #10 #12 #15 #20 would be totally impractical.
But if you insist you need this then I'd suggest to try expression register, sort of
:argadd <C-R>=join(expand("*.py",1,1))<CR>
I often find myself using something like:
sed -ri 's/<\/(abc|def ghi|j klm)>//g' someFile.html
to perform substitutions on multiple possible patterns, in this case, a closing html tag to be deleted, saving me the time and effort to do this three separate times for three closing tags I want deleted.
Is there a way to do this using substitute on vim's cli? I haven't yet found a way to do it, but it would be more efficient than going to a terminal cli or running sed from within vim if it could be done natively instead.
Yes, you don't need to use an external program at all:
:%s#</\(foo\|bar\|baz\)>##g
You can use the silent ! command to silently execute shell commands from inside vim:
:silent !sed -ri 's/<\/(abc|def ghi|j klm)>//g' %
This will execute the command in the shell silently (it won't take you away from vim to see any shell output). The % means the current buffer name. Vim will then notify you that the file you are editing has been changed and will ask you if you want to load the changes, press l for load and the new changes from the sed shell command will appear.
I know that you can use m and then a to add a child node in NERDTree to add files or directories one at a time. Is there anyway to type out a list, e.g. {Book,Author}.php and get a corresponding file or directory for each one in the list?
If on Bash Shell, I would do this in Vim command mode:
q:i!touch {Book,Author}.php
q:i -- Enter into Vim command history window (q:), then insert (i), it also let you edit commands with all Vim's editing power.
! -- To use shell
**touch mydir/{my_file_1,my_file_2}.php -- This will create the empty files.
actually, do it in Bash Shell will be simpler.
I want to debug a process, hence I attached strace to the process and redirected the output to a file and then performed the operation. During the process it has created a lot of processes. So here is what I want to do, I want to select all the system calls executed by a process. To do that I used grep command with pattern as pid:
:grep pid %
It shows the result but I am not able to traverse through the result, it promts
Press ENTER or type command to continue
and returns to the file. What I would like to do is store the result in a buffer and then have a look into it and if required save it into a file or else discard it and return to the original file. Is there a way to do this with out exiting from the vim editor? Thanks in advance.
I would like to search with the result and store that in a buffer.
Over the years of reading all kind of logs, I learned this little trick:
:%!grep pattern
It simply replaces the current buffer contents with grep output (so to go back to the original logs you have to simply press u).
You can also use it with other tools:
:%!ack pattern
:%!ag pattern
:%!rg pattern
Note that you can also run these commands on other files then the current one. The following 2 commands would replace the current buffer with results of grepping over the current file (second % character, which would be redundant for grep in this case) and otherfile.txt respectively:
:%!grep pattern %
:%!grep pattern otherfile.txt
For me it's the simplest and the best solution for fast grepping of big files in Vim and I'm pretty surprised no one ever mentioned it.
You can go to older searches, and back easily:
:copen
:colder " goes to older
:cnewer " newer
You can have another search using lvimgrep (uses location window):
:lopen
:lnext
etc...
It also has history:
:lolder
:lnewer
You can read into any buffer:
:r!grep bla **/*.cs
Finally, any command that gives output, can be redirected with the redir command:
:redir >> file
:grep bla **/*.cs
:redir END
See :he redir for the many ways to use it (redirect into registers or variables).
I thought that :grep results were stored by default in the quickfix window.
Try to use :copen after running a grep command. I expect that you'll find your results there.
( :cclose to close the quickfix window)
It is not really a buffer, but as long as you are not starting another search your result list will stay intact.
You can "yank" the content of the quickfix window to a new buffer.
Go into quickfix with :copen
Yank its content with yG
open a new buffer with :new
Paste the content with p
Save it with :w Process1.txt
Repeat and rinse for multiple search/process.
#romainl 's answer on how grep results into separate buffer or split window gives a much cleaner answer than quickfix/location lists.
:vnew | 0r!grep foo #
:tabe | 0r!grep foo #
but Quickfix lists are sort of intended for what you are doing but not the way you are doing it; however, it's tedious to set up unless it's a recurrent task.
Vim already does incremental search within the currently open file but can you do
an incremental search across multiple files?
AFAIK this is not possible. However you can start to type a word that is in an opened buffer and hit ctrl-xctrl-n to start searching for such a word in all opened buffers.
from :help grepadd
*:grepa* *:grepadd*
:grepa[dd][!] [arguments]
Just like ":grep", but instead of making a new list of
errors the matches are appended to the current list.
Example: >
:call setqflist([])
:bufdo grepadd! something %
The first command makes a new error list which is
empty. The second command executes "grepadd" for each
listed buffer. Note the use of ! to avoid that
":grepadd" jumps to the first error, which is not
allowed with |:bufdo|.
An example that uses the argument list and avoids
errors for files without matches: >
:silent argdo try
\ | grepadd! something %
\ | catch /E480:/
\ | endtry"