I have some $somePaths array of 4 folders. I want to open some files from this folders in VIM. The following opens them in tabs.
vim -p `for i in ${somePaths[#];}; do echo $i/src/main.cpp; done`
Actually I'd like to have those files in split windows (cross-like). How it can be done?
Apart from -p, Vim also offers the -o and -O command-line arguments for horizontal / vertical splits. Unfortunately, they cannot be mixed. To build you own custom window layout, you have to pass the explicit window placement commands via -c. This example
$ vim 1 -c 'bel vsplit 2' -c '1wincmd w' -c 'bel split 3' -c '3wincmd w' -c 'bel split 4'
creates a layout that looks like this:
+-----------+-----------+
| | |
| | |
| | |
|1 |2 |
+-----------+-----------+
| | |
| | |
| | |
|3 |4 |
+-----------+-----------+
To keep passing the list of files as one block, you can use the fact that the buffer numbers increase monotonically, and refer to buffer numbers in the command:
$ vim -c 'bel vert sbuf 2' -c '1wincmd w' -c 'bel sbuf 3' -c '3wincmd w' -c 'bel sbuf 4' a b c d
vim has :vertical command, which could be useful in your case. give this a try:
vim +'vertical all' [your file list]
You can try using -O4 instead of -p.
The accepted solution posted above is good and solves your use case, however I would like to point out an alternate way of achieving something similar without much effort or configuration.
VIM has inbuilt support for record sessions, :h :mksession, what that allows you to do is save the current vim session (open files, splits, tabs, windows, etc, depending on the value of :h 'sessionoptions'. Although record and maintaining sessions can be slightly tedious, what I'd suggest is use either of xolox/vim-session (I've used it previously) or tpope/vim-obsession (use it now). That will allow you to re-open a session exactly as you left off!
Here is what I do, I have this snippet in my ~/.zshrc:
function vim() {
tmux rename-window "vim - ${PWD##*/}"
if test $# -gt 0; then
env vim --servername ${PWD##*/} "$#"
elif test -f ~/.vim/sessions/${PWD##*/}.vim; then
env vim --servername ${PWD##*/} -S ~/.vim/sessions/${PWD##*/}.vim
else
env vim --servername ${PWD##*/} -c Obsession\ ~/.vim/sessions/${PWD##*/}.vim
fi
}
What that does basically is check if vim is launched as it is without any arguments and checks if a session already exists & loads it, or using tpope/vim-obsession starts recording a new session, which will be loaded the next time you open vim. The session name is just the name of the directory you launch vim in. If you do pass any arguments to vim however it would behave like you'd expect and doesn't bother worrying about sessions.
This way, I can now just launch vim in any directory and first time I do so, it will start recording a new session, whereas on subsequent invocations it will load that session and tpope/vim-obsession keeps it updated.
Related
I am trying to open all the files listed in file a.lst:
symptom1.log
symptom2.log
symptom3.log
symptom4.log
But trying the following command:
cat a.lst | tr "\n" " " | vim -
opens only the stdin output
symptom1.log symptom2.log symptom3.log symptom4.log
It doesn't open symptom1.log, symptom2.log, symptom3.log & symptom4.log in vim.
How to open all the files listed in a.lst using vim?
You could use xargs to line upp the arguments to vi:
vim $(cat 1.t | xargs)
or
cat a.lst | xargs vim
If you want them open in split view, use -o (horizontal) or -O (vertical):
cat a.lst | xargs vim -o
cat a.lst | xargs vim -O
while read f ; do cat $f ; done < a.lst | vim -
I like a variation on Qiau's xargs option:
xargs vim < a.lst
This works because the input redirection is applied to the xargs command rather than vim.
If your shell is bash, another option is this:
vim $(<a.lst)
This works because within the $(...), input redirection without a command simply prints the results of the input, hence expanding the file into a list of files for vim to open.
UPDATE:
You mentioned in comments that you are using csh as your shell. So another option for you might be:
vim `cat a.lst`
This should work in POSIX shells as well, but I should point out that backquotes are deprecated in some other shells (notably bash) in favour of the $(...) alternative.
Note that redirection can happen in multiple places on your command line. This should also work in both csh and bash:
< a.lst xargs vim
vim may complain that its input is not coming from a terminal, but it appears to work for me anyway.
Is there a way to write a script that would be applied to the clipboard content ( I'm using Linux\Gentoo)?
When copy-pasting it would be nice to bind a keystroke that would (e.g -) remove all line breaks from the copied text.
I couldn't find where to start such a task (where should such a script be placed\how to reference the clipboard) so just a hint of where to start would be appreciated.
Thanks!
You need to install xsel to access your clipboard. Then you can just use a small script and piping. I use this to prepend four spaces to my current selection in order to get a version I can paste into StackOverflow editors:
xsel | while IFS='' read a; do echo " $a"; done | xsel
Default for xsel is to manipulate (or query) your PRIMARY selection (what you just marked with the mouse). You can use the clipboard (C-c, C-v stuff) instead by using the option -b.
To remove all line breaks from your current clipboard, just try this:
xsel -b | tr '\n' '\r' | sed 's/\r*//g' | xsel -b
I'm regularly invoking gvim -d with two filenames; I'd like the second to be systematically opened in read only (since it's in a reference directory, and shouldn't be modified). The first shouldn't be read only, however, because I'll be pulling some of the diffs from the second into it. So what do I have to do to achieve this?
$ gvim -d file1 file2 +'wincmd l | set ro | wincmd h'
does the trick.
Assuming you use bash, you can put it into an alias:
alias vd='/usr/bin/gvimdiff +"wincmd l | set ro | wincmd h"'
Is there a way to execute a Vim command on a file from the command line?
I know the opposite is true like this:
:!python %
But what if I wanted to :retab a file without opening it in Vim? For example:
> vim myfile.c
:retab | wq
This will open myfile.c, replace the tabs with spaces, and then save and close. I'd like to chain this sequence together to a single command somehow.
It would be something like this:
> vim myfile.c retab | wq
This works:
gvim -c "set et|retab|wq" foo.txt
set et (= set expandtab) ensures the tab characters get replaced with the correct number of spaces (otherwise, retab won't work).
I don't normally use it, but vim -c ... also works
The solution as given above presumes the default tab stop of eight is appropriate. If, say, a tab stop of four is intended, use the command sequence "set ts=4|set et|retab|wq".
You have several options:
-c "commands" : will play Ex commands as you entered them in the command line.
In your example : vim myfile -c 'retab | wq'. This is what Firstrock suggested.
-S "vim source file" : will source given vim script
(like running vim -c "source 'vim source file'"):
If you have a file script.vim containing:
retab
wq
Then you can use vim myfile.c -s script.vim (the extension does not really matter)
-s "scriptin file": will play contents of file as it contains normal mode commands: If you have script.txt containing:
:retab
ZZ
with end of lines consisting of a single ^M character (for example you saved the script using the :set fileformat=mac | w), then you can run: vim myfile.c -S script.txt (ZZ is another way to exit vim and save current file).
Note that you can record those scripts with vim my_file -W script.txt, but it suffers a bug if you happen to use gvim (the GUI).
Not a direct answer to your question, but if you want to replace tabs with spaces (or do any other regex search/replace) for a list of files, you can just use in-place sed search/replace:
sed -i 's/\t/ /g' foo1.txt foo2.txt
or
ls *.txt | xargs sed -i 's/\t/ /g'
(In this example I am replacing each tab character with three spaces.)
NOTE: the -i flag means operate in-place.
From the sed man page:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension
supplied)
I want to get automatically to the positions of the results in Vim after grepping, on command line. Is there such feature?
Files to open in Vim on the lines given by grep:
% grep --colour -n checkWordInFile *
SearchToUser.java:170: public boolean checkWordInFile(String word, File file) {
SearchToUser.java~:17: public boolean checkWordInFile(String word, File file) {
SearchToUser.java~:41: if(checkWordInFile(word, f))
If you pipe the output from grep into vim
% grep -n checkWordInFile * | vim -
you can put the cursor on the filename and hit gF to jump to the line in that file that's referenced by that line of grep output. ^WF will open it in a new window.
From within vim you can do the same thing with
:tabedit
:r !grep -n checkWordInFile *
which is equivalent to but less convenient than
:lgrep checkWordInFile *
:lopen
which brings up the superfantastic quickfix window so you can conveniently browse through search results.
You can alternatively get slower but in-some-ways-more-flexible results by using vim's native grep:
:lvimgrep checkWordInFile *
:lopen
This one uses vim REs and paths (eg allowing **). It can take 2-4 times longer to run (maybe more), but you get to use fancy \(\)\#<=s and birds of a feather.
Have a look at "Grep search tools integration with Vim" and "Find in files within Vim". Basically vim provides these commands for searching files:
:grep
:lgrep
:vimgrep
:lvimgrep
The articles feature more information regarding their usage.
You could do this:
% vim "+/checkWordInFile" $(grep -l checkWordInFile *)
This will put in the vim command line a list of all the files that match the regex. The "+/..." option will tell vim to search from the start of each file until it finds the first line that matches the regex.
Correction:
The +/... option will only search the first file for the regex. To search in every file you need this:
% vim "-c bufdo /checkWordInFile" $(grep -l checkWordInFile *)
If this is something you need to do often you could write a bash function so that you only need to specify the regex once (assuming that the regex is valid for both grep and vim).
I think this is what you are looking for:
http://www.vim.org/scripts/script.php?script_id=2184
When you open a file:line, for instance when coping and pasting from an error from your compiler (or grep output) vim tries to open a file with a colon in its name. With this little script in your plugins folder if the stuff after the colon is a number and a file exists with the name especified before the colon vim will open this file and take you to the line you wished in the first place.
It's definitely what I was looking for.
I highly recommend ack.vim over grep for this functionality.
http://github.com/mileszs/ack.vim
http://betterthangrep.com/
You probably want to make functions for these. :)
Sequential vim calls (console)
grep -rn "implements" app | # Or any (with "-n") you like
awk '{
split($0,a,":"); # split on ":"
print "</dev/tty vim", a[1], "+" a[2] # results in lines with "</dev/tty vim <foundfile> +<linenumber>
}' |
parallel --halt-on-error 1 -j1 --tty bash -ec # halt on error and "-e" important to make it possible to quit in the middle
Use :cq from vim to stop editing.
Concurrent opening in tabs (gvim)
Start the server:
gvim --servername GVIM
Open the tabs:
grep -rn "implements" app | # again, any grep you like (with "-n")
awk "{ # double quotes because of $PWD
split(\$0,a,\":\"); # split on ":"
print \":tabedit $PWD/\" a[1] \"<CR>\" a[2] \"G\" # Vim commands. Open file, then jump to line
}" |
parallel gvim --servername GVIM --remote-send # of course the servername needs to match
If you use git, results are often more meaningful when you search only in the files tracked by git. To open files at the given line which is a search result of git grep in vim you will need the fugitive plugin, then
:copen
:Ggrep pattern
Will give you the list in a buffer and you can choose to open files from your git grep results.
In this particular example:
vim SearchToUser.java +170