diff options
author | Michael Smith <mikesmiffy128@gmail.com> | 2022-05-22 22:47:23 +0100 |
---|---|---|
committer | Michael Smith <mikesmiffy128@gmail.com> | 2022-05-22 22:47:23 +0100 |
commit | 95aea6b533e71e478d61d18fac71cca116c56a4d (patch) | |
tree | 1a1f42f723772258cc54551495826768f374474a /start/signify |
Add all the plugins I currently use
Diffstat (limited to 'start/signify')
-rw-r--r-- | start/signify/LICENSE | 20 | ||||
-rw-r--r-- | start/signify/README.md | 54 | ||||
-rw-r--r-- | start/signify/autoload/sy.vim | 199 | ||||
-rw-r--r-- | start/signify/autoload/sy/debug.vim | 48 | ||||
-rw-r--r-- | start/signify/autoload/sy/fold.vim | 125 | ||||
-rw-r--r-- | start/signify/autoload/sy/highlight.vim | 94 | ||||
-rw-r--r-- | start/signify/autoload/sy/jump.vim | 29 | ||||
-rw-r--r-- | start/signify/autoload/sy/repo.vim | 512 | ||||
-rw-r--r-- | start/signify/autoload/sy/sign.vim | 275 | ||||
-rw-r--r-- | start/signify/autoload/sy/util.vim | 109 | ||||
-rw-r--r-- | start/signify/doc/signify.txt | 689 | ||||
-rw-r--r-- | start/signify/plugin/signify.vim | 120 |
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 |