How do I accept both changes in vimdiff hunk? - vim

When resolving merge conflicts, a fairly common pattern is that both I and another person have modified a list or some other section of code which commonly gets appended to. Such as:
global.registerFeature(fc);
global.registerFeature(fb);
global.registerFeature(fa);
<<<<<<<
global.registerFeature(aNewFeature);
=======
global.registerFeature(anotherNewFeature);
>>>>>>>
When I look at a merge conflict like this in vimdiff, vim gives me options for choosing one or the other. But what I want to do is apply both diffs. I usually just resort to editing the merged file directly (just deleting the merge markers); but is there an easier way to do this in vimdiff?

To combine changes from both the target and merge branches in a single command:
You can just delete the lines with Git conflict markers. The following two methods will delete all lines that start with:
<<<<<<<
=======
>>>>>>>
Method 1: Manually Entering and Executing a Command
:g/^<\{7}\|^|\{7}\|^=\{7}\|^>\{7}/d
Method 2: Implementing a User Defined Command
"Delete all Git conflict markers
"Creates the command :GremoveConflictMarkers
function! RemoveConflictMarkers() range
echom a:firstline.'-'.a:lastline
execute a:firstline.','.a:lastline . ' g/^<\{7}\|^|\{7}\|^=\{7}\|^>\{7}/d'
endfunction
"-range=% default is whole file
command! -range=% GremoveConflictMarkers <line1>,<line2>call RemoveConflictMarkers()
Vim diffget and diffput will only choose one branch or the other. So the only real solution other than the one given above is to manually yank and paste from both files into the working copy.

I'm not sure exactly what version control system you are using, but here is a guide for using Vim to do merges with Mercurial: https://www.mercurial-scm.org/wiki/MergingWithVim
You should be able to do something similar with whatever you are using, although keep in mind that vimdiff is not really meant for complicated merges, so it will be a bit kludgy. That same page links to the splice plugin, which is supposed to help with doing complex merges.

Related

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.

Vim: Is it possible to have a filtered view of a file?

In a given text file, I would like to work on a "filtered view" (hiding lines with a pattern), but still to be able to edit visible lines : the filtering would only affect the visibility of some lines, and as soon as I would reset the filter, the hidden lines would appear again.
The feature I describe could be compared to the & key in the less command (except, of course, that less can't edit the file's content) :
&some_pattern <RETURN> starts a new filter,
& <RETURN> reset the filter.
Does such a feature exist in vim, natively or as a plugin?
This usually is done with folding; you can easily define a 'foldexpr' that filters lines based on a regular expression match; see Folding with Regular Expression for implementations.
However, a single fold line will remain for each condensed block. To do away with those, I can only think of the NrrwRgn plugin, which transfers selected lines into a separate scratch buffer. It's usually only for a single block, but :help NR-multi-example suggests this works on ranges, too:
For example before editing your config file, you decide to strip all comments
for making big changes but when you write your changes back, these comments
will stay in your file. You would do it like this: >
:v/^#/NRP
:NRMulti
It can be done with plain Vim, and it's named folding. Drew Neil has two screencasts about it that you might find informative.

VIM: Respect only current code block

I have started working on a huge PHP application that has thousands of lines of code in each file, with lots of huge if blocks, classes, and functions all existing in the same file. I'm not the only dev working on it, so I cannot refactor!
I have tried using the Tags List plugin but it does not really help. Is there any way to have VIM respect only a particular code block, and ignore the rest of the file? I am hoping for some or all of these features:
Enable line numbering only for the current code block, starting from 1 at the line containing the opening {, and showing no numbering for lines preceding it or after the closing }.
Searching with / would be restricted only to the block in question.
I am thinking along the lines of selecting the current block and editing it in a new buffer when enabling the mode, then replacing the existing block with the edited block when exiting the mode. However, I am having trouble actually implementing this feature. My current version is this:
map <F7> <Esc>mO<C-V>aBy:new<Return>p:set nu<Return>:set ft=php<Return>ggi<?php<Return><Esc>
map <F8> <Esc>ggdd<C-V>aBx:bp<Return>`O<C-V>aBp
However, this has several issues, such as the inability to perform incremental saves.
I would be very surprised if Vim allows the kind of line numbering you ask for.
This plugin (and 1 or 2 similar ones IIRC) allows you to visually select a region of your current file, work on it in another buffer and put everything back in its place in the original file on :w.
Even if it's not the solution you are wanting, I think the following can help you to solve your problem.
You can use phpfolding plugin, which folds by PHP syntax (functions, classes, methods, PhpDoc...)
You can then select a fold by pressing v$ over the closed fold and execute whatever you want with :whatever. For example, :s/this/self/g to substitute all this for self in the fold. When you press :, vim will automatically add '<,'> to denote following command it's only for the visually selected text.

Syntax of Greplace

I want to change some words in several files using VIM. To do this, I found out about Greplace, which appears to be made to do just that. However, in the documentation there is no sample of the syntax of Greplace (there is a sample of Gsearch, but I need the replace function).
Say I want to change "foo" for "bar" in all ".asp" files, how could that be achieved with Greplace (or any other method). I do not care about confirmation (it's fine if it requires confirmation; it's also fine if it does not).
It's trivial to do without a dedicated plugin.
$ vim *.asp
:bufdo %s/foo/bar/ge | update
:q
:bufdo runs the following commands on all buffers.
%s/foo/bar/ge replaces foo with bar on all lines and all occurrences in each line. The e flag makes sure :s doesn't emit an error if it doesn't find foo, since foo may not exist in all the files.
| is Vim's way of separating multiple commands to run. See :help :bar
update saves the file back to disk, only if any changes were actually made.

Use vimdiff to replace entire file?

I'm using vimdiff for a git merge. Is there a quick way to select 1 file to use, right now i'm just selecting everything from one buffer, replacing the $MERGE with that, and then saving. I guess I can macro that, but was wondering if there is a better way.
Thanks!
Several ways:
:%diffput
to do 'put' all changes from the current buffer to the 'other' buffer. This makes it easy with three-way diffs:
:%diffput OURS
The 'OURS' pattern will match uniquely on buffernames participating in the current diff
All the above can be done in reverse, substituting do or :diffget
You should take a look at Tim Pope's Fugitive plugin. It's a really usefull plugin.
When you run Gdiff in a conflicted file, 3 files are opened - target, merged and working copy. You would switch to the file you want to save, and execute Gwrite! to save that file.
There is a whole Vimcast explaining how to resolve merge conflicts with this plugin(And other 5 vimcasts explaining more about Fugitive.vim).
I think :%diffget LO or :%diffget RE is what you need.
Note: you need to run it in the MERGED part of vim windows. You can move cursor around the windows using Ctrl+w;←/↑/→/↓
Make sure that all participating buffers are in diff mode (see :h start-vimdiff on how to start diff mode)
Do v for VISUAL MODE in the Base
Select the whole file (press Page Down all the way)
Write : then diffget <buffer number/name> (: ls will list all buffers, generally in vimdiff they are from right to left 1-3 or 4 if 3 way diff)
Afterwards just : wqa and you are done
Alternatively, after step 0., one could do :%diffget <buffer number> to get all changes from the specified buffer as :diffget also accepts ranges. (See :% and :diffget.)
The reverse would also work: :%diffput <buffer> will send all changes to buffer number, making the two buffers have the same content.

Resources