vim-signify/autoload/sy/sign.vim

278 lines
8.1 KiB
VimL
Raw Normal View History

2013-09-30 04:19:31 -04:00
" vim: et sw=2 sts=2
scriptencoding utf-8
" Init: values {{{1
if get(g:, 'signify_sign_show_text', 1)
let s:sign_delete = get(g:, 'signify_sign_delete', '_')
else
let s:sign_delete = ' '
endif
let s:sign_show_count = get(g:, 'signify_sign_show_count', 1)
let s:delete_highlight = ['', 'SignifyLineDelete']
2017-01-18 10:28:35 -05:00
" Function: #id_next {{{1
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
function! sy#sign#get_current_signs(sy) abort
let a:sy.internal = {}
let a:sy.external = {}
2013-07-17 06:30:58 -04:00
redir => signlist
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.
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
let a:sy.internal[line] = { 'type': type, 'id': id }
2014-10-04 09:55:49 -04:00
else
let a:sy.external[line] = id
2014-10-04 09:55:49 -04:00
endif
endfor
endfunction
2014-10-04 09:55:49 -04:00
" Function: #process_diff {{{1
function! sy#sign#process_diff(sy, vcs, 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]
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 =~ "^@@ "')
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])
" Workaround for non-conventional diff output in older Fossil versions:
" https://fossil-scm.org/forum/forumpost/834ce0f1e1
" Fixed as of: https://fossil-scm.org/index.html/info/7fd2a3652ea7368a
if a:vcs == 'fossil' && new_line == 0
let new_line = old_line - 1 - deleted
endif
2014-10-04 09:55:49 -04:00
" 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
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)
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
call add(ids, s:add_sign(a:sy, 1, 'SignifyRemoveFirstLine'))
elseif s:sign_show_count
let text = s:sign_delete . (old_count <= 99 ? old_count : '>')
while strwidth(text) > 2
let text = substitute(text, '.', '', '')
endwhile
call add(ids, s:add_sign(a:sy, new_line, 'SignifyDelete'. old_count, text))
2014-10-04 09:55:49 -04:00
else
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
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
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
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
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
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)
call add(a:sy.hunks, {
2014-10-04 09:55:49 -04:00
\ 'ids' : ids,
\ '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.
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
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>", 'n')
endif
if empty(a:sy.updated_by) && empty(a:sy.hunks)
call sy#verbose('Successful exit value, but no diff. Keep VCS for time being.', a:vcs)
return
endif
2017-04-18 11:18:19 -04:00
call sy#verbose('Signs updated.', a:vcs)
let a:sy.updated_by = a:vcs
2017-04-18 11:18:19 -04:00
if len(a:sy.vcs) > 1
call sy#verbose('Disable all other VCS.', a:vcs)
let a:sy.vcs = [a:vcs]
endif
let a:sy.stats = [added, modified, deleted]
2014-10-04 09:55:49 -04:00
endfunction
Add finer grained control over signs and highlights I wanted to be able to customize signify in a way that wasn't possible with the current set of options. This commit adds 2 new options and 2 new highlight groups. Specifically, we can now 1. differentiate between changes, deletes AND signs that have both with the `signify_sign_changedelete` option. 2. disable showing the number of deleted lines in the sign column with the `signify_sign_delete_use_count` option. 3. highlight lines with changes and deletes specifically with the `SignifySignChangeDelete` highlight group. 4. highlight the first line differently with the `SignifySignDeleteFirstLine` highlight group. All of these default to existing settings/highlight groups, so everything should continue working the way it does now. -------------------------------------------------------------------------------- For those that are curious, I wanted to configure signify to show no symbols in the sign column, and to just use the highlight groups to give me all the information I needed. I am able to achieve that now with the following settings and the Solarized colorscheme: let g:signify_sign_add = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_change = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_changedelete = "__" let g:signify_sign_delete = "__" let g:signify_sign_delete_first_line = "‾‾" let g:signify_sign_delete_use_count = 0 hi SignifySignDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=12 hi SignifySignDeleteFirstLine ctermfg=1 ctermbg=12 hi SignifySignChangeDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=3 You can see it in action here: https://twitter.com/_bentomas/status/486266117204090880
2014-10-04 13:35:51 -04:00
" Function: #remove_all_signs {{{1
function! sy#sign#remove_all_signs(bufnr) abort
let sy = getbufvar(a:bufnr, 'sy')
for hunk in sy.hunks
Add finer grained control over signs and highlights I wanted to be able to customize signify in a way that wasn't possible with the current set of options. This commit adds 2 new options and 2 new highlight groups. Specifically, we can now 1. differentiate between changes, deletes AND signs that have both with the `signify_sign_changedelete` option. 2. disable showing the number of deleted lines in the sign column with the `signify_sign_delete_use_count` option. 3. highlight lines with changes and deletes specifically with the `SignifySignChangeDelete` highlight group. 4. highlight the first line differently with the `SignifySignDeleteFirstLine` highlight group. All of these default to existing settings/highlight groups, so everything should continue working the way it does now. -------------------------------------------------------------------------------- For those that are curious, I wanted to configure signify to show no symbols in the sign column, and to just use the highlight groups to give me all the information I needed. I am able to achieve that now with the following settings and the Solarized colorscheme: let g:signify_sign_add = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_change = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_changedelete = "__" let g:signify_sign_delete = "__" let g:signify_sign_delete_first_line = "‾‾" let g:signify_sign_delete_use_count = 0 hi SignifySignDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=12 hi SignifySignDeleteFirstLine ctermfg=1 ctermbg=12 hi SignifySignChangeDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=3 You can see it in action here: https://twitter.com/_bentomas/status/486266117204090880
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
Add finer grained control over signs and highlights I wanted to be able to customize signify in a way that wasn't possible with the current set of options. This commit adds 2 new options and 2 new highlight groups. Specifically, we can now 1. differentiate between changes, deletes AND signs that have both with the `signify_sign_changedelete` option. 2. disable showing the number of deleted lines in the sign column with the `signify_sign_delete_use_count` option. 3. highlight lines with changes and deletes specifically with the `SignifySignChangeDelete` highlight group. 4. highlight the first line differently with the `SignifySignDeleteFirstLine` highlight group. All of these default to existing settings/highlight groups, so everything should continue working the way it does now. -------------------------------------------------------------------------------- For those that are curious, I wanted to configure signify to show no symbols in the sign column, and to just use the highlight groups to give me all the information I needed. I am able to achieve that now with the following settings and the Solarized colorscheme: let g:signify_sign_add = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_change = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_changedelete = "__" let g:signify_sign_delete = "__" let g:signify_sign_delete_first_line = "‾‾" let g:signify_sign_delete_use_count = 0 hi SignifySignDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=12 hi SignifySignDeleteFirstLine ctermfg=1 ctermbg=12 hi SignifySignChangeDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=3 You can see it in action here: https://twitter.com/_bentomas/status/486266117204090880
2014-10-04 13:35:51 -04:00
endfor
endfor
let sy.hunks = []
Add finer grained control over signs and highlights I wanted to be able to customize signify in a way that wasn't possible with the current set of options. This commit adds 2 new options and 2 new highlight groups. Specifically, we can now 1. differentiate between changes, deletes AND signs that have both with the `signify_sign_changedelete` option. 2. disable showing the number of deleted lines in the sign column with the `signify_sign_delete_use_count` option. 3. highlight lines with changes and deletes specifically with the `SignifySignChangeDelete` highlight group. 4. highlight the first line differently with the `SignifySignDeleteFirstLine` highlight group. All of these default to existing settings/highlight groups, so everything should continue working the way it does now. -------------------------------------------------------------------------------- For those that are curious, I wanted to configure signify to show no symbols in the sign column, and to just use the highlight groups to give me all the information I needed. I am able to achieve that now with the following settings and the Solarized colorscheme: let g:signify_sign_add = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_change = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_changedelete = "__" let g:signify_sign_delete = "__" let g:signify_sign_delete_first_line = "‾‾" let g:signify_sign_delete_use_count = 0 hi SignifySignDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=12 hi SignifySignDeleteFirstLine ctermfg=1 ctermbg=12 hi SignifySignChangeDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=3 You can see it in action here: https://twitter.com/_bentomas/status/486266117204090880
2014-10-04 13:35:51 -04:00
endfunction
" Function: s:add_sign {{{1
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
if has_key(a:sy.internal, a:line)
2014-10-04 09:55:49 -04:00
" There is a sign on this line already.
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.
return a:sy.internal[a:line].id
else
2014-10-04 09:55:49 -04:00
" Update sign by overwriting the ID of the current sign.
let id = a:sy.internal[a:line].id
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')
let id = sy#sign#id_next(a:sy)
2014-10-04 09:55:49 -04:00
endif
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,
\ a:sy.buffer)
2014-10-04 09:55:49 -04:00
return id
2013-07-17 06:30:58 -04:00
endfunction
Add finer grained control over signs and highlights I wanted to be able to customize signify in a way that wasn't possible with the current set of options. This commit adds 2 new options and 2 new highlight groups. Specifically, we can now 1. differentiate between changes, deletes AND signs that have both with the `signify_sign_changedelete` option. 2. disable showing the number of deleted lines in the sign column with the `signify_sign_delete_use_count` option. 3. highlight lines with changes and deletes specifically with the `SignifySignChangeDelete` highlight group. 4. highlight the first line differently with the `SignifySignDeleteFirstLine` highlight group. All of these default to existing settings/highlight groups, so everything should continue working the way it does now. -------------------------------------------------------------------------------- For those that are curious, I wanted to configure signify to show no symbols in the sign column, and to just use the highlight groups to give me all the information I needed. I am able to achieve that now with the following settings and the Solarized colorscheme: let g:signify_sign_add = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_change = "\<Char-0xa0>\<Char-0xa0>" let g:signify_sign_changedelete = "__" let g:signify_sign_delete = "__" let g:signify_sign_delete_first_line = "‾‾" let g:signify_sign_delete_use_count = 0 hi SignifySignDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=12 hi SignifySignDeleteFirstLine ctermfg=1 ctermbg=12 hi SignifySignChangeDelete term=bold,underline cterm=bold,underline ctermfg=1 ctermbg=3 You can see it in action here: https://twitter.com/_bentomas/status/486266117204090880
2014-10-04 13:35:51 -04:00
" Function: s:external_sign_present {{{1
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.
execute 'sign unplace' a:sy.internal[a:line].id 'buffer='.a:sy.buffer
2014-10-04 09:55:49 -04:00
endif
return 1
endif
2014-10-04 09:55:49 -04:00
endfunction