vimdiff: Zum nächsten Unterschied innerhalb der Zeile springen?


35

vimdiffist sehr praktisch zum Vergleichen von Dateien. Ich verwende es jedoch oft für Dateien mit langen Zeilen und relativ wenigen Unterschieden innerhalb der Zeilen.

vimdiff hebt Unterschiede innerhalb einer Zeile korrekt hervor (ganze Zeile pink, unterschiedliche Zeichen rot). In diesen Fällen wäre es schön, zum nächsten Unterschied innerhalb der Zeile springen zu können .

Sie können zum "nächsten Unterschied" ( ]c) springen, dies springt jedoch mit einem Unterschied zur nächsten Zeile.

Gibt es eine Möglichkeit, zum nächsten anderen Zeichen in der aktuellen Zeile zu wechseln?

Antworten:


8

Ich sehe zwei Lösungen:

  1. Sie müssten die aktuelle Syntaxhervorhebung testen, um zum roten Teil in der Zeile zu springen.
  2. Sie müssten die aktuelle Zeile in beiden Puffern extrahieren und das erste Zeichen finden, das sich unterscheidet, um den Cursor richtig zu positionieren

Beide Lösungen müssen nach dem] c ausgeführt werden und erfordern vim-Scripting.

EDIT: Hier ist ein erster Entwurf, der zu funktionieren scheint:

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

Ich habe dies aufgegeben, da es anscheinend keinen einfachen Weg gibt, dies zu erreichen. Da Ihre Antwort zu tun scheint, was ich wollte, nehme ich sie als Dank an.
Sleske

2
Seitdem habe ich den Code in dieses Skript eingefügt. Code.google.com/p/lh-vim/source/browse/misc/trunk/plugin/… (das macht ein paar andere Dinge), und das habe ich leider auch beobachtete eine Endlosschleife, die von Zeit zu Zeit auftritt. Ich werde es irgendwann reparieren.
Luc Hermitte

12

Dies ist eine einfache Problemumgehung:

Sie können verwenden set wrap.

Dies führt zu Problemen, wenn der Unterschied dazu führt, dass der Text ungleichmäßig viele Zeilen enthält.


1
Schnell und dreckig, aber es hat die Arbeit für mich erledigt.
Möbius

2

Ich kann auch nicht herausfinden, wie ich das machen soll vimdiff, aber vielleicht checkst du wdiffstattdessen aus. Es werden die Unterschiede zwischen zwei Dateien jeweils wortweise angezeigt.

Ich musste es aus dem Quellcode kompilieren:

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

1

Gemessen an der Dokumentation ist dies nicht möglich.


2
Interessant. Wo haben Sie das in den Dokumenten gefunden? Ich konnte dort nichts finden.
sleske

1
In Vim tippte ich::help vimdiff
Nathan Fellman
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.