XOR zwei Zeilen, um Unterschiede zu sehen

7

Ich muss ein "XOR" -ähnliches aus zwei Zeilen berechnen, um jedes Zeichen zu finden, das sich zwischen den beiden Zeilen unterscheidet. Ich weiß, dass die vim-diffFunktion dies leicht erreichen kann, aber um zwei Zeilen zu vergleichen, wollte ich alles im selben Puffer halten.

z.B

1wYT4SH8f8VjRA25u8AItlrTdAY4Y7n-g8if8VjRA3q25u8AItlrTdwTbv8if8VjRA3q25u8AItlrTdJjMY
1wYT4SH8f8VjRA25u8AItlrTdAY4Y7n-g8if8VjRA3q25u8AIt1rTdwTbv8if8VjRA3q25u8AItlrTdJjMY
                                                  1

Wie geht das?

nobe4
quelle

Antworten:

13

Diese Lösung zeigt nicht den Unterschied zwischen den beiden Linien, sondern hebt sie hervor und ermöglicht es Ihnen, mit nund Nwie folgt durch sie zu navigieren :

Screencast der Funktion

Fügen Sie dazu diese Funktion hinzu .vimrc:

function! CompareLines(line1, line2)
    let l1 = getline(a:line1)
    let l2 = getline(a:line2)
    let pattern = ""

    for i in range(strlen(l1))
        if strpart(l1, i, 1) != strpart(l2, i, 1)
            if pattern != ""
                let pattern = pattern . "\\|"
            endif
            let pattern = pattern . "\\%" . a:line1 . "l" . "\\%" . ( i+1 ) . "c"
            let pattern = pattern . "\\|" . "\\%" . a:line2 . "l" . "\\%" . ( i+1 ) . "c"
        endif
    endfor

    execute "let @/='" . pattern . "'"
    set hlsearch
    normal n
endfunction

Sie können die Funktion aufrufen, bei der :call CompareLines(1, 2)die Argumente die Nummern der zu vergleichenden Zeilen sind.

So fügen Sie weitere Details zur Funktionsweise der Funktion hinzu:

  • In den ersten Zeilen werden die zu vergleichenden Zeilen in einigen Variablen angezeigt.
  • Die Schleife durchläuft diese Zeichenfolgen. Jedes Zeichen der Zeichenfolgen wird verglichen und wenn sie nicht mit einem Muster des Formulars übereinstimmen \%Xl\%Yc, wird der Variablen hinzugefügt, patternwobei Xund Ydie Zeile und die Spalte eines Zeichens sind.

    (Siehe :h /ordinary-atomund insbesondere die letzten Zeilen, in denen erklärt wird, dass das Muster \%23ldie Übereinstimmung mit der 23. Zeile und \%23cder 23. Spalte zulässt. )

  • Sobald das Muster erstellt ist, wird es in das Suchregister eingefügt ( let @/=erlauben Sie, den Inhalt des Registers zu definieren, und das Muster muss in Anführungszeichen gesetzt werden).

  • Schließlich set hlsearchwerden alle Übereinstimmungen des Musters hervorgehoben und normal nder Cursor auf das erste andere Zeichen gesetzt.

Hinweis 1 Die Funktion ändert Ihren Suchverlauf.

Hinweis 2 Der Teil, der das Muster für die Suche verwendet, könnte wahrscheinlich erheblich verbessert werden.

Und als Bonus Fügen Sie diese Zeile zu Ihrer hinzu .vimrc, um einen Befehl zu erstellen, der den Aufruf der Funktion beschleunigt:

command! -nargs=* CompLines call CompareLines(<f-args>)

Auf diese Weise können Sie einfach :CompLines 1 2zwei Zeilen vergleichen.


BEARBEITEN Und hier ist eine verbesserte Version der Funktion und des Befehls. Der Unterschied besteht darin, dass Sie es auf drei verschiedene Arten aufrufen können:

  • :CL unterscheidet die aktuelle Zeile und die folgende
  • :CL 23 unterscheidet die aktuelle Zeile und die Zeile 23
  • :CL 23 42 wird die Zeilen 23 und 42 unterscheiden

Hier ist der Code:

command! -nargs=* CL call CompareLines(<f-args>)

function! CompareLines(...)

    " Check the number of arguments
    " And get lines numbers
    if len(a:000) == 0
        let l1=line(".")
        let l2=line(".")+1
    elseif len(a:000) == 1
        let l1 =line(".")
        let l2 =a:1
    elseif len(a:000) == 2
        let l1 = a:1
        let l2 = a:2
    else
        echom "bad number of arguments"
        return;
    endif

    " Get the content of the lines
    let line1 = getline(l1)
    let line2 = getline(l2)

    let pattern = ""

    " Compare lines and create pattern of diff
    for i in range(strlen(line1))
        if strpart(line1, i, 1) != strpart(line2, i, 1)
            if pattern != ""
                let pattern = pattern . "\\|"
            endif
            let pattern = pattern . "\\%" . l1 . "l" . "\\%" . ( i+1 ) . "c"
            let pattern = pattern . "\\|" . "\\%" . l2 . "l" . "\\%" . ( i+1 ) . "c"
        endif
    endfor

    " Search and highlight the diff
    execute "let @/='" . pattern . "'"
    set hlsearch
    normal n
endfunction

EDIT 2 Ich habe es zu einem Plugin gemacht . Sie können es mit einem normalen Plugin-Manager installieren mit (zB):

Plug 'statox/vim-compare-lines'
statox
quelle