diffchar.vim icon indicating copy to clipboard operation
diffchar.vim copied to clipboard

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

Open sblask opened this issue 5 years ago • 5 comments

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?

sblask avatar Jan 23 '20 04:01 sblask

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.

rickhowe avatar Jan 23 '20 11:01 rickhowe

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!

sblask avatar Jan 24 '20 11:01 sblask

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.

rickhowe avatar Jan 24 '20 14:01 rickhowe

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...

sblask avatar Feb 06 '20 22:02 sblask

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

rickhowe avatar Feb 07 '20 10:02 rickhowe