rickhowe / diffchar.vim

Highlight the exact differences, based on characters and words
http://www.vim.org/scripts/script.php?script_id=4932
MIT License
217 stars 10 forks source link

Modifications to a line are indicated differently depending on whether the line before or after was deleted #22

Open sblask opened 4 years ago

sblask commented 4 years ago

Consider the following:

123
456
789

When I change it to

123
456 x

the x is indicated as added. However, when I change it to:

456 x
789

the whole line with the x is indicated as changed.

It's the same kind of change and imho should be indicated the same, but because a line was deleted before and not after, it isn't. Is there anything you can do about that?

rickhowe commented 4 years ago

Which lines are indicated as added/deleted/changed are depending on the diff algorithm which vim is using. My plugin actually follows that. You can try to set different algorithms in the diffopt option.

sblask commented 4 years ago

Bummer. Tried all the algorithms available and combined the different options. Nothing helped. Now this is a toy example, but I encounter this kind of diff quite often. Also tried googling for more options, but couldn't find anything. If you have any more tips based on your experience, I'd be very grateful!

rickhowe commented 4 years ago

You may find some useful option of diff command which would help you and can set it usingdiffexpr option. If you know which range of lines should be compared between two (in your example, line '456' and '456 x'), my another plugin spotdiff.vim might help you.

sblask commented 4 years ago

Thanks for the suggestion. Just tried it, but I think I prefer https://github.com/AndrewRadev/linediff.vim especially because I can't diff side-by-side with spotdiff(or did I miss anything?).

Regarding my original problem, I think I would need two diff blocks, one for the deletion of 123 and one for the change. But is seems like all algorithms try to minimize the number of blocks...

rickhowe commented 4 years ago

FYI, this is a sample code to implement a line-by-line comparison in vimdiff.

set diffexpr=LineByLineCmp()
function! LineByLineCmp()
    let [f1, f2, fo] = [readfile(v:fname_in), readfile(v:fname_new), []]
    let eq = ''
    for ln in range(min([len(f1), len(f2)]))
        let eq .= (f1[ln] == f2[ln]) ? '=' : '!'
    endfor
    let ln = 1
    for ed in split(eq, '\%(=\+\|!\+\)\zs')
        let en = len(ed)
        if ed[0] == '!'
            let cs = (1 < en) ? ln . ',' . (ln + en - 1) : ln
            let fo += [cs . 'c' . cs]
        endif
        let ln += en
    endfor
    call writefile(fo, v:fname_out)
endfunction