vimdiff: Lompat ke perbedaan berikutnya di dalam baris?

35

vimdiffsangat berguna untuk membandingkan file. Namun, saya sering menggunakannya pada file dengan garis panjang dan perbedaan yang relatif sedikit di dalam garis.

vimdiff akan menyoroti perbedaan di dalam garis dengan benar (seluruh garis merah muda, karakter yang berbeda merah). Dalam kasus ini, alangkah baiknya untuk dapat melompat ke perbedaan berikutnya di dalam garis .

Anda dapat melompat ke "perbedaan berikutnya" ( ]c), tetapi ini akan melompat ke baris berikutnya dengan perbedaan.

Apakah ada cara untuk pergi ke karakter berbeda berikutnya di dalam baris saat ini?

sleske
sumber

Jawaban:

8

Saya melihat dua solusi:

  1. Anda harus menguji penyorotan sintaks saat ini untuk melompat ke bagian merah di baris.
  2. Anda harus mengekstrak baris saat ini di kedua buffer dan menemukan karakter pertama yang berbeda untuk memposisikan kursor dengan benar

Kedua solusi perlu dijalankan setelah] c, dan memerlukan skrip vim.

EDIT: Ini adalah konsep pertama yang sepertinya berfungsi:

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
sumber
Saya sudah menyerah pada ini, karena sepertinya tidak ada cara mudah untuk mencapainya. Karena jawaban Anda tampaknya melakukan apa yang saya inginkan, saya akan menerimanya sebagai ucapan terima kasih.
sleske
2
Sejak itu, saya memasukkan kode ini ke dalam kode skrip ini.google.com/p/lh-vim/source/browse/misc/trunk/plugin/… (yang melakukan beberapa hal lainnya), dan sayangnya, saya sudah mengamati loop tak terbatas yang terjadi dari waktu ke waktu. Saya akhirnya akan memperbaikinya.
Luc Hermitte
12

Ini adalah solusi yang mudah:

Anda bisa menggunakannya set wrap.

Ini akan menimbulkan masalah jika perbedaan tersebut menyebabkan teks untuk membungkus dalam jumlah baris yang tidak sama.

Parag Jain
sumber
1
Cepat dan kotor, tetapi itu berhasil bagi saya.
Mobius
2

Saya tidak tahu bagaimana melakukan ini dengan vimdiffbaik, tetapi Anda mungkin memeriksa wdiff. Ini menunjukkan perbedaan antara dua file satu kata pada suatu waktu.

Saya harus mengkompilasinya dari sumber:

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
sumber
1

Menilai dari dokumentasi, itu tidak bisa dilakukan.

Nathan Fellman
sumber
2
Menarik. Di mana Anda menemukan ini di dokumen? Saya tidak dapat menemukan apa pun di sana.
sleske
1
Di Vim saya mengetik::help vimdiff
Nathan Fellman