summaryrefslogtreecommitdiff
path: root/start/signify
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-05-22 22:47:23 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-05-22 22:47:23 +0100
commit95aea6b533e71e478d61d18fac71cca116c56a4d (patch)
tree1a1f42f723772258cc54551495826768f374474a /start/signify
Add all the plugins I currently use
Diffstat (limited to 'start/signify')
-rw-r--r--start/signify/LICENSE20
-rw-r--r--start/signify/README.md54
-rw-r--r--start/signify/autoload/sy.vim199
-rw-r--r--start/signify/autoload/sy/debug.vim48
-rw-r--r--start/signify/autoload/sy/fold.vim125
-rw-r--r--start/signify/autoload/sy/highlight.vim94
-rw-r--r--start/signify/autoload/sy/jump.vim29
-rw-r--r--start/signify/autoload/sy/repo.vim512
-rw-r--r--start/signify/autoload/sy/sign.vim275
-rw-r--r--start/signify/autoload/sy/util.vim109
-rw-r--r--start/signify/doc/signify.txt689
-rw-r--r--start/signify/plugin/signify.vim120
12 files changed, 2274 insertions, 0 deletions
diff --git a/start/signify/LICENSE b/start/signify/LICENSE
new file mode 100644
index 0000000..f5b3716
--- /dev/null
+++ b/start/signify/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Marco Hinz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/start/signify/README.md b/start/signify/README.md
new file mode 100644
index 0000000..c15d0d5
--- /dev/null
+++ b/start/signify/README.md
@@ -0,0 +1,54 @@
+![vim-signify](https://raw.githubusercontent.com/mhinz/vim-signify/master/pictures/signify-logo.png)
+
+---
+
+_Signify (or just Sy) uses the sign column to indicate added, modified and
+removed lines in a file that is managed by a version control system (VCS)._
+
+---
+
+- Supports **git**, **mercurial**, **darcs**, **bazaar**, **subversion**,
+ **cvs**, **rcs**, **fossil**, **accurev**, **perforce**, **tfs**.
+- **Asynchronous** execution of VCS tools for Vim 7.4.1967+ and Neovim.
+- **Preserves signs** from other plugins.
+- Handles **nested repositories** controlled by different VCS.
+- Provides mappings for **navigating hunks** ("blocks of changed lines").
+- Provides an **operator** that acts on hunks.
+- Alternative workflow: Disable the plugin by default and **toggle it per
+ buffer** on demand.
+- Optional **line highlighting**.
+- Optional **skipping of filetypes/filenames**.
+- Optional **stats in the statusline**.
+- **Works out of the box**, but allows fine-grained configuration.
+- **Great documentation** and **handsome maintainers**!
+
+---
+
+_Similar plugin for git: [vim-gitgutter](https://github.com/airblade/vim-gitgutter)_
+
+## Installation
+
+Use your favorite [plugin
+manager](https://github.com/mhinz/vim-galore#managing-plugins), e.g. using
+[vim-plug](https://github.com/junegunn/vim-plug):
+
+ Plug 'mhinz/vim-signify'
+
+## Documentation
+
+1. Understand how the plugin works:
+ [`:h signify-modus-operandi`](https://github.com/mhinz/vim-signify/blob/master/doc/signify.txt#L52)
+1. Spare the plugin some work and read: `:h g:signify_vcs_list`
+
+## Demo
+
+![Example:signify in action](https://raw.githubusercontent.com/mhinz/vim-signify/master/pictures/signify-demo.gif)
+
+## Author and Feedback
+
+If you like this plugin, star it! It's a great way of getting feedback. The same
+goes for reporting issues or feature requests.
+
+Contact: [Twitter](https://twitter.com/_mhinz_)
+
+Co-maintainer: [@jamessan](https://github.com/jamessan)
diff --git a/start/signify/autoload/sy.vim b/start/signify/autoload/sy.vim
new file mode 100644
index 0000000..b994aff
--- /dev/null
+++ b/start/signify/autoload/sy.vim
@@ -0,0 +1,199 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Init: values {{{1
+let s:has_doau_modeline = v:version > 703 || v:version == 703 && has('patch442')
+
+" Function: #start {{{1
+function! sy#start() abort
+ if g:signify_locked
+ call sy#verbose('Locked.')
+ return
+ endif
+
+ let sy_path = resolve(expand('%:p'))
+ if has('win32')
+ let sy_path = substitute(sy_path, '\v^(\w):\\\\', '\1:\\', '')
+ endif
+
+ if s:skip(sy_path)
+ call sy#verbose('Skip file: '. sy_path)
+ if exists('b:sy')
+ call sy#sign#remove_all_signs(bufnr(''))
+ unlet! b:sy
+ endif
+ return
+ endif
+
+ if !exists('b:sy') || b:sy.path != sy_path
+ call sy#verbose('Register new file: '. sy_path)
+ let b:sy = {
+ \ 'path': sy_path,
+ \ 'buffer': bufnr(''),
+ \ 'active': 0,
+ \ 'detecting': 0,
+ \ 'vcs': [],
+ \ 'hunks': [],
+ \ 'signid': 0x100,
+ \ 'updated_by': '',
+ \ 'stats': [-1, -1, -1],
+ \ 'info': {
+ \ 'dir': fnamemodify(sy_path, ':p:h'),
+ \ 'path': sy#util#escape(sy_path),
+ \ 'file': sy#util#escape(fnamemodify(sy_path, ':t'))
+ \ }}
+ if get(g:, 'signify_disable_by_default')
+ call sy#verbose('Disabled by default.')
+ return
+ endif
+ let b:sy.active = 1
+ call sy#repo#detect()
+ elseif has('vim_starting')
+ call sy#verbose("Don't run Sy more than once during startup.")
+ return
+ elseif !b:sy.active
+ call sy#verbose('Inactive buffer.')
+ return
+ elseif empty(b:sy.vcs)
+ if get(b:sy, 'retry')
+ let b:sy.retry = 0
+ call sy#verbose('Redetecting VCS.')
+ call sy#repo#detect()
+ else
+ if get(b:sy, 'detecting')
+ call sy#verbose('Detection is already in progress.')
+ else
+ call sy#verbose('No VCS found. Disabling.')
+ call sy#disable()
+ endif
+ endif
+ else
+ for vcs in b:sy.vcs
+ let job_id = get(b:, 'sy_job_id_'. vcs)
+ if type(job_id) != type(0) || job_id > 0
+ call sy#verbose('Update is already in progress.', vcs)
+ else
+ call sy#verbose('Updating signs.', vcs)
+ call sy#repo#get_diff_start(vcs)
+ endif
+ endfor
+ endif
+endfunction
+
+" Function: #set_signs {{{1
+function! sy#set_signs(sy, vcs, diff) abort
+ call sy#verbose('set_signs()', a:vcs)
+
+ if a:sy.stats == [-1, -1, -1]
+ let a:sy.stats = [0, 0, 0]
+ endif
+
+ if empty(a:diff)
+ call sy#verbose('No changes found.', a:vcs)
+ let a:sy.stats = [0, 0, 0]
+ call sy#sign#remove_all_signs(a:sy.buffer)
+ return
+ endif
+
+ if get(g:, 'signify_line_highlight')
+ call sy#highlight#line_enable()
+ else
+ call sy#highlight#line_disable()
+ endif
+
+ call sy#sign#process_diff(a:sy, a:vcs, a:diff)
+
+ if exists('#User#Signify')
+ execute 'doautocmd' (s:has_doau_modeline ? '<nomodeline>' : '') 'User Signify'
+ endif
+endfunction
+
+" Function: #stop {{{1
+function! sy#stop(bufnr) abort
+ let sy = getbufvar(a:bufnr, 'sy')
+ if empty(sy)
+ return
+ endif
+
+ call sy#sign#remove_all_signs(a:bufnr)
+endfunction
+
+" Function: #enable {{{1
+function! sy#enable() abort
+ if !exists('b:sy')
+ call sy#start()
+ return
+ endif
+
+ if !b:sy.active
+ let b:sy.active = 1
+ let b:sy.retry = 1
+ call sy#start()
+ endif
+endfunction
+
+" Function: #disable {{{1
+function! sy#disable() abort
+ if exists('b:sy') && b:sy.active
+ call sy#stop(b:sy.buffer)
+ let b:sy.active = 0
+ let b:sy.stats = [-1, -1, -1]
+ endif
+endfunction
+
+" Function: #toggle {{{1
+function! sy#toggle() abort
+ if !exists('b:sy') || !b:sy.active
+ call sy#enable()
+ else
+ call sy#disable()
+ endif
+endfunction
+
+" Function: #buffer_is_active {{{1
+function! sy#buffer_is_active()
+ return exists('b:sy') && b:sy.active
+endfunction
+
+" Function: #verbose {{{1
+function! sy#verbose(msg, ...) abort
+ if &verbose
+ if type(a:msg) == type([])
+ for msg in a:msg
+ echomsg printf('[sy%s] %s', (a:0 ? ':'.a:1 : ''), msg)
+ endfor
+ else
+ echomsg printf('[sy%s] %s', (a:0 ? ':'.a:1 : ''), a:msg)
+ endif
+ endif
+endfunction
+
+" Function: s:skip {{{1
+function! s:skip(path)
+ if &diff || !filereadable(a:path)
+ return 1
+ endif
+
+ if exists('g:signify_skip_filetype')
+ if has_key(g:signify_skip_filetype, &filetype)
+ return 1
+ elseif has_key(g:signify_skip_filetype, 'help') && (&buftype == 'help')
+ return 1
+ endif
+ endif
+
+ if exists('g:signify_skip_filename') && has_key(g:signify_skip_filename, a:path)
+ return 1
+ endif
+
+ if exists('g:signify_skip_filename_pattern')
+ for pattern in g:signify_skip_filename_pattern
+ if a:path =~ pattern
+ return 1
+ endif
+ endfor
+ endif
+
+ return 0
+endfunction
diff --git a/start/signify/autoload/sy/debug.vim b/start/signify/autoload/sy/debug.vim
new file mode 100644
index 0000000..5beafd5
--- /dev/null
+++ b/start/signify/autoload/sy/debug.vim
@@ -0,0 +1,48 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Function: #list_active_buffers {{{1
+function! sy#debug#list_active_buffers() abort
+ for b in range(1, bufnr('$'))
+ if !buflisted(b) || empty(getbufvar(b, 'sy'))
+ continue
+ endif
+
+ let sy = copy(getbufvar(b, 'sy'))
+ let path = remove(sy, 'path')
+
+ echo "\n". path ."\n". repeat('=', strlen(path))
+
+ for k in ['active', 'buffer', 'vcs', 'stats', 'signid']
+ if k == 'stats'
+ echo printf("%10s = %d added, %d changed, %d removed\n",
+ \ k,
+ \ sy.stats[0],
+ \ sy.stats[1],
+ \ sy.stats[2])
+ else
+ echo printf("%10s = %s\n", k, string(sy[k]))
+ endif
+ endfor
+
+ if empty(sy.hunks)
+ echo printf("%10s = %s\n", 'hunks', '[]')
+ else
+ for i in range(len(sy.hunks))
+ if i == 0
+ echo printf("%10s = start: %d, end: %d, IDs: %s\n",
+ \ 'hunks',
+ \ sy.hunks[i].start,
+ \ sy.hunks[i].end,
+ \ string(sy.hunks[i].ids))
+ else
+ echo printf("%20s: %d, %s: %d, %s: %s\n",
+ \ 'start', sy.hunks[i].start,
+ \ 'end', sy.hunks[i].end,
+ \ 'IDs', string(sy.hunks[i].ids))
+ endif
+ endfor
+ endif
+ endfor
+endfunction
diff --git a/start/signify/autoload/sy/fold.vim b/start/signify/autoload/sy/fold.vim
new file mode 100644
index 0000000..e3afb97
--- /dev/null
+++ b/start/signify/autoload/sy/fold.vim
@@ -0,0 +1,125 @@
+" vim: et sw=2 sts=2
+
+" Function: SignifyFoldExpr {{{1
+function! SignifyFoldExpr(lnum)
+ return s:levels[a:lnum]
+endfunction
+
+" Function: SignifyFoldText {{{1
+function! SignifyFoldText()
+ let linelen = &textwidth ? &textwidth : 80
+ let marker = &foldmarker[:stridx(&foldmarker, ',')-1]
+ let range = foldclosedend(v:foldstart) - foldclosed(v:foldstart) + 1
+
+ let left = substitute(getline(v:foldstart), marker, '', '')
+ let leftlen = len(left)
+
+ let right = printf('%d [%d]', range, v:foldlevel)
+ let rightlen = len(right)
+
+ let tmp = strpart(left, 0, linelen - rightlen)
+ let tmplen = len(tmp)
+
+ if leftlen > tmplen
+ let left = strpart(tmp, 0, tmplen - 4) . '... '
+ let leftlen = tmplen
+ endif
+
+ let fill = repeat(' ', linelen - (leftlen + rightlen))
+
+ " return left . fill . right . repeat(' ', 100)
+ return left . fill . right
+endfunction
+
+" Function: #dispatch {{{1
+function! sy#fold#dispatch(do_tab) abort
+ if a:do_tab
+ call sy#fold#enable(1)
+ else
+ call sy#fold#toggle()
+ endif
+endfunction
+
+" Function: #enable {{{1
+function! sy#fold#enable(do_tab) abort
+ execute sy#util#return_if_no_changes()
+
+ if a:do_tab
+ tabedit %
+ endif
+
+ let [s:context0, s:context1] = get(g:, 'signify_fold_context', [3, 8])
+ let s:levels = s:get_levels(s:get_lines())
+
+ setlocal foldexpr=SignifyFoldExpr(v:lnum)
+ setlocal foldtext=SignifyFoldText()
+ setlocal foldmethod=expr
+ setlocal foldlevel=0
+endfunction
+
+" Function: #disable {{{1
+function! sy#fold#disable() abort
+ let &l:foldmethod = b:sy_folded.method
+ let &l:foldtext = b:sy_folded.text
+ normal! zv
+endfunction
+
+" Function: #toggle {{{1
+function! sy#fold#toggle() abort
+ if exists('b:sy_folded')
+ call sy#fold#disable()
+ if b:sy_folded.method == 'manual'
+ loadview
+ endif
+ unlet b:sy_folded
+ else
+ let b:sy_folded = { 'method': &foldmethod, 'text': &foldtext }
+ if &foldmethod == 'manual'
+ let old_vop = &viewoptions
+ mkview
+ let &viewoptions = old_vop
+ endif
+ call sy#fold#enable(0)
+ endif
+
+ redraw!
+ call sy#start()
+endfunction
+
+" Function: s:get_lines {{{1
+function! s:get_lines() abort
+ let signlist = sy#util#execute('sign place buffer='. b:sy.buffer)
+
+ let lines = []
+ for line in split(signlist, '\n')[2:]
+ call insert(lines, matchlist(line, '\v^\s+line\=(\d+)')[1], 0)
+ endfor
+
+ return reverse(lines)
+endfunction
+" }}}
+
+" Function: s:get_levels {{{1
+function! s:get_levels(lines) abort
+ let levels = {}
+
+ for line in range(1, line('$'))
+ let levels[line] = 2
+ endfor
+
+ for line in a:lines
+ for l in range(line - s:context1, line + s:context1)
+ if (l < 1) || (l > line('$'))
+ continue
+ endif
+ if levels[l] == 2
+ let levels[l] = 1
+ endif
+ for ll in range(line - s:context0, line + s:context0)
+ let levels[ll] = 0
+ endfor
+ endfor
+ endfor
+
+ return levels
+endfunction
diff --git a/start/signify/autoload/sy/highlight.vim b/start/signify/autoload/sy/highlight.vim
new file mode 100644
index 0000000..2ebe507
--- /dev/null
+++ b/start/signify/autoload/sy/highlight.vim
@@ -0,0 +1,94 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Init: values {{{1
+if get(g:, 'signify_sign_show_text', 1)
+ let s:sign_add = get(g:, 'signify_sign_add', '+')
+ let s:sign_delete_first_line = get(g:, 'signify_sign_delete_first_line', '‾')
+ let s:sign_change = get(g:, 'signify_sign_change', '!')
+ let s:sign_changedelete = get(g:, 'signify_sign_changedelete', s:sign_change)
+else
+ let s:sign_add = ' '
+ let s:sign_delete_first_line = ' '
+ let s:sign_change = ' '
+ let s:sign_changedelete = ' '
+endif
+
+let s:sign_show_count = get(g:, 'signify_sign_show_count', 1)
+
+" Function: #setup {{{1
+function! sy#highlight#setup() abort
+ highlight default link SignifyLineAdd DiffAdd
+ highlight default link SignifyLineDelete DiffDelete
+ highlight default link SignifyLineDeleteFirstLine SignifyLineDelete
+ highlight default link SignifyLineChange DiffChange
+ highlight default link SignifyLineChangeDelete SignifyLineChange
+
+ highlight default link SignifySignAdd DiffAdd
+ highlight default link SignifySignDelete DiffDelete
+ highlight default link SignifySignDeleteFirstLine SignifySignDelete
+ highlight default link SignifySignChange DiffChange
+ highlight default link SignifySignChangeDelete SignifySignChange
+endfunction
+
+" Function: #line_enable {{{1
+function! sy#highlight#line_enable() abort
+ execute 'sign define SignifyAdd text='. s:sign_add 'texthl=SignifySignAdd linehl=SignifyLineAdd'
+ execute 'sign define SignifyChange text='. s:sign_change 'texthl=SignifySignChange linehl=SignifyLineChange'
+ execute 'sign define SignifyRemoveFirstLine text='. s:sign_delete_first_line 'texthl=SignifySignDeleteFirstLine linehl=SignifyLineDeleteFirstLine'
+
+ if s:sign_show_count
+ let s:sign_changedelete = substitute(s:sign_changedelete, '^.\zs.*', '', '')
+ for n in range(1, 9)
+ execute 'sign define SignifyChangeDelete'. n 'text='. s:sign_changedelete . n 'texthl=SignifySignChangeDelete linehl=SignifyLineChangeDelete'
+ endfor
+ execute 'sign define SignifyChangeDeleteMore text='. s:sign_changedelete .'> texthl=SignifySignChangeDelete linehl=SignifyLineChangeDelete'
+ else
+ for n in range(1, 9)
+ execute 'sign define SignifyChangeDelete'. n 'text='. s:sign_changedelete 'texthl=SignifySignChangeDelete linehl=SignifyLineChangeDelete'
+ endfor
+ execute 'sign define SignifyChangeDeleteMore text='. s:sign_changedelete 'texthl=SignifySignChangeDelete linehl=SignifyLineChangeDelete'
+ endif
+
+ let g:signify_line_highlight = 1
+endfunction
+
+" Function: #line_disable {{{1
+function! sy#highlight#line_disable() abort
+ execute 'sign define SignifyAdd text='. s:sign_add 'texthl=SignifySignAdd linehl='
+ execute 'sign define SignifyChange text='. s:sign_change 'texthl=SignifySignChange linehl='
+ execute 'sign define SignifyRemoveFirstLine text='. s:sign_delete_first_line 'texthl=SignifySignDeleteFirstLine linehl='
+
+ if s:sign_show_count
+ while strwidth(s:sign_changedelete) > 1
+ let s:sign_changedelete = substitute(s:sign_changedelete, '.', '', '')
+ endwhile
+ for n in range(1, 9)
+ execute 'sign define SignifyChangeDelete'. n 'text='. s:sign_changedelete . n 'texthl=SignifySignChangeDelete linehl='
+ endfor
+ execute 'sign define SignifyChangeDeleteMore text='. s:sign_changedelete .'> texthl=SignifySignChangeDelete linehl='
+ else
+ for n in range(1, 9)
+ execute 'sign define SignifyChangeDelete'. n 'text='. s:sign_changedelete 'texthl=SignifySignChangeDelete linehl='
+ endfor
+ execute 'sign define SignifyChangeDeleteMore text='. s:sign_changedelete 'texthl=SignifySignChangeDelete linehl='
+ endif
+
+ let g:signify_line_highlight = 0
+endfunction
+
+" Function: #line_toggle {{{1
+function! sy#highlight#line_toggle() abort
+ if get(g:, 'signify_line_highlight')
+ call sy#highlight#line_disable()
+ else
+ call sy#highlight#line_enable()
+ endif
+
+ redraw!
+ call sy#start()
+endfunction
+" }}}
+
+call sy#highlight#setup()
diff --git a/start/signify/autoload/sy/jump.vim b/start/signify/autoload/sy/jump.vim
new file mode 100644
index 0000000..69756b1
--- /dev/null
+++ b/start/signify/autoload/sy/jump.vim
@@ -0,0 +1,29 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Function: #next_hunk {{{1
+function! sy#jump#next_hunk(count)
+ execute sy#util#return_if_no_changes()
+
+ let lnum = line('.')
+ let hunks = filter(copy(b:sy.hunks), 'v:val.start > lnum')
+ let hunk = get(hunks, a:count - 1, get(hunks, -1, {}))
+
+ if !empty(hunk)
+ execute 'sign jump '. hunk.ids[0] .' buffer='. b:sy.buffer
+ endif
+endfunction
+
+" Function: #prev_hunk {{{1
+function! sy#jump#prev_hunk(count)
+ execute sy#util#return_if_no_changes()
+
+ let lnum = line('.')
+ let hunks = filter(copy(b:sy.hunks), 'v:val.start < lnum')
+ let hunk = get(hunks, 0 - a:count, get(hunks, 0, {}))
+
+ if !empty(hunk)
+ execute 'sign jump '. hunk.ids[0] .' buffer='. b:sy.buffer
+ endif
+endfunction
diff --git a/start/signify/autoload/sy/repo.vim b/start/signify/autoload/sy/repo.vim
new file mode 100644
index 0000000..64bf07a
--- /dev/null
+++ b/start/signify/autoload/sy/repo.vim
@@ -0,0 +1,512 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Function: #detect {{{1
+function! sy#repo#detect() abort
+ for vcs in s:vcs_list
+ let b:sy.detecting += 1
+ call sy#repo#get_diff_start(vcs)
+ endfor
+endfunction
+
+" Function: s:callback_nvim_stdout{{{1
+function! s:callback_nvim_stdout(_job_id, data, _event) dict abort
+ if empty(self.stdoutbuf) || empty(self.stdoutbuf[-1])
+ let self.stdoutbuf += a:data
+ else
+ let self.stdoutbuf = self.stdoutbuf[:-2]
+ \ + [self.stdoutbuf[-1] . get(a:data, 0, '')]
+ \ + a:data[1:]
+ endif
+endfunction
+
+" Function: s:callback_nvim_exit {{{1
+function! s:callback_nvim_exit(_job_id, exitval, _event) dict abort
+ call s:job_exit(self.bufnr, self.vcs, a:exitval, self.stdoutbuf)
+endfunction
+
+" Function: s:callback_vim_stdout {{{1
+function! s:callback_vim_stdout(_job_id, data) dict abort
+ let self.stdoutbuf += [a:data]
+endfunction
+
+" Function: s:callback_vim_close {{{1
+function! s:callback_vim_close(channel) dict abort
+ let job = ch_getjob(a:channel)
+ while 1
+ if job_status(job) == 'dead'
+ let exitval = job_info(job).exitval
+ break
+ endif
+ sleep 10m
+ endwhile
+ call s:job_exit(self.bufnr, self.vcs, exitval, self.stdoutbuf)
+endfunction
+
+" Function: s:job_exit {{{1
+function! s:job_exit(bufnr, vcs, exitval, diff) abort
+ call sy#verbose('job_exit()', a:vcs)
+ let sy = getbufvar(a:bufnr, 'sy')
+ if empty(sy)
+ call sy#verbose(printf('No b:sy found for %s', bufname(a:bufnr)), a:vcs)
+ return
+ elseif !empty(sy.updated_by) && sy.updated_by != a:vcs
+ call sy#verbose(printf('Signs already got updated by %s.', sy.updated_by), a:vcs)
+ return
+ elseif empty(sy.vcs) && sy.active
+ let sy.detecting -= 1
+ endif
+ call sy#repo#get_diff_{a:vcs}(sy, a:exitval, a:diff)
+ call setbufvar(a:bufnr, 'sy_job_id_'.a:vcs, 0)
+endfunction
+
+" Function: sy#get_diff_start {{{1
+function! sy#repo#get_diff_start(vcs) abort
+ call sy#verbose('get_diff_start()', a:vcs)
+
+ let job_id = get(b:, 'sy_job_id_'.a:vcs)
+ " Neovim
+ if has('nvim')
+ if job_id
+ silent! call jobstop(job_id)
+ endif
+
+ let [cmd, options] = s:initialize_job(a:vcs)
+ let [cwd, chdir] = sy#util#chdir()
+
+ call sy#verbose(['CMD: '. string(cmd), 'CMD DIR: '. b:sy.info.dir, 'ORIG DIR: '. cwd], a:vcs)
+
+ try
+ execute chdir fnameescape(b:sy.info.dir)
+ catch
+ echohl ErrorMsg
+ echomsg 'signify: Changing directory failed: '. b:sy.info.dir
+ echohl NONE
+ return
+ endtry
+ let b:sy_job_id_{a:vcs} = jobstart(cmd, extend(options, {
+ \ 'on_stdout': function('s:callback_nvim_stdout'),
+ \ 'on_exit': function('s:callback_nvim_exit'),
+ \ }))
+ execute chdir fnameescape(cwd)
+
+ " Newer Vim
+ elseif has('patch-7.4.1967')
+ if type(job_id) != type(0)
+ silent! call job_stop(job_id)
+ endif
+
+ let [cmd, options] = s:initialize_job(a:vcs)
+ let [cwd, chdir] = sy#util#chdir()
+
+ call sy#verbose(['CMD: '. string(cmd), 'CMD DIR: '. b:sy.info.dir, 'ORIG DIR: '. cwd], a:vcs)
+
+ try
+ execute chdir fnameescape(b:sy.info.dir)
+ catch
+ echohl ErrorMsg
+ echomsg 'signify: Changing directory failed: '. b:sy.info.dir
+ echohl NONE
+ return
+ endtry
+ let opts = {
+ \ 'in_io': 'null',
+ \ 'out_cb': function('s:callback_vim_stdout', options),
+ \ 'close_cb': function('s:callback_vim_close', options),
+ \ }
+ let b:sy_job_id_{a:vcs} = job_start(cmd, opts)
+ execute chdir fnameescape(cwd)
+
+ " Older Vim
+ else
+ let diff = split(s:run(a:vcs), '\n')
+ call sy#repo#get_diff_{a:vcs}(b:sy, v:shell_error, diff)
+ endif
+endfunction
+
+" Function: s:get_diff_end {{{1
+function! s:get_diff_end(sy, found_diff, vcs, diff) abort
+ call sy#verbose('get_diff_end()', a:vcs)
+ if a:found_diff
+ if index(a:sy.vcs, a:vcs) == -1
+ let a:sy.vcs += [a:vcs]
+ endif
+ call sy#set_signs(a:sy, a:vcs, a:diff)
+ else
+ call sy#verbose('No valid diff found. Disabling this VCS.', a:vcs)
+ endif
+endfunction
+
+" Function: #get_diff_git {{{1
+function! sy#repo#get_diff_git(sy, exitval, diff) abort
+ call sy#verbose('get_diff_git()', 'git')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'git', diff)
+endfunction
+
+" Function: #get_diff_hg {{{1
+function! sy#repo#get_diff_hg(sy, exitval, diff) abort
+ call sy#verbose('get_diff_hg()', 'hg')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'hg', diff)
+endfunction
+
+" Function: #get_diff_svn {{{1
+function! sy#repo#get_diff_svn(sy, exitval, diff) abort
+ call sy#verbose('get_diff_svn()', 'svn')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'svn', diff)
+endfunction
+
+" Function: #get_diff_bzr {{{1
+function! sy#repo#get_diff_bzr(sy, exitval, diff) abort
+ call sy#verbose('get_diff_bzr()', 'bzr')
+ let [found_diff, diff] = (a:exitval =~ '[012]') ? [1, a:diff] : [0, []]
+ call s:get_diff_end(a:sy, found_diff, 'bzr', diff)
+endfunction
+
+" Function: #get_diff_darcs {{{1
+function! sy#repo#get_diff_darcs(sy, exitval, diff) abort
+ call sy#verbose('get_diff_darcs()', 'darcs')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'darcs', diff)
+endfunction
+
+" Function: #get_diff_fossil {{{1
+function! sy#repo#get_diff_fossil(sy, exitval, diff) abort
+ call sy#verbose('get_diff_fossil()', 'fossil')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'fossil', diff)
+endfunction
+
+" Function: #get_diff_cvs {{{1
+function! sy#repo#get_diff_cvs(sy, exitval, diff) abort
+ call sy#verbose('get_diff_cvs()', 'cvs')
+ let [found_diff, diff] = [0, []]
+ if a:exitval == 1
+ for diffline in a:diff
+ if diffline =~ '^+++'
+ let [found_diff, diff] = [1, a:diff]
+ break
+ endif
+ endfor
+ elseif a:exitval == 0 && len(a:diff) == 0
+ let found_diff = 1
+ endif
+ call s:get_diff_end(a:sy, found_diff, 'cvs', diff)
+endfunction
+
+" Function: #get_diff_rcs {{{1
+function! sy#repo#get_diff_rcs(sy, exitval, diff) abort
+ call sy#verbose('get_diff_rcs()', 'rcs')
+ let [found_diff, diff] = a:exitval == 2 ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'rcs', diff)
+endfunction
+
+" Function: #get_diff_accurev {{{1
+function! sy#repo#get_diff_accurev(sy, exitval, diff) abort
+ call sy#verbose('get_diff_accurev()', 'accurev')
+ let [found_diff, diff] = (a:exitval >= 2) ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'accurev', diff)
+endfunction
+
+" Function: #get_diff_perforce {{{1
+function! sy#repo#get_diff_perforce(sy, exitval, diff) abort
+ call sy#verbose('get_diff_perforce()', 'perforce')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, a:diff]
+ call s:get_diff_end(a:sy, found_diff, 'perforce', diff)
+endfunction
+
+" Function: #get_diff_tfs {{{1
+function! sy#repo#get_diff_tfs(sy, exitval, diff) abort
+ call sy#verbose('get_diff_tfs()', 'tfs')
+ let [found_diff, diff] = a:exitval ? [0, []] : [1, s:strip_context(a:diff)]
+ call s:get_diff_end(a:sy, found_diff, 'tfs', diff)
+endfunction
+
+" Function: #get_stats {{{1
+function! sy#repo#get_stats() abort
+ return exists('b:sy') ? b:sy.stats : [-1, -1, -1]
+endfunction
+
+" Function: #debug_detection {{{1
+function! sy#repo#debug_detection()
+ if !exists('b:sy')
+ echomsg 'signify: I cannot detect any changes!'
+ return
+ endif
+
+ for vcs in s:vcs_list
+ let cmd = s:expand_cmd(vcs, g:signify_vcs_cmds)
+ echohl Statement
+ echo cmd
+ echo repeat('=', len(cmd))
+ echohl NONE
+
+ let diff = s:run(vcs)
+ if v:shell_error
+ echohl ErrorMsg
+ echo diff
+ echohl NONE
+ else
+ echo empty(diff) ? "<none>" : diff
+ endif
+ echo "\n"
+ endfor
+endfunction
+
+" Function: #diffmode {{{1
+function! sy#repo#diffmode(do_tab) abort
+ execute sy#util#return_if_no_changes()
+
+ let vcs = b:sy.updated_by
+ if !has_key(g:signify_vcs_cmds_diffmode, vcs)
+ echomsg 'SignifyDiff has no support for: '. vcs
+ echomsg 'Open an issue for it at: https://github.com/mhinz/vim-signify/issues'
+ return
+ endif
+ let cmd = s:expand_cmd(vcs, g:signify_vcs_cmds_diffmode)
+ call sy#verbose('SignifyDiff: '. cmd, vcs)
+ let ft = &filetype
+ let fenc = &fenc
+ if a:do_tab
+ tabedit %
+ endif
+ diffthis
+ let [cwd, chdir] = sy#util#chdir()
+ try
+ execute chdir fnameescape(b:sy.info.dir)
+ leftabove vnew
+ if has('iconv')
+ silent put =iconv(system(cmd), fenc, &enc)
+ else
+ silent put =system(cmd)
+ endif
+ finally
+ execute chdir fnameescape(cwd)
+ endtry
+ silent 1delete
+ set buftype=nofile bufhidden=wipe nomodified
+ let &filetype = ft
+ diffthis
+ wincmd p
+ normal! ]czt
+endfunction
+
+" Function: s:initialize_job {{{1
+function! s:initialize_job(vcs) abort
+ let vcs_cmd = s:expand_cmd(a:vcs, g:signify_vcs_cmds)
+ if has('win32')
+ if has('nvim')
+ let cmd = &shell =~ '\v%(cmd|powershell)' ? vcs_cmd : ['sh', '-c', vcs_cmd]
+ else
+ if &shell =~ 'cmd'
+ let cmd = vcs_cmd
+ elseif empty(&shellxquote)
+ let cmd = join([&shell, &shellcmdflag, &shellquote, vcs_cmd, &shellquote])
+ else
+ let cmd = join([&shell, &shellcmdflag, &shellxquote, vcs_cmd, &shellxquote])
+ endif
+ endif
+ else
+ let cmd = ['sh', '-c', vcs_cmd]
+ endif
+ let options = {
+ \ 'stdoutbuf': [],
+ \ 'vcs': a:vcs,
+ \ 'bufnr': bufnr('%'),
+ \ }
+ return [cmd, options]
+endfunction
+
+" Function: s:get_vcs_path {{{1
+function! s:get_vcs_path(vcs) abort
+ return (a:vcs =~# '\v(git|cvs|accurev|tfs)') ? b:sy.info.file : b:sy.info.path
+endfunction
+
+" Function: s:expand_cmd {{{1
+function! s:expand_cmd(vcs, vcs_cmds) abort
+ let cmd = a:vcs_cmds[a:vcs]
+ let cmd = s:replace(cmd, '%f', s:get_vcs_path(a:vcs))
+ let cmd = s:replace(cmd, '%d', s:difftool)
+ let cmd = s:replace(cmd, '%n', s:devnull)
+ return cmd
+endfunction
+
+" Function: s:run {{{1
+function! s:run(vcs)
+ let [cwd, chdir] = sy#util#chdir()
+ try
+ execute chdir fnameescape(b:sy.info.dir)
+ let ret = system(s:expand_cmd(a:vcs, g:signify_vcs_cmds))
+ catch
+ " This exception message can be seen via :SignifyDebugUnknown.
+ " E.g. unquoted VCS programs in vcd_cmds can lead to E484.
+ let ret = v:exception .' at '. v:throwpoint
+ finally
+ execute chdir fnameescape(cwd)
+ return ret
+ endtry
+endfunction
+
+" Function: s:replace {{{1
+function! s:replace(cmd, pat, sub)
+ let parts = split(a:cmd, a:pat, 1)
+ return join(parts, a:sub)
+endfunction
+
+" Function: s:strip_context {{{1
+function! s:strip_context(context)
+ let diff = []
+ let hunk = []
+ let state = 0
+ let lines = a:context
+ let linenr = 0
+
+ while linenr < len(lines)
+ let line = lines[linenr]
+
+ if state == 0
+ if line =~ "^@@ "
+ 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])
+ let hunk = []
+ let state = 1
+ else
+ call add(diff,line)
+ endif
+ let linenr += 1
+ elseif index([1,2,3],state) >= 0 && index(['\','/'],line[0]) >= 0
+ let linenr += 1
+ call add(hunk,line)
+ elseif state == 1
+ if line[0] == ' '
+ let old_line += 1
+ let new_line += 1
+ let old_count -= 1
+ let new_count -= 1
+ let linenr += 1
+ else
+ let old_count_part = 0
+ let new_count_part = 0
+ let state = 2
+ endif
+ elseif state == 2
+ if line[0] == '-'
+ call add(hunk,line)
+ let old_count_part += 1
+ let linenr += 1
+ else
+ let state = 3
+ endif
+ elseif state == 3
+ if line[0] == '+'
+ call add(hunk,line)
+ let new_count_part += 1
+ let linenr += 1
+ else
+ call add(diff, printf("@@ -%d%s +%d%s @@",(old_count_part == 0 && old_line > 0) ? old_line -1 : old_line, old_count_part == 1 ? "" : printf(",%d", old_count_part), (new_count_part == 0 && new_line > 0) ? new_line - 1 : new_line, new_count_part == 1 ? "" : printf(",%d", new_count_part)))
+ let diff += hunk
+ let hunk = []
+ let old_count -= old_count_part
+ let new_count -= new_count_part
+ let old_line += old_count_part
+ let new_line += new_count_part
+ let state = 1
+ endif
+ endif
+
+ if state > 0 && new_count <= 0 && old_count <= 0
+ if len(hunk) > 0
+ call add(diff, printf("@@ -%d%s +%d%s @@",(old_count_part == 0 && old_line > 0) ? old_line -1 : old_line, old_count_part == 1 ? "" : printf(",%d", old_count_part), (new_count_part == 0 && new_line > 0) ? new_line - 1 : new_line, new_count_part == 1 ? "" : printf(",%d", new_count_part)))
+ let diff = diff + hunk
+ let hunk = []
+ endif
+ let state = 0
+ endif
+ endwhile
+ if len(hunk) > 0
+ call add(diff, printf("@@ -%d%s +%d%s @@",(old_count_part == 0 && old_line > 0) ? old_line -1 : old_line, old_count_part == 1 ? "" : printf(",%d", old_count_part), (new_count_part == 0 && new_line > 0) ? new_line - 1 : new_line, new_count_part == 1 ? "" : printf(",%d", new_count_part)))
+ let diff = diff + hunk
+ let hunk = []
+ endif
+ return diff
+endfunction
+
+" Variables {{{1
+let s:difftool = get(g:, 'signify_difftool', 'diff')
+if executable(s:difftool)
+ let s:vcs_dict = {
+ \ 'git': 'git',
+ \ 'hg': 'hg',
+ \ 'svn': 'svn',
+ \ 'darcs': 'darcs',
+ \ 'bzr': 'bzr',
+ \ 'fossil': 'fossil',
+ \ 'cvs': 'cvs',
+ \ 'rcs': 'rcsdiff',
+ \ 'accurev': 'accurev',
+ \ 'perforce': 'p4',
+ \ 'tfs': 'tf'
+ \ }
+else
+ call sy#verbose('No "diff" executable found. Disable support for svn, darcs, bzr.')
+ let s:vcs_dict = {
+ \ 'git': 'git',
+ \ 'hg': 'hg',
+ \ 'fossil': 'fossil',
+ \ 'cvs': 'cvs',
+ \ 'rcs': 'rcsdiff',
+ \ 'accurev': 'accurev',
+ \ 'perforce': 'p4',
+ \ 'tfs': 'tf'
+ \ }
+endif
+
+let s:vcs_list = get(g:, 'signify_vcs_list', [])
+if empty(s:vcs_list)
+ let s:vcs_list = keys(filter(s:vcs_dict, 'executable(v:val)'))
+endif
+
+let s:default_vcs_cmds = {
+ \ 'git': 'git diff --no-color --no-ext-diff -U0 -- %f',
+ \ 'hg': 'hg diff --color=never --config aliases.diff= --nodates -U0 -- %f',
+ \ 'svn': 'svn diff --diff-cmd %d -x -U0 -- %f',
+ \ 'bzr': 'bzr diff --using %d --diff-options=-U0 -- %f',
+ \ 'darcs': 'darcs diff --no-pause-for-gui --no-unified --diff-opts=-U0 -- %f',
+ \ 'fossil': 'fossil diff --unified -c 0 -- %f',
+ \ 'cvs': 'cvs diff -U0 -- %f',
+ \ 'rcs': 'rcsdiff -U0 %f 2>%n',
+ \ 'accurev': 'accurev diff %f -- -U0',
+ \ 'perforce': 'p4 info '. sy#util#shell_redirect('%n') . (has('win32') ? ' &&' : ' && env P4DIFF= P4COLORS=') .' p4 diff -du0 %f',
+ \ 'tfs': 'tf diff -version:W -noprompt -format:Unified %f'
+ \ }
+
+let s:default_vcs_cmds_diffmode = {
+ \ 'git': 'git show HEAD:./%f',
+ \ 'hg': 'hg cat %f',
+ \ 'svn': 'svn cat %f',
+ \ 'bzr': 'bzr cat %f',
+ \ 'darcs': 'darcs show contents -- %f',
+ \ 'fossil': 'fossil cat %f',
+ \ 'cvs': 'cvs up -p -- %f 2>%n',
+ \ 'perforce': 'p4 print %f',
+ \ }
+
+if exists('g:signify_vcs_cmds')
+ call extend(g:signify_vcs_cmds, s:default_vcs_cmds, 'keep')
+else
+ let g:signify_vcs_cmds = s:default_vcs_cmds
+endif
+if exists('g:signify_vcs_cmds_diffmode')
+ call extend(g:signify_vcs_cmds_diffmode, s:default_vcs_cmds_diffmode, 'keep')
+else
+ let g:signify_vcs_cmds_diffmode = s:default_vcs_cmds_diffmode
+endif
+
+let s:difftool = sy#util#escape(s:difftool)
+let s:devnull = has('win32') || has ('win64') ? 'NUL' : '/dev/null'
diff --git a/start/signify/autoload/sy/sign.vim b/start/signify/autoload/sy/sign.vim
new file mode 100644
index 0000000..23b7038
--- /dev/null
+++ b/start/signify/autoload/sy/sign.vim
@@ -0,0 +1,275 @@
+" 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']
+
+" Function: #id_next {{{1
+function! sy#sign#id_next(sy) abort
+ let id = a:sy.signid
+ let a:sy.signid += 1
+ return id
+endfunction
+
+" Function: #get_current_signs {{{1
+function! sy#sign#get_current_signs(sy) abort
+ let a:sy.internal = {}
+ let a:sy.external = {}
+
+ let signlist = sy#util#execute('sign place buffer='. a:sy.buffer)
+
+ for signline in split(signlist, '\n')[2:]
+ let tokens = matchlist(signline, '\v^\s+\S+\=(\d+)\s+\S+\=(\d+)\s+\S+\=(.*)$')
+ 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
+ endif
+ let a:sy.internal[line] = { 'type': type, 'id': id }
+ else
+ let a:sy.external[line] = id
+ endif
+ endfor
+endfunction
+
+
+" Function: #process_diff {{{1
+function! sy#sign#process_diff(sy, vcs, diff) abort
+ let a:sy.signtable = {}
+ let a:sy.hunks = []
+ let [added, modified, deleted] = [0, 0, 0]
+
+ call sy#sign#get_current_signs(a:sy)
+
+ " Determine where we have to put our signs.
+ for line in filter(a:diff, 'v:val =~ "^@@ "')
+ let a:sy.lines = []
+ 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
+
+ " 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'))
+ 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
+ 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))
+ else
+ call add(ids, s:add_sign(a:sy, new_line, 'SignifyDeleteMore', s:sign_delete))
+ 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'))
+ 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'))
+ 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))
+
+ " 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'))
+ endwhile
+ while offset < new_count
+ let added += 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, 'SignifyAdd'))
+ endwhile
+ endif
+ endif
+
+ if !empty(ids)
+ call add(a:sy.hunks, {
+ \ 'ids' : ids,
+ \ 'start': a:sy.lines[0],
+ \ 'end' : a:sy.lines[-1] })
+ endif
+ endfor
+
+ " 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
+ endfor
+
+ if has('gui_macvim') && has('gui_running') && mode() == 'n'
+ " 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
+
+ call sy#verbose('Signs updated.', a:vcs)
+ let a:sy.updated_by = a:vcs
+ 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]
+endfunction
+
+" Function: #remove_all_signs {{{1
+function! sy#sign#remove_all_signs(bufnr) abort
+ let sy = getbufvar(a:bufnr, 'sy')
+
+ for hunk in sy.hunks
+ for id in hunk.ids
+ execute 'sign unplace' id 'buffer='.a:bufnr
+ endfor
+ endfor
+
+ let sy.hunks = []
+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
+
+ if has_key(a:sy.internal, a:line)
+ " There is a sign on this line already.
+ if a:type == a:sy.internal[a:line].type
+ " Keep current sign since the new one is of the same type.
+ return a:sy.internal[a:line].id
+ else
+ " Update sign by overwriting the ID of the current sign.
+ let id = a:sy.internal[a:line].id
+ endif
+ endif
+
+ if !exists('id')
+ let id = sy#sign#id_next(a:sy)
+ endif
+
+ 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)
+
+ return id
+endfunction
+
+" 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)
+ " Remove Sy signs from lines with other signs.
+ execute 'sign unplace' a:sy.internal[a:line].id 'buffer='.a:sy.buffer
+ endif
+ return 1
+ endif
+endfunction
+
diff --git a/start/signify/autoload/sy/util.vim b/start/signify/autoload/sy/util.vim
new file mode 100644
index 0000000..43a9cc6
--- /dev/null
+++ b/start/signify/autoload/sy/util.vim
@@ -0,0 +1,109 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+" Function: #escape {{{1
+function! sy#util#escape(path) abort
+ if exists('+shellslash')
+ let old_ssl = &shellslash
+ if fnamemodify(&shell, ':t') == 'cmd.exe'
+ set noshellslash
+ else
+ set shellslash
+ endif
+ endif
+
+ let path = shellescape(a:path)
+
+ if exists('old_ssl')
+ let &shellslash = old_ssl
+ endif
+
+ return path
+endfunction
+
+" Function: #refresh_windows {{{1
+function! sy#util#refresh_windows() abort
+ if exists('*win_getid')
+ let winid = win_getid()
+ else
+ let winnr = winnr()
+ endif
+
+ if !get(g:, 'signify_cmdwin_active')
+ keepjumps windo if exists('b:sy') | call sy#start() | endif
+ endif
+
+ if exists('winid')
+ call win_gotoid(winid)
+ else
+ execute winnr .'wincmd w'
+ endif
+endfunction
+
+" Function: #hunk_text_object {{{1
+function! sy#util#hunk_text_object(emptylines) abort
+ execute sy#util#return_if_no_changes()
+
+ let lnum = line('.')
+ let hunks = filter(copy(b:sy.hunks), 'v:val.start <= lnum && v:val.end >= lnum')
+
+ if empty(hunks)
+ echomsg 'signify: Here is no hunk.'
+ return
+ endif
+
+ execute hunks[0].start
+ normal! V
+
+ if a:emptylines
+ let lnum = hunks[0].end
+ while getline(lnum+1) =~ '^$'
+ let lnum += 1
+ endwhile
+ execute lnum
+ else
+ execute hunks[0].end
+ endif
+endfunction
+
+" Function: #shell_redirect {{{1
+function! sy#util#shell_redirect(path) abort
+ " if shellredir contains a %s it is replaced with the path
+ " otherwise, just append it (from :help shellredir:
+ " The name of the temporary file can be represented by '%s' if necessary
+ " (the file name is appended automatically if no %s appears in the value
+ " of this option)
+ if &shellredir =~# '%s'
+ return substitute(&shellredir, '\C%s', a:path, 'g')
+ else
+ return &shellredir .' '. a:path
+ endif
+endfunction
+
+" Function: #chdir {{{1
+function! sy#util#chdir() abort
+ let chdir = haslocaldir()
+ \ ? 'lcd'
+ \ : (exists(':tcd') && haslocaldir(-1, 0)) ? 'tcd' : 'cd'
+ return [getcwd(), chdir]
+endfunction
+
+" Function: #has_changes {{{1
+function! sy#util#return_if_no_changes() abort
+ if !exists('b:sy') || empty(b:sy.hunks)
+ echomsg 'signify: There are no changes.'
+ return 'return'
+ endif
+ return ''
+endfunction
+
+" Function: #execute {{{1
+function! sy#util#execute(cmd) abort
+ let lang = v:lang
+ redir => output
+ silent! execute a:cmd
+ redir END
+ silent! execute 'language message' lang
+ return output
+endfunction
diff --git a/start/signify/doc/signify.txt b/start/signify/doc/signify.txt
new file mode 100644
index 0000000..4d4e07d
--- /dev/null
+++ b/start/signify/doc/signify.txt
@@ -0,0 +1,689 @@
+*signify.txt* Indicate changed lines within a file using a VCS.
+*signify*
+>
+ ___
+ __ __ /'___\
+ ____/\_\ __ ___ /\_\/\ \__/ __ __
+ /',__\/\ \ /'_ `\ /' _ `\/\ \ \ ,__\/\ \/\ \
+ /\__, `\ \ \/\ \L\ \/\ \/\ \ \ \ \ \_/\ \ \_\ \
+ \/\____/\ \_\ \____ \ \_\ \_\ \_\ \_\ \/`____ \
+ \/___/ \/_/\/___L\ \/_/\/_/\/_/\/_/ `/___/> \
+ /\____/ /\___/
+ \_/__/ \/__/
+<
+ by Marco Hinz~
+
+==============================================================================
+TOC *signify-contents*
+
+ INTRO .......................... |signify-intro|
+ MODUS OPERANDI ................. |signify-modus-operandi|
+ DEBUG .......................... |signify-debug|
+ SIGNS .......................... |signify-signs|
+ OPTIONS ........................ |signify-options|
+ COMMANDS ....................... |signify-commands|
+ AUTOCOMMAND .................... |signify-autocommand|
+ MAPPINGS ....................... |signify-mappings|
+ COLORS ......................... |signify-colors|
+ FAQ ............................ |signify-faq|
+ EXAMPLE ........................ |signify-example|
+
+==============================================================================
+INTRO *signify-intro*
+
+Signify uses the sign column to indicate added, modified and removed lines
+based on the data of an underlying version control system.
+
+Supported VCS:~
+>
+ git
+ mercurial
+ darcs
+ bzr
+ subversion
+ cvs
+ rcs
+ fossil
+ accurev
+ perforce
+ tfs
+<
+==============================================================================
+MODUS OPERANDI *signify-modus-operandi*
+
+When you open a new buffer, Sy registers it as `active` and tries to figure out
+whether the underlying file is controlled by a VCS (version control system) or
+not.
+
+For that, it asynchronously tries all the `diff` subcommands of all the VCS
+tools that are supported and executable. It's recommended to set
+|g:signify_vcs_list| to limit the VCS to test for.
+
+If one of the checks produces a proper diff, that VCS will automatically be
+used for all successive calls to Sy.
+
+If none of the checks produces a proper diff, the VCS will be set to `unknown`.
+The next time Sy gets run, the buffer will be marked as `inactive`, so it won't
+look for changes anymore.
+
+Or you set |g:signify_disable_by_default|, which registers all new buffers as
+`inactive`, and enable Sy on demand using |signify-:SignifyToggle|.
+
+By default, Sy is rather conservative and only updates signs when opening a
+new buffer or writing it. If you want more agressive sign updating, have a
+look at |g:signify_realtime|.
+
+Use |signify-:SignifyList| to list all buffers managed by Sy and their current
+state.
+
+==============================================================================
+DEBUG *signify-debug*
+
+If signs aren't showing up as expected, see if |signify-:SignifyDebug| shows
+anything suspicious. It will try all VCS and shows either errors or a diff for
+each VCS.
+
+If the output looks fine though, create an issue on Github:
+
+ https://github.com/mhinz/vim-signify/issues/new
+
+Make sure to mention your Vim version and which Sy version you use (latest
+release or master).
+
+Additionally, include the output of |:messages| after executing one of the
+following:
+
+ - opening the buffer via `vim -V1 <file>`
+ - or running `:verb w` in the buffer
+
+==============================================================================
+SIGNS *signify-signs*
+
+ `+` This line was added.
+
+ `!` This line was modified.
+
+ `_1` The number of deleted lines below this sign. If the number is larger
+ `99` than 9, the `_` will be omitted. For numbers larger than 99, `_>`
+ `_>` will be shown instead.
+
+ `!1` This line was modified and a number of lines below were deleted.
+ `!>` It is a combination of `!` and `_`. If the number is larger than 9,
+ `!>` will be shown instead.
+
+ `‾` The first line was removed. It's a special case of the `_` sign.
+
+See |g:signify_sign_add| on how to use different signs.
+
+==============================================================================
+OPTIONS *signify-options*
+
+Put these variables into your vimrc. The provided examples also indicate the
+default values, as long as no "Default:" section is given.
+
+Most important options:~
+
+ |g:signify_vcs_list|
+ |g:signify_realtime|
+
+Other options:~
+
+ |g:signify_vcs_cmds|
+ |g:signify_vcs_cmds_diffmode|
+ |g:signify_disable_by_default|
+ |g:signify_skip_filetype|
+ |g:signify_skip_filename|
+ |g:signify_skip_filename_pattern|
+ |g:signify_update_on_bufenter|
+ |g:signify_update_on_focusgained|
+ |g:signify_line_highlight|
+ |g:signify_sign_add|
+ |g:signify_sign_delete|
+ |g:signify_sign_delete_first_line|
+ |g:signify_sign_change|
+ |g:signify_sign_changedelete|
+ |g:signify_sign_show_count|
+ |g:signify_sign_show_text|
+ |g:signify_cursorhold_normal|
+ |g:signify_cursorhold_insert|
+ |g:signify_difftool|
+ |g:signify_fold_context|
+
+------------------------------------------------------------------------------
+ *g:signify_vcs_list* >
+ let g:signify_vcs_list = [ 'git', 'hg' ]
+<
+Default: empty
+Possible values: 'accurev'
+ 'bzr'
+ 'cvs'
+ 'darcs'
+ 'fossil'
+ 'git'
+ 'hg'
+ 'perforce'
+ 'rcs'
+ 'svn'
+ 'tfs'
+
+NOTE: This is the most important option, so read closely.
+
+This option determines what VCS to check for.
+
+This can improve buffer loading time, since by default all supported and
+installed VCS will be checked for. This only happens once, when signs get set
+the first time. Afterwards, the VCS will either be remembered or registered as
+inactive when no VCS was found.
+
+If your Vim is recent enough, these checks will happen asynchronously.
+
+NOTE: If you don't set this option, updating signs for a non-VCS file can lead
+to a significant delay since all supported and installed VCS will be tested
+for. (But this also happens only once, afterwards the buffer is registered as
+inactive.)
+
+NOTE: Some VCS rely on a an external diff tool to work properly (svn, darcs,
+bzr, fossil), thus you have to make sure that Vim can find a valid diff tool.
+So either the one you set through |g:signify_difftool| or "diff" by default.
+
+------------------------------------------------------------------------------
+ *g:signify_realtime* >
+ let g:signify_realtime = 0
+<
+By default, the plugin is quite conservative and only updates on:
+
+ |BufRead| Opening a buffer.
+ |BufWritePost| Saving a buffer.
+
+When this option is set, you get more aggressive sign updates:
+
+ |BufEnter| Opening or switching to another buffer.
+ |WinEnter| Opening or switching to another window.
+ |BufWritePost| Saving a buffer.
+ |FocusGained| When the window containing Vim gains focus.
+ Disable with |g:signify_update_on_focusgained|.
+ |CursorHold| After 'updatetime' milliseconds without moving the cursor
+ in normal mode. Disable with |g:signify_cursorhold_normal|.
+ This also saves the buffer!~
+ |CursorHoldI| After 'updatetime' milliseconds without moving the cursor
+ in insert mode. Disable with |g:signify_cursorhold_insert|.
+ This also saves the buffer!~
+
+You can check the autocmds yourself: `:au signify`
+
+NOTE: Running Sy on all these events would block too often for older Vim
+versions, thus this option requires Vim 7.4.1967+, which is the minimum
+version needed for asynchronous execution. Older Vim versions silently ignore
+this option.
+
+------------------------------------------------------------------------------
+ *g:signify_vcs_cmds* >
+ let g:signify_vcs_cmds = {
+ \ 'cvs': 'cvs -d '. $CVSROOT .' diff -U0 -- %f' }
+<
+This is a |dict|. They key is any version control system from |g:signify_vcs_list|
+and the value is the corresponding command-line.
+
+Modifiers:~
+
+ %f actual filepath
+ %d |g:signify_difftool|
+ %n Unix: `/dev/null`, Windows: `NUL`
+
+Redirection: Instead of `>foo` use `sy#util#shell_redirect('foo')`. This
+helper function takes 'shellredir' into account.
+
+The output format mustn't change, otherwise Sy won't give any reasonable
+results. It's probably wise to start with the respective default values.
+
+If your VCS program is not in `$PATH` and you have to specify an absolute path,
+escape spaces by quoting, e.g.:
+>
+ let g:signify_vcs_cmds = {
+ \ 'git': '"C:\Program Files (x86)\Git\bin\git.exe" diff --no-color --no-ext-diff -U0 -- %f'
+ \ }
+<
+NOTE: Always test these commands on the shell first and make sure that no
+colors are emitted. Our parser expects lines in the diff output to start with
+"@@", but with colors the line starts with escape sequences instead.
+
+Default:
+>
+ let g:signify_vcs_cmds = {
+ \ 'git': 'git diff --no-color --no-ext-diff -U0 -- %f',
+ \ 'hg': 'hg diff --config extensions.color=! --config defaults.diff= --nodates -U0 -- %f',
+ \ 'svn': 'svn diff --diff-cmd %d -x -U0 -- %f',
+ \ 'bzr': 'bzr diff --using %d --diff-options=-U0 -- %f',
+ \ 'darcs': 'darcs diff --no-pause-for-gui --diff-command="%d -U0 %1 %2" -- %f',
+ \ 'fossil': 'fossil diff --unified -c 0 -- %f',
+ \ 'cvs': 'cvs diff -U0 -- %f',
+ \ 'rcs': 'rcsdiff -U0 %f 2>%n',
+ \ 'accurev': 'accurev diff %f -- -U0',
+ \ 'perforce': 'p4 info '. sy#util#shell_redirect('%n') . (has('win32') ? ' &&' : ' && env P4DIFF= P4COLORS=') .' p4 diff -du0 %f',
+ \ 'tfs': 'tf diff -version:W -noprompt %f',
+ \ }
+<
+------------------------------------------------------------------------------
+ *g:signify_vcs_cmds_diffmode* >
+ let g:signify_vcs_cmds_diffmode = {
+ \ 'git': 'git show HEAD:./%f',
+ \ 'hg': 'hg cat %f',
+ \ 'svn': 'svn cat %f',
+ \ 'bzr': 'bzr cat %f',
+ \ 'darcs': 'darcs show contents -- %f',
+ \ 'cvs': 'cvs up -p -- %f 2>%n',
+ \ 'perforce': 'p4 print %f',
+ \ }
+<
+The command to use for |:SignifyDiff|. This option takes the same format as
+|g:signify_vcs_cmds|.
+
+------------------------------------------------------------------------------
+ *g:signify_disable_by_default* >
+ let g:signify_disable_by_default = 0
+<
+This makes Sy not looking for changes for each new buffer. You can easily
+enable it later using |signify-:SignifyToggle|.
+
+------------------------------------------------------------------------------
+ *g:signify_skip_filename_pattern*
+ *g:signify_skip_filename*
+ *g:signify_skip_filetype*
+>
+ let g:signify_skip_filetype = { 'vim': 1, 'c': 1 }
+ let g:signify_skip_filename = { '/home/user/.vimrc': 1 }
+<
+Don't activate the plugin for these filetypes and/or filenames. Filenames have
+to be absolute paths.
+
+These options must be |Dict|s for faster lookup.
+>
+ let g:signify_skip_filename_pattern = [ 'foo.*bar', 'tmp' ]
+<
+Don't activate the plugin for filenames matching these patterns.
+
+Default: <none>
+
+------------------------------------------------------------------------------
+ *g:signify_update_on_bufenter* >
+ let g:signify_update_on_bufenter = 0
+<
+Update signs when entering a buffer that was modified.
+
+NOTE: This also saves the buffer to disk!
+
+------------------------------------------------------------------------------
+ *g:signify_update_on_focusgained* >
+ let g:signify_update_on_focusgained = 0
+<
+Update the signs on |FocusGained|, thus when the window holding Vim gains focus.
+It does so by executing |signify-:SignifyRefresh|.
+
+NOTE: The |FocusGained| event is fired for all GUIs and even a few terminal
+emulators. If you use tmux, put `set-option -g focus-events on` in your
+tmux.conf.
+
+------------------------------------------------------------------------------
+ *g:signify_line_highlight* >
+ let g:signify_line_highlight = 0
+<
+Enable line highlighting in addition to using signs by default.
+
+------------------------------------------------------------------------------
+ *g:signify_sign_add*
+ *g:signify_sign_delete*
+ *g:signify_sign_delete_first_line*
+ *g:signify_sign_change*
+ *g:signify_sign_changedelete*
+>
+ let g:signify_sign_add = '+'
+ let g:signify_sign_delete = '_'
+ let g:signify_sign_delete_first_line = '‾'
+ let g:signify_sign_change = '!'
+ let g:signify_sign_changedelete = g:signify_sign_change
+<
+The sign to use if a line was added, deleted or changed or a combination of
+these.
+
+You can use unicode characters, but signs must not take up more than two
+cells. Otherwise |E239| is thrown.
+
+If |g:signify_sign_show_count| is set, |g:signify_sign_delete| and
+|g:signify_sign_changedelete| get truncated as needed.
+
+------------------------------------------------------------------------------
+ *g:signify_sign_show_count* >
+ let g:signify_sign_show_count = 1
+<
+Add the number of deleted lines to |g:signify_sign_delete| (up to 99) and
+|g:signify_sign_changedelete| (up to 9). Otherwise only the normal signs will
+be shown.
+
+------------------------------------------------------------------------------
+ *g:signify_sign_show_text* >
+ let g:signify_sign_show_text = 1
+<
+Don't show any text in the sign column. (Actually it will show a non-breaking
+space.)
+
+This is useful if you only want to see colors instead. If your colorscheme
+doesn't do it for you, you can set the background color of a particular sign
+yourself: |signify-colors|.
+
+If you want no sign column at all and use Vim 7.4.2201+, use 'signcolumn'.
+
+------------------------------------------------------------------------------
+ *g:signify_cursorhold_normal*
+ *g:signify_cursorhold_insert* >
+ let g:signify_cursorhold_normal = 0
+ let g:signify_cursorhold_insert = 0
+<
+Additionally trigger sign updates in normal or insert mode after 'updatetime'
+miliseconds without any keypresses. This fires only once between keypresses,
+thus not every 'updatetime' miliseconds.
+
+NOTE: This also saves the buffer to disk!
+
+------------------------------------------------------------------------------
+ *g:signify_difftool* >
+ let g:signify_difftool = 'gnudiff'
+<
+This will avoid the attempt to find the proper diff tool for version control
+systems that rely on an external diff tool that supports the -U0 flag. These
+are: svn, bzr, darcs, fossil.
+
+Default: "diff"
+
+------------------------------------------------------------------------------
+ *g:signify_fold_context* >
+ let g:signify_fold_context = [0, 3]
+<
+This changes the number of lines of context that |signify-:SignifyFold| should
+use. The first element describes the context at foldlevel 0 and the second the
+context at foldlevel 1.
+
+Example:~
+
+Using "[0,3]" means that after using :SignifyFold, only changed lines will be
+unfolded. Using |zo| (and similar |fold-commands|) on a folded line will reveal
+3 more lines of context. Using |zo| a second time will reveal everything.
+
+Default: [3, 8]
+
+==============================================================================
+COMMAND *signify-commands*
+ *signify-:SignifyEnable* >
+ :SignifyEnable
+<
+Enable the plugin for the current buffer only.
+
+Can also be used to when a repository was initialized while Sy was already
+loaded.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyDisable* >
+ :SignifyDisable
+<
+Disable the plugin for the current buffer only.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyToggle* >
+ :SignifyToggle
+<
+Toggle the plugin for the current buffer only.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyToggleHighlight* >
+ :SignifyToggleHighlight
+<
+Toggle line highlighting for lines containing changes.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyRefresh* >
+ :SignifyRefresh
+<
+Refresh signs in all windows.
+
+NOTE: Nothing will happen, if :SignifyRefresh is used from the |cmdline-window|.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyDiff* >
+ :SignifyDiff[!]
+<
+Open a new tab with two windows using |diff-mode| to show the differences
+between the current file and its version that was last checked in.
+
+With [!], no new tab will be opened.
+
+Also see |g:signify_vcs_cmds_diffmode|.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyFold* >
+ :SignifyFold[!]
+<
+Open the current buffer in a new tabpage and set 'foldexpr' so that only
+changed lines with their surrounding context are unfolded.
+
+The number of lines per context can be changed via |g:signify_fold_context|.
+
+The |foldtext| will be set so that the left side shows the first line in the
+fold and the right side shows something like "50 [1]" which whereas "50"
+stands for the number of folded lines and the "1" is the foldlevel.
+
+If [!] is given, Sy will do the same without opening an extra tabpage. Another
+":SignifyFold!" will toggle back to the previous settings.
+
+See |folds| to learn more about folding.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyList* >
+ :SignifyList
+<
+Outputs debug info for all managed buffers.
+
+------------------------------------------------------------------------------
+ *signify-:SignifyDebug* >
+ :SignifyDebug
+<
+In case no signs are shown, although the buffer contains a file controlled by
+a supported VCS, use this command.
+
+It will show all tried commands and their output. Errors will be highlighted
+via |hl-ErrorMsg|.
+
+==============================================================================
+AUTOCOMMAND *signify-autocommand*
+
+User SignifySetup~
+
+ This event fires at the end of `plugin/signify.vim`, in case you want to
+ change any of the default autocmds, commands, or mappings.
+
+User Signify~
+
+ This event fires when Sy updated the signs.
+
+NOTE: Autocmds don't nest by default. If you use any command that triggers new
+events, make sure to use |autocmd-nested|.
+
+==============================================================================
+MAPPINGS *signify-mappings*
+
+------------------------------------------------------------------------------
+Hunk jumping:~
+
+ ]c Jump to next hunk.
+ [c Jump to previous hunk.
+
+ ]C Jump to last hunk.
+ [C Jump to first hunk.
+
+These keys only get mapped by default when:
+
+ - The keys are not mapped already (by you or another plugin).
+ - There are no other keys that are mapped to do the same (to avoid duplicate
+ mappings).
+
+Mapping other keys:
+>
+ nmap <leader>gj <plug>(signify-next-hunk)
+ nmap <leader>gk <plug>(signify-prev-hunk)
+ nmap <leader>gJ 9999<leader>gj
+ nmap <leader>gK 9999<leader>gk
+<
+------------------------------------------------------------------------------
+Hunk text object:~
+>
+ omap ic <plug>(signify-motion-inner-pending)
+ xmap ic <plug>(signify-motion-inner-visual)
+ omap ac <plug>(signify-motion-outer-pending)
+ xmap ac <plug>(signify-motion-outer-visual)
+<
+"ic" operates on all lines of the current hunk. "ac" does the same, but also
+removes all trailing empty lines.
+
+NOTE: Don't be surprised that this also works with "deleted lines".
+
+==============================================================================
+COLORS *signify-colors*
+
+This plugin defines highlighting groups for two different places: for lines
+and signs. Per default these don't really exist but are linked to the standard
+highlighting groups: |hl-DiffAdd|, |hl-DiffChange|, |hl-DiffDelete|:
+>
+ highlight link SignifyLineAdd DiffAdd
+ highlight link SignifyLineChange DiffChange
+ highlight link SignifyLineDelete DiffDelete
+ highlight link SignifyLineChangeDelete SignifyLineChange
+ highlight link SignifyLineDeleteFirstLine SignifyLineDelete
+
+ highlight link SignifySignAdd DiffAdd
+ highlight link SignifySignChange DiffChange
+ highlight link SignifySignDelete DiffDelete
+ highlight link SignifySignChangeDelete SignifySignChange
+ highlight link SignifySignDeleteFirstLine SignifySignDelete
+<
+Thus if you do not want to change the standard highlighting groups, but want
+different colors for either your signs or lines, you can overwrite these
+highlighting groups in your vimrc.
+
+Assuming you prefer |hl-DiffText| over |hl-DiffChange| for changed lines:
+>
+ highlight link SignifyLineChange DiffText
+<
+Personally I use (256 colors terminal):
+>
+ " highlight lines in Sy and vimdiff etc.)
+
+ highlight DiffAdd cterm=bold ctermbg=none ctermfg=119
+ highlight DiffDelete cterm=bold ctermbg=none ctermfg=167
+ highlight DiffChange cterm=bold ctermbg=none ctermfg=227
+
+ " highlight signs in Sy
+
+ highlight SignifySignAdd cterm=bold ctermbg=237 ctermfg=119
+ highlight SignifySignDelete cterm=bold ctermbg=237 ctermfg=167
+ highlight SignifySignChange cterm=bold ctermbg=237 ctermfg=227
+<
+For Unix people there is a small script, showcolors.bash, in the repo that
+shows all 256 colors available to the terminal. That makes picking the right
+numbers much easier.
+
+Default highlight groups:~
+
+The sign column (often mistakenly called "gutter") itself (all lines without
+signs) is highlighted by |hl-SignColumn|. Some colorschemes define no background
+color for |hl-Normal| but for |hl-SignColumn|. To avoid that visible difference:
+>
+ highlight SignColumn ctermbg=NONE cterm=NONE guibg=NONE gui=NONE
+<
+==============================================================================
+FAQ *signify-faq*
+
+ |signify-faq-01| What about vim-flagship support?
+ |signify-faq-02| The plugin is slow!
+ |signify-faq-03| Line highlighting without showing signs?
+
+------------------------------------------------------------------------------
+ *signify-faq-01*
+What about vim-flagship support?~
+
+sy#repo#get_stats() returns a list with 3 integers for added, modified and
+removed lines. Create a wrapper function around it and return a string:
+>
+ function! s:sy_stats_wrapper()
+ let symbols = ['+', '-', '~']
+ let [added, modified, removed] = sy#repo#get_stats()
+ let stats = [added, removed, modified] " reorder
+ let hunkline = ''
+
+ for i in range(3)
+ if stats[i] > 0
+ let hunkline .= printf('%s%s ', symbols[i], stats[i])
+ endif
+ endfor
+
+ if !empty(hunkline)
+ let hunkline = printf('[%s]', hunkline[:-2])
+ endif
+
+ return hunkline
+ endfunction
+
+ autocmd User Flags call Hoist('buffer', function('s:sy_stats_wrapper'))
+<
+------------------------------------------------------------------------------
+ *signify-faq-02*
+The plugin is slow!~
+
+ * Set |g:signify_vcs_list|. Always.
+
+ * Sy relies on external tools. Check if these are the bottleneck.
+
+ If you use a centralized VCS like Subversion, is the connection to the
+ server slow?
+
+ If you use a decentralized VCS like Git, are you working on a slow remote
+ file system?
+
+ * Vim its sign handling code is known to be slow. If the delay is very long,
+ chances are the diff is just huge. This often happens after adding (or
+ removing) a huge file to the repo.
+
+------------------------------------------------------------------------------
+ *signify-faq-03*
+Line highlighting without showing signs?~
+
+The line highlighting relies on signs being placed. The sign column is being
+shown automatically if there are placed signs.
+
+With a recent Vim, you can change that behaviour using 'signcolumn'.
+
+==============================================================================
+EXAMPLE *signify-example*
+
+An example configuration for Sy:
+>
+ let g:signify_vcs_list = [ 'git', 'hg' ]
+ let g:signify_cursorhold_insert = 1
+ let g:signify_cursorhold_normal = 1
+ let g:signify_update_on_bufenter = 0
+ let g:signify_update_on_focusgained = 1
+
+ nnoremap <leader>gt :SignifyToggle<CR>
+ nnoremap <leader>gh :SignifyToggleHighlight<CR>
+ nnoremap <leader>gr :SignifyRefresh<CR>
+ nnoremap <leader>gd :SignifyDebug<CR>
+
+ " hunk jumping
+ nmap <leader>gj <plug>(signify-next-hunk)
+ nmap <leader>gk <plug>(signify-prev-hunk)
+
+ " hunk text object
+ omap ic <plug>(signify-motion-inner-pending)
+ xmap ic <plug>(signify-motion-inner-visual)
+ omap ac <plug>(signify-motion-outer-pending)
+ xmap ac <plug>(signify-motion-outer-visual)
+<
+==============================================================================
+vim: et tw=78
diff --git a/start/signify/plugin/signify.vim b/start/signify/plugin/signify.vim
new file mode 100644
index 0000000..3a13442
--- /dev/null
+++ b/start/signify/plugin/signify.vim
@@ -0,0 +1,120 @@
+" vim: et sw=2 sts=2
+
+scriptencoding utf-8
+
+if exists('g:loaded_signify') || !has('signs') || &compatible
+ finish
+endif
+
+" Init: values {{{1
+let g:loaded_signify = 1
+let g:signify_locked = 0
+let s:has_doau_modeline = v:version > 703 || v:version == 703 && has('patch442')
+
+" Init: autocmds {{{1
+augroup signify
+ autocmd!
+
+ autocmd QuickFixCmdPre *vimgrep* let g:signify_locked = 1
+ autocmd QuickFixCmdPost *vimgrep* let g:signify_locked = 0
+
+ autocmd CmdwinEnter * let g:signify_cmdwin_active = 1
+ autocmd CmdwinLeave * let g:signify_cmdwin_active = 0
+
+ autocmd BufWritePost * call sy#start()
+
+ if get(g:, 'signify_realtime') && has('patch-7.4.1967')
+ autocmd WinEnter * call sy#start()
+ if get(g:, 'signify_update_on_bufenter')
+ autocmd BufEnter * nested call s:save()
+ else
+ autocmd BufEnter * call sy#start()
+ endif
+ if get(g:, 'signify_cursorhold_normal', 1)
+ autocmd CursorHold * nested call s:save()
+ endif
+ if get(g:, 'signify_cursorhold_insert', 1)
+ autocmd CursorHoldI * nested call s:save()
+ endif
+ if get(g:, 'signify_update_on_focusgained', 1)
+ autocmd FocusGained * SignifyRefresh
+ endif
+ else
+ autocmd BufRead * call sy#start()
+ if get(g:, 'signify_update_on_bufenter')
+ autocmd BufEnter * nested call s:save()
+ endif
+ if get(g:, 'signify_cursorhold_normal')
+ autocmd CursorHold * nested call s:save()
+ endif
+ if get(g:, 'signify_cursorhold_insert')
+ autocmd CursorHoldI * nested call s:save()
+ endif
+ if get(g:, 'signify_update_on_focusgained')
+ autocmd FocusGained * SignifyRefresh
+ endif
+ endif
+
+ if has('gui_running') && has('win32') && argc()
+ " Fix 'no signs at start' race.
+ autocmd GUIEnter * redraw
+ endif
+augroup END
+
+" Init: commands {{{1
+
+command! -nargs=0 -bar SignifyList call sy#debug#list_active_buffers()
+command! -nargs=0 -bar SignifyDebug call sy#repo#debug_detection()
+command! -nargs=0 -bar -bang SignifyFold call sy#fold#dispatch(<bang>1)
+command! -nargs=0 -bar -bang SignifyDiff call sy#repo#diffmode(<bang>1)
+command! -nargs=0 -bar SignifyRefresh call sy#util#refresh_windows()
+command! -nargs=0 -bar SignifyEnable call sy#enable()
+command! -nargs=0 -bar SignifyDisable call sy#disable()
+command! -nargs=0 -bar SignifyToggle call sy#toggle()
+command! -nargs=0 -bar SignifyToggleHighlight call sy#highlight#line_toggle()
+
+" Init: mappings {{{1
+let s:cpoptions = &cpoptions
+set cpoptions+=B
+
+" hunk jumping
+nnoremap <silent> <expr> <plug>(signify-next-hunk) &diff
+ \ ? ']c'
+ \ : ":\<c-u>call sy#jump#next_hunk(v:count1)\<cr>"
+nnoremap <silent> <expr> <plug>(signify-prev-hunk) &diff
+ \ ? '[c'
+ \ : ":\<c-u>call sy#jump#prev_hunk(v:count1)\<cr>"
+
+if empty(maparg(']c', 'n')) && !hasmapto('<plug>(signify-next-hunk)', 'n')
+ nmap ]c <plug>(signify-next-hunk)
+ if empty(maparg(']C', 'n')) && !hasmapto('9999]c', 'n')
+ nmap ]C 9999]c
+ endif
+endif
+if empty(maparg('[c', 'n')) && !hasmapto('<plug>(signify-prev-hunk)', 'n')
+ nmap [c <plug>(signify-prev-hunk)
+ if empty(maparg('[C', 'n')) && !hasmapto('9999[c', 'n')
+ nmap [C 9999[c
+ end
+endif
+
+" hunk text object
+onoremap <silent> <plug>(signify-motion-inner-pending) :<c-u>call sy#util#hunk_text_object(0)<cr>
+xnoremap <silent> <plug>(signify-motion-inner-visual) :<c-u>call sy#util#hunk_text_object(0)<cr>
+onoremap <silent> <plug>(signify-motion-outer-pending) :<c-u>call sy#util#hunk_text_object(1)<cr>
+xnoremap <silent> <plug>(signify-motion-outer-visual) :<c-u>call sy#util#hunk_text_object(1)<cr>
+
+let &cpoptions = s:cpoptions
+unlet s:cpoptions
+
+" Function: save {{{1
+
+function! s:save()
+ if exists('b:sy') && b:sy.active && &modified && &modifiable && ! &readonly
+ write
+ endif
+endfunction
+
+if exists('#User#SignifySetup')
+ execute 'doautocmd' (s:has_doau_modeline ? '<nomodeline>' : '') 'User SignifySetup'
+endif