Vim: Tabe multiple files? - vim

I know about running
vim -p file1 file2 file3
But is there away to do something similar from within vim?
What I've thought about wanting to do is
:tabe file1 file2 file3
or (IMO worse, but still an improvement):
:edit file1 file2 file3
...but neither of those are possible, by default at least.

try this:
:args file1 file2 file3 |tab sall
this will only put newly opened file (file1, file2, file3) in tabs, not all buffers.
if you want to open all buffers in tabs, replace sall to sball
btw, is tab convenient to work with? personally I like working with buffer more...

Upon browsing the web more extensively, researching in regards to this question, the best solution I've found so far is:
:arga file1 file2 file3 (...)
Which will create buffers for all the input files.
Then follow that by:
:tab sball
Which will open all the buffers into separate tabs.
But maybe there's an even better/shorter way? If not maybe I'm helping someone else out there, having the same problem/question.

Related

How to search for a single word in multiple gvim files from the command line?

I want to open up multiple files in different tabs and search for the same word in all of them. Then I want to jump to the first occurrence of the found word in each file.
Doing this works, but it doesn't jump to the first occurrence:
gvim -p -cmd "/word" file1 file2 file3 file4 file5 file6 file7
I need to manually press 'n' to go to the next match.
Vim doesn't provide a way to execute a command for every file on the command line. The -c option causes the command to be executed after the first file is read, and --cmd happens before any files are opened.
If you want to do this, you'd probably need to define a script with a function that did that (say, Search), load the script with -S, and then execute it with --remote-send option. On many systems, gvim starts up with a default server name by default, but if it doesn't, you'd need to use --servername with your initial process.
Alternatively, you could do this from the command line with grep, which would be more flexible, but of course wouldn't appear in an editor.
Since you're opening the files in separate tab pages, you can use :help :tabdo to execute the search in every page.
If it's okay to just go to the line of the first match, you can directly do the search via :/:
vim -p -c 'tabdo /word/' file1 file2 file3 file4 file5 file6 file7
To also go to the beginning of the first match within the line, we need something like this, using normal mode n:
vim -p -c "/word" -c 'tabdo 1normal! n' file1 file2 file3 file4 file5 file6 file7
You might be interested in :grep and :vimgrep, which populate the quickfix list:
$ gvim file*
:vimgrep /pattern/ ##
The ## means search the argument list, which you can view with :args. It’s what :next and :prev use.
Now, you can navigate the searches with :cnext and :cprev; or, you can open the quickfix window :copen and hit enter on any line.
You could still pop open all the files in tabs with :cfdo tabedit but at this point it might not be necessary!

gvim: Traces of previously opened files seen when reading a file

I am seeing this strange issue where if I open a file in gvim on linux.
For e.g, if I am reading file2 in gvim, some of the lines in file2 have traces of file1 I had opened earlier. Here are the snapshots of the original contents of file1, file2 and also a snapshot showing file1 overlapping file2.
>
As seen in the snapshots, traces of file1 is present while reading file2 (highlighted).
How to fix this?

vim select and copy text between two files

I have the following scenario, two open files with
vim -O2 file1.txt file2.txt
My cursor is in file1.txt. I want to select some lines (say from line 80 to 100)
in file2.txt but without having to move my cursor to file2.txt and yank there the
text. And if possible using the command line of vim. Do you have any suggestion?
thanks.
The closest I can think of is:
:bn|80,100y|bp|pu
switch to the next buffer
yank
switch back
put yanked stuff
This should work:
:call setline(80, getbufline(bufnr('file2.txt'), 80, 100))
If you have something like sed installed, another possibility is:
:r!sed -n '80,100p' file2.txt
Are you looking for diffput?
vimdiff file1.txt file2.txt
:80,100diffput

Why doesn't "sort file1 > file1" work?

When I am trying to sort a file and save the sorted output in itself, like this
sort file1 > file1;
the contents of the file1 is getting erased altogether, whereas when i am trying to do the same with 'tee' command like this
sort file1 | tee file1;
it works fine [ed: "works fine" only for small files with lucky timing, will cause lost data on large ones or with unhelpful process scheduling], i.e it is overwriting the sorted output of file1 in itself and also showing it on standard output.
Can someone explain why the first case is not working?
As other people explained, the problem is that the I/O redirection is done before the sort command is executed, so the file is truncated before sort gets a chance to read it. If you think for a bit, the reason why is obvious - the shell handles the I/O redirection, and must do that before running the command.
The sort command has 'always' (since at least Version 7 UNIX) supported a -o option to make it safe to output to one of the input files:
sort -o file1 file1 file2 file3
The trick with tee depends on timing and luck (and probably a small data file). If you had a megabyte or larger file, I expect it would be clobbered, at least in part, by the tee command. That is, if the file is large enough, the tee command would open the file for output and truncate it before sort finished reading it.
It doesn't work because '>' redirection implies truncation, and to avoid keeping the whole output of sort in the memory before re-directing to the file, bash truncates and redirects output before running sort. Thus, contents of the file1 file will be truncated before sort will have a chance to read it.
It's unwise to depend on either of these command to work the way you expect.
The way to modify a file in place is to write the modified version to a new file, then rename the new file to the original name:
sort file1 > file1.tmp && mv file1.tmp file1
This avoids the problem of reading the file after it's been partially modified, which is likely to mess up the results. It also makes it possible to deal gracefully with errors; if the file is N bytes long, and you only have N/2 bytes of space available on the file system, you can detect the failure creating the temporary file and not do the rename.
Or you can rename the original file, then read it and write to a new file with the same name:
mv file1 file1.bak && sort file1.bak > file1
Some commands have options to modify files in place (for example, perl and sed both have -i options (note that the syntax of sed's -i option can vary). But these options work by creating temporary files; it's just done internally.
Redirection has higher precedence. So in the first case, > file1 executes first and empties the file.
The first command doesn't work (sort file1 > file1), because when using the redirection operator (> or >>) shell creates/truncates file before the sort command is even invoked, since it has higher precedence.
The second command works (sort file1 | tee file1), because sort reads lines from the file first, then writes sorted data to standard output.
So when using any other similar command, you should avoid using redirection operator when reading and writing into the same file, but you should use relevant in-place editors for that (e.g. ex, ed, sed), for example:
ex '+%!sort' -cwq file1
or use other utils such as sponge.
Luckily for sort there is the -o parameter which write results to the file (as suggested by #Jonathan), so the solution is straight forward: sort -o file1 file1.
Bash open a new empty file when reads the pipe, and then calls to sort.
In the second case, tee opens the file after sort has already read the contents.
You can use this method
sort file1 -o file1
This will sort and store back to the original file. Also, you can use this command to remove duplicated line:
sort -u file1 -o file1

redirection and vim

I was wondering if there's a way to see the output of any command,
straight inside vim, rather than first redirecting it into a file and
then opening that file.
E.x. I need something like
$ gvim < diff -r dir1/ dir2/
This gives ambiguous redirect error message
I just want to see the diffs between dir1 and dir2 straight inside
gvim.
Can any one provide a nice hack?
diff file1 file2 | vim -R -
The -R makes it read-only so you don't accidentally modify the input (which may or may not be your desired behavior). The single dash tells vim to reads its input over standard input. Works for other commands, too.
Also, when already in Vim:
:r! diff file1 file2
vim -d file1 file2
Although I would also suggest vimdiff or vim -d for the case of looking at a diff, I just have to share this (more general) approach for using vim usage in pipes: vipe (from the moreutils package in Ubuntu).
For example:
find -name '*.png' | vipe | xargs rm
would allow you to first edit (in vim) the list of .png files found before passing it to xargs rm.
jst use gvimdiff instead
or vimdiff
to paste the output of a command straight into vim, for example ls, try
:%r!ls
BTW, there is a DirDiff plugin.
You can do this with
diff -r dir1/ dir2/ | gvim -
the '-' option to vim (or gvim) tells vim to open STDIN
I often use vimdiff -g <file1> <file2>
One of the most simple and convenient ways is to do it like this:
vimdiff -R <file1> <file2>
Again the '-R' flag is to open it for read-only mode to avoid any accidental changes.
What you are looking for is called process substitution:
vim <(diff -r dir1/ dir2/)
But the DirDiff plugin mentioned by Luc is much more useful for comparing directories.

Resources