Commits

Nicola Paolucci committed 3c23e57

Squashed '.vim/bundle/airblade-vim-gitgutter/' content from commit ff031d0

git-subtree-dir: .vim/bundle/airblade-vim-gitgutter
git-subtree-split: ff031d022f2123353bc93a3aa97290287c10a287

Comments (0)

Files changed (5)

+/doc/tags
+## Vim Git Gutter
+
+A Vim plugin which shows a git diff in the 'gutter' (sign column).  It shows whether each line has been added, modified, and where lines have been removed.
+
+This is a port of the [Git Gutter][st2gg] plugin for Sublime Text 2.
+
+
+### Screenshot
+
+![screenshot](https://raw.github.com/airblade/vim-gitgutter/master/screenshot.png)
+
+In the screenshot above you can see:
+
+* Line 15 has been modified.
+* Lines 21-24 are new.
+* A line or lines were removed between lines 25 and 26.
+
+
+### Installation
+
+Before installation, please check your Vim supports signs by running `:echo has('signs')`.  `1` means you're all set; `0` means you need to install a Vim with signs support.  If you're compiling Vim yourself you need the 'big' or 'huge' feature set.  [MacVim][] supports signs.
+
+If you don't have a preferred installation method, I recommend installing [pathogen.vim][pathogen], and then simply copy and paste:
+
+```
+cd ~/.vim/bundle
+git clone git://github.com/airblade/vim-gitgutter.git
+```
+
+Or for [Vundle](https://github.com/gmarik/vundle) users:
+
+Add `Bundle 'airblade/vim-gitgutter'` to your `~/.vimrc` and then:
+
+* either within Vim: `:BundleInstall`
+* or in your shell: `vim +BundleInstall +qall`
+
+
+### Usage
+
+You don't have to do anything: it just works.
+
+Please note the plugin diffs your saved buffers, i.e. the files on disk.  It produces the same result as running `git diff` on the command line.  It won't see any unsaved changes to a buffer.
+
+You can explicitly turn vim-gitgutter off and on (defaults to on):
+
+* turn off with `:GitGutterDisable`
+* turn on with `:GitGutterEnable`
+* toggle with `:GitGutterToggle`.
+
+And you can turn line highlighting on and off (defaults to off):
+
+* turn on with `:GitGutterLineHighlightsEnable`
+* turn off with `:GitGutterLineHighlightsDisable`
+* toggle with `:GitGutterLineHighlightsToggle`.
+
+Furthermore you can jump between hunks:
+
+* jump to next hunk: `]h`
+* jump to previous hunk: `[h`.
+
+Both of those take a preceding count.
+
+To set your own mappings for these, for example `gh` and `gH`:
+
+```viml
+nmap gh <Plug>GitGutterNextHunk
+nmap gH <Plug>GitGutterPrevHunk
+```
+
+Finally, you can force vim-gitgutter to update its signs across all visible buffers with `:GitGutterAll`.
+
+See the customisation section below for how to change the defaults.
+
+
+### Customisation
+
+You can customise:
+
+* The sign column's colours
+* Whether or not the sign column is shown when there aren't any signs (defaults to no)
+* The signs' colours and symbols
+* Line highlights
+* Extra arguments for `git diff`
+* Whether or not to escape `grep` (default to no)
+* Whether or not vim-gitgutter is on initially (defaults to on)
+* Whether or not signs are shown (defaults to yes)
+* Whether or not line highlighting is on initially (defaults to off)
+* Whether or not vim-gitgutter runs eagerly (defaults to yes)
+
+Please note that vim-gitgutter won't override any colours or highlights you've set in your colorscheme.
+
+
+#### Sign column
+
+The background colour of the sign column is controlled by the `SignColumn` highlight group.  This will be either set in your colorscheme or Vim's default.
+
+To find out where it's set, and to what it's set, use `:verbose highlight SignColumn`.
+
+If your `SignColumn` is not set (`:highlight SignColumn` gives you `SignColumn xxx cleared`), vim-gitgutter will set it to the same as your line number column (i.e. the `LineNr` highlight group).
+
+To change your sign column's appearance, update your colorscheme or `~/.vimrc` like this:
+
+* For the same appearance as your line number column: `highlight clear SignColumn`
+* For a specific appearance on terminal Vim: `highlight SignColumn ctermbg=whatever`
+* For a specific appearance on gVim/MacVim: `highlight SignColumn guibg=whatever`
+
+By default the sign column will appear when there are signs to show and disappear when there aren't.  If you would always like the sign column to be there, add `let g:gitgutter_sign_column_always = 1` to your `~/.vimrc`.
+
+
+#### Signs' colours and symbols
+
+To customise the colours, set up the following highlight groups in your colorscheme or `~/.vimrc`:
+
+```viml
+GitGutterAdd          " an added line
+GitGutterChange       " a changed line
+GitGutterDelete       " at least one removed line
+GitGutterChangeDelete " a changed line followed by at least one removed line
+```
+
+You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd DiffAdd`.
+
+To customise the symbols, add the following to your `~/.vimrc`:
+
+```viml
+let g:gitgutter_sign_added = 'xx'
+let g:gitgutter_sign_modified = 'yy'
+let g:gitgutter_sign_removed = 'zz'
+let g:gitgutter_sign_modified_removed = 'ww'
+```
+
+#### Whether or not signs are shown
+
+If you never want signs to be shown (presumably you only want the line highlights), add this to your `~/.vimrc`:
+
+```viml
+let g:gitgutter_signs = 0
+```
+
+#### Line highlights
+
+Similarly to the signs' colours, set up the following highlight groups in your colorscheme or `~/.vimrc`:
+
+```viml
+GitGutterAddLine          " default: links to DiffAdd
+GitGutterChangeLine       " default: links to DiffChange
+GitGutterDeleteLine       " default: links to DiffDelete
+GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault, i.e. DiffChange
+```
+
+#### Extra arguments for `git diff`
+
+If you want to pass extra arguments to `git diff`, for example to ignore whitespace, do so like this:
+
+```viml
+let g:gitgutter_diff_args = '-w'
+```
+
+#### Whether or not to escape `grep`
+
+If you have `grep` aliased to something which changes its output, for example `grep --color=auto -H`, you will need to tell vim-gitgutter to use raw grep:
+
+```viml
+let g:gitgutter_escape_grep = 1
+```
+
+#### To turn off vim-gitgutter by default
+
+Add `let g:gitgutter_enabled = 0` to your `~/.vimrc`.
+
+
+#### To turn on line highlighting by default
+
+Add `let g:gitgutter_highlight_lines = 1` to your `~/.vimrc`.
+
+
+#### To stop vim-gitgutter running eagerly
+
+By default the plugin runs every time you read a file, on `BufEnter`, `TabEnter` and `FocusGained`.
+
+This can cause a noticeable lag for some people so you can set the plugin to run instead only when you read or write a file.
+
+To turn off eager execution, add this to your `~/.vimrc`:
+
+```
+let g:gitgutter_eager = 0
+```
+
+Note that `FocusGained` cannot be used with gVim on Windows due to a Vim/shell bug causing an infinite loop.
+
+
+### FAQ
+
+> Why are the colours in the sign column weird?
+
+Your colorscheme is configuring the `SignColumn` highlight group weirdly.  Please see the section above on customising the sign column.
+
+> There's a noticeable lag when vim-gitter runs; how can I avoid it?
+
+By default vim-gitgutter runs often so the signs are as accurate as possible.  However on some systems this causes a noticeable lag.  If you would like to trade a little accuracy for speed, add this to your `~/.vimrc`:
+
+```viml
+let g:gitgutter_eager = 0
+```
+
+> Why is no sign shown if I delete the first line(s) in a file?
+
+vim-gitgutter shows removed lines with a sign on the line above.  In this case there isn't a line above so vim-gitgutter can't show the sign.
+
+> What happens if I also use another plugin which uses signs (e.g. Syntastic)?
+
+Vim only allows one sign per line.  Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else.  If so it doesn't do anything.  In other words vim-gitgutter won't overwrite another plugin's signs.  It also won't remove another plugin's signs.
+
+> Why aren't any signs showing at all?
+
+Here are some things you can check:
+
+* Your git config is compatible with the version of git which your Vim is calling (`:echo system('git --version')`).
+* Your Vim supports signs (`:echo has('signs')` should give `1`).
+* Your file is being tracked by git and has unstaged, saved changes.
+
+
+### Alternatives
+
+Related:
+
+* [textobj-gitgutter][togg] (lets you treat diff hunks as text objects)
+* [vim-gitgutter][mercurial] - Mercurial fork
+
+Vim alternatives:
+
+* [git-gutter-vim][ggv]
+* [vim-git-inline-diff][vgid]
+* [quickfixsigns_vim][qf] (a superset of this functionality)
+* [iwilldiffer][iwd]
+* [svndiff][svndiff]
+* [sign-diff][signdiff]
+* [changesPlugin][changes]
+
+Other editors:
+
+* [Git Gutter][st2gg] for Sublime Text 2
+* [git-gutter.el][gge] for Emacs
+
+Also, this may be of interest:
+
+* [fugitive.vim][fugitive] is a full-on Git wrapper.  It doesn't show git diffs in the gutter (ha!) but it does a bazillion other git things.
+
+
+### Shameless Plug
+
+If this plugin has helped you, or you'd like to learn more about Vim, why not check out these two screencasts I wrote for PeepCode:
+
+* [Smash Into Vim I][siv1]
+* [Smash Into Vim II][siv2]
+
+You can read reviews at PeepCode and also on my [portfolio][].
+
+
+### Intellectual Property
+
+Copyright Andrew Stewart, AirBlade Software Ltd.  Released under the MIT licence.
+
+
+  [st2gg]: https://github.com/jisaacks/GitGutter
+  [pathogen]: https://github.com/tpope/vim-pathogen
+  [qf]: https://github.com/tomtom/quickfixsigns_vim
+  [fugitive]: https://github.com/tpope/vim-fugitive
+  [siv1]: https://peepcode.com/products/smash-into-vim-i
+  [siv2]: https://peepcode.com/products/smash-into-vim-ii
+  [portfolio]: http://airbladesoftware.com/portfolio#vim
+  [vgid]: https://github.com/luxflux/vim-git-inline-diff
+  [gge]: https://github.com/syohex/emacs-git-gutter
+  [iwd]: https://bitbucket.org/sirpengi/iwilldiffer
+  [svndiff]: http://www.vim.org/scripts/script.php?script_id=1881
+  [signdiff]: http://www.vim.org/scripts/script.php?script_id=2712
+  [changes]: http://www.vim.org/scripts/script.php?script_id=3052
+  [ggv]: https://github.com/akiomik/git-gutter-vim
+  [togg]:https://github.com/gilligan/textobj-gitgutter
+  [mercurial]: https://github.com/safetydank/vim-gitgutter
+  [macvim]: http://code.google.com/p/macvim/

doc/gitgutter.txt

+*gitgutter.txt*              A Vim plugin which shows a git diff in the gutter.
+
+
+                           Vim Git Gutter
+
+
+Author:            Andy Stewart <http://airbladesoftware.com/>
+Plugin Homepage:   <https://github.com/airblade/vim-gitgutter>
+
+===============================================================================
+CONTENTS                                                    *GitGutterContents*
+
+  1.  Introduction ................. |GitGutterIntroduction|
+  2.  Installation ................. |GitGutterInstallation|
+  3.  Usage ........................ |GitGutterUsage|
+  4.  Commands ..................... |GitGutterCommands|
+  5.  FAQ .......................... |GitGutterFAQ|
+
+===============================================================================
+1. INTRODUCTION                                         *GitGutterIntroduction*
+                                                                    *GitGutter*
+
+Vim Git Gutter is a Vim plugin which shows a git diff in the 'gutter' (sign
+column). It shows whether each line has been added, modified, and where lines
+have been removed.
+
+This is a port of the Git Gutter plugin for Sublime Text 2.
+
+===============================================================================
+2. INSTALLATION                                         *GitGutterInstallation*
+
+If you don't have a preferred installation method, I recommend installing
+pathogen.vim, and then simply copy and paste:
+>
+  cd ~/.vim/bundle
+  git clone git://github.com/airblade/vim-gitgutter.git
+<
+Or for Vundle users:
+
+Add Bundle 'airblade/vim-gitgutter' to your |vimrc| and then:
+
+  - either within Vim: :BundleInstall
+  - or in your shell: vim +BundleInstall +qall
+
+===============================================================================
+3. USAGE                                                       *GitGutterUsage*
+
+You don't have to do anything: it just works.
+
+===============================================================================
+4. COMMANDS                                                 *GitGutterCommands*
+
+Commands for turning Git Gutter on and off:
+
+  :GitGutterDisable                                         *:GitGutterDisable*
+      Explicitly turn Git Gutter off.
+
+  :GitGutterEnable                                           *:GitGutterEnable*
+      Explicitly turn Git Gutter on.
+
+  :GitGutterToggle                                           *:GitGutterToggle*
+      Explicitly turn Git Gutter on if it was off and vice versa.
+
+  :GitGutter                                                       *:GitGutter*
+      Update signs for the current buffer.
+
+  :GitGutterAll                                                 *:GitGutterAll*
+      Update signs across all buffers.
+
+Commands for turning line highlighting on and off (defaults to off):
+
+  :GitGutterLineHighlightsEnable               *:GitGutterLineHighlightsEnable*
+      Explicitly turn line highlighting on.
+
+  :GitGutterLineHighlightsDisable             *:GitGutterLineHighlightsDisable*
+      Explicitly turn line highlighting off.
+
+  :GitGutterLineHighlightsToggle               *:GitGutterLineHighlightsToggle*
+      Explicitly turn line highlighting on if it was off and vice versa.
+
+Commands for jumping between marked hunks:
+
+  :GitGutterNextHunk                                       *:GitGutterNextHunk*
+      Jump to the next marked hunk.  Takes a count.
+
+  :GitGutterPrevHunk                                       *:GitGutterPrevHunk*
+      Jump to the previous marked hunk.  Takes a count.
+
+===============================================================================
+5. CUSTOMISATION                                       *GitGutterCustomisation*
+
+You can customise:
+
+- The sign column's colours
+- The signs' colours and symbols
+- Line highlights
+- Extra arguments for git-diff
+- Whether or not to escape grep (defaults to no)
+- Whether or not vim-gitgutter is on initially (defaults to on)
+- Whether or not signs are shown (defaults to yes)
+- Whether or not line highlighting is on initially (defaults to off)
+- Whether or not vim-gitgutter runs eagerly (defaults to yes)
+
+Please note that vim-gitgutter won't override any colours or highlights you've
+set in your colorscheme.
+
+SIGN COLUMN
+
+The background colour of the sign column is controlled by the |hlSignColumn|
+highlight group.  This will be either set in your colorscheme or Vim's default.
+
+To find out where it's set, and to what it's set, use:
+>
+  :verbose highlight SignColumn
+<
+
+If your `SignColumn` is not set, i.e if
+>
+  :highlight SignColumn  " gives you `SignColumn xxx cleared`
+<
+vim-gitgutter will set it to the same as your line number column (i.e. the
+|hl-LineNr| highlight group).
+
+To change your sign column's appearance, update your colorscheme or |vimrc|
+like this:
+
+  Desired appearance                  Command ~
+  Same as line number column          highlight clear SignColumn
+  User-defined (terminal Vim)         highlight SignColumn ctermbg={whatever}
+  User-defined (graphical Vim)        highlight SignColumn guibg={whatever}
+
+SIGNS' COLOURS AND SYMBOLS
+
+To customise the colours, set up the following highlight groups in your
+colorscheme or |vimrc|:
+
+>
+  GitGutterAdd          " an added line
+  GitGutterChange       " a changed line
+  GitGutterDelete       " at least one removed line
+  GitGutterChangeDelete " a changed line followed by at least one removed line
+<
+
+You can either set these with `highlight GitGutterAdd {key}={arg}...` or link
+them to existing highlight groups with, say:
+>
+  highlight link GitGutterAdd DiffAdd
+<
+
+To customise the symbols, add the following to your |vimrc|:
+>
+  let g:gitgutter_sign_added = 'xx'
+  let g:gitgutter_sign_modified = 'yy'
+  let g:gitgutter_sign_removed = 'zz'
+  let g:gitgutter_sign_modified_removed = 'ww'
+<
+
+SIGNS
+
+To never show signs, use this:
+>
+  let git:gitgutter_signs = 0
+<
+
+LINE HIGHLIGHTS
+
+Similarly to the signs' colours, set up the following highlight groups in your
+colorscheme or |vimrc|:
+>
+  GitGutterAddLine          " default: links to DiffAdd
+  GitGutterChangeLine       " default: links to DiffChange
+  GitGutterDeleteLine       " default: links to DiffDelete
+  GitGutterChangeDeleteLine " default: links to GitGutterChangeLineDefault
+<
+
+EXTRA ARGUMENTS FOR GIT-DIFF
+
+To pass extra arguments to git-diff, add this to your |vimrc|:
+>
+  let g:gitgutter_diff_args = '-w'
+<
+
+TO ESCAPE GREP
+
+To avoid any alias you have for grep, use this:
+>
+  let g:gitgutter_escape_grep = 1
+<
+
+TO TURN OFF VIM-GITGUTTER BY DEFAULT
+
+Add to your |vimrc|
+>
+  let g:gitgutter_enabled = 0
+<
+
+TO TURN ON LINE HIGHLIGHTING BY DEFAULT
+
+Add to your |vimrc|
+>
+  let g:gitgutter_highlight_lines = 1
+<
+
+TO STOP VIM-GITGUTTER RUNNING EAGERLY
+
+Add to your |vimrc|
+>
+  let g:gitgutter_eager = 0
+<
+
+
+===============================================================================
+6. FAQ                                                           *GitGutterFAQ*
+
+a. Why are the colours in the sign column weird?
+
+  Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly.
+  Please see |GitGutterCustomisation| on customising the sign column.
+
+b. Why is no sign shown if I delete the first line(s) in a file?
+
+  vim-gitgutter shows removed lines with a sign on the line above.  In this
+  case there isn't a line above so vim-gitgutter can't show the sign.
+
+c. What happens if I also use another plugin which uses signs (e.g. Syntastic)?
+
+  Vim only allows one sign per line. Before adding a sign to a line,
+  vim-gitgutter checks whether a sign has already been added by somebody else.
+  If so it doesn't do anything. In other words vim-gitgutter won't overwrite
+  another plugin's signs. It also won't remove another plugin's signs.

plugin/gitgutter.vim

+if exists('g:loaded_gitgutter') || !executable('git') || !has('signs') || &cp
+  finish
+endif
+let g:loaded_gitgutter = 1
+
+" Initialisation {{{
+
+function! s:set(var, default)
+  if !exists(a:var)
+    if type(a:default)
+      exe 'let' a:var '=' string(a:default)
+    else
+      exe 'let' a:var '=' a:default
+    endif
+  endif
+endfunction
+
+call s:set('g:gitgutter_enabled',               1)
+call s:set('g:gitgutter_signs',                 1)
+call s:set('g:gitgutter_highlight_lines',       0)
+let s:highlight_lines = g:gitgutter_highlight_lines
+call s:set('g:gitgutter_sign_column_always',    0)
+call s:set('g:gitgutter_eager' ,                1)
+call s:set('g:gitgutter_sign_added',            '+')
+call s:set('g:gitgutter_sign_modified',         '~')
+call s:set('g:gitgutter_sign_removed',          '_')
+call s:set('g:gitgutter_sign_modified_removed', '~_')
+call s:set('g:gitgutter_diff_args',             '')
+call s:set('g:gitgutter_escape_grep',           0)
+
+let s:file = ''
+
+function! s:init()
+  if !exists('g:gitgutter_initialised')
+    call s:define_sign_column_highlight()
+    call s:define_highlights()
+    call s:define_signs()
+
+    " Vim doesn't namespace sign ids so every plugin shares the same
+    " namespace.  Sign ids are simply integers so to avoid clashes with other
+    " signs we guess at a clear run.
+    "
+    " Note also we currently never reset s:next_sign_id.
+    let s:first_sign_id = 3000
+    let s:next_sign_id = s:first_sign_id
+    let s:sign_ids = {}  " key: filename, value: list of sign ids
+    let s:other_signs = []
+    let s:dummy_sign_id = 153
+
+    let s:grep_available = executable('grep')
+    let s:grep_command = ' | ' . (g:gitgutter_escape_grep ? '\grep' : 'grep') . ' -e "^@@ "'
+
+    let g:gitgutter_initialised = 1
+  endif
+endfunction
+
+" }}}
+
+" Utility {{{
+
+function! s:is_active()
+  return g:gitgutter_enabled && s:exists_file() && s:is_in_a_git_repo() && s:is_tracked_by_git()
+endfunction
+
+function! s:current_file()
+  return expand('%:p')
+endfunction
+
+function! s:set_file(file)
+  let s:file = a:file
+endfunction
+
+function! s:file()
+  return s:file
+endfunction
+
+function! s:exists_file()
+  return filereadable(s:file())
+endfunction
+
+function! s:directory_of_file()
+  return shellescape(fnamemodify(s:file(), ':h'))
+endfunction
+
+function! s:discard_stdout_and_stderr()
+  if !exists('s:discard')
+    if &shellredir ==? '>%s 2>&1'
+      let s:discard = ' > /dev/null 2>&1'
+    else
+      let s:discard = ' >& /dev/null'
+    endif
+  endif
+  return s:discard
+endfunction
+
+function! s:command_in_directory_of_file(cmd)
+  return 'cd ' . s:directory_of_file() . ' && ' . a:cmd
+endfunction
+
+function! s:is_in_a_git_repo()
+  let cmd = 'git rev-parse' . s:discard_stdout_and_stderr()
+  call system(s:command_in_directory_of_file(cmd))
+  return !v:shell_error
+endfunction
+
+function! s:is_tracked_by_git()
+  let cmd = 'git ls-files --error-unmatch' . s:discard_stdout_and_stderr() . ' ' . shellescape(s:file())
+  call system(s:command_in_directory_of_file(cmd))
+  return !v:shell_error
+endfunction
+
+function! s:differences(hunks)
+  return len(a:hunks) != 0
+endfunction
+
+function! s:snake_case_to_camel_case(text)
+  return substitute(a:text, '\v(.)(\a+)(_(.)(.+))?', '\u\1\l\2\u\4\l\5', '')
+endfunction
+
+" }}}
+
+" Highlights and signs {{{
+
+function! s:define_sign_column_highlight()
+  highlight default link SignColumn LineNr
+endfunction
+
+function! s:define_highlights()
+  " Highlights used by the signs.
+  highlight GitGutterAddDefault          guifg=#009900 guibg=NONE ctermfg=2 ctermbg=NONE
+  highlight GitGutterChangeDefault       guifg=#bbbb00 guibg=NONE ctermfg=3 ctermbg=NONE
+  highlight GitGutterDeleteDefault       guifg=#ff2222 guibg=NONE ctermfg=1 ctermbg=NONE
+  highlight default link GitGutterChangeDeleteDefault GitGutterChangeDefault
+
+  highlight default link GitGutterAdd          GitGutterAddDefault
+  highlight default link GitGutterChange       GitGutterChangeDefault
+  highlight default link GitGutterDelete       GitGutterDeleteDefault
+  highlight default link GitGutterChangeDelete GitGutterChangeDeleteDefault
+
+  " Highlights used for the whole line.
+  highlight default link GitGutterAddLine          DiffAdd
+  highlight default link GitGutterChangeLine       DiffChange
+  highlight default link GitGutterDeleteLine       DiffDelete
+  highlight default link GitGutterChangeDeleteLine GitGutterChangeLineDefault
+endfunction
+
+function! s:define_signs()
+  sign define GitGutterLineAdded
+  sign define GitGutterLineModified
+  sign define GitGutterLineRemoved
+  sign define GitGutterLineModifiedRemoved
+  sign define GitGutterDummy
+
+  if g:gitgutter_signs
+    call s:define_sign_symbols()
+    call s:define_sign_text_highlights()
+  endif
+  call s:define_sign_line_highlights()
+endfunction
+
+function! s:define_sign_symbols()
+  exe "sign define GitGutterLineAdded           text=" . g:gitgutter_sign_added
+  exe "sign define GitGutterLineModified        text=" . g:gitgutter_sign_modified
+  exe "sign define GitGutterLineRemoved         text=" . g:gitgutter_sign_removed
+  exe "sign define GitGutterLineModifiedRemoved text=" . g:gitgutter_sign_modified_removed
+endfunction
+
+function! s:define_sign_text_highlights()
+  sign define GitGutterLineAdded           texthl=GitGutterAdd
+  sign define GitGutterLineModified        texthl=GitGutterChange
+  sign define GitGutterLineRemoved         texthl=GitGutterDelete
+  sign define GitGutterLineModifiedRemoved texthl=GitGutterChangeDelete
+endfunction
+
+function! s:define_sign_line_highlights()
+  if s:highlight_lines
+    sign define GitGutterLineAdded           linehl=GitGutterAddLine
+    sign define GitGutterLineModified        linehl=GitGutterChangeLine
+    sign define GitGutterLineRemoved         linehl=GitGutterDeleteLine
+    sign define GitGutterLineModifiedRemoved linehl=GitGutterChangeDeleteLine
+  else
+    sign define GitGutterLineAdded           linehl=
+    sign define GitGutterLineModified        linehl=
+    sign define GitGutterLineRemoved         linehl=
+    sign define GitGutterLineModifiedRemoved linehl=
+  endif
+  redraw!
+endfunction
+
+" }}}
+
+" Diff processing {{{
+
+function! s:run_diff()
+  let cmd = 'git diff --no-ext-diff --no-color -U0 ' . g:gitgutter_diff_args . ' ' . shellescape(s:file())
+  if s:grep_available
+    let cmd .= s:grep_command
+  endif
+  let diff = system(s:command_in_directory_of_file(cmd))
+  return diff
+endfunction
+
+function! s:parse_diff(diff)
+  let hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
+  let hunks = []
+  for line in split(a:diff, '\n')
+    let matches = matchlist(line, hunk_re)
+    if len(matches) > 0
+      let from_line  = str2nr(matches[1])
+      let from_count = (matches[2] == '') ? 1 : str2nr(matches[2])
+      let to_line    = str2nr(matches[3])
+      let to_count   = (matches[4] == '') ? 1 : str2nr(matches[4])
+      call add(hunks, [from_line, from_count, to_line, to_count])
+    endif
+  endfor
+  return hunks
+endfunction
+
+function! s:process_hunks(hunks)
+  let modified_lines = []
+  for hunk in a:hunks
+    call extend(modified_lines, s:process_hunk(hunk))
+  endfor
+  return modified_lines
+endfunction
+
+function! s:process_hunk(hunk)
+  let modifications = []
+  let from_line  = a:hunk[0]
+  let from_count = a:hunk[1]
+  let to_line    = a:hunk[2]
+  let to_count   = a:hunk[3]
+
+  if s:is_added(from_count, to_count)
+    call s:process_added(modifications, from_count, to_count, to_line)
+
+  elseif s:is_removed(from_count, to_count)
+    call s:process_removed(modifications, from_count, to_count, to_line)
+
+  elseif s:is_modified(from_count, to_count)
+    call s:process_modified(modifications, from_count, to_count, to_line)
+
+  elseif s:is_modified_and_added(from_count, to_count)
+    call s:process_modified_and_added(modifications, from_count, to_count, to_line)
+
+  elseif s:is_modified_and_removed(from_count, to_count)
+    call s:process_modified_and_removed(modifications, from_count, to_count, to_line)
+
+  endif
+  return modifications
+endfunction
+
+" }}}
+
+" Diff utility {{{
+
+function! s:is_added(from_count, to_count)
+  return a:from_count == 0 && a:to_count > 0
+endfunction
+
+function! s:is_removed(from_count, to_count)
+  return a:from_count > 0 && a:to_count == 0
+endfunction
+
+function! s:is_modified(from_count, to_count)
+  return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count
+endfunction
+
+function! s:is_modified_and_added(from_count, to_count)
+  return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count
+endfunction
+
+function! s:is_modified_and_removed(from_count, to_count)
+  return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count
+endfunction
+
+function! s:process_added(modifications, from_count, to_count, to_line)
+  let offset = 0
+  while offset < a:to_count
+    let line_number = a:to_line + offset
+    call add(a:modifications, [line_number, 'added'])
+    let offset += 1
+  endwhile
+endfunction
+
+function! s:process_removed(modifications, from_count, to_count, to_line)
+  call add(a:modifications, [a:to_line, 'removed'])
+endfunction
+
+function! s:process_modified(modifications, from_count, to_count, to_line)
+  let offset = 0
+  while offset < a:to_count
+    let line_number = a:to_line + offset
+    call add(a:modifications, [line_number, 'modified'])
+    let offset += 1
+  endwhile
+endfunction
+
+function! s:process_modified_and_added(modifications, from_count, to_count, to_line)
+  let offset = 0
+  while offset < a:from_count
+    let line_number = a:to_line + offset
+    call add(a:modifications, [line_number, 'modified'])
+    let offset += 1
+  endwhile
+  while offset < a:to_count
+    let line_number = a:to_line + offset
+    call add(a:modifications, [line_number, 'added'])
+    let offset += 1
+  endwhile
+endfunction
+
+function! s:process_modified_and_removed(modifications, from_count, to_count, to_line)
+  let offset = 0
+  while offset < a:to_count
+    let line_number = a:to_line + offset
+    call add(a:modifications, [line_number, 'modified'])
+    let offset += 1
+  endwhile
+  call add(a:modifications, [a:to_line + offset - 1, 'modified_removed'])
+endfunction
+
+" }}}
+
+" Sign processing {{{
+
+function! s:clear_signs(file_name)
+  if exists('s:sign_ids') && has_key(s:sign_ids, a:file_name)
+    for id in s:sign_ids[a:file_name]
+      exe ":sign unplace" id "file=" . a:file_name
+    endfor
+    let s:sign_ids[a:file_name] = []
+  endif
+endfunction
+
+" This assumes there are no GitGutter signs in the file.
+" If this is untenable we could change the regexp to exclude GitGutter's
+" signs.
+function! s:find_other_signs(file_name)
+  redir => signs
+  silent exe ":sign place file=" . a:file_name
+  redir END
+  let s:other_signs = []
+  for sign_line in split(signs, '\n')
+    if sign_line =~ '^\s\+\w\+='
+      let matches = matchlist(sign_line, '^\s\+\w\+=\(\d\+\)')
+      let line_number = str2nr(matches[1])
+      call add(s:other_signs, line_number)
+    endif
+  endfor
+endfunction
+
+function! s:show_signs(file_name, modified_lines)
+  for line in a:modified_lines
+    let line_number = line[0]
+    let type = 'GitGutterLine' . s:snake_case_to_camel_case(line[1])
+    call s:add_sign(line_number, type, a:file_name)
+  endfor
+endfunction
+
+function! s:add_sign(line_number, name, file_name)
+  let id = s:next_sign_id()
+  if !s:is_other_sign(a:line_number)  " Don't clobber other people's signs.
+    exe ":sign place" id "line=" . a:line_number "name=" . a:name "file=" . a:file_name
+    call s:remember_sign(id, a:file_name)
+  endif
+endfunction
+
+function! s:next_sign_id()
+  let next_id = s:next_sign_id
+  let s:next_sign_id += 1
+  return next_id
+endfunction
+
+function! s:remember_sign(id, file_name)
+  if has_key(s:sign_ids, a:file_name)
+    let sign_ids_for_file = s:sign_ids[a:file_name]
+    call add(sign_ids_for_file, a:id)
+  else
+    let sign_ids_for_file = [a:id]
+  endif
+  let s:sign_ids[a:file_name] = sign_ids_for_file
+endfunction
+
+function! s:is_other_sign(line_number)
+  return index(s:other_signs, a:line_number) == -1 ? 0 : 1
+endfunction
+
+function! s:add_dummy_sign()
+  let last_line = line('$')
+  exe ":sign place" s:dummy_sign_id "line=" . (last_line + 1) "name=GitGutterDummy file=" . s:file()
+endfunction
+
+function! s:remove_dummy_sign()
+  if exists('s:dummy_sign_id')
+    exe ":sign unplace" s:dummy_sign_id "file=" . s:file()
+  endif
+endfunction
+
+" }}}
+
+" Public interface {{{
+
+function! GitGutterAll()
+  for buffer_id in tabpagebuflist() 
+    call GitGutter(expand('#' . buffer_id . ':p'))
+  endfor
+endfunction
+command GitGutterAll call GitGutterAll()
+
+function! GitGutter(file)
+  call s:set_file(a:file)
+  if s:is_active()
+    call s:init()
+    let diff = s:run_diff()
+    let s:hunks = s:parse_diff(diff)
+    let modified_lines = s:process_hunks(s:hunks)
+    if g:gitgutter_sign_column_always
+      call s:add_dummy_sign()
+    else
+      if s:differences(s:hunks)
+        call s:add_dummy_sign()  " prevent flicker
+      else
+        call s:remove_dummy_sign()
+      endif
+    endif
+    call s:clear_signs(a:file)
+    call s:find_other_signs(a:file)
+    call s:show_signs(a:file, modified_lines)
+  endif
+endfunction
+command GitGutter call GitGutter(s:current_file())
+
+function! GitGutterDisable()
+  let g:gitgutter_enabled = 0
+  call s:clear_signs(s:file())
+  call s:remove_dummy_sign()
+endfunction
+command GitGutterDisable call GitGutterDisable()
+
+function! GitGutterEnable()
+  let g:gitgutter_enabled = 1
+  call GitGutter(s:current_file())
+endfunction
+command GitGutterEnable call GitGutterEnable()
+
+function! GitGutterToggle()
+  if g:gitgutter_enabled
+    call GitGutterDisable()
+  else
+    call GitGutterEnable()
+  endif
+endfunction
+command GitGutterToggle call GitGutterToggle()
+
+function! GitGutterLineHighlightsDisable()
+  let s:highlight_lines = 0
+  call s:define_sign_line_highlights()
+endfunction
+command GitGutterLineHighlightsDisable call GitGutterLineHighlightsDisable()
+
+function! GitGutterLineHighlightsEnable()
+  let s:highlight_lines = 1
+  call s:define_sign_line_highlights()
+endfunction
+command GitGutterLineHighlightsEnable call GitGutterLineHighlightsEnable()
+
+function! GitGutterLineHighlightsToggle()
+  let s:highlight_lines = (s:highlight_lines ? 0 : 1)
+  call s:define_sign_line_highlights()
+endfunction
+command GitGutterLineHighlightsToggle call GitGutterLineHighlightsToggle()
+
+function! GitGutterNextHunk(count)
+  if s:is_active()
+    let current_line = line('.')
+    let hunk_count = 0
+    for hunk in s:hunks
+      if hunk[2] > current_line
+        let hunk_count += 1
+        if hunk_count == a:count
+          execute 'normal!' hunk[2] . 'G'
+          break
+        endif
+      endif
+    endfor
+  endif
+endfunction
+command -count=1 GitGutterNextHunk call GitGutterNextHunk(<count>)
+
+function! GitGutterPrevHunk(count)
+  if s:is_active()
+    let current_line = line('.')
+    let hunk_count = 0
+    for hunk in reverse(copy(s:hunks))
+      if hunk[2] < current_line
+        let hunk_count += 1
+        if hunk_count == a:count
+          execute 'normal!' hunk[2] . 'G'
+          break
+        endif
+      endif
+    endfor
+  endif
+endfunction
+command -count=1 GitGutterPrevHunk call GitGutterPrevHunk(<count>)
+
+" Returns the git-diff hunks for the file or an empty list if there
+" aren't any hunks.
+"
+" The return value is a list of lists.  There is one inner list per hunk.
+"
+"   [
+"     [from_line, from_count, to_line, to_count],
+"     [from_line, from_count, to_line, to_count],
+"     ...
+"   ]
+"
+" where:
+"
+" `from`  - refers to the staged file
+" `to`    - refers to the working tree's file
+" `line`  - refers to the line number where the change starts
+" `count` - refers to the number of lines the change covers
+function! GitGutterGetHunks()
+  return s:is_active() ? s:hunks : []
+endfunction
+
+nnoremap <silent> <Plug>GitGutterNextHunk :<C-U>execute v:count1 . "GitGutterNextHunk"<CR>
+nnoremap <silent> <Plug>GitGutterPrevHunk :<C-U>execute v:count1 . "GitGutterPrevHunk"<CR>
+
+if !hasmapto('<Plug>GitGutterNextHunk') && maparg(']h', 'n') ==# ''
+  nmap ]h <Plug>GitGutterNextHunk
+  nmap [h <Plug>GitGutterPrevHunk
+endif
+
+augroup gitgutter
+  autocmd!
+  if g:gitgutter_eager
+    autocmd BufEnter,BufWritePost,FileWritePost * call GitGutter(s:current_file())
+    autocmd TabEnter * call GitGutterAll()
+    if !has('gui_win32')
+      autocmd FocusGained * call GitGutterAll()
+    endif
+  else
+    autocmd BufReadPost,BufWritePost,FileReadPost,FileWritePost * call GitGutter(s:current_file())
+  endif
+  autocmd ColorScheme * call s:define_sign_column_highlight() | call s:define_highlights()
+augroup END
+
+" }}}
+
+" vim:set et sw=2 fdm=marker:

screenshot.png

Added
New image