vimdiff: passa alla differenza successiva nella riga?


35

vimdiffè molto utile per confrontare i file. Tuttavia, lo uso spesso su file con linee lunghe e relativamente poche differenze all'interno delle linee.

vimdiff evidenzierà correttamente le differenze all'interno di una linea (linea intera rosa, caratteri diversi in rosso). In questi casi, sarebbe bello poter passare alla differenza successiva all'interno della linea .

Puoi saltare alla "differenza successiva" ( ]c), ma questo salterà alla riga successiva con una differenza.

C'è un modo per passare al prossimo personaggio diverso all'interno della riga corrente?

Risposte:


8

Vedo due soluzioni:

  1. dovresti testare l'evidenziazione della sintassi corrente per saltare alla parte rossa nella linea.
  2. dovresti estrarre la linea corrente in entrambi i buffer e trovare il primo carattere che differisce per posizionare correttamente il cursore

Entrambe le soluzioni devono essere eseguite dopo la] c e richiedono lo scripting vim.

EDIT: ecco una prima bozza che sembra funzionare:

nnoremap <expr> <silent> <F3>   (&diff ? "]c:call \<sid>NextDiff()\<cr>" : ":cn\<cr>")

function! s:GotoWinline(w_l)
  normal! H
  while winline() < a:w_l
    normal! j
  endwhile
  " todo: beware of cases where the window is too little
endfunction

" Better ]c, [c jump
function! s:NextDiff()
  if ! &diffopt =~ 'filler' | return | endif

  let ignore_blanks = &diffopt =~ 'iwhite'

  " Assert: called just after a ]c or a [c
  " Forces the cursos to be synchronized in all synced windows
  " let diff_l = line()
  try 
    let foldenable = &foldenable
    set nofoldenable

    let w_l = winline() " problematic with enabled lines (from diff...)
    " echomsg w_l.'|'.line('.').'|'.getline('.')

    let lines = {}
    windo if &diff | call <sid>GotoWinline(w_l) | let lines[winnr()]={'text':getline('.'), 'number':line('.')} | endif
  finally
    let &foldenable = foldenable
  endtry

  " echomsg string(lines)
  if len(lines) < 2 | return | endif

  let indices = repeat([0], len(lines))
  let tLines = values(lines)
  let found = 0
  " infinite loop on two empty texts...
  while ! found
    let c = ''
    let next_idx = []
    let i = 0
    while i != len(indices)
      let crt_line = tLines[i].text
      let n = indices[i]
      if len(crt_line) == n
    let found = 1
    break
      endif

      let c2 = (len(crt_line) == n) ? 'EOL' : crt_line[n]
      if empty(c) 
    let c = c2
      endif

      " checks match
      let n += 1
      if c =~ '\s'
    if (c2 != c) && (ignore_blanks && c2 !~ '\s')
      let found = 1
      break
    else " advance
      while ignore_blanks && (n == len(crt_line) || crt_line[n] =~ '\s')
        let n += 1
      endwhile
    endif
      else
    if c2 != c
      let found = 1
      break
    endif
      endif
      let next_idx += [n]

      let i += 1
    endwhile
    if found | break | endif

    let indices = next_idx
  endwhile

  " now goto the right column
  let windows = keys(lines)
  " Assert len(windows) == len(indices)
  let w = 0
  while w != len(windows)
    " echomsg 'W#'.windows[w].' -> :'(tLines[w].number).'normal! '.(indices[w]+1).'|'
    exe windows[w].'wincmd w'
    silent! exe (tLines[w].number).'normal! 0'.(indices[w]).'l'
    let w += 1
  endwhile
  " echomsg string(indices)
endfunction

Ho rinunciato a questo, poiché sembra che non ci sia un modo semplice per realizzarlo. Dal momento che la tua risposta sembra fare quello che volevo, la accetterò come ringraziamento.
sleske,

2
Da allora, ho inserito il codice in questo script code.google.com/p/lh-vim/source/browse/misc/trunk/plugin/… (che fa alcune altre cose) e, sfortunatamente, ho osservato un ciclo infinito che si verifica di volta in volta. Alla fine lo risolverò.
Luc Hermitte,

12

Questa è una soluzione semplice:

È possibile utilizzare set wrap.

Ciò creerà problemi se la differenza provoca il ritorno a capo del testo in un numero diseguale di righe.


1
Veloce e sporco, ma ha fatto il lavoro per me.
Mobius,

2

Non riesco a capire come farlo con vimdiffentrambi, ma potresti dare un'occhiata wdiffinvece. Mostra le differenze tra due file una parola alla volta.

Ho dovuto compilarlo dalla fonte:

curl http://ftp.gnu.org/gnu/wdiff/wdiff-1.2.1.tar.gz > wdiff-1.2.1.tar.gz
tar -xzvf wdiff-1.2.1.tar.gz
cd wdiff-1.2.1
./configure
make
make install

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.