Am 24.08.2010 04:31, schrieb rudy b:
> Hi,
> I have a question about "diff".
> I've always found "diff" very powerful, and I've never had any issue
> with this commad.
> Expect that I encoutered a problem, that I wish "diff" would be just
> slightly more flexible.
>
> Usually "diff" is very smart in aligning the lines in a way to
> optimise its match.
> Is there any way that I can set some sort of flag for the "diff"
> command to start comparing the files line by line ONLY (and not try to
> use any of its smart matching algorithms) ?
> line#1 (file1)      ....  line#1 (file2)
> line#2 (file1)      ....  line#2 (file2)
> line#3 (file1)      ....  line#3 (file2)
> ...
> line#n (file1)      ....  line#n (file2)
>
> thanks in advance,
> Rudy

This kind of diff can be done in Vimscript, see attached plugin!  It's
simple yet, for example 'diffopt' is ignored.

Usage:

:SetLineByLineDiff
    enable line-by-line diff (set 'diffexpr' to a different value)

:SetLineByLineDiff!
    disable, set 'diffexpr' back to the default

--
Andy

--
You received this message from the "vim_use" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
" File:         diffbyline.vim
" Created:      2010 Sep 28
" Last Change:  2010 Oct 02
" Rev Days:     3
" Author:       Andy Wokula <anw...@yahoo.de>

" :SetLineByLineDiff[!]
"
"   set the 'diffexpr' to enable a trivial line-by-line diff algorithm (the
"   diff program has no option for this).  Reset 'diffexpr' with [!].

com! -bar -bang SetLineByLineDiff  call s:SetDiffExpr(<bang>0)


func! s:SetDiffExpr(bang)
    if !a:bang
        set diffexpr=DiffLineByLine()
        echo "'diffexpr' changed to enable line-by-line diff"
    else
        " XXX restore the previous value
        set diffexpr&
        echo "'diffexpr' restored"
    endif
endfunc

func! DiffLineByLine()
    let result = []     " diff output lines
    let oldlines = readfile(v:fname_in)
    let newlines = readfile(v:fname_new)

    let len_oldlines = len(oldlines)
    let len_newlines = len(newlines)
    let len_common = min([len_oldlines, len_newlines])

    " different number of lines allowed
    "   first common lines -> change(s) only
    "   rest -> append (er, no, see below)

    let idx = 0
    let change_start = -1
    while idx < len_common
        if oldlines[idx] !=# newlines[idx]
            " XXX above test is case sensitive and ignores 'diffopt'
            if change_start == -1
                let change_start = idx
            endif
            let change_end = idx
        elseif change_start >= 0
            " line-idx is just after a block of changed lines

            " prepare a diff block
            if change_start < change_end
                let range = (1+change_start). ",". (1+change_end)
            else
                let range = 1+change_start
            endif
            let ed_cmd = range. "c". range
            call add(result, ed_cmd)
            call extend(result, map(oldlines[change_start : change_end], '"< ". 
v:val'))
            call add(result, '---')
            call extend(result, map(newlines[change_start : change_end], '"> ". 
v:val'))

            let change_start = -1
        endif
        let idx += 1
    endwhile

    if change_start >= 0

        " XXX extract to function? (paragraph copied from above)
        if change_start < change_end
            let range = (1+change_start). ",". (1+change_end)
        else
            let range = 1+change_start
        endif
        let ed_cmd = range. "c". range
        call add(result, ed_cmd)
        call extend(result, map(oldlines[change_start : change_end], '"< ". 
v:val'))
        call add(result, '---')
        call extend(result, map(newlines[change_start : change_end], '"> ". 
v:val'))

    endif

    if len_oldlines < len_newlines
        let append_start = len_oldlines
        let append_end = len_newlines - 1
        let old_range = append_start    " append below this line
        if append_start < append_end
            let new_range = (1+append_start). ",". (1+append_end)
        else
            let new_range = 1+append_start
        endif
        let ed_cmd = old_range. "a". new_range
        call add(result, ed_cmd)
        call extend(result, map(newlines[append_start : append_end], '"> ". 
v:val'))
    
    elseif len_oldlines > len_newlines
        let delete_start = len_newlines
        let delete_end = len_oldlines - 1
        let new_range = delete_start    " delete below this line
        if delete_start < delete_end
            let old_range = (1+delete_start). ",". (1+delete_end)
        else
            let old_range = 1+delete_start
        endif
        let ed_cmd = old_range. "d". new_range
        call add(result, ed_cmd)
        call extend(result, map(oldlines[delete_start : delete_end], '"< ". 
v:val'))
    
    endif

    " Decho result
    " XXX strange: :Decho prints at least two result lists, first is
    "   ['1c1', '< line1', '---', '> line2'] and belongs nowhere (is this an
    "   internal diff test by Vim?)

    call writefile(result, v:fname_out)

endfunc

Reply via email to