2013-09-30 04:19:31 -04:00
|
|
|
|
" vim: et sw=2 sts=2
|
|
|
|
|
|
2013-08-19 11:36:16 -04:00
|
|
|
|
scriptencoding utf-8
|
|
|
|
|
|
2013-12-05 19:51:33 -05:00
|
|
|
|
" Init: values {{{1
|
2016-09-28 11:05:40 -04:00
|
|
|
|
if get(g:, 'signify_sign_show_text', 1)
|
|
|
|
|
let s:sign_delete = get(g:, 'signify_sign_delete', '_')
|
|
|
|
|
let s:sign_show_count = get(g:, 'signify_sign_show_count', 1)
|
|
|
|
|
else
|
|
|
|
|
let s:sign_delete = ' '
|
|
|
|
|
let s:sign_show_count = 0
|
|
|
|
|
endif
|
2014-10-07 06:49:41 -04:00
|
|
|
|
let s:delete_highlight = ['', 'SignifyLineDelete']
|
2013-12-05 19:51:33 -05:00
|
|
|
|
|
2017-01-18 10:28:35 -05:00
|
|
|
|
" Function: #id_next {{{1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
function! sy#sign#id_next(sy) abort
|
|
|
|
|
let id = a:sy.signid
|
|
|
|
|
let a:sy.signid += 1
|
2017-01-18 10:28:35 -05:00
|
|
|
|
return id
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
" Function: #get_current_signs {{{1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
function! sy#sign#get_current_signs(sy) abort
|
|
|
|
|
let a:sy.internal = {}
|
|
|
|
|
let a:sy.external = {}
|
2013-09-06 10:22:09 -04:00
|
|
|
|
|
2013-07-17 06:30:58 -04:00
|
|
|
|
redir => signlist
|
2017-01-30 08:50:32 -05:00
|
|
|
|
silent! execute 'sign place buffer='. a:sy.buffer
|
2013-07-17 06:30:58 -04:00
|
|
|
|
redir END
|
|
|
|
|
|
2014-10-04 09:55:49 -04:00
|
|
|
|
for signline in split(signlist, '\n')[2:]
|
2016-12-15 08:13:53 -05:00
|
|
|
|
let tokens = matchlist(signline, '\v^\s+\S+\=(\d+)\s+\S+\=(\d+)\s+\S+\=(.*)$')
|
2014-10-04 09:55:49 -04:00
|
|
|
|
let line = str2nr(tokens[1])
|
|
|
|
|
let id = str2nr(tokens[2])
|
|
|
|
|
let type = tokens[3]
|
|
|
|
|
|
|
|
|
|
if type =~# '^Signify'
|
|
|
|
|
" Handle ambiguous signs. Assume you have signs on line 3 and 4.
|
|
|
|
|
" Removing line 3 would lead to the second sign to be shifted up
|
|
|
|
|
" to line 3. Now there are still 2 signs, both one line 3.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if has_key(a:sy.internal, line)
|
|
|
|
|
execute 'sign unplace' a:sy.internal[line].id 'buffer='.a:sy.buffer
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let a:sy.internal[line] = { 'type': type, 'id': id }
|
2014-10-04 09:55:49 -04:00
|
|
|
|
else
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let a:sy.external[line] = id
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
|
|
|
|
endfor
|
|
|
|
|
endfunction
|
2013-12-06 16:43:51 -05:00
|
|
|
|
|
|
|
|
|
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" Function: #process_diff {{{1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
function! sy#sign#process_diff(sy, diff) abort
|
|
|
|
|
let a:sy.signtable = {}
|
|
|
|
|
let a:sy.hunks = []
|
2014-10-04 09:55:49 -04:00
|
|
|
|
let [added, modified, deleted] = [0, 0, 0]
|
|
|
|
|
|
2017-01-30 08:50:32 -05:00
|
|
|
|
call sy#sign#get_current_signs(a:sy)
|
2014-10-04 09:55:49 -04:00
|
|
|
|
|
|
|
|
|
" Determine where we have to put our signs.
|
2017-01-17 17:12:00 -05:00
|
|
|
|
for line in filter(a:diff, 'v:val =~ "^@@ "')
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let a:sy.lines = []
|
2014-10-04 09:55:49 -04:00
|
|
|
|
let ids = []
|
|
|
|
|
|
|
|
|
|
let tokens = matchlist(line, '^@@ -\v(\d+),?(\d*) \+(\d+),?(\d*)')
|
|
|
|
|
|
|
|
|
|
let old_line = str2nr(tokens[1])
|
|
|
|
|
let new_line = str2nr(tokens[3])
|
|
|
|
|
|
|
|
|
|
let old_count = empty(tokens[2]) ? 1 : str2nr(tokens[2])
|
|
|
|
|
let new_count = empty(tokens[4]) ? 1 : str2nr(tokens[4])
|
|
|
|
|
|
|
|
|
|
" 2 lines added:
|
|
|
|
|
|
|
|
|
|
" @@ -5,0 +6,2 @@ this is line 5
|
|
|
|
|
" +this is line 5
|
|
|
|
|
" +this is line 5
|
|
|
|
|
if (old_count == 0) && (new_count >= 1)
|
|
|
|
|
let added += new_count
|
|
|
|
|
let offset = 0
|
|
|
|
|
while offset < new_count
|
|
|
|
|
let line = new_line + offset
|
|
|
|
|
let offset += 1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, 'SignifyAdd'))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endwhile
|
|
|
|
|
|
|
|
|
|
" 2 lines removed:
|
|
|
|
|
|
|
|
|
|
" @@ -6,2 +5,0 @@ this is line 5
|
|
|
|
|
" -this is line 6
|
|
|
|
|
" -this is line 7
|
|
|
|
|
elseif (old_count >= 1) && (new_count == 0)
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, new_line) | continue | endif
|
2014-10-04 09:55:49 -04:00
|
|
|
|
let deleted += old_count
|
|
|
|
|
if new_line == 0
|
2017-01-30 08:50:32 -05:00
|
|
|
|
call add(ids, s:add_sign(a:sy, 1, 'SignifyRemoveFirstLine'))
|
2014-10-07 06:49:41 -04:00
|
|
|
|
elseif s:sign_show_count
|
2014-10-04 13:35:51 -04:00
|
|
|
|
if old_count <= 99
|
|
|
|
|
let text = substitute(s:sign_delete . old_count, '.*\ze..$', '', '')
|
|
|
|
|
else
|
|
|
|
|
let text = s:sign_delete .'>'
|
|
|
|
|
endif
|
2017-01-30 08:50:32 -05:00
|
|
|
|
call add(ids, s:add_sign(a:sy, new_line, 'SignifyDelete'. old_count, text))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
else
|
2017-01-30 08:50:32 -05:00
|
|
|
|
call add(ids, s:add_sign(a:sy, new_line, 'SignifyDeleteMore', s:sign_delete))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
" 2 lines changed:
|
|
|
|
|
|
|
|
|
|
" @@ -5,2 +5,2 @@ this is line 4
|
|
|
|
|
" -this is line 5
|
|
|
|
|
" -this is line 6
|
|
|
|
|
" +this os line 5
|
|
|
|
|
" +this os line 6
|
|
|
|
|
elseif old_count == new_count
|
|
|
|
|
let modified += old_count
|
|
|
|
|
let offset = 0
|
|
|
|
|
while offset < new_count
|
|
|
|
|
let line = new_line + offset
|
|
|
|
|
let offset += 1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, 'SignifyChange'))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endwhile
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
" 2 lines changed; 2 lines removed:
|
|
|
|
|
|
|
|
|
|
" @@ -5,4 +5,2 @@ this is line 4
|
|
|
|
|
" -this is line 5
|
|
|
|
|
" -this is line 6
|
|
|
|
|
" -this is line 7
|
|
|
|
|
" -this is line 8
|
|
|
|
|
" +this os line 5
|
|
|
|
|
" +this os line 6
|
|
|
|
|
if old_count > new_count
|
|
|
|
|
let modified += new_count
|
|
|
|
|
let removed = old_count - new_count
|
|
|
|
|
let deleted += removed
|
|
|
|
|
let offset = 0
|
|
|
|
|
while offset < new_count - 1
|
|
|
|
|
let line = new_line + offset
|
|
|
|
|
let offset += 1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, 'SignifyChange'))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endwhile
|
|
|
|
|
let line = new_line + offset
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, (removed > 9)
|
|
|
|
|
\ ? 'SignifyChangeDeleteMore'
|
|
|
|
|
\ : 'SignifyChangeDelete'. removed))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
|
|
|
|
|
" lines changed and added:
|
|
|
|
|
|
|
|
|
|
" @@ -5 +5,3 @@ this is line 4
|
|
|
|
|
" -this is line 5
|
|
|
|
|
" +this os line 5
|
|
|
|
|
" +this is line 42
|
|
|
|
|
" +this is line 666
|
|
|
|
|
else
|
|
|
|
|
let modified += old_count
|
|
|
|
|
let offset = 0
|
|
|
|
|
while offset < old_count
|
|
|
|
|
let line = new_line + offset
|
|
|
|
|
let offset += 1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, 'SignifyChange'))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
let added += 1
|
|
|
|
|
endwhile
|
|
|
|
|
while offset < new_count
|
|
|
|
|
let line = new_line + offset
|
|
|
|
|
let offset += 1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if s:external_sign_present(a:sy, line) | continue | endif
|
|
|
|
|
call add(ids, s:add_sign(a:sy, line, 'SignifyAdd'))
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endwhile
|
|
|
|
|
endif
|
|
|
|
|
endif
|
|
|
|
|
|
|
|
|
|
if !empty(ids)
|
2017-01-30 08:50:32 -05:00
|
|
|
|
call add(a:sy.hunks, {
|
2014-10-04 09:55:49 -04:00
|
|
|
|
\ 'ids' : ids,
|
2017-01-30 08:50:32 -05:00
|
|
|
|
\ 'start': a:sy.lines[0],
|
|
|
|
|
\ 'end' : a:sy.lines[-1] })
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
2013-07-17 06:30:58 -04:00
|
|
|
|
endfor
|
2013-11-18 17:02:21 -05:00
|
|
|
|
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" Remove obsoleted signs.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
for line in filter(keys(a:sy.internal), '!has_key(a:sy.signtable, v:val)')
|
|
|
|
|
execute 'sign unplace' a:sy.internal[line].id 'buffer='.a:sy.buffer
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endfor
|
2013-07-17 06:30:58 -04:00
|
|
|
|
|
2017-04-12 05:18:38 -04:00
|
|
|
|
if has('gui_macvim') && has('gui_running') && mode() == 'n'
|
2017-02-24 11:41:32 -05:00
|
|
|
|
" MacVim needs an extra kick in the butt, when setting signs from the
|
|
|
|
|
" exit handler. :redraw would trigger a "hanging cursor" issue.
|
|
|
|
|
call feedkeys("\<c-l>")
|
2017-02-19 19:15:50 -05:00
|
|
|
|
endif
|
|
|
|
|
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let a:sy.stats = [added, modified, deleted]
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endfunction
|
2013-09-06 09:34:13 -04:00
|
|
|
|
|
2014-10-04 13:35:51 -04:00
|
|
|
|
" Function: #remove_all_signs {{{1
|
2014-11-25 11:25:40 -05:00
|
|
|
|
function! sy#sign#remove_all_signs(bufnr) abort
|
|
|
|
|
let sy = getbufvar(a:bufnr, 'sy')
|
|
|
|
|
|
|
|
|
|
for hunk in sy.hunks
|
2014-10-04 13:35:51 -04:00
|
|
|
|
for id in hunk.ids
|
2017-01-18 10:28:35 -05:00
|
|
|
|
execute 'sign unplace' id 'buffer='.a:bufnr
|
2014-10-04 13:35:51 -04:00
|
|
|
|
endfor
|
|
|
|
|
endfor
|
|
|
|
|
|
2014-11-25 11:25:40 -05:00
|
|
|
|
let sy.hunks = []
|
2014-10-04 13:35:51 -04:00
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
" Function: s:add_sign {{{1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
function! s:add_sign(sy, line, type, ...) abort
|
|
|
|
|
call add(a:sy.lines, a:line)
|
|
|
|
|
let a:sy.signtable[a:line] = 1
|
2013-07-17 06:30:58 -04:00
|
|
|
|
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if has_key(a:sy.internal, a:line)
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" There is a sign on this line already.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
if a:type == a:sy.internal[a:line].type
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" Keep current sign since the new one is of the same type.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
return a:sy.internal[a:line].id
|
2013-12-05 19:51:33 -05:00
|
|
|
|
else
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" Update sign by overwriting the ID of the current sign.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let id = a:sy.internal[a:line].id
|
2013-12-05 19:51:33 -05:00
|
|
|
|
endif
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
2013-07-17 06:30:58 -04:00
|
|
|
|
|
2014-10-04 09:55:49 -04:00
|
|
|
|
if !exists('id')
|
2017-01-30 08:50:32 -05:00
|
|
|
|
let id = sy#sign#id_next(a:sy)
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
2013-09-06 09:34:13 -04:00
|
|
|
|
|
2014-10-04 09:55:49 -04:00
|
|
|
|
if a:type =~# 'SignifyDelete'
|
|
|
|
|
execute printf('sign define %s text=%s texthl=SignifySignDelete linehl=%s',
|
|
|
|
|
\ a:type,
|
|
|
|
|
\ a:1,
|
|
|
|
|
\ s:delete_highlight[g:signify_line_highlight])
|
|
|
|
|
endif
|
|
|
|
|
execute printf('sign place %d line=%d name=%s buffer=%s',
|
|
|
|
|
\ id,
|
|
|
|
|
\ a:line,
|
|
|
|
|
\ a:type,
|
2017-01-30 08:50:32 -05:00
|
|
|
|
\ a:sy.buffer)
|
2014-10-04 09:55:49 -04:00
|
|
|
|
|
|
|
|
|
return id
|
2013-07-17 06:30:58 -04:00
|
|
|
|
endfunction
|
|
|
|
|
|
2014-10-04 13:35:51 -04:00
|
|
|
|
" Function: s:external_sign_present {{{1
|
2017-01-30 08:50:32 -05:00
|
|
|
|
function! s:external_sign_present(sy, line) abort
|
|
|
|
|
if has_key(a:sy.external, a:line)
|
|
|
|
|
if has_key(a:sy.internal, a:line)
|
2014-10-04 09:55:49 -04:00
|
|
|
|
" Remove Sy signs from lines with other signs.
|
2017-01-30 08:50:32 -05:00
|
|
|
|
execute 'sign unplace' a:sy.internal[a:line].id 'buffer='.a:sy.buffer
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endif
|
|
|
|
|
return 1
|
2013-09-06 09:34:13 -04:00
|
|
|
|
endif
|
2014-10-04 09:55:49 -04:00
|
|
|
|
endfunction
|
|
|
|
|
|