From 83332ee8dfc3aa331ccb7f5fd4a898acdc6d1d3d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 17 Jan 2018 14:04:33 -0800 Subject: [PATCH] Fix diff for deleted lines at end of buffer No long assumes that the old buffer content was the shorter one when there were different number of lines - fixes the case where we run past the `line_count`. Remove some branches that are not reachable. --- autoload/lsc/diff.vim | 33 ++++++++++++++------------------- test/diff_test.vim | 7 +++++++ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/autoload/lsc/diff.vim b/autoload/lsc/diff.vim index f6cd3b21..574ff0c3 100644 --- a/autoload/lsc/diff.vim +++ b/autoload/lsc/diff.vim @@ -6,27 +6,14 @@ " Finds a single change between the common prefix, and common postfix. function! lsc#diff#compute(old, new) abort let [start_line, start_char] = s:FirstDifference(a:old, a:new) - if len(a:old) <= start_line && strlen(a:old[-1]) <= start_char - let start_line = len(a:old) - let end_line = 0 - let end_char = 0 - else - let [end_line, end_char] = - \ s:LastDifference(a:old[start_line:], a:new[start_line:], start_char) - endif + let [end_line, end_char] = + \ s:LastDifference(a:old[start_line:], a:new[start_line:], start_char) let text = s:ExtractText(a:new, start_line, start_char, end_line, end_char) let length = s:Length(a:old, start_line, start_char, end_line, end_char) let adj_end_line = len(a:old) + end_line - let adj_end_char = strlen(a:old[end_line]) + end_char - " End is exclusive - if end_char == 1 - let adj_end_line += 1 - let adj_end_char = 0 - else - let adj_end_char += 1 - endif + let adj_end_char = end_line == 0 ? 0 : strlen(a:old[end_line]) + end_char + 1 let result = { 'range': {'start': {'line': start_line, 'character': start_char}, \ 'end': {'line': adj_end_line, 'character': adj_end_char}}, @@ -47,7 +34,7 @@ function! s:FirstDifference(old, new) abort let i += 1 endwhile if i >= line_count - return [len(a:old) - 1, strlen(a:old[-1])] + return [line_count - 1, strlen(a:old[line_count - 1])] endif let old_line = a:old[i] let new_line = a:new[i] @@ -62,6 +49,7 @@ endfunction function! s:LastDifference(old, new, start_char) abort let line_count = min([len(a:old), len(a:new)]) + if line_count == 0 | return [0, 0] | endif let i = -1 while i >= -1 * line_count if a:old[i] !=# a:new[i] | break | endif @@ -86,6 +74,7 @@ endfunction function! s:ExtractText(lines, start_line, start_char, end_line, end_char) abort if a:start_line == len(a:lines) + a:end_line + if a:end_line == 0 | return '' | endif let result = a:lines[a:start_line][a:start_char:a:end_char] " json_encode treats empty string computed this was as 'null' if strlen(result) == 0 | let result = '' | endif @@ -96,14 +85,20 @@ function! s:ExtractText(lines, start_line, start_char, end_line, end_char) abort for line in a:lines[a:start_line + 1:a:end_line - 1] let result .= line."\n" endfor - let result .= a:lines[a:end_line][:a:end_char] + if a:end_line != 0 + let result .= a:lines[a:end_line][:a:end_char] + endif return result endfunction function! s:Length(lines, start_line, start_char, end_line, end_char) \ abort let adj_end_line = len(a:lines) + a:end_line - let adj_end_char = strlen(a:lines[adj_end_line]) + a:end_char + if adj_end_line >= len(a:lines) + let adj_end_char = a:end_char - 1 + else + let adj_end_char = strlen(a:lines[adj_end_line]) + a:end_char + endif if a:start_line == adj_end_line return adj_end_char - a:start_char + 1 endif diff --git a/test/diff_test.vim b/test/diff_test.vim index cd7b9a0e..6709666b 100644 --- a/test/diff_test.vim +++ b/test/diff_test.vim @@ -55,6 +55,7 @@ function! TestDiff() abort \ ) " Line inserted at end + " It's important this appears to *prefix* the newline call s:TestDiff( \ [2,3,2,3], 0, "\nanother", \ "foo\nbar\nbaz", @@ -146,6 +147,12 @@ function! TestDiff() abort \ "foo\nbar\nbaz", \ "foo\nbar\nba") + " Delete lines at end + call s:TestDiff( + \ [0, 3, 2, 3], 8, '', + \ "foo\nbar\nbaz", + \ "foo") + " Handles multiple blank lines call s:TestDiff( \ [5,1,5,2], 1, 'x',