From e4d9685d577ef361d3ea073de129ceea98fb9194 Mon Sep 17 00:00:00 2001 From: Matěj Cepl Date: Thu, 5 Sep 2013 15:22:33 +0200 Subject: Add DiffSplitHunk function. Splits the hunk in which the cursor is making sure that all surrounding hunk headers are correct (i.e., adjusts the original hunk header). --- .../2734cfa4-242a-4b3a-8141-3251b444d3f3/body | 4 + .../2734cfa4-242a-4b3a-8141-3251b444d3f3/values | 29 +++ .../33c92587-7117-40d5-be4a-6241ce251d75/body | 5 + .../33c92587-7117-40d5-be4a-6241ce251d75/values | 29 +++ .../ca31d12d-ef83-4275-a364-7802b2ad35b0/values | 50 ++++ .be/737c1d14-cca7-4efd-be60-fca75b19ef73/settings | 1 + .be/version | 1 + .gitignore | 1 + ftplugin/diff_navigator.vim | 261 ++++++++++++++++----- test.patch | 110 +++++++++ 10 files changed, 430 insertions(+), 61 deletions(-) create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/body create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/values create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/body create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/values create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/values create mode 100644 .be/737c1d14-cca7-4efd-be60-fca75b19ef73/settings create mode 100644 .be/version create mode 100644 .gitignore create mode 100644 test.patch diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/body b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/body new file mode 100644 index 0000000..8a9959a --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/body @@ -0,0 +1,4 @@ +Something similar to what Emacs EDiff does. +Also it should be possible to use splitdiff? +(Although it is rather brutal ... we want one diff, +not messy temp files all around) diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/values b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/values new file mode 100644 index 0000000..3a56077 --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/2734cfa4-242a-4b3a-8141-3251b444d3f3/values @@ -0,0 +1,29 @@ +{ + + + + + + + "Author": "Mat\u011bj Cepl ", + + + + + + + "Content-type": "text/plain", + + + + + + + "Date": "Thu, 05 Sep 2013 13:06:37 +0000" + + + + + + +} diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/body b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/body new file mode 100644 index 0000000..eb57f47 --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/body @@ -0,0 +1,5 @@ +Splitdiff is a bad idea ... splits just on the level of files, not +hunks. + +For more information about the format, see +https://en.wikipedia.org/wiki/Diff#Unified_format diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/values b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/values new file mode 100644 index 0000000..5139834 --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/comments/33c92587-7117-40d5-be4a-6241ce251d75/values @@ -0,0 +1,29 @@ +{ + + + + + + + "Author": "Mat\u011bj Cepl ", + + + + + + + "Content-type": "text/plain", + + + + + + + "Date": "Thu, 05 Sep 2013 13:22:15 +0000" + + + + + + +} diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/values b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/values new file mode 100644 index 0000000..71bc97b --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/bugs/ca31d12d-ef83-4275-a364-7802b2ad35b0/values @@ -0,0 +1,50 @@ +{ + + + + + + + "creator": "Mat\u011bj Cepl ", + + + + + + + "reporter": "Mat\u011bj Cepl ", + + + + + + + "severity": "minor", + + + + + + + "status": "open", + + + + + + + "summary": "Split patch", + + + + + + + "time": "Thu, 05 Sep 2013 13:05:53 +0000" + + + + + + +} diff --git a/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/settings b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/settings new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.be/737c1d14-cca7-4efd-be60-fca75b19ef73/settings @@ -0,0 +1 @@ +{} diff --git a/.be/version b/.be/version new file mode 100644 index 0000000..38d39ae --- /dev/null +++ b/.be/version @@ -0,0 +1 @@ +Bugs Everywhere Directory v1.5 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..55292ee --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.be/id-cache diff --git a/ftplugin/diff_navigator.vim b/ftplugin/diff_navigator.vim index fa4f5b1..81eed48 100644 --- a/ftplugin/diff_navigator.vim +++ b/ftplugin/diff_navigator.vim @@ -23,84 +23,223 @@ " Only do this when not done yet for this buffer +" Usually, not needed, just for the keeping normal API if exists("b:did_ftplugin") finish endif let b:did_ftplugin = 1 -" Annotate each hunk with it's number and name of the changed file -if !exists("*s:DiffAnnotate") - function s:DiffAnnotate() - if !executable('filterdiff') - echohl WarningMsg - echo "You need to install filterdiff first (part of patchutils)" - echohl None - return - endif - let l:cursorpos = winsaveview() - %!filterdiff --annotate - call winrestview(cursorpos) - endfunction +" Load this plugin only once +if exists("g:loaded_diff_navigator") + finish endif +let g:loaded_diff_navigator = 1 + +function s:checkFilterDiff() + if !executable('filterdiff') + echohl WarningMsg + echo "You need to install filterdiff first (part of patchutils)" + echohl None + return 0 + endif + return 1 +endfunction + +" Given the linenumber of the hunk returned its parsed content +" +" From http://www.clearchain.com/blog/posts/splitting-a-patch +" ----------------------------------------------------------- +" +" here’s at least some info about the format of a patch file. +" +" @@ -143,6 +143,13 @@ +" +" the first number is the starting line for this hunk in oldfile +" the second number is the number of original source lines in this +" hunk (this includes lines marked with “-”) +" the third number is the starting line for this hunk in newfile +" the last number is the number of lines after the hunk has been applied. +function s:parseHunkHeader(lineno) + let inline = getline(a:lineno) + " Thanks for somian from #vim IRC channel for this incredible RE + let hunk_nos = substitute(inline, + \ '\_^\S\S\s\+-\(\d\+\),\(\d\+\)\s\++\(\d\+\),\(\d\+\)\s\+\S\S\(\_.*\)', + \ "\\1,\\2,\\3,\\4,\\5","") + let result = split(hunk_nos, ",") + + return { + \ 'line': a:lineno, + \ 'oldFirst': result[0], + \ 'oldCount': result[1], + \ 'newFirst': result[2], + \ 'newCount': result[3], + \ 'remainderLine': result[4] + \ } +endfunction + +" Get hunk header from the hunk surrounding cursor +function s:getCurrentHunkHeader() + if getline(".") =~ '^+++ \|^--- ' + let lineno = search('^@@[ +-\,\d]*@@.*$', 'ncW') + else + let lineno = search('^@@[ +-\,\d]*@@.*$', 'bncW') + endif + + return s:parseHunkHeader(lineno) +endfunction + +" Generate hunk header line +function s:createHunkHeader(oldStart, oldLen, newStart, newLen, remaind) + return "@@ -" . a:oldStart . "," . a:oldLen . + \ " +" . a:newStart . "," . a:newLen . " @@" . a:remaind +endfunction + +" Return number of lines in the range between start and end line (both +" inclusive) which are from the state before patch and the one after +" patch is applied. +function s:countLines(start, end) + let context_lines = 0 + let old_lines = 0 + let new_lines = 0 + + for line in getline(a:start, a:end) + let first_char = strpart(line, 0, 1) + if first_char == ' ' + context_lines += 1 + elseif first_char == '-' + old_lines += 1 + elseif first_char == '+' + new_lines += 1 + else + endif + endfor + + return [context_lines + old_lines, context_lines + new_lines] +endfunction + +" ------------------------------------------------------------- + +" Annotate each hunk with it's number and name of the changed file +function s:DiffAnnotate() + if s:checkFilterDiff() + let l:cursorpos = winsaveview() + %!filterdiff --annotate + call winrestview(cursorpos) + endif +endfunction " Print annotation of current hunk -if !exists("*s:DiffShowHunk") - function s:DiffShowHunk() - " if the current line begins with '+++' or '---', then it makes sense to search - " forwards - if getline(".") =~ '^+++ \|^--- ' - let l:lineno = search('^@@[ +-\,\d]*@@.*$', 'ncW') - else - let l:lineno = search('^@@[ +-\,\d]*@@.*$', 'bncW') - endif - if l:lineno == 0 - return - endif - let l:hunk_annotation = substitute(getline(lineno), '^@@[ +-\,\d]*@@\s*\(.*\)$', '\1', '') - echo l:hunk_annotation - endfunction -endif +function s:DiffShowHunk() + " if the current line begins with '+++' or '---', then it makes + " sense to search forwards + let hunk_header = s:getCurrentHunkHeader() + let l:hunk_annotation = substitute(getline(hunk_header['line']), + \ '^@@[ +-\,\d]*@@\s*\(.*\)$', '\1', '') + echo l:hunk_annotation +endfunction " Skip to next hunk -if !exists("*s:DiffNextHunk") - function s:DiffNextHunk() - call search('^@@[ +-\,\d]*@@', 'sW') - endfunction -endif +function s:DiffNextHunk() + call search('^@@[ +-\,\d]*@@', 'sW') +endfunction " Skip to previous hunk -if !exists("*s:DiffPrevHunk") - function s:DiffPrevHunk() - call search('^@@[ +-\,\d]*@@', 'bsW') - endfunction -endif +function s:DiffPrevHunk() + call search('^@@[ +-\,\d]*@@', 'bsW') +endfunction " Skip to next changed file -if !exists("*s:DiffNextFile") - function s:DiffNextFile() - call search('^--- ', 'sW') - endfunction -endif +function s:DiffNextFile() + call search('^--- ', 'sW') +endfunction -" Skip to previous changed file -if !exists("*s:DiffPrevFile") - function s:DiffPrevFile() - call search('^--- ', 'bsW') - endfunction -endif +" Skip to previous changed file +function s:DiffPrevFile() + call search('^--- ', 'bsW') +endfunction + +function s:DiffSplitHunk() + let old_cur_header = s:getCurrentHunkHeader() + let cur_line_no = line(".") + + " With this hunk: + " + " @@ -20,8 +20,17 @@ Hunk #1, a/tests/test_ec_curves.py + " + " import unittest + " #import sha + " -from M2Crypto import EC, Rand + " -from test_ecdsa import ECDSATestCase as ECDSATest + " +try: + " + from M2Crypto import EC, Rand +"-- " + from test_ecdsa import ECDSATestCase as ECDSATest + " +# AttributeError: 'module' object has no attribute 'ec_init' + " +#except AttributeError: + " +except: + " + EC_Module_Available = False + " + print("No EC modules available") + " +else: + " + EC_Module_Available = True + " + print("EC modules are available") + " + " creates above the line + " @@ -25,3 +25,12 @@ + " + " and the original hunk line is now + " @@ -20,5 +20,5 @@ Hunk #1, a/tests/test_ec_curves.py + " + " + " Start line below header and stop one line above the current line + let diff_lines = s:countLines(old_cur_header['line'] + 1, + \ cur_line_no - 1) + let diff_old = diff_lines[0] + let diff_new = diff_lines[1] + + " IN THE NEW START HUNK HEADER + " 1. length is number of lines above the current position which + " are either context or deleted lines (-) + " 2. length is number of lines above the current position which + " are either context or added lines (+) + " Start positions are same as well the stuff after the second @@ + let new_start_del_start = old_cur_header['oldFirst'] + let new_start_del_len = diff_old + let new_start_add_start = old_cur_header['newFirst'] + let new_start_add_len = diff_new + let @x = s:createHunkHeader(new_start_del_start, new_start_del_len, + \ new_start_add_start, new_start_add_len, + \ old_cur_header['remainderLine']) + let window_state = winsaveview() + " write the new original header line + setpos(".", old_cur_header['line']) + normal ^d$"xp + winrestview(window_state) -command! -buffer DiffAnnotate call s:DiffAnnotate() -command! -buffer DiffShowHunk call s:DiffShowHunk() -command! -buffer DiffNextHunk call s:DiffNextHunk() -command! -buffer DiffPrevHunk call s:DiffPrevHunk() -command! -buffer DiffNextFile call s:DiffNextFile() -command! -buffer DiffPrevFile call s:DiffPrevFile() + " IN THE NEW HUNK HEADER + " new lengths = original len - new len + " new starts = original start + (difference) + let new_pos_del_start = old_cur_header['oldFirst'] + diff_old + let new_pos_del_len = old_cur_header['oldCount'] - diff_old + let new_pos_add_start = old_cur_header['newFirst'] + diff_new + let new_pos_add_len = old_cur_header['newCount'] - diff_new + let @x = s:createHunkHeader(new_pos_del_start, new_pos_del_len, + \ new_pos_add_start, new_pos_add_len, "") + execute "normal! O\\"xP" + +endfunction + +" Define new commands +command DiffAnnotate call s:DiffAnnotate() +command DiffShowHunk call s:DiffShowHunk() +command DiffNextHunk call s:DiffNextHunk() +command DiffPrevHunk call s:DiffPrevHunk() +command DiffNextFile call s:DiffNextFile() +command DiffPrevFile call s:DiffPrevFile() " Default },{,(,) do not make much sense in diffs, so remap them to " make something useful -nnoremap } :DiffNextFile -nnoremap { :DiffPrevFile -nnoremap ) :DiffNextHunk -nnoremap ( :DiffPrevHunk - +nnoremap