vimdiff: ข้ามไปยังส่วนต่างภายในของบรรทัดหรือไม่


35

vimdiffมีประโยชน์มากสำหรับการเปรียบเทียบไฟล์ อย่างไรก็ตามฉันมักจะใช้กับไฟล์ที่มีเส้นยาวและมีความแตกต่างกันเล็กน้อย

vimdiff จะเน้นความแตกต่างภายในเส้นอย่างถูกต้อง (สีชมพูทั้งเส้น, ตัวอักษรที่แตกต่างกันสีแดง) ในกรณีนี้มันจะดีที่จะสามารถที่จะข้ามไปยังความแตกต่างต่อไปภายในสาย

คุณสามารถข้ามไปที่ "ความแตกต่างต่อไป" ( ]c) แต่สิ่งนี้จะข้ามไปที่บรรทัดถัดไปด้วยความแตกต่าง

มีวิธีที่จะไปที่ตัวละครที่แตกต่างกันต่อไปภายในบรรทัดปัจจุบันหรือไม่?

คำตอบ:


8

ฉันเห็นวิธีแก้ไขปัญหาสองข้อ:

  1. คุณจะต้องทดสอบไวยากรณ์ปัจจุบันที่เน้นเพื่อข้ามไปยังส่วนสีแดงในบรรทัด
  2. คุณจะต้องแยกบรรทัดปัจจุบันในบัฟเฟอร์ทั้งสองและค้นหาอักขระตัวแรกที่แตกต่างเพื่อวางเคอร์เซอร์อย่างถูกต้อง

โซลูชันทั้งสองจะต้องถูกเรียกใช้หลังจาก] c และต้องการ vim scripting

แก้ไข: นี่คือร่างแรกที่ดูเหมือนว่าจะทำงาน:

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

ฉันยอมแพ้กับสิ่งนี้เพราะดูเหมือนว่าจะไม่มีวิธีง่ายๆในการทำให้สำเร็จ เนื่องจากคำตอบของคุณดูเหมือนจะทำในสิ่งที่ฉันต้องการฉันจะยอมรับมันเป็นคำขอบคุณ
sleske

2
ตั้งแต่นั้นมาฉันใส่รหัสลงในสคริปต์นี้code.google.com/p/lh-vim/source/browse/misc/trunk/plugin/ … (นั่นทำสิ่งอื่น ๆ ไม่กี่อย่าง) และน่าเสียดายที่ฉัน สังเกตวงวนอนันต์ที่เกิดขึ้นเป็นครั้งคราว ในที่สุดฉันจะแก้ไขมัน
Luc Hermitte

12

นี่เป็นวิธีแก้ปัญหาง่ายๆ:

set wrapคุณสามารถใช้

สิ่งนี้จะสร้างปัญหาหากความแตกต่างทำให้ข้อความตัดในจำนวนบรรทัดที่ไม่เท่ากัน


1
รวดเร็วและสกปรก แต่มันก็ทำงานให้ฉันได้
Mobius

2

ฉันไม่สามารถหาวิธีการทำเช่นนี้vimdiffได้ แต่คุณอาจลองwdiffใช้แทน มันแสดงความแตกต่างระหว่างสองไฟล์ทีละคำ

ฉันต้องรวบรวมจากแหล่งที่มา:

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

ตัดสินโดยเอกสารมันไม่สามารถทำได้


2
น่าสนใจ คุณพบสิ่งนี้ได้ที่ไหนในเอกสาร ฉันไม่พบสิ่งใดที่นั่น
sleske

1
ในกลุ่มฉันพิมพ์::help vimdiff
Nathan Fellman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.