does vimdiff support merging diffs - vim

Can vimdiff support a merge of diffs that are on the same line (so that I get the aggregate of them?)
example: starting with the following conflict markers:
I
like
apples
peaches
<<<<<<< HEAD
bananas
=======
cherries
>>>>>>> diverge
for supper
in the example above, can I use the do and dp commands to actually merge the diffs, or can I only end up with one of the other?
put another way, If I'd like to end up with
I
like
apples
peaches
bananas
cherries
for supper
then can I do this with diffpush and get, or do I have to drop back to basic vim commands to select the hunks to merge? as bananas and cherries are on the same line, diffget and push can control which I pick, but I dont seem to be able to have both and merge.

Not without a plugin/mapping. By default, you will need to resort to normal editing commands.
It looks like the "Splice" plugin ( https://github.com/sjl/splice.vim ) provides mappings to select hunks from multiple files; I haven't used it though so it may not work the way I assume.

Related

Visual selection and replacement in vim

How can I select different portions of multiple non-contiguous lines and replace them with the same/different text?
Example: Let's say my buffer looks like this-
Roses are reed,
Violets aree blue,
Sugaar is sweet,
And so are you,
I want to change in 1st line the 3rd word ('reed') to 'red, yellow and green', in 2nd line 'aree' to 'are', in 3rd line 'Sugaar' to 'Sugar and molasses' and in 4th line 'you,' to 'you.'.
Say my cursor is at 'R' of 'Roses'. I want to select all four of these wrongs at once and nothing other the wrongs. After I'm done selecting I want to be able to move to 'reed' by pressing some key (say Ctrl+j), then after changing I want to be able to press some key (say Ctrl+j) and move the next visual selection which is 'aree'.
Is there any plugin that does this?
There are multiple cursors plugins that attempt to create parallel editing functionality seen in other editors to Vim (which is difficult). If I understand your use case right, that wouldn't help here, though, because all places would be edited in the same way (so reed, areee, etc. would all be replaced with the same red).
Instead, what you seem to be asking for, is a way to search for all wrongly spelled words, and then edit them one by one, individually. You can do this with standard search, using regular expression branches:
/reed\|areee\|Sugaar\|you,/
You can then simply press next to go to the next match after you're done. Note that the branches have to be unique (so I searched for you, instead of simply ,). Adding word boundaries (\<reed\> instead of reed) is a good idea, too.
plugin recommendations
multiple cursors is a famous plugin for parallel editing
My SearchAlternatives plugin lets you add the current word under the cursor as a search branch with a quick (<Leader>+ by default) key mapping. (However, if you're already on the word, why not correct it immediately?)
My SpellCheck plugin populates the quickfix list with all misspelled words and locations. You can then use quickfix navigation (e.g. :cnext) to quickly go to each. The plugin also offers mappings to fix spelling errors directly from the quickfix list.

How do I accept both changes in vimdiff hunk?

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.

The way to improve vimdiff similarity-searching mechanism

I'm trying to understand how vimdiff work.
Here I tried to diff two simple files. The 1st:
abcdefghijklmnopqrstuvwxyz
foo
abcdefghijklmnopqrstuvwxyz iii
bar
The 2nd:
abcdefghijklmnopqrstuvwxyz
abcdefghijklmnopqrstuvwxyz
Here is result from diffmerge utility:
And here is result from vim:
Note that vim doesn't see the similarity between abc...xyz and abc...xyz iii lines and doesn't arrange them visually on one line.
Is there some settings to improve vimdiff in such cases?
As pointed out in the comments, vim uses the external utility diff which doesn't do word diffs nor can it find moved-and-modified lines.
Even resorting to diffexpr is unsatisfactory, since Vim expects the data from the external utility to be in a "ed" style diff. This rules out using alternative diff utilities that make word or even char based diffs, like diffmerge.
The workaround some industrious plugin authors have cooked up is to wrap the results of these more sophisticated diffs and translate their output into the "ed" style diff for Vim to consume. I know of two such plugins which take this approach: chardiff and vim-diff-enhanced. Both give you word diffs. In addition, Vim-diff-enhanced allows you to toggle between various diff algorithms (myers, histogram, patience) so one may decide which diff produces the best result on a case by case basis.
I use vim-diff-enhanced, and it is better than the default diff but still not great. (note: it depends on git.) For example, I tried your test, as described in the question, and it did NOT recognize that lines 5 and 3 were the same (even with :set diffopt+=iwhite). Although, if I removed or added something to line 2 of your first sample file, then vimdiff matched the results you obtained from diffmerge.

highlight based on external file search

I have two text files, ones is the file I'm currently working, the other is kind of dictionary. What I would like to do is to search the first one using the latter as input. I'd like to highlight all matching lines.
E.g.:
File1:
I like eggs
I like meat
I don't like eggplant
My mom likes chocolate
I like chocolate too
File2:
meat
chocolate
In this example the those lines should be highlighted:
I like meat
My mom likes chocolate
I like chocolate too
The approach is similar to the answer I've given to your related question: Use readfile(), join() the lines to a pattern, then use :match.
Here's how I would build this interactively on the command-line:
:match Search /.*\%(<C-R>=join(readfile('file2'), '\|')<CR>\).*/<CR>
Note that this quick one-liner omits error handling, regular expression escaping, etc. In case you need to do this often, I'd suggest you turn this into a custom command, just like I have shown you in the linked answer.

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