Editing multiple files simultaneously with Vim - vim

I need to add several lines all at the same location to multiple files. I was wondering if I could possibly open all files with Vim, and only make the changes in one file for which the changes will be made in all files simultaneously. I really want to avoid opening X number of files, copying this, pasting, then repeating for each file of X files...There's gotta be a better way to do this, hopefully with vim...
Thanks!
Amit

You could record macro and execute it on other files. See http://www.thegeekstuff.com/2009/01/vi-and-vim-macro-tutorial-how-to-record-and-play/ for detailed tutorial.

You can use the windo command to operate in all windows. Combine this with a substitute command and you have this (say you want to add "This is a new line." at line 2 in every file):
:windo 2s/\(.*\)/This is a new line.^M\1
Off course, as others noted, there are much better tools for this job (awk comes to mind).

Related

Vimdiff - How to hide all same lines in both files and show only different ones

vimdiff file1 file2
besides differences shows also same lines from both files. Is it possible to hide them? How to do it?
As Vim is a text editor (not a specialized diff viewer), the full contents of both files are kept (so you can do edits and persist them). Vim usually just "hides" multiple identical lines by folding them away; they are still present, just not visible.
You can influence how many identical lines are kept around changes (default: 6 lines above and below) via the context value of the 'diffopt' option. So, to completely fold all identical lines:
:set diffopt+=context:0
It is still showing common lines if common line is going in sequence with different. one after another
The solution suggested by Ingo Karkat worked perfectly in Linux. Thanks for sharing it. However, it's not working on Mac.

Give vimdiff some hints

I've got two c++ files that I want to diff with vimdiff. One of them has a lot more function definitions at the start, before both have a common function that I'm actually interested in. However, vimdiff seems incapable to ignore all the function defs before the common one (perhaps because of different arguments).
Is there any way I can give a hint to vimdiff that, say, line xxx in file1.cxx is equals to line yyy in file2.cxx?
I'm open for alternative solutions without vimdiff, but they must be on linux and very preferably command line, since I'm ssh-ing and any graphical interface is a bit uncomfortable.
Vim just delegates the actual work of comparing the files to the external diff utility, cp. :help diff-diffexpr. The help page also shows how a different utility can be used. Unfortunately, I'm not aware of any more "intelligent" or configurable diff tool that would help in your situation.
A workaround might be (temporarily) removing the excess functions that you're not interested in, anyway. With the BlockDiff plugin, you don't actually need to modify the files. Just select the interesting lines in both windows and execute :[range]BlockDiff on them. Only those sections will then be diffed in a separate tab page. (The plugin mentions this requires a GUI, but Vim in a terminal supports tab pages just as well.)

vim: multiple "sessions" in the same instance?

I work on a growing project with vim. I like to have most of the project files open in the same session. However, as the project's growing, I start to have too many files open at the same time; switching between files [*] starts getting a bit unproductive at 40+ files because the list gets too long (for, say, 20 files this way of navigating works very well for me, however).
Is there a way to split the session in multiple "sub-sessions" in the same instance of vim?
How I imagine it is that each session would contain, say, 20 files and only list those with :ls, and that I could switch between them in the same vim window (basicallly the same as if I'd run multiple instances of vim in the same shell and switch between them with Ctrl-Z; fg %X, just without leaving vim).
[*] I like to navigate between files with :ls followed by :bX (or directly :bX in case I've memorized a buffer number), along with :bp/:bn, and I always have at least two split open, and this workflow works quite well for me, so I'm not looking for more efficient alternatives to :ls.
I never use :ls. However I often work on big projects, and I open (many) files from different projects (and I'm still able to compile what I want in the mode I want (debug, release, ...), generate tags independently for each project, have different coding styles, etc)
Your question seems to be about "How do I go from one file to another". I have many split windows opened simultaneously and I jump from one to the other with:
:sb, which supports tab completion on filenames (already opened in buffer)
:sp **/filename*<tab> (When it's not already opened)
an old plugin of mine -- others usually use Unite, command-T or other similar plugins -- to merge :sp and :sb into one command.
Tags. The default integration of tags (/csope) is already nice. Yet, I've developed lh-tags, in order to simply the tags navigation in a world of overloaded and overridden functions as it's the case in C++.
EDIT: I've just pushed a highly experimental :Project <name> :ls feature in lh-vim-lib. Note: this new project feature wasn't meant to do what you're looking for, but it's easy to have a restricted :ls thanks to it.
To use it, you'll have to first register buffers to one project or another. Here, I recommend plugins like local_vimrc if each project can be distinguished as files under a given directory. For each root directory place a _vimrc_local.vim file in it that'll contain:
:let s:k_version = 1
" Global definitions executed everytime we enter a file belonging to the project
" This is where we set g:lobal_variables and options for project-unaware plugins.
....
" Then the anti-reinclusion guards for buffer definitions
if &cp || (exists("b:loaded__my_foobar_project_settings")
\ && (b:loaded__my_foobar_project_settings > s:k_version)
\ && !exists('g:force_reload__my_foobar_project_settings'))
finish
endif
let b:loaded__my_foobar_project_settings = s:k_version
let s:cpo_save=&cpo
set cpo&vim
" HERE, we say the current buffer belongs to a project
" solution 1 when we need more control
:call lh#project#define(s:, {'name': 'YouProjectName'})
" OR solution 2 which is easier to manipulate (tab completion, ...)
:Project --define YourProjectName
You can also have a smaller granularity if you wish (this is something which is still poorly documented).
Then, you'll be able to consult the list of projects with :Project --list, or to consult the buffers associated to a given project with :Project YouProjectName :ls.

Making AutoComplPop search entire project (or open buffers)?

I started using AutoComplPop for automatic code completions. It works great on the single file I am editing, but if file1 is making a reference to a method defined in file2, it doesn't find it.
The docs don't specify if there is a way to make it search a whole project directory, or even just all open buffers, so I can't tell if this is simply not something the plugin does, or if I need to enable something.
I was testing it out on two Ruby files, if that's relevant. Thanks!
Looks like that the cause of the problem is that ACP set the complete option for its purposes to .,w,b,k (see line #125 in autocomplpop/plugin/acp.vim),
call l9#defineVariableDefault('g:acp_completeOption', '.,w,b,k')
while the default value that is used when pressing \<C-n> is .,w,b,u,t,i. And it appears that the very last letter i actually makes the difference: for some reason vim would not use word from an include file opened in a buffer to complete words in another buffer. So, b option is not enough, i must also be included. Adding the following line into my .vimrc helped
let g:acp_completeOption = '.,w,b,u,t,i'
At least it worked for C++ files, but I'm not sure it fixes the problem for the case of Ruby scripts.
Depending on what is on the left of the cursor, ACP (like all the alternatives) decides what completion mechanism to use.
But ACP only uses Vim's default completion mechanisms: if <C-x><C-o> and <C-n>/<C-p> don't provide what you are looking for, ACP won't help. Try them out first.
Oh cool, this plugin looks a lot like neocomplcache but maybe cleaner...looks a little old. Little concerning that there are so many open tickets on that project and no updates in two years.
Anyway, according to the documentation it doesn't...really...say. Very likely its one of the following things:
Your pwd. If the root directory for your source is some/path then that should also be your current working directory. Try typing :cd some/path to see if that makes a difference.
The runtime path rtp. See if adding the directory with your source files to &rtp does the trick.
The path. Same deal as the &rtp setting.
Very likely this plugin is just falling back on the built in ruby omni completion functions bundled with vim. Try help ft-ruby-omni.
I just had the same problem, and I actually found a solution for this.
Apparently you have to set in your .vimrc file the following:
let g:acp_behaviorKeywordCommand = "\<C-x>\<C-i>"
This will make acp look in every file included by your source for completions, as if you were actually typing <C-p>. However, it is slow, after trying it I decided to revert using <C-p> when there are no matches and default behaviour in the other cases.

In Vim, what is the "alternate file"?

I just ran :help registers in Vim and noticed that # 'contains the name of the alternate file'.
I have seen an example for renaming files that goes like this:
" Save the current file, foo.txt, as bar.txt
:w bar.txt
" Start editing bar.txt
:e#
So apparently in that case, the file you just saved out is the "alternate file."
Can someone give me a more general definition for the "alternate file" and what else you might use it for?
The alternate file is the file that was last edited in the current window. Actually when you use some command to open a new buffer, if the buffer that was displayed had a filename associated with it, that filename is recorded as alternate file name.
See :help alternate-file.
Very useful for...
Pasting in the name of a file I've just been looking at into the current file.
You can use <C-R># for this in insert mode or "#p in normal mode.
Not that useful for...
Jumping back and forth between two files. It does the job very well, but this is just something I don't generally need to do.
Even in the example given, I'd probably use:saveas bar.txt instead.
An Example:
Say if you're doing a bit of C programming and want to call some function. You can't remember the name of the function, so you place a mark on your current location mA and jump into several different files using tags or grep to find out where the function is declared and what it's actually called.
Ah - found it. You can copy the name and return to the mark yiw'A
Uh-oh - we also need to #include the file! Easy - just use the alternate file name register to paste the file name in... Gi#include"<C-R>#"
Be pleased that you've avoided the distraction of having to go back to the function's declaration and copy out the file name via :let #"=#% or something similar.
What I'd rather do when jumping between files:
When editing two files, it's probably easier to split them, so you can keep both on screen at the same time. If I'm editing 2 files I'll usually be comparing them in some way.
Usually I'm interested in 1-3 files (any more and I get confused). I'll often jump into or directly open many other files. Marking the interesting files, or traversing the jump list is usually the way to get around in this case.
If you're editing C/C++ where you're switching between a file and it's header, use a plugin! It will be much more convenient.
I use it in the buffer context to return to the last buffer that I was editing
vim foo bar
:n
:e#
will take you back to foo in that case
I 've always interpreted the "alternate file" as being the "previous file", so it is an handy way to jump back to the buffer you were editing.

Resources