vimdiff: Passer à la différence suivante à l'intérieur de la ligne?

35

vimdiffest très pratique pour comparer des fichiers. Cependant, je l'utilise souvent sur des fichiers avec de longues lignes et relativement peu de différences à l'intérieur des lignes.

vimdiff mettra correctement en évidence les différences à l’intérieur d’une ligne (ligne entière en rose, caractères différents en rouge). Dans ces cas, il serait intéressant de pouvoir passer à la différence suivante dans la ligne .

Vous pouvez sauter à la "différence suivante" ( ]c), mais cela passera à la ligne suivante avec une différence.

Est-il possible d'aller au prochain caractère différent dans la ligne en cours?

sleske
la source

Réponses:

8

Je vois deux solutions:

  1. vous devez tester la coloration syntaxique actuelle pour passer à la partie rouge de la ligne.
  2. vous devrez extraire la ligne en cours dans les deux tampons et trouver le premier caractère différent pour positionner correctement le curseur

Les deux solutions doivent être exécutées après le] c et nécessitent l'utilisation de scripts vim.

EDIT: Voici un premier projet qui semble fonctionner:

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
Luc Hermitte
la source
J'ai abandonné cela, car il semble qu'il n'y ait pas de moyen facile d'y parvenir. Puisque ta réponse semble faire ce que je voulais, je l’accepterai comme remerciement.
Sleske
2
Depuis lors, j'ai inséré le code dans ce script code.google.com/p/lh-vim/source/browse/misc/trunk/plugin/… (cela fait quelques autres choses), et malheureusement, j'ai observé une boucle infinie qui se produit de temps en temps. Je vais éventuellement le réparer.
Luc Hermitte
12

Ceci est une solution de contournement facile:

Vous pouvez utiliser set wrap.

Cela créera des problèmes si la différence entraîne le texte dans un nombre inégal de lignes.

Parag Jain
la source
1
Rapide et sale, mais cela a fait le travail pour moi.
Mobius
2

Je ne peux pas comprendre comment faire cela avec l'un vimdiffou l'autre, mais vous pouvez vérifier à la wdiffplace. Il montre les différences entre deux fichiers, un mot à la fois.

Je devais le compiler à partir de la source:

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
David Winiecki
la source
1

À en juger par la documentation, cela ne peut être fait.

Nathan Fellman
la source
2
Intéressant. Où l'avez-vous trouvé dans la documentation? Je n'ai rien trouvé là-bas.
Sleske
1
Dans Vim, j'ai tapé::help vimdiff
Nathan Fellman