Esta solução não mostra a diferença entre as duas linhas, mas as destaca e permite navegar através delas com n
e N
desta forma:
Para fazer isso, adicione esta função ao seu .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
Você pode chamar a função com :call CompareLines(1, 2)
onde os argumentos são os números das linhas a serem comparadas.
Para adicionar um pouco mais de detalhes sobre como a função funciona:
- As primeiras linhas obtêm as linhas para comparar em algumas variáveis.
O loop percorre essas strings. Cada caractere das seqüências de caracteres é comparado e, quando não corresponde, um padrão do formulário \%Xl\%Yc
é adicionado à variável pattern
where X
e Y
são a linha e a coluna de um caractere.
(Veja :h /ordinary-atom
e especialmente as últimas linhas que explicam que o padrão \%23l
permite coincidir com a 23ª linha e \%23c
a 23ª coluna)
Uma vez que o padrão é construído, ele é injetado no registro de pesquisa ( let @/=
permita definir o conteúdo do registro e o padrão deve ser citado).
Finalmente, set hlsearch
é usado para destacar todas as correspondências do padrão e normal n
traz o cursor para o primeiro caractere diferente.
Nota 1 A função mudará seu histórico de pesquisa.
Nota 2 A parte que usa o padrão para fazer a pesquisa provavelmente poderia ser bastante aprimorada.
E como um bônus Adicione esta linha ao seu .vimrc
para criar um comando que agilizará a chamada da função:
command! -nargs=* CompLines call CompareLines(<f-args>)
Dessa forma, você pode usar de maneira simples :CompLines 1 2
para comparar duas linhas.
EDIT E aqui está uma versão aprimorada da função e do comando. A diferença é que você pode chamá-lo de três maneiras diferentes:
:CL
irá diferir a linha atual e a seguinte
:CL 23
irá diferir a linha atual e a linha 23
:CL 23 42
irá diferir as linhas 23 e 42
Aqui está o código:
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 Fiz um plugin . Você pode instalá-lo com um gerenciador de plugins comum com (por exemplo):
Plug 'statox/vim-compare-lines'