Skip to content

Commit

Permalink
Fix diff for deleted lines at end of buffer
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
natebosch committed Jan 17, 2018
1 parent 2a5fbe2 commit 83332ee
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 19 deletions.
33 changes: 14 additions & 19 deletions autoload/lsc/diff.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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}},
Expand All @@ -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]
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
7 changes: 7 additions & 0 deletions test/diff_test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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',
Expand Down

0 comments on commit 83332ee

Please sign in to comment.