From 89c34f74cbbe470201dce0e80e15686b80a2ac18 Mon Sep 17 00:00:00 2001 From: Andy Stewart Date: Thu, 18 Oct 2018 09:45:55 +0100 Subject: [PATCH] Display unambiguous sign when hunks overlap. See #556. --- autoload/gitgutter/highlight.vim | 6 ++++++ autoload/gitgutter/hunk.vim | 3 +++ autoload/gitgutter/sign.vim | 13 ++++++++++++- plugin/gitgutter.vim | 1 + test/test_gitgutter.vim | 10 ++++++++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/autoload/gitgutter/highlight.vim b/autoload/gitgutter/highlight.vim index 3fa4a91..71f177c 100644 --- a/autoload/gitgutter/highlight.vim +++ b/autoload/gitgutter/highlight.vim @@ -73,6 +73,7 @@ function! gitgutter#highlight#define_signs() abort sign define GitGutterLineModified sign define GitGutterLineRemoved sign define GitGutterLineRemovedFirstLine + sign define GitGutterLineRemovedAboveAndBelow sign define GitGutterLineModifiedRemoved sign define GitGutterDummy @@ -86,6 +87,7 @@ function! s:define_sign_text() abort execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed execute "sign define GitGutterLineRemovedFirstLine text=" . g:gitgutter_sign_removed_first_line + execute "sign define GitGutterLineRemovedAboveAndBelow text=" . g:gitgutter_sign_removed_above_and_below execute "sign define GitGutterLineModifiedRemoved text=" . g:gitgutter_sign_modified_removed endfunction @@ -99,12 +101,14 @@ function! gitgutter#highlight#define_sign_text_highlights() abort sign define GitGutterLineModified texthl=GitGutterChange sign define GitGutterLineRemoved texthl=GitGutterDelete sign define GitGutterLineRemovedFirstLine texthl=GitGutterDelete + sign define GitGutterLineRemovedAboveAndBelow texthl=GitGutterDelete sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDelete else sign define GitGutterLineAdded texthl=GitGutterAddInvisible sign define GitGutterLineModified texthl=GitGutterChangeInvisible sign define GitGutterLineRemoved texthl=GitGutterDeleteInvisible sign define GitGutterLineRemovedFirstLine texthl=GitGutterDeleteInvisible + sign define GitGutterLineRemovedAboveAndBelow texthl=GitGutterDeleteInvisible sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDeleteInvisible endif endfunction @@ -115,12 +119,14 @@ function! s:define_sign_line_highlights() abort sign define GitGutterLineModified linehl=GitGutterChangeLine sign define GitGutterLineRemoved linehl=GitGutterDeleteLine sign define GitGutterLineRemovedFirstLine linehl=GitGutterDeleteLine + sign define GitGutterLineRemovedAboveAndBelow linehl=GitGutterDeleteLine sign define GitGutterLineModifiedRemoved linehl=GitGutterChangeDeleteLine else sign define GitGutterLineAdded linehl= sign define GitGutterLineModified linehl= sign define GitGutterLineRemoved linehl= sign define GitGutterLineRemovedFirstLine linehl= + sign define GitGutterLineRemovedAboveAndBelow linehl= sign define GitGutterLineModifiedRemoved linehl= endif endfunction diff --git a/autoload/gitgutter/hunk.vim b/autoload/gitgutter/hunk.vim index 4da3bb9..c779b59 100644 --- a/autoload/gitgutter/hunk.vim +++ b/autoload/gitgutter/hunk.vim @@ -93,6 +93,9 @@ function! s:current_hunk() abort return current_hunk endfunction +" A line can be in 0 or 1 hunks, with the following exception: when the first +" line(s) of a file has been deleted, and the new second line (and +" optionally below) has been deleted, the new first line is in two hunks. function! gitgutter#hunk#cursor_in_hunk(hunk) abort let current_line = line('.') diff --git a/autoload/gitgutter/sign.vim b/autoload/gitgutter/sign.vim index b65563d..8c14859 100644 --- a/autoload/gitgutter/sign.vim +++ b/autoload/gitgutter/sign.vim @@ -170,7 +170,16 @@ function! s:upsert_new_gitgutter_signs(bufnr, modified_lines) abort let other_signs = gitgutter#utility#getbufvar(a:bufnr, 'other_signs') let old_gitgutter_signs = gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs') - for line in a:modified_lines + " Handle special case where the first line is the site of two hunks: + " lines deleted above at the start of the file, and lines deleted below from + " the (new) second line down. + if a:modified_lines[0:1] == [[1, 'removed_first_line'], [1, 'removed']] + let modified_lines = [[1, 'removed_above_and_below'] + a:modified_lines[2:]] + else + let modified_lines = a:modified_lines + endif + + for line in modified_lines let line_number = line[0] " if index(other_signs, line_number) == -1 " don't clobber others' signs let name = s:highlight_name_for_change(line[1]) @@ -213,6 +222,8 @@ function! s:highlight_name_for_change(text) abort return 'GitGutterLineModified' elseif a:text ==# 'modified_removed' return 'GitGutterLineModifiedRemoved' + elseif a:text ==# 'removed_above_and_below' + return 'GitGutterLineRemovedAboveAndBelow' endif endfunction diff --git a/plugin/gitgutter.vim b/plugin/gitgutter.vim index 1759771..3a68689 100644 --- a/plugin/gitgutter.vim +++ b/plugin/gitgutter.vim @@ -44,6 +44,7 @@ else call s:set('g:gitgutter_sign_removed_first_line', '_^') endif +call s:set('g:gitgutter_sign_removed_above_and_below', '[') call s:set('g:gitgutter_sign_modified_removed', '~_') call s:set('g:gitgutter_git_args', '') call s:set('g:gitgutter_diff_args', '') diff --git a/test/test_gitgutter.vim b/test/test_gitgutter.vim index 98b4220..96a2d2c 100644 --- a/test/test_gitgutter.vim +++ b/test/test_gitgutter.vim @@ -117,6 +117,16 @@ function Test_remove_first_lines() endfunction +function Test_overlapping_hunks() + execute '3d' + execute '1d' + call s:trigger_gitgutter() + + let expected = ["line=1 id=3000 name=GitGutterLineRemovedAboveAndBelow"] + call assert_equal(expected, s:signs('fixture.txt')) +endfunction + + function Test_edit_file_with_same_name_as_a_branch() normal 5Gi* call system('git checkout -b fixture.txt')