New Upstream Snapshot - vim-gitgutter

Ready changes

Summary

Merged new upstream version: 0~20200414+git20221221.1.00df108 (was: 0~20200414).

Resulting package

Built on 2023-01-20T05:19 (took 5m26s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots vim-gitgutter

Lintian Result

Diff

diff --git a/.github/issue_template.md b/.github/issue_template.md
deleted file mode 100644
index d700ce9..0000000
--- a/.github/issue_template.md
+++ /dev/null
@@ -1,4 +0,0 @@
-> What is the latest commit SHA in your installed vim-gitgutter?
-
-> What vim/nvim version are you on?
-
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 82fb253..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,5 +0,0 @@
-/doc/tags
-/misc
-/test/*.actual
-*.log
-
diff --git a/README.mkd b/README.mkd
index bb39d14..408bb2f 100644
--- a/README.mkd
+++ b/README.mkd
@@ -1,9 +1,11 @@
 ## vim-gitgutter
 
-A Vim plugin which shows a git diff in the 'gutter' (sign column).  It shows which lines have been added, modified, or removed.  You can also preview, stage, and undo individual hunks; and stage partial hunks.  The plugin also provides a hunk text object.
+A Vim plugin which shows a git diff in the sign column.  It shows which lines have been added, modified, or removed.  You can also preview, stage, and undo individual hunks; and stage partial hunks.  The plugin also provides a hunk text object.
 
 The signs are always up to date and the plugin never saves your buffer.
 
+The name "gitgutter" comes from the Sublime Text 3 plugin which inspired this in 2013.
+
 Features:
 
 * Shows signs for added, modified, and removed lines.
@@ -16,6 +18,7 @@ Features:
 * Stage partial hunks.
 * Provides a hunk text object.
 * Diffs against index (default) or any commit.
+* Heeds git's "assume unchanged" bit.
 * Allows folding all unchanged text.
 * Provides fold text showing whether folded lines have been changed.
 * Can load all hunk locations into quickfix list or the current window's location list.
@@ -33,6 +36,10 @@ Constraints:
 * Supports git only.  If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify).
 * Relies on the `FocusGained` event.  If your terminal doesn't report focus events, either use something like [Terminus][] or set `let g:gitgutter_terminal_reports_focus=0`.  For tmux, `set -g focus-events on` in your tmux.conf.
 
+Compatibility:
+
+Compatible back to Vim 7.4, and probably 7.3.
+
 
 ### Screenshot
 
@@ -71,13 +78,16 @@ nvim -u NONE -c "helptags vim-gitgutter/doc" -c q
 
 ### Windows
 
-I recommend configuring vim-gitgutter with the full path to your git executable.  For example:
+There is a potential risk on Windows due to `cmd.exe` prioritising the current folder over folders in `PATH`.  If you have a file named `git.*` (i.e. with any extension in `PATHEXT`) in your current folder, it will be executed instead of git whenever the plugin calls git.
+
+You can avoid this risk by configuring the full path to your git executable.  For example:
 
 ```viml
+" This path probably won't work
 let g:gitgutter_git_executable = 'C:\Program Files\Git\bin\git.exe'
 ```
 
-This is to avoid a problem which occurs if you have file named `git.*` (i.e. with any extension in `PATHEXT`) in your current folder.  `cmd.exe` prioritises the current folder over folders in `PATH` and will try to execute your file instead of the `git` binary.
+Unfortunately I don't know the correct escaping for the path - if you do, please let me know!
 
 
 ### Getting started
@@ -88,6 +98,10 @@ You can jump between hunks with `[c` and `]c`.  You can preview, stage, and undo
 
 You cannot unstage a staged hunk.
 
+After updating the signs, the plugin fires the `GitGutter` User autocommand.
+
+After staging a hunk or part of a hunk, the plugin fires the `GitGutterStage` User autocommand.
+
 
 #### Activation
 
@@ -127,12 +141,15 @@ The same caveat applies to line number highlighting as to line highlighting just
 
 If you switch off both line highlighting and signs, you won't see the sign column.
 
-To keep your Vim snappy, vim-gitgutter will suppress the signs when a file has more than 500 changes.  As soon as the number of changes falls below the limit vim-gitgutter will show the signs again.  You can configure the threshold with:
+In older Vims (pre 8.1.0614 / Neovim 0.4.0) vim-gitgutter will suppress the signs when a file has more than 500 changes, to avoid slowing down the UI.  As soon as the number of changes falls below the limit vim-gitgutter will show the signs again.  You can configure the threshold with:
 
 ```viml
-let g:gitgutter_max_signs = 500  " default value
+let g:gitgutter_max_signs = 500  " default value (Vim < 8.1.0614, Neovim < 0.4.0)
+let g:gitgutter_max_signs = -1   " default value (otherwise)
 ```
 
+You can also remove the limit by setting `g:gitgutter_max_signs = -1`.
+
 #### Hunks
 
 You can jump between hunks:
@@ -149,7 +166,17 @@ nmap ]h <Plug>(GitGutterNextHunk)
 nmap [h <Plug>(GitGutterPrevHunk)
 ```
 
-You can load all your hunks into the quickfix list with `:GitGutterQuickFix`.  Note this ignores any unsaved changes in your buffers. If the option `g:gitgutter_use_location_list` is set, this command will load hunks into the current window's location list instead.
+When you jump between hunks, a message like `Hunk 4 of 11` is shown on the command line. If you want to turn the message off, you can use:
+
+```viml
+let g:gitgutter_show_msg_on_hunk_jumping = 0
+```
+
+You can load all your hunks into the quickfix list with `:GitGutterQuickFix`.  Note this ignores any unsaved changes in your buffers. If the option `g:gitgutter_use_location_list` is set, this command will load hunks into the current window's location list instead.  Use `:copen` (or `:lopen`) to open the quickfix / location list or add a custom command like this:
+
+```viml
+command! Gqf GitGutterQuickFix | copen
+```
 
 You can stage or undo an individual hunk when your cursor is in it:
 
@@ -212,6 +239,11 @@ Finally, you can force vim-gitgutter to update its signs across all visible buff
 See the customisation section below for how to change the defaults.
 
 
+### Vimdiff
+
+Use the `GitGutterDiffOrig` command to open a vimdiff view of the current buffer, respecting `g:gitgutter_diff_relative_to` and `:gitgutter_diff_base`.
+
+
 ### Folding
 
 Use the `GitGutterFold` command to fold all unchanged lines, leaving just the hunks visible.  Use `zr` to unfold 3 lines of context above and below a hunk.
@@ -257,6 +289,9 @@ You can customise:
 * How to handle non-gitgutter signs
 * The signs' colours and symbols
 * Line highlights
+* Line number highlights (only in Neovim 0.3.2 or higher)
+* The diff syntax colours used in the preview window
+* The intra-line diff highlights used in the preview window
 * Whether the diff is relative to the index (default) or working tree.
 * The base of the diff
 * Extra arguments for `git` when running `git diff`
@@ -270,6 +305,7 @@ You can customise:
 * Whether to clobber or preserve non-gitgutter signs
 * The priority of gitgutter's signs.
 * Whether to use a floating/popup window for hunk previews
+* The appearance of a floating/popup window for hunk previews
 * Whether to populate the quickfix list or a location list with all hunks
 
 Please note that vim-gitgutter won't override any colours or highlights you've set in your colorscheme.
@@ -277,19 +313,14 @@ Please note that vim-gitgutter won't override any colours or highlights you've s
 
 #### Sign column
 
-By default vim-gitgutter will make the sign column look like the line number column.
-
-To customise your sign column's background color, first tell vim-gitgutter to leave it alone:
+Set the `SignColumn` highlight group to change the sign column's colour.  For example:
 
 ```viml
-let g:gitgutter_override_sign_column_highlight = 0
-```
+" vim-gitgutter used to do this by default:
+highlight! link SignColumn LineNr
 
-And then either update your colorscheme's `SignColumn` highlight group or set it in your vimrc:
-
-```viml
-highlight SignColumn ctermbg=whatever    " terminal Vim
-highlight SignColumn guibg=whatever      " gVim/MacVim
+" or you could do this:
+highlight SignColumn guibg=whatever ctermbg=whatever
 ```
 
 By default the sign column will appear when there are signs to show and disappear when there aren't.  To always have the sign column, add to your vimrc:
@@ -308,31 +339,22 @@ let g:gitgutter_sign_allow_clobber = 1
 
 #### Signs' colours and symbols
 
-By default vim-gitgutter uses your colourscheme's `Diff*` highlight groups' foreground colours for the signs' foreground colours.  For example, your `DiffAdd` foreground colour will be used for the `+` sign's foreground colour.
-
-The signs' background colours will all be set to the sign column's background colour.
+If you or your colourscheme has defined `GitGutter*` highlight groups, the plugin will use them for the signs' colours.
 
-If you don't like the default colours, you can either fix your colourscheme's `Diff*` highlights or configure your own `GitGutter*` highlight groups.  These groups are:
+If you want the background colours to match the sign column, but don't want to update the `GitGutter*` groups yourself, you can get the plugin to do it:
 
 ```viml
-GitGutterAdd          " an added line             (default: links to DiffAdd)
-GitGutterChange       " a changed line            (default: links to DiffChange)
-GitGutterDelete       " at least one removed line (default: links to DiffDelete)
-GitGutterChangeDelete " a changed line followed by at least one removed line (default: links to GitGutterChange)
+let g:gitgutter_set_sign_backgrounds = 1
 ```
 
-You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd MyDiffAdd`.
-
-To get vim-gitgutter's original colours (based on git-diff's colours in my terminal):
+If no `GitGutter*` highlight groups exist, the plugin will check the `Diff*` highlight groups.  If their foreground colours differ the plugin will use them; if not, these colours will be used:
 
 ```viml
-highlight GitGutterAdd    guifg=#009900 guibg=<X> ctermfg=2 ctermbg=<Y>
-highlight GitGutterChange guifg=#bbbb00 guibg=<X> ctermfg=3 ctermbg=<Y>
-highlight GitGutterDelete guifg=#ff2222 guibg=<X> ctermfg=1 ctermbg=<Y>
+highlight GitGutterAdd    guifg=#009900 ctermfg=2
+highlight GitGutterChange guifg=#bbbb00 ctermfg=3
+highlight GitGutterDelete guifg=#ff2222 ctermfg=1
 ```
 
-– where you would replace `<X>` and `<Y>` with the background colour of your `SignColumn` in the gui and the terminal respectively.  For example, with the solarized colorscheme and a dark background, `guibg=#073642` and `ctermbg=0`.
-
 To customise the symbols, add the following to your `~/.vimrc`:
 
 ```viml
@@ -340,6 +362,7 @@ let g:gitgutter_sign_added = 'xx'
 let g:gitgutter_sign_modified = 'yy'
 let g:gitgutter_sign_removed = 'zz'
 let g:gitgutter_sign_removed_first_line = '^^'
+let g:gitgutter_sign_removed_above_and_below = '{'
 let g:gitgutter_sign_modified_removed = 'ww'
 ```
 
@@ -382,6 +405,35 @@ highlight link GitGutterChangeLineNr Underlined
 ```
 
 
+#### The diff syntax colours used in the preview window
+
+To change the diff syntax colours used in the preview window, set up the `diff*` highlight groups in your colorscheme or `~/.vimrc`:
+
+```viml
+diffAdded   " if not set: use GitGutterAdd's foreground colour
+diffChanged " if not set: use GitGutterChange's foreground colour
+diffRemoved " if not set: use GitGutterDelete's foreground colour
+```
+
+Note the `diff*` highlight groups are used in any buffer whose `'syntax'` is `diff`.
+
+
+#### The intra-line diff highlights used in the preview window
+
+To change the intra-line diff highlights used in the preview window, set up the following highlight groups in your colorscheme or `~/.vimrc`:
+
+```viml
+GitGutterAddIntraLine    " default: gui=reverse cterm=reverse
+GitGutterDeleteIntraLine " default: gui=reverse cterm=reverse
+```
+
+For example, to use `DiffAdd` for intra-line added regions:
+
+```viml
+highlight link GitGutterAddIntraLine DiffAdd
+```
+
+
 #### Whether the diff is relative to the index or working tree
 
 By default diffs are relative to the index.  How you can make them relative to the working tree:
@@ -474,6 +526,11 @@ let g:gitgutter_async = 0
 Add `let g:gitgutter_preview_win_floating = 1` to your `~/.vimrc`.  Note that on Vim this prevents you staging (partial) hunks via the preview window.
 
 
+#### The appearance of a floating/popup window for hunk previews
+
+Set `g:gitgutter_floating_window_options` to a dictionary of the options you want.  This dictionary is passed directly to `popup_create()` (Vim) / `nvim_open_win()` (Neovim).
+
+
 #### To load all hunks into the current window's location list instead of the quickfix list
 
 Add `let g:gitgutter_use_location_list = 1` to your `~/.vimrc`.
@@ -634,16 +691,6 @@ This plugin is for showing changes between the buffer and the index (and staging
 
 Your colorscheme is configuring the `SignColumn` highlight group weirdly.  Please see the section above on customising the sign column.
 
-> Why are the colours in the preview window weird?
-
-Probably because your colourscheme doesn't configure the `diff{Added,Changed,Removed}` highlight groups.  Try this in `after/syntax/diff.vim`:
-
-```viml
-highlight link diffAdded DiffAdd
-highlight link diffChanged DiffChange
-highlight link diffRemoved DiffDelete
-```
-
 > What happens if I also use another plugin which uses signs (e.g. Syntastic)?
 
 You can configure whether GitGutter preserves or clobbers other signs using `g:gitgutter_sign_allow_clobber`.  Set to `1` to clobber other signs (default on Vim >= 8.1.0614 and NeoVim >= 0.4.0) or `0` to preserve them.
@@ -659,7 +706,10 @@ Here are some things you can check:
 * Verify `:echo system("git --version")` succeeds.
 * Verify your git config is compatible with the version of git returned by the command above.
 * Verify your Vim supports signs (`:echo has('signs')` should give `1`).
-* Verify your file is being tracked by git and has unstaged changes.
+* Verify your file is being tracked by git and has unstaged changes.  Check whether the plugin thinks git knows about your file: `:echo b:gitgutter.path` should show the path to the file in the repo.
+* Execute `:sign place group=gitgutter`; you should see a list of signs.
+  - If the signs are listed: this is a colorscheme / highlight problem.  Compare `:highlight GitGutterAdd` with `:highlight SignColumn`.
+  - If no signs are listed: the call to git-diff is probably failing.  Add `let g:gitgutter_log=1` to your vimrc, restart, reproduce the problem, and look at the `gitgutter.log` file in the plugin's directory.
 
 #### When the whole file is marked as added
 
@@ -682,8 +732,6 @@ If this plugin has helped you, or you'd like to learn more about Vim, why not ch
 
 This was one of PeepCode's all-time top three bestsellers and is now available at Pluralsight.
 
-You can read reviews on my [website][airblade].
-
 
 ### Intellectual Property
 
diff --git a/autoload/gitgutter.vim b/autoload/gitgutter.vim
index 69849a3..6978979 100644
--- a/autoload/gitgutter.vim
+++ b/autoload/gitgutter.vim
@@ -21,6 +21,10 @@ endfunction
 function! gitgutter#process_buffer(bufnr, force) abort
   " NOTE a:bufnr is not necessarily the current buffer.
 
+  if gitgutter#utility#getbufvar(a:bufnr, 'enabled', -1) == -1
+    call gitgutter#utility#setbufvar(a:bufnr, 'enabled', g:gitgutter_enabled)
+  endif
+
   if gitgutter#utility#is_active(a:bufnr)
 
     if has('patch-7.4.1559')
@@ -33,8 +37,6 @@ function! gitgutter#process_buffer(bufnr, force) abort
       return
     endif
 
-    call gitgutter#utility#set_diff_base_if_fugitive(a:bufnr)
-
     if a:force || s:has_fresh_changes(a:bufnr)
 
       let diff = 'NOT SET'
@@ -42,6 +44,8 @@ function! gitgutter#process_buffer(bufnr, force) abort
         let diff = gitgutter#diff#run_diff(a:bufnr, g:gitgutter_diff_relative_to, 0)
       catch /gitgutter not tracked/
         call gitgutter#debug#log('Not tracked: '.gitgutter#utility#file(a:bufnr))
+      catch /gitgutter assume unchanged/
+        call gitgutter#debug#log('Assume unchanged: '.gitgutter#utility#file(a:bufnr))
       catch /gitgutter diff failed/
         call gitgutter#debug#log('Diff failed: '.gitgutter#utility#file(a:bufnr))
         call gitgutter#hunk#reset(a:bufnr)
@@ -57,22 +61,28 @@ endfunction
 
 
 function! gitgutter#disable() abort
-  " get list of all buffers (across all tabs)
+  call s:toggle_each_buffer(0)
+  let g:gitgutter_enabled = 0
+endfunction
+
+function! gitgutter#enable() abort
+  call s:toggle_each_buffer(1)
+  let g:gitgutter_enabled = 1
+endfunction
+
+function s:toggle_each_buffer(enable)
   for bufnr in range(1, bufnr('$') + 1)
     if buflisted(bufnr)
       let file = expand('#'.bufnr.':p')
       if !empty(file)
-        call s:clear(bufnr)
+        if a:enable
+          call gitgutter#buffer_enable(bufnr)
+        else
+          call gitgutter#buffer_disable(bufnr)
+        end
       endif
     endif
   endfor
-
-  let g:gitgutter_enabled = 0
-endfunction
-
-function! gitgutter#enable() abort
-  let g:gitgutter_enabled = 1
-  call gitgutter#all(1)
 endfunction
 
 function! gitgutter#toggle() abort
@@ -84,23 +94,24 @@ function! gitgutter#toggle() abort
 endfunction
 
 
-function! gitgutter#buffer_disable() abort
-  let bufnr = bufnr('')
+function! gitgutter#buffer_disable(...) abort
+  let bufnr = a:0 ? a:1 : bufnr('')
   call gitgutter#utility#setbufvar(bufnr, 'enabled', 0)
   call s:clear(bufnr)
 endfunction
 
-function! gitgutter#buffer_enable() abort
-  let bufnr = bufnr('')
+function! gitgutter#buffer_enable(...) abort
+  let bufnr = a:0 ? a:1 : bufnr('')
   call gitgutter#utility#setbufvar(bufnr, 'enabled', 1)
   call gitgutter#process_buffer(bufnr, 1)
 endfunction
 
-function! gitgutter#buffer_toggle() abort
-  if gitgutter#utility#getbufvar(bufnr(''), 'enabled', 1)
-    call gitgutter#buffer_disable()
+function! gitgutter#buffer_toggle(...) abort
+  let bufnr = a:0 ? a:1 : bufnr('')
+  if gitgutter#utility#getbufvar(bufnr, 'enabled', 1)
+    call gitgutter#buffer_disable(bufnr)
   else
-    call gitgutter#buffer_enable()
+    call gitgutter#buffer_enable(bufnr)
   endif
 endfunction
 
@@ -181,10 +192,21 @@ endfunction
 " - this runs synchronously
 " - it ignores unsaved changes in buffers
 " - it does not change to the repo root
-function! gitgutter#quickfix()
+function! gitgutter#quickfix(current_file)
+  let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' rev-parse --show-cdup'
+  let path_to_repo = get(systemlist(cmd), 0, '')
+  if !empty(path_to_repo) && path_to_repo[-1:] != '/'
+    let path_to_repo .= '/'
+  endif
+
   let locations = []
-  let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager '.g:gitgutter_git_args.
-        \ ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args. ' '. g:gitgutter_diff_base
+  let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager'.
+        \ ' diff --no-ext-diff --no-color -U0'.
+        \ ' --src-prefix=a/'.path_to_repo.' --dst-prefix=b/'.path_to_repo.' '.
+        \ g:gitgutter_diff_args. ' '. g:gitgutter_diff_base
+  if a:current_file
+    let cmd = cmd.' -- '.expand('%:p')
+  endif
   let diff = systemlist(cmd)
   let lnum = 0
   for line in diff
@@ -196,6 +218,10 @@ function! gitgutter#quickfix()
     elseif line =~ '^diff --git "'
       let [_, fnamel, _, fnamer] = split(line, '"')
       let fname = fnamel ==# fnamer ? fnamel : fnamel[2:]
+    elseif line =~ '^diff --cc [^"]'
+      let fname = line[10:]
+    elseif line =~ '^diff --cc "'
+      let [_, fname] = split(line, '"')
     elseif line =~ '^@@'
       let lnum = matchlist(line, '+\(\d\+\)')[1]
     elseif lnum > 0
@@ -209,3 +235,31 @@ function! gitgutter#quickfix()
     call setloclist(0, locations)
   endif
 endfunction
+
+
+function! gitgutter#difforig()
+  let bufnr = bufnr('')
+  let path = gitgutter#utility#repo_path(bufnr, 1)
+  let filetype = &filetype
+
+  vertical new
+  set buftype=nofile
+  let &filetype = filetype
+
+  if g:gitgutter_diff_relative_to ==# 'index'
+    let index_name = gitgutter#utility#get_diff_base(bufnr).':'.path
+    let cmd = gitgutter#utility#cd_cmd(bufnr,
+          \ g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager show '.index_name
+          \ )
+    " NOTE: this uses &shell to execute cmd.  Perhaps we should use instead
+    " gitgutter#utility's use_known_shell() / restore_shell() functions.
+    silent! execute "read ++edit !" cmd
+  else
+    silent! execute "read ++edit" path
+  endif
+
+  0d_
+  diffthis
+  wincmd p
+  diffthis
+endfunction
diff --git a/autoload/gitgutter/async.vim b/autoload/gitgutter/async.vim
index 1cc2b16..8b9f130 100644
--- a/autoload/gitgutter/async.vim
+++ b/autoload/gitgutter/async.vim
@@ -1,11 +1,13 @@
 let s:available = has('nvim') || (
       \   has('job') && (
-      \     (has('patch-7-4-1826') && !has('gui_running')) ||
-      \     (has('patch-7-4-1850') &&  has('gui_running')) ||
-      \     (has('patch-7-4-1832') &&  has('gui_macvim'))
+      \     (has('patch-7.4.1826') && !has('gui_running')) ||
+      \     (has('patch-7.4.1850') &&  has('gui_running')) ||
+      \     (has('patch-7.4.1832') &&  has('gui_macvim'))
       \   )
       \ )
 
+let s:jobs = {}
+
 function! gitgutter#async#available()
   return s:available
 endfunction
@@ -28,11 +30,12 @@ function! gitgutter#async#execute(cmd, bufnr, handler) abort
           \   'on_exit':   function('s:on_exit_nvim')
           \ }))
   else
-    call job_start(command, {
+    let job = job_start(command, {
           \   'out_cb':   function('s:on_stdout_vim', options),
           \   'err_cb':   function('s:on_stderr_vim', options),
           \   'close_cb': function('s:on_exit_vim', options)
           \ })
+    let s:jobs[s:job_id(job)] = 1
   endif
 endfunction
 
@@ -83,6 +86,8 @@ endfunction
 
 function! s:on_exit_vim(channel) dict abort
   let job = ch_getjob(a:channel)
+  let jobid = s:job_id(job)
+  if has_key(s:jobs, jobid) | unlet s:jobs[jobid] | endif
   while 1
     if job_status(job) == 'dead'
       let exit_code = job_info(job).exitval
@@ -95,3 +100,8 @@ function! s:on_exit_vim(channel) dict abort
     call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
   endif
 endfunction
+
+function! s:job_id(job)
+  " Vim
+  return job_info(a:job).process
+endfunction
diff --git a/autoload/gitgutter/debug.vim b/autoload/gitgutter/debug.vim
index 79d197e..def5b80 100644
--- a/autoload/gitgutter/debug.vim
+++ b/autoload/gitgutter/debug.vim
@@ -22,16 +22,6 @@ function! gitgutter#debug#debug()
   call s:separator()
 
   call s:option('updatetime')
-  call s:option('shell')
-  call s:option('shellcmdflag')
-  call s:option('shellpipe')
-  call s:option('shellquote')
-  call s:option('shellredir')
-  call s:option('shellslash')
-  call s:option('shelltemp')
-  call s:option('shelltype')
-  call s:option('shellxescape')
-  call s:option('shellxquote')
 endfunction
 
 
@@ -52,10 +42,10 @@ function! s:git_version()
 endfunction
 
 function! s:grep_version()
-  let v = system('grep --version')
+  let v = system(g:gitgutter_grep.' --version')
   call s:output( substitute(v, '\n$', '', '') )
 
-  let v = system('grep --help')
+  let v = system(g:gitgutter_grep.' --help')
   call s:output( substitute(v, '\%x00', '', 'g') )
 endfunction
 
diff --git a/autoload/gitgutter/diff.vim b/autoload/gitgutter/diff.vim
index db827f5..794cd14 100644
--- a/autoload/gitgutter/diff.vim
+++ b/autoload/gitgutter/diff.vim
@@ -12,7 +12,6 @@ endfunction
 
 let s:c_flag = s:git_supports_command_line_config_override()
 
-
 let s:temp_from = tempname()
 let s:temp_buffer = tempname()
 let s:counter = 0
@@ -71,13 +70,17 @@ let s:counter = 0
 "                      grep is available.
 function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort
   if gitgutter#utility#repo_path(a:bufnr, 0) == -1
-    throw 'gitgutter author fail'
+    throw 'gitgutter path not set'
   endif
 
   if gitgutter#utility#repo_path(a:bufnr, 0) == -2
     throw 'gitgutter not tracked'
   endif
 
+  if gitgutter#utility#repo_path(a:bufnr, 0) == -3
+    throw 'gitgutter assume unchanged'
+  endif
+
   " Wrap compound commands in parentheses to make Windows happy.
   " bash doesn't mind the parentheses.
   let cmd = '('
@@ -120,7 +123,7 @@ function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort
     endif
 
     " Write file from index to temporary file.
-    let index_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1)
+    let index_name = gitgutter#utility#get_diff_base(a:bufnr).':'.gitgutter#utility#repo_path(a:bufnr, 1)
     let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager show '.index_name.' > '.from_file.' && '
 
   elseif a:from ==# 'working_tree'
@@ -128,7 +131,7 @@ function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort
   endif
 
   " Call git-diff.
-  let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager '.g:gitgutter_git_args
+  let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager'
   if s:c_flag
     let cmd .= ' -c "diff.autorefreshindex=0"'
     let cmd .= ' -c "diff.noprefix=false"'
@@ -182,7 +185,7 @@ function! gitgutter#diff#handler(bufnr, diff) abort
   let modified_lines = gitgutter#diff#process_hunks(a:bufnr, gitgutter#hunk#hunks(a:bufnr))
 
   let signs_count = len(modified_lines)
-  if signs_count > g:gitgutter_max_signs
+  if g:gitgutter_max_signs != -1 && signs_count > g:gitgutter_max_signs
     call gitgutter#utility#warn_once(a:bufnr, printf(
           \ 'exceeded maximum number of signs (%d > %d, configured by g:gitgutter_max_signs).',
           \ signs_count, g:gitgutter_max_signs), 'max_signs')
@@ -400,7 +403,16 @@ function! s:write_buffer(bufnr, file)
     let bufcontents[0]=''.bufcontents[0]
   endif
 
-  call writefile(bufcontents, a:file, 'b')
+  " The file we are writing to is a temporary file.  Sometimes the parent
+  " directory is deleted outside Vim but, because Vim caches the directory
+  " name at startup and does not check for its existence subsequently, Vim
+  " does not realise.  This causes E482 errors.
+  try
+    call writefile(bufcontents, a:file, 'b')
+  catch /E482/
+    call mkdir(fnamemodify(a:file, ':h'), '', '0700')
+    call writefile(bufcontents, a:file, 'b')
+  endtry
 endfunction
 
 
diff --git a/autoload/gitgutter/diff_highlight.vim b/autoload/gitgutter/diff_highlight.vim
index ec21b44..803dd6e 100644
--- a/autoload/gitgutter/diff_highlight.vim
+++ b/autoload/gitgutter/diff_highlight.vim
@@ -150,12 +150,6 @@ function! s:lcs(s1, s2)
   return a:s1[endindex - maxlength + 1 : endindex]
 endfunction
 
-if $VIM_GITGUTTER_TEST
-  function! gitgutter#diff_highlight#lcs(s1, s2)
-    return s:lcs(a:s1, a:s2)
-  endfunction
-endif
-
 
 " Returns 0-based index of last character of common prefix
 " If there is no common prefix, returns -1.
@@ -168,19 +162,13 @@ function! s:common_prefix(a, b)
     return -1
   endif
   for i in range(len)
-    if a:a[i:i] != a:b[i:i]
+    if a:a[i:i] !=# a:b[i:i]
       return i - 1
     endif
   endfor
   return i
 endfunction
 
-if $VIM_GITGUTTER_TEST
-  function! gitgutter#diff_highlight#common_prefix(a, b)
-    return s:common_prefix(a:a, a:b)
-  endfunction
-endif
-
 
 " Returns 0-based indices of start of common suffix
 "
@@ -199,12 +187,6 @@ function! s:common_suffix(a, b, start)
   return [sa+1, sb+1]
 endfunction
 
-if $VIM_GITGUTTER_TEST
-  function! gitgutter#diff_highlight#common_suffix(a, b, start)
-    return s:common_suffix(a:a, a:b, a:start)
-  endfunction
-endif
-
 
 " Split a string on another string.
 " Assumes 1 occurrence of the delimiter.
@@ -217,9 +199,3 @@ function! s:split(str, delimiter)
 
   return [a:str[:i-1], a:str[i+len(a:delimiter):]]
 endfunction
-
-if $VIM_GITGUTTER_TEST
-  function! gitgutter#diff_highlight#split(str, delimiter)
-    return s:split(a:str, a:delimiter)
-  endfunction
-endif
diff --git a/autoload/gitgutter/highlight.vim b/autoload/gitgutter/highlight.vim
index e8ac1a2..3684549 100644
--- a/autoload/gitgutter/highlight.vim
+++ b/autoload/gitgutter/highlight.vim
@@ -64,14 +64,6 @@ function! gitgutter#highlight#linenr_toggle() abort
 endfunction
 
 
-function! gitgutter#highlight#define_sign_column_highlight() abort
-  if g:gitgutter_override_sign_column_highlight
-    highlight! link SignColumn LineNr
-  else
-    highlight default link SignColumn LineNr
-  endif
-endfunction
-
 function! gitgutter#highlight#define_highlights() abort
   let [guibg, ctermbg] = s:get_background_colors('SignColumn')
 
@@ -84,12 +76,24 @@ function! gitgutter#highlight#define_highlights() abort
   highlight default link GitGutterChangeDeleteInvisible GitGutterChangeInvisible
 
   " When they are visible.
-  " By default use Diff* foreground colors with SignColumn's background.
-  for type in ['Add', 'Change', 'Delete']
-    let [guifg, ctermfg] = s:get_foreground_colors('Diff'.type)
-    execute "highlight GitGutter".type."Default guifg=".guifg." guibg=".guibg." ctermfg=".ctermfg." ctermbg=".ctermbg
-    execute "highlight default link GitGutter".type." GitGutter".type."Default"
+  for type in ["Add", "Change", "Delete"]
+    if hlexists("GitGutter".type) && s:get_foreground_colors("GitGutter".type) != ['NONE', 'NONE']
+      if g:gitgutter_set_sign_backgrounds
+        execute "highlight GitGutter".type." guibg=".guibg." ctermbg=".ctermbg
+      endif
+      continue
+    elseif s:useful_diff_colours()
+      let [guifg, ctermfg] = s:get_foreground_colors('Diff'.type)
+    else
+      let [guifg, ctermfg] = s:get_foreground_fallback_colors(type)
+    endif
+    execute "highlight GitGutter".type." guifg=".guifg." guibg=".guibg." ctermfg=".ctermfg." ctermbg=".ctermbg
   endfor
+
+  if hlexists("GitGutterChangeDelete") && g:gitgutter_set_sign_backgrounds
+    execute "highlight GitGutterChangeDelete guibg=".guibg." ctermbg=".ctermbg
+  endif
+
   highlight default link GitGutterChangeDelete GitGutterChange
 
   " Highlights used for the whole line.
@@ -105,8 +109,16 @@ function! gitgutter#highlight#define_highlights() abort
   highlight default link GitGutterChangeDeleteLineNr CursorLineNr
 
   " Highlights used intra line.
-  highlight GitGutterAddIntraLine    gui=reverse cterm=reverse
-  highlight GitGutterDeleteIntraLine gui=reverse cterm=reverse
+  highlight default GitGutterAddIntraLine    gui=reverse cterm=reverse
+  highlight default GitGutterDeleteIntraLine gui=reverse cterm=reverse
+  " Set diff syntax colours (used in the preview window) - diffAdded,diffChanged,diffRemoved -
+  " to match the signs, if not set aleady.
+  for [dtype,type] in [['Added','Add'], ['Changed','Change'], ['Removed','Delete']]
+    if !hlexists('diff'.dtype)
+      let [guifg, ctermfg] = s:get_foreground_colors('GitGutter'.type)
+      execute "highlight diff".dtype." guifg=".guifg." ctermfg=".ctermfg." guibg=NONE ctermbg=NONE"
+    endif
+  endfor
 endfunction
 
 function! gitgutter#highlight#define_signs() abort
@@ -163,12 +175,12 @@ function! s:define_sign_line_highlights() abort
     sign define GitGutterLineRemovedAboveAndBelow  linehl=GitGutterDeleteLine
     sign define GitGutterLineModifiedRemoved       linehl=GitGutterChangeDeleteLine
   else
-    sign define GitGutterLineAdded                 linehl=
-    sign define GitGutterLineModified              linehl=
-    sign define GitGutterLineRemoved               linehl=
-    sign define GitGutterLineRemovedFirstLine      linehl=
-    sign define GitGutterLineRemovedAboveAndBelow  linehl=
-    sign define GitGutterLineModifiedRemoved       linehl=
+    sign define GitGutterLineAdded                 linehl=NONE
+    sign define GitGutterLineModified              linehl=NONE
+    sign define GitGutterLineRemoved               linehl=NONE
+    sign define GitGutterLineRemovedFirstLine      linehl=NONE
+    sign define GitGutterLineRemovedAboveAndBelow  linehl=NONE
+    sign define GitGutterLineModifiedRemoved       linehl=NONE
   endif
 endfunction
 
@@ -183,12 +195,12 @@ function! s:define_sign_linenr_highlights() abort
         sign define GitGutterLineRemovedAboveAndBelow  numhl=GitGutterDeleteLineNr
         sign define GitGutterLineModifiedRemoved       numhl=GitGutterChangeDeleteLineNr
       else
-        sign define GitGutterLineAdded                 numhl=
-        sign define GitGutterLineModified              numhl=
-        sign define GitGutterLineRemoved               numhl=
-        sign define GitGutterLineRemovedFirstLine      numhl=
-        sign define GitGutterLineRemovedAboveAndBelow  numhl=
-        sign define GitGutterLineModifiedRemoved       numhl=
+        sign define GitGutterLineAdded                 numhl=NONE
+        sign define GitGutterLineModified              numhl=NONE
+        sign define GitGutterLineRemoved               numhl=NONE
+        sign define GitGutterLineRemovedFirstLine      numhl=NONE
+        sign define GitGutterLineRemovedAboveAndBelow  numhl=NONE
+        sign define GitGutterLineModifiedRemoved       numhl=NONE
       endif
     catch /E475/
     endtry
@@ -214,3 +226,20 @@ function! s:get_background_colors(group) abort
   let guibg = s:get_hl(a:group, 'bg', 'gui')
   return [guibg, ctermbg]
 endfunction
+
+function! s:useful_diff_colours()
+  let [guifg_add, ctermfg_add] = s:get_foreground_colors('DiffAdd')
+  let [guifg_del, ctermfg_del] = s:get_foreground_colors('DiffDelete')
+
+  return guifg_add != guifg_del && ctermfg_add != ctermfg_del
+endfunction
+
+function! s:get_foreground_fallback_colors(type)
+  if a:type == 'Add'
+    return ['#009900', '2']
+  elseif a:type == 'Change'
+    return ['#bbbb00', '3']
+  elseif a:type == 'Delete'
+    return ['#ff2222', '1']
+  endif
+endfunction
diff --git a/autoload/gitgutter/hunk.vim b/autoload/gitgutter/hunk.vim
index 4f0f7c7..a54b01c 100644
--- a/autoload/gitgutter/hunk.vim
+++ b/autoload/gitgutter/hunk.vim
@@ -1,4 +1,6 @@
 let s:winid = 0
+let s:preview_bufnr = 0
+let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
 
 function! gitgutter#hunk#set_hunks(bufnr, hunks) abort
   call gitgutter#utility#setbufvar(a:bufnr, 'hunks', a:hunks)
@@ -44,39 +46,63 @@ endfunction
 
 function! gitgutter#hunk#next_hunk(count) abort
   let bufnr = bufnr('')
-  if gitgutter#utility#is_active(bufnr)
-    let current_line = line('.')
-    let hunk_count = 0
-    for hunk in gitgutter#hunk#hunks(bufnr)
-      if hunk[2] > current_line
-        let hunk_count += 1
-        if hunk_count == a:count
-          execute 'normal!' hunk[2] . 'Gzv'
-          return
+  if !gitgutter#utility#is_active(bufnr) | return | endif
+
+  let hunks = gitgutter#hunk#hunks(bufnr)
+  if empty(hunks)
+    call gitgutter#utility#warn('No hunks in file')
+    return
+  endif
+
+  let current_line = line('.')
+  let hunk_count = 0
+  for hunk in hunks
+    if hunk[2] > current_line
+      let hunk_count += 1
+      if hunk_count == a:count
+        execute 'normal!' hunk[2] . 'Gzv'
+        if g:gitgutter_show_msg_on_hunk_jumping
+          redraw | echo printf('Hunk %d of %d', index(hunks, hunk) + 1, len(hunks))
+        endif
+        if gitgutter#hunk#is_preview_window_open()
+          call gitgutter#hunk#preview()
         endif
+        return
       endif
-    endfor
-    call gitgutter#utility#warn('No more hunks')
-  endif
+    endif
+  endfor
+  call gitgutter#utility#warn('No more hunks')
 endfunction
 
 function! gitgutter#hunk#prev_hunk(count) abort
   let bufnr = bufnr('')
-  if gitgutter#utility#is_active(bufnr)
-    let current_line = line('.')
-    let hunk_count = 0
-    for hunk in reverse(copy(gitgutter#hunk#hunks(bufnr)))
-      if hunk[2] < current_line
-        let hunk_count += 1
-        if hunk_count == a:count
-          let target = hunk[2] == 0 ? 1 : hunk[2]
-          execute 'normal!' target . 'Gzv'
-          return
+  if !gitgutter#utility#is_active(bufnr) | return | endif
+
+  let hunks = gitgutter#hunk#hunks(bufnr)
+  if empty(hunks)
+    call gitgutter#utility#warn('No hunks in file')
+    return
+  endif
+
+  let current_line = line('.')
+  let hunk_count = 0
+  for hunk in reverse(copy(hunks))
+    if hunk[2] < current_line
+      let hunk_count += 1
+      if hunk_count == a:count
+        let target = hunk[2] == 0 ? 1 : hunk[2]
+        execute 'normal!' target . 'Gzv'
+        if g:gitgutter_show_msg_on_hunk_jumping
+          redraw | echo printf('Hunk %d of %d', index(hunks, hunk) + 1, len(hunks))
         endif
+        if gitgutter#hunk#is_preview_window_open()
+          call gitgutter#hunk#preview()
+        endif
+        return
       endif
-    endfor
-    call gitgutter#utility#warn('No previous hunks')
-  endif
+    endif
+  endfor
+  call gitgutter#utility#warn('No previous hunks')
 endfunction
 
 " Returns the hunk the cursor is currently in or an empty list if the cursor
@@ -223,7 +249,7 @@ function! s:hunk_op(op, ...)
       let hunk_diff = join(hunk_header + hunk_body, "\n")."\n"
 
       call s:goto_original_window()
-      call s:close_hunk_preview_window()
+      call gitgutter#hunk#close_hunk_preview_window()
       call s:stage(hunk_diff)
     endif
 
@@ -237,9 +263,10 @@ function! s:hunk_op(op, ...)
     let g:gitgutter_async = async
 
     call gitgutter#hunk#set_hunks(bufnr, gitgutter#diff#parse_diff(diff))
+    call gitgutter#diff#process_hunks(bufnr, gitgutter#hunk#hunks(bufnr))  " so the hunk summary is updated
 
     if empty(s:current_hunk())
-      call gitgutter#utility#warn('cursor is not in a hunk')
+      call gitgutter#utility#warn('Cursor is not in a hunk')
     elseif s:cursor_in_two_hunks()
       let choice = input('Choose hunk: upper or lower (u/l)? ')
       " Clear input
@@ -249,7 +276,7 @@ function! s:hunk_op(op, ...)
       elseif choice =~ 'l'
         call a:op(gitgutter#diff#hunk_diff(bufnr, diff, 1))
       else
-        call gitgutter#utility#warn('did not recognise your choice')
+        call gitgutter#utility#warn('Did not recognise your choice')
       endif
     else
       let hunk_diff = gitgutter#diff#hunk_diff(bufnr, diff)
@@ -273,7 +300,11 @@ function! s:stage(hunk_diff)
         \ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' apply --cached --unidiff-zero - '),
         \ diff)
   if v:shell_error
-    call gitgutter#utility#warn('patch does not apply')
+    call gitgutter#utility#warn('Patch does not apply')
+  else
+    if exists('#User#GitGutterStage')
+      execute 'doautocmd' s:nomodeline 'User GitGutterStage'
+    endif
   endif
 
   " Refresh gitgutter's view of buffer.
@@ -351,12 +382,6 @@ function! s:fix_file_references(filepath, hunk_diff)
   return join(lines, "\n")."\n"
 endfunction
 
-if $VIM_GITGUTTER_TEST
-  function! gitgutter#hunk#fix_file_references(filepath, hunk_diff)
-    return s:fix_file_references(a:filepath, a:hunk_diff)
-  endfunction
-endif
-
 
 function! s:adjust_hunk_summary(hunk_diff) abort
   let line_adjustment = s:line_adjustment_for_current_hunk()
@@ -396,18 +421,11 @@ endfunction
 function! s:open_hunk_preview_window()
   if g:gitgutter_preview_win_floating
     if exists('*nvim_open_win')
-      call s:close_hunk_preview_window()
+      call gitgutter#hunk#close_hunk_preview_window()
 
       let buf = nvim_create_buf(v:false, v:false)
       " Set default width and height for now.
-      let s:winid = nvim_open_win(buf, v:false, {
-            \ 'relative': 'cursor',
-            \ 'row': 1,
-            \ 'col': 0,
-            \ 'width': 42,
-            \ 'height': &previewheight,
-            \ 'style': 'minimal'
-            \ })
+      let s:winid = nvim_open_win(buf, v:false, g:gitgutter_floating_window_options)
       call nvim_buf_set_option(buf, 'filetype',  'diff')
       call nvim_buf_set_option(buf, 'buftype',   'acwrite')
       call nvim_buf_set_option(buf, 'bufhidden', 'delete')
@@ -415,17 +433,26 @@ function! s:open_hunk_preview_window()
       call nvim_buf_set_name(buf, 'gitgutter://hunk-preview')
 
       " Assumes cursor is in original window.
-      autocmd CursorMoved <buffer> ++once call s:close_hunk_preview_window()
+      autocmd CursorMoved <buffer> ++once call gitgutter#hunk#close_hunk_preview_window()
+
+      if g:gitgutter_close_preview_on_escape
+        " Map <Esc> to close the floating preview.
+        nnoremap <buffer> <silent> <Esc> :<C-U>call gitgutter#hunk#close_hunk_preview_window()<CR>
+        " Ensure that when the preview window is closed, the map is removed.
+        autocmd User GitGutterPreviewClosed silent! nunmap <buffer> <Esc>
+        autocmd CursorMoved <buffer> ++once silent! nunmap <buffer> <Esc>
+        execute "autocmd WinClosed <buffer=".winbufnr(s:winid)."> doautocmd" s:nomodeline "User GitGutterPreviewClosed"
+      endif
 
       return
     endif
 
     if exists('*popup_create')
-      let s:winid = popup_create('', {
-            \ 'line': 'cursor+1',
-            \ 'col': 'cursor',
-            \ 'moved': 'any',
-            \ })
+      if g:gitgutter_close_preview_on_escape
+        let g:gitgutter_floating_window_options.filter = function('s:close_popup_on_escape')
+      endif
+
+      let s:winid = popup_create('', g:gitgutter_floating_window_options)
 
       call setbufvar(winbufnr(s:winid), '&filetype', 'diff')
 
@@ -433,34 +460,61 @@ function! s:open_hunk_preview_window()
     endif
   endif
 
+  if exists('&previewpopup')
+    let [previewpopup, &previewpopup] = [&previewpopup, '']
+  endif
+
+  " Specifying where to open the preview window can lead to the cursor going
+  " to an unexpected window when the preview window is closed (#769).
+  silent! noautocmd execute g:gitgutter_preview_win_location 'pedit gitgutter://hunk-preview'
   silent! wincmd P
-  if !&previewwindow
-    noautocmd execute g:gitgutter_preview_win_location &previewheight 'new gitgutter://hunk-preview'
-    doautocmd WinEnter
+  setlocal statusline=%{''}
+  doautocmd WinEnter
+  if exists('*win_getid')
     let s:winid = win_getid()
-    set previewwindow
-    setlocal filetype=diff buftype=acwrite bufhidden=delete
-    " Reset some defaults in case someone else has changed them.
-    setlocal noreadonly modifiable noswapfile
+  else
+    let s:preview_bufnr = bufnr('')
+  endif
+  setlocal filetype=diff buftype=acwrite bufhidden=delete
+  " Reset some defaults in case someone else has changed them.
+  setlocal noreadonly modifiable noswapfile
+  if g:gitgutter_close_preview_on_escape
+    " Ensure cursor goes to the expected window.
+    nnoremap <buffer> <silent> <Esc> :<C-U>wincmd p<Bar>pclose<CR>
+  endif
+
+  if exists('&previewpopup')
+    let &previewpopup=previewpopup
   endif
 endfunction
 
 
+function! s:close_popup_on_escape(winid, key)
+  if a:key == "\<Esc>"
+    call popup_close(a:winid)
+    return 1
+  endif
+  return 0
+endfunction
+
+
 " Floating window: does not care where cursor is.
 " Preview window: assumes cursor is in preview window.
 function! s:populate_hunk_preview_window(header, body)
-  let body_length = len(a:body)
-  let height = min([body_length, &previewheight])
-
   if g:gitgutter_preview_win_floating
     if exists('*nvim_open_win')
       " Assumes cursor is not in previewing window.
       call nvim_buf_set_var(winbufnr(s:winid), 'hunk_header', a:header)
 
-      let width = max(map(copy(a:body), 'strdisplaywidth(v:val)'))
+      let [_scrolloff, &scrolloff] = [&scrolloff, 0]
+
+      let [width, height] = s:screen_lines(a:body)
+      let height = min([height, g:gitgutter_floating_window_options.height])
       call nvim_win_set_width(s:winid, width)
       call nvim_win_set_height(s:winid, height)
 
+      let &scrolloff=_scrolloff
+
       call nvim_buf_set_lines(winbufnr(s:winid), 0, -1, v:false, [])
       call nvim_buf_set_lines(winbufnr(s:winid), 0, -1, v:false, a:body)
       call nvim_buf_set_option(winbufnr(s:winid), 'modified', v:false)
@@ -486,12 +540,15 @@ function! s:populate_hunk_preview_window(header, body)
 
   else
     let b:hunk_header = a:header
-    execute 'resize' height
 
     %delete _
     call setline(1, a:body)
     setlocal nomodified
 
+    let [_, height] = s:screen_lines(a:body)
+    execute 'resize' height
+    1
+
     call clearmatches()
     for region in gitgutter#diff_highlight#process(a:body)
       let group = region[1] == '+' ? 'GitGutterAddIntraLine' : 'GitGutterDeleteIntraLine'
@@ -503,10 +560,32 @@ function! s:populate_hunk_preview_window(header, body)
 endfunction
 
 
+" Calculates the number of columns and the number of screen lines the given
+" array of lines will take up, taking account of wrapping.
+function! s:screen_lines(lines)
+  let [_virtualedit, &virtualedit]=[&virtualedit, 'all']
+  let cursor = getcurpos()
+  normal! 0g$
+  let available_width = virtcol('.')
+  call setpos('.', cursor)
+  let &virtualedit=_virtualedit
+  let width = min([max(map(copy(a:lines), 'strdisplaywidth(v:val)')), available_width])
+
+  if exists('*reduce')
+    let height = reduce(a:lines, { acc, val -> acc + strdisplaywidth(val) / width + (strdisplaywidth(val) % width == 0 ? 0 : 1) }, 0)
+  else
+    let height = eval(join(map(copy(a:lines), 'strdisplaywidth(v:val) / width + (strdisplaywidth(v:val) % width == 0 ? 0 : 1)'), '+'))
+  endif
+
+  return [width, height]
+endfunction
+
+
 function! s:enable_staging_from_hunk_preview_window()
   augroup gitgutter_hunk_preview
     autocmd!
-    execute 'autocmd BufWriteCmd <buffer='.winbufnr(s:winid).'> GitGutterStageHunk'
+    let bufnr = s:winid != 0 ? winbufnr(s:winid) : s:preview_bufnr
+    execute 'autocmd BufWriteCmd <buffer='.bufnr.'> GitGutterStageHunk'
   augroup END
 endfunction
 
@@ -517,8 +596,9 @@ function! s:goto_original_window()
 endfunction
 
 
-function! s:close_hunk_preview_window()
-  call setbufvar(winbufnr(s:winid), '&modified', 0)
+function! gitgutter#hunk#close_hunk_preview_window()
+  let bufnr = s:winid != 0 ? winbufnr(s:winid) : s:preview_bufnr
+  call setbufvar(bufnr, '&modified', 0)
 
   if g:gitgutter_preview_win_floating
     if win_id2win(s:winid) > 0
@@ -529,4 +609,21 @@ function! s:close_hunk_preview_window()
   endif
 
   let s:winid = 0
+  let s:preview_bufnr = 0
+endfunction
+
+
+function gitgutter#hunk#is_preview_window_open()
+  if g:gitgutter_preview_win_floating
+    if win_id2win(s:winid) > 0
+      execute win_id2win(s:winid).'wincmd c'
+    endif
+  else
+    for i in range(1, winnr('$'))
+      if getwinvar(i, '&previewwindow')
+        return 1
+      endif
+    endfor
+  endif
+  return 0
 endfunction
diff --git a/autoload/gitgutter/utility.vim b/autoload/gitgutter/utility.vim
index f642c2b..b81efbe 100644
--- a/autoload/gitgutter/utility.vim
+++ b/autoload/gitgutter/utility.vim
@@ -30,7 +30,7 @@ endfunction
 
 function! gitgutter#utility#warn(message) abort
   echohl WarningMsg
-  echo 'vim-gitgutter: ' . a:message
+  echo a:message
   echohl None
   let v:warningmsg = a:message
 endfunction
@@ -39,7 +39,7 @@ function! gitgutter#utility#warn_once(bufnr, message, key) abort
   if empty(gitgutter#utility#getbufvar(a:bufnr, a:key))
     call gitgutter#utility#setbufvar(a:bufnr, a:key, '1')
     echohl WarningMsg
-    redraw | echom 'vim-gitgutter: ' . a:message
+    redraw | echom a:message
     echohl None
     let v:warningmsg = a:message
   endif
@@ -48,8 +48,7 @@ endfunction
 " Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
 " This function does not and should not make any system calls.
 function! gitgutter#utility#is_active(bufnr) abort
-  return g:gitgutter_enabled &&
-        \ gitgutter#utility#getbufvar(a:bufnr, 'enabled', 1) &&
+  return gitgutter#utility#getbufvar(a:bufnr, 'enabled') &&
         \ !pumvisible() &&
         \ s:is_file_buffer(a:bufnr) &&
         \ s:exists_file(a:bufnr) &&
@@ -109,6 +108,7 @@ endfunction
 " * non-empty string - path
 " *               -1 - pending
 " *               -2 - not tracked by git
+" *               -3 - assume unchanged
 function! gitgutter#utility#repo_path(bufnr, shellesc) abort
   let p = gitgutter#utility#getbufvar(a:bufnr, 'path', '')
   return a:shellesc ? gitgutter#utility#shellescape(p) : p
@@ -117,9 +117,14 @@ endfunction
 
 let s:set_path_handler = {}
 
-function! s:set_path_handler.out(buffer, path) abort
-  let path = s:strip_trailing_new_line(a:path)
-  call gitgutter#utility#setbufvar(a:buffer, 'path', path)
+function! s:set_path_handler.out(buffer, listing) abort
+  let listing = s:strip_trailing_new_line(a:listing)
+  let [status, path] = [listing[0], listing[2:]]
+  if status =~# '[a-z]'
+    call gitgutter#utility#setbufvar(a:buffer, 'path', -3)
+  else
+    call gitgutter#utility#setbufvar(a:buffer, 'path', path)
+  endif
 
   if type(self.continuation) == type(function('tr'))
     call self.continuation()
@@ -141,9 +146,13 @@ function! gitgutter#utility#set_repo_path(bufnr, continuation) abort
   " * non-empty string - path
   " *               -1 - pending
   " *               -2 - not tracked by git
+  " *               -3 - assume unchanged
 
   call gitgutter#utility#setbufvar(a:bufnr, 'path', -1)
-  let cmd = gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' ls-files --error-unmatch --full-name -z -- '.gitgutter#utility#shellescape(s:filename(a:bufnr)))
+  let cmd = gitgutter#utility#cd_cmd(a:bufnr,
+        \ g:gitgutter_git_executable.' '.g:gitgutter_git_args.
+        \ ' ls-files -v --error-unmatch --full-name -z -- '.
+        \ gitgutter#utility#shellescape(s:filename(a:bufnr)))
 
   if g:gitgutter_async && gitgutter#async#available() && !has('vim_starting')
     let handler = copy(s:set_path_handler)
@@ -152,17 +161,25 @@ function! gitgutter#utility#set_repo_path(bufnr, continuation) abort
     return 'async'
   endif
 
-  let path = gitgutter#utility#system(cmd)
+  let listing = gitgutter#utility#system(cmd)
+
   if v:shell_error
     call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
+    return
+  endif
+
+  let listing = s:strip_trailing_new_line(listing)
+  let [status, path] = [listing[0], listing[2:]]
+  if status =~# '[a-z]'
+    call gitgutter#utility#setbufvar(a:bufnr, 'path', -3)
   else
-    call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
+    call gitgutter#utility#setbufvar(a:bufnr, 'path', path)
   endif
 endfunction
 
 
 function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
-  let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() ? 'cd /d' : 'cd')
+  let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() && s:dos_shell() ? 'cd /d' : 'cd')
   return cd.' '.s:dir(a:bufnr).' && '.a:cmd
 endfunction
 
@@ -170,26 +187,36 @@ function! s:unc_path(bufnr)
   return s:abs_path(a:bufnr, 0) =~ '^\\\\'
 endfunction
 
+function! s:dos_shell()
+  return &shell == 'cmd.exe' || &shell == 'command.com'
+endfunction
+
 function! s:use_known_shell() abort
   if has('unix') && &shell !=# 'sh'
-    let [s:shell, s:shellcmdflag, s:shellredir] = [&shell, &shellcmdflag, &shellredir]
+    let [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote] = [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote]
     let &shell = 'sh'
     set shellcmdflag=-c shellredir=>%s\ 2>&1
   endif
+  if has('win32') && (&shell =~# 'pwsh' || &shell =~# 'powershell')
+    let [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote] = [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote]
+    let &shell = 'cmd.exe'
+    set shellcmdflag=/s\ /c shellredir=>%s\ 2>&1 shellpipe=>%s\ 2>&1 shellquote= shellxquote="
+  endif
 endfunction
 
 function! s:restore_shell() abort
-  if has('unix') && exists('s:shell')
-    let [&shell, &shellcmdflag, &shellredir] = [s:shell, s:shellcmdflag, s:shellredir]
+  if (has('unix') || has('win32')) && exists('s:shell')
+    let [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote] = [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote]
   endif
 endfunction
 
-function! gitgutter#utility#set_diff_base_if_fugitive(bufnr)
+function! gitgutter#utility#get_diff_base(bufnr)
   let p = resolve(expand('#'.a:bufnr.':p'))
   let ml = matchlist(p, '\v^fugitive:/.*/(\x{40,})/')
   if !empty(ml) && !empty(ml[1])
-    let g:gitgutter_diff_base = ml[1].'^'
+    return ml[1].'^'
   endif
+  return g:gitgutter_diff_base
 endfunction
 
 function! s:abs_path(bufnr, shellesc)
diff --git a/debian/changelog b/debian/changelog
index 316f4f4..11ad555 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+vim-gitgutter (0~20200414+git20221221.1.00df108-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Fri, 20 Jan 2023 05:15:03 -0000
+
 vim-gitgutter (0~20200414-2) unstable; urgency=medium
 
   * Team upload.
diff --git a/doc/gitgutter.txt b/doc/gitgutter.txt
index 074f334..3ad150c 100644
--- a/doc/gitgutter.txt
+++ b/doc/gitgutter.txt
@@ -1,7 +1,7 @@
 *gitgutter.txt*              A Vim plugin which shows a git diff in the gutter.
 
 
-                           Vim Git Gutter
+                           Vim GitGutter
 
 
 Author:            Andy Stewart <https://airbladesoftware.com/>
@@ -27,13 +27,16 @@ CONTENTS                                                            *gitgutter*
 ===============================================================================
 INTRODUCTION                                           *gitgutter-introduction*
 
-GitGutter is a Vim plugin which shows a git diff in the 'gutter' (sign column).
+GitGutter is a Vim plugin which shows a git diff in the sign column.
 It shows which lines have been added, modified, or removed.  You can also
 preview, stage, and undo individual hunks.  The plugin also provides a hunk
 text object.
 
 The signs are always up to date and the plugin never saves your buffer.
 
+The name "gitgutter" comes from the Sublime Text 3 plugin which inspired this
+one in 2013.
+
 
 ===============================================================================
 INSTALLATION                                           *gitgutter-installation*
@@ -60,15 +63,20 @@ Neovim:~
 ===============================================================================
 WINDOWS                                                     *gitgutter-windows*
 
-I recommend configuring vim-gitgutter with the full path to your git executable.
+There is a potential risk on Windows due to `cmd.exe` prioritising the current
+folder over folders in `PATH`.  If you have a file named `git.*` (i.e. with
+any extension in `PATHEXT`) in your current folder, it will be executed
+instead of git whenever the plugin calls git.
+
+You can avoid this risk by configuring the full path to your git executable.
 For example:
 >
+    " This path probably won't work
     let g:gitgutter_git_executable = 'C:\Program Files\Git\bin\git.exe'
 <
-This is to avoid a problem which occurs if you have file named "git.*" (i.e.
-with any extension in "PATHEXT") in your current folder.  "cmd.exe" prioritises
-the current folder over folders in 'PATH' and will try to execute your file
-instead of the "git" binary.
+
+Unfortunately I don't know the correct escaping for the path - if you do,
+please let me know!
 
 
 ===============================================================================
@@ -85,6 +93,15 @@ Commands for turning vim-gitgutter on and off:~
                                                    *gitgutter-:GitGutterToggle*
 :GitGutterToggle        Toggle vim-gitgutter on or off for all buffers.
 
+                                            *gitgutter-:GitGutterBufferDisable*
+:GitGutterBufferDisable Turn vim-gitgutter off for current buffer.
+
+                                             *gitgutter-:GitGutterBufferEnable*
+:GitGutterBufferEnable  Turn vim-gitgutter on for current buffer.
+
+                                             *gitgutter-:GitGutterBufferToggle*
+:GitGutterBufferToggle  Toggle vim-gitgutter on or off for current buffer.
+
                                                          *gitgutter-:GitGutter*
 :GitGutter              Update signs for the current buffer.  You shouldn't
                         need to run this.
@@ -143,7 +160,18 @@ Commands for jumping between hunks:~
 :GitGutterQuickFix      Load all hunks into the |quickfix| list.  Note this
                         ignores any unsaved changes in your buffers. The
                         |g:gitgutter_use_location_list| option can be set to
-                        populate the location list of the current window instead
+                        populate the location list of the current window
+                        instead.  Use |:copen| (or |:lopen|) to open a buffer
+                        containing the search results in linked form; or add a
+                        custom command like this:
+>
+                          command! Gqf GitGutterQuickFix | copen
+<
+                                                 *gitgutter-:GitGutterQuickFixCurrentFile*
+:GitGutterQuickFixCurrentFile     Same as :GitGutterQuickFix, but only load hunks for
+                                  the file in the focused buffer. This has the same
+                                  functionality as :GitGutterQuickFix when the focused
+                                  buffer is empty.
 
 
 Commands for operating on a hunk:~
@@ -163,21 +191,44 @@ Commands for operating on a hunk:~
 
                                               *gitgutter-:GitGutterPreviewHunk*
 :GitGutterPreviewHunk   Preview the hunk the cursor is in.
-                        Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview
-                        window.
 
                         To stage part of the hunk, move to the preview window,
                         delete any lines you do not want to stage, and
                         |GitGutterStageHunk|.
 
+                        To close a non-floating preview window use |:pclose|
+                        or |CTRL-W_z| or |CTRL-W_CTRL-Z|; or normal window-
+                        closing (|:quit| or |:close| or |CTRL-W_c|) if your cursor
+                        is in the preview window.
+
+                        To close a floating window when the cursor is in the
+                        original buffer, move the cursor.
+
+                        To close a floating window when the cursor is in the
+                        floating window use normal window-closing, or move to
+                        the original window with |CTRL-W_p|.  Alternatively set
+                        |g:gitgutter_close_preview_on_escape| and use <Esc>.
+
+                        Two functions are available for your own logic:
+>
+                          gitgutter#hunk#is_preview_window_open()
+                          gitgutter#hunk#close_hunk_preview_window()
+<
+
 Commands for folds:~
 
                                                      *gitgutter-:GitGutterFold*
 :GitGutterFold          Fold all unchanged lines.  Execute again to undo.
 
 
+Other commands:~
+
+                                                 *gitgutter-:GitGutterDiffOrig*
+:GitGutterDiffOrig      Similar to |:DiffOrig| but shows gitgutter's diff.
+
+
 ===============================================================================
-AUTOCOMMAND                                             *gitgutter-autocommand*
+AUTOCOMMANDS                                           *gitgutter-autocommands*
 
 User GitGutter~
 
@@ -189,6 +240,10 @@ event GitGutter.  You can listen for this event, for example:
 A dictionary `g:gitgutter_hook_context` is made available during its execution,
 which contains an entry `bufnr` that contains the buffer number being updated.
 
+User GitGutterStage~
+
+After staging a hunk or part of a hunk vim-gitgutter fires a |User| |autocmd|
+with the event GitGutterStage.  Staging always happens in the current buffer.
 
 ===============================================================================
 MAPPINGS                                                   *gitgutter-mappings*
@@ -299,11 +354,17 @@ Signs:~
     |g:gitgutter_sign_removed|
     |g:gitgutter_sign_removed_first_line|
     |g:gitgutter_sign_modified_removed|
-    |g:gitgutter_override_sign_column_highlight|
+    |g:gitgutter_set_sign_backgrounds|
+
+Hunk jumping:~
+
+    |g:gitgutter_show_msg_on_hunk_jumping|
 
 Hunk previews:~
 
     |g:gitgutter_preview_win_floating|
+    |g:gitgutter_floating_window_options|
+    |g:gitgutter_close_preview_on_escape|
 
 Terminal:~
 
@@ -405,13 +466,16 @@ Default: 0
 Determines whether or not to show line number highlights.
 
                                                         *g:gitgutter_max_signs*
-Default: 500
+Default: 500 (Vim < 8.1.0614, Neovim < 0.4.0)
+          -1 (otherwise)
 
 Sets the maximum number of signs to show in a buffer.  Vim is slow at updating
 signs, so to avoid slowing down the GUI the number of signs is capped.  When
 the number of changed lines exceeds this value, the plugin removes all signs
 and displays a warning message.
 
+When set to -1 the limit is not applied.
+
                                                    *g:gitgutter_sign_priority*
 Default: 10
 
@@ -428,6 +492,7 @@ will not preserve non-gitgutter signs.
                                           *g:gitgutter_sign_modified*
                                           *g:gitgutter_sign_removed*
                                           *g:gitgutter_sign_removed_first_line*
+                                          *g:gitgutter_sign_removed_above_and_below*
                                           *g:gitgutter_sign_modified_removed*
 Defaults:
 >
@@ -435,31 +500,20 @@ Defaults:
     let g:gitgutter_sign_modified           = '~'
     let g:gitgutter_sign_removed            = '_'
     let g:gitgutter_sign_removed_first_line = '‾'
+    let g:gitgutter_sign_removed_above_and_below = '_¯'
     let g:gitgutter_sign_modified_removed   = '~_'
 <
 You can use unicode characters but not images.  Signs must not take up more than
 2 columns.
 
-                                   *g:gitgutter_override_sign_column_highlight*
-Default: 1
-
-Controls whether to make the sign column look like the line-number column (i.e.
-the |hl-LineNr| highlight group).
-
-To customise your sign column's background color, first tell vim-gitgutter to
-leave it alone:
->
-    let g:gitgutter_override_sign_column_highlight = 0
-<
-
-And then either update your colorscheme's |hlSignColumn| highlight group or set
-it in your |vimrc|:
+                                              *g:gitgutter_set_sign_backgrounds*
+Default: 0
 
-  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}
+Only applies to existing GitGutter* highlight groups.  See
+|gitgutter-highlights|.
 
+Controls whether to override the signs' background colours to match the
+|hl-SignColumn|.
 
                                              *g:gitgutter_preview_win_floating*
 Default: 0 (Vim)
@@ -470,6 +524,34 @@ Whether to use floating/popup windows for hunk previews.  Note that if you use
 popup windows on Vim you will not be able to stage partial hunks via the
 preview window.
 
+                                          *g:gitgutter_floating_window_options*
+Default:
+>
+    " Vim
+    {
+        \ 'line': 'cursor+1',
+        \ 'col': 'cursor',
+        \ 'moved': 'any'
+    }
+
+    " Neovim
+    {
+        \ 'relative': 'cursor',
+        \ 'row': 1,
+        \ 'col': 0,
+        \ 'width': 42,
+        \ 'height': &previewheight,
+        \ 'style': 'minimal'
+    }
+<
+This dictionary is passed directly to |popup_create()| (Vim) or
+|nvim_open_win()| (Neovim).
+
+                                          *g:gitgutter_close_preview_on_escape*
+Default: 0
+
+Whether pressing <Esc> in a preview window closes it.
+
                                            *g:gitgutter_terminal_reports_focus*
 Default: 1
 
@@ -518,24 +600,27 @@ Default: 0
 When switched on, the :GitGutterQuickFix command populates the location list
 of the current window instead of the global quickfix list.
 
+                                         *g:gitgutter_show_msg_on_hunk_jumping*
+Default: 1
+
+When switched on, a message like "Hunk 4 of 11" is shown on hunk jumping.
+
 
 ===============================================================================
 HIGHLIGHTS                                               *gitgutter-highlights*
 
-To change the signs' colours, set up the following highlight groups in your
-colorscheme or |vimrc|:
+To change the signs' colours, specify these highlight groups in your |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
+    highlight GitGutterAdd    guifg=#009900 ctermfg=2
+    highlight GitGutterChange guifg=#bbbb00 ctermfg=3
+    highlight GitGutterDelete guifg=#ff2222 ctermfg=1
 <
 
-You can either set these with `highlight GitGutterAdd {key}={arg}...` or link
-them to existing highlight groups with, say:
->
-  highlight link GitGutterAdd MyDiffAdd
-<
+See |highlight-guifg| and |highlight-ctermfg| for the values you can use.
+
+If you do not like the signs' background colours and you do not want to update
+the GitGutter* highlight groups yourself, you can get the plugin to do it
+|g:gitgutter_set_sign_backgrounds|.
 
 To change the line highlights, set up the following highlight groups in your
 colorscheme or |vimrc|:
@@ -562,6 +647,26 @@ For example, to use |hl-Underlined| instead of |hl-CursorLineNr|:
 >
     highlight link GitGutterChangeLineNr Underlined
 <
+To change the diff syntax colours used in the preview window, set up the diff*
+highlight groups in your colorscheme or |vimrc|:
+>
+    diffAdded   " if not set: use GitGutterAdd's foreground colour
+    diffChanged " if not set: use GitGutterChange's foreground colour
+    diffRemoved " if not set: use GitGutterDelete's foreground colour
+<
+Note the diff* highlight groups are used in any buffer whose 'syntax' is
+"diff".
+
+To change the intra-line diff highlights used in the preview window, set up
+the following highlight groups in your colorscheme or |vimrc|:
+>
+    GitGutterAddIntraLine    " default: gui=reverse cterm=reverse
+    GitGutterDeleteIntraLine " default: gui=reverse cterm=reverse
+<
+For example, to use |hl-DiffAdd| for intra-line added regions:
+>
+    highlight link GitGutterAddIntraLine DiffAdd
+<
 
 
 ===============================================================================
@@ -592,8 +697,11 @@ c. Why can't I unstage staged changes?
 d. Why are the colours in the sign column weird?
 
   Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly.
-  Please see |g:gitgutter_override_sign_column_highlight| on customising the
-  sign column.
+  Here are two ways you could change the colours:
+>
+    highlight! link SignColumn LineNr
+    highlight SignColumn guibg=whatever ctermbg=whatever
+<
 
 e. What happens if I also use another plugin which uses signs (e.g. Syntastic)?
 
@@ -632,6 +740,22 @@ When no signs are showing at all:~
 <
   If the result is -2, the plugin thinks your file is not tracked by git.
 
+6. Check whether the signs have been placed:
+>
+    :sign place group=gitgutter
+<
+  If you see a list of signs, this is a colorscheme / highlight problem.
+  Compare these two highlight values:
+>
+    :highlight GitGutterAdd
+    :highlight SignColumn
+<
+  If no signs are listed, the call to git-diff is probably failing.  Turn on
+  logging by adding the following to your vimrc, restart, reproduce the problem,
+  and examing the gitgutter.log file in the plugin's directory.
+>
+    let g:gitgutter_log = 1
+<
 
 When the whole file is marked as added:~
 
@@ -657,3 +781,4 @@ Terminus (https://github.com/wincent/terminus) or set:
     let g:gitgutter_terminal_reports_focus = 0
 <
 
+  vim:tw=78:et:ft=help:norl:
diff --git a/plugin/gitgutter.vim b/plugin/gitgutter.vim
index 1e3cf23..008724e 100644
--- a/plugin/gitgutter.vim
+++ b/plugin/gitgutter.vim
@@ -8,68 +8,90 @@ let g:loaded_gitgutter = 1
 " Initialisation {{{
 
 if v:version < 703 || (v:version == 703 && !has("patch105"))
-  call gitgutter#utility#warn('requires Vim 7.3.105')
+  call gitgutter#utility#warn('Requires Vim 7.3.105')
   finish
 endif
 
-function! s:set(var, default) abort
-  if !exists(a:var)
-    if type(a:default)
-      execute 'let' a:var '=' string(a:default)
-    else
-      execute 'let' a:var '=' a:default
-    endif
+let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
+
+function! s:obsolete(var)
+  if exists(a:var)
+    call gitgutter#utility#warn(a:var.' is obsolete and has no effect.')
   endif
 endfunction
 
-call s:set('g:gitgutter_preview_win_location',     'bo')
+
+let g:gitgutter_preview_win_location = get(g:, 'gitgutter_preview_win_location', 'bo')
 if exists('*nvim_open_win')
-  call s:set('g:gitgutter_preview_win_floating', 1)
+  let g:gitgutter_preview_win_floating = get(g:, 'gitgutter_preview_win_floating', 1)
+  let g:gitgutter_floating_window_options = get(g:, 'gitgutter_floating_window_options', {
+        \ 'relative': 'cursor',
+        \ 'row': 1,
+        \ 'col': 0,
+        \ 'width': 42,
+        \ 'height': &previewheight,
+        \ 'style': 'minimal'
+        \ })
 else
-  call s:set('g:gitgutter_preview_win_floating', 0)
+  let default = exists('&previewpopup') ? !empty(&previewpopup) : 0
+  let g:gitgutter_preview_win_floating = get(g:, 'gitgutter_preview_win_floating', default)
+  let g:gitgutter_floating_window_options = get(g:, 'gitgutter_floating_window_options', {
+        \ 'line': 'cursor+1',
+        \ 'col': 'cursor',
+        \ 'moved': 'any'
+        \ })
 endif
-call s:set('g:gitgutter_enabled',                     1)
-call s:set('g:gitgutter_max_signs',                 500)
-call s:set('g:gitgutter_signs',                       1)
-call s:set('g:gitgutter_highlight_lines',             0)
-call s:set('g:gitgutter_highlight_linenrs',           0)
-call s:set('g:gitgutter_sign_priority',              10)
+let g:gitgutter_enabled = get(g:, 'gitgutter_enabled', 1)
+if exists('*sign_unplace')
+  let g:gitgutter_max_signs = get(g:, 'gitgutter_max_signs', -1)
+else
+  let g:gitgutter_max_signs = get(g:, 'gitgutter_max_signs', 500)
+endif
+let g:gitgutter_signs             = get(g:, 'gitgutter_signs', 1)
+let g:gitgutter_highlight_lines   = get(g:, 'gitgutter_highlight_lines', 0)
+let g:gitgutter_highlight_linenrs = get(g:, 'gitgutter_highlight_linenrs', 0)
+let g:gitgutter_sign_priority     = get(g:, 'gitgutter_sign_priority', 10)
 " Nvim 0.4.0 has an expanding sign column
 " The sign_place() function supports sign priority.
 if (has('nvim-0.4.0') || exists('*sign_place')) && !exists('g:gitgutter_sign_allow_clobber')
   let g:gitgutter_sign_allow_clobber = 1
 endif
-call s:set('g:gitgutter_sign_allow_clobber',          0)
-call s:set('g:gitgutter_override_sign_column_highlight', 1)
-call s:set('g:gitgutter_sign_added',                   '+')
-call s:set('g:gitgutter_sign_modified',                '~')
-call s:set('g:gitgutter_sign_removed',                 '_')
+let g:gitgutter_sign_allow_clobber   = get(g:, 'gitgutter_sign_allow_clobber', 0)
+let g:gitgutter_set_sign_backgrounds = get(g:, 'gitgutter_set_sign_backgrounds', 0)
+let g:gitgutter_sign_added           = get(g:, 'gitgutter_sign_added', '+')
+let g:gitgutter_sign_modified        = get(g:, 'gitgutter_sign_modified', '~')
+let g:gitgutter_sign_removed         = get(g:, 'gitgutter_sign_removed', '_')
 
 if gitgutter#utility#supports_overscore_sign()
-  call s:set('g:gitgutter_sign_removed_first_line', '‾')
+  let g:gitgutter_sign_removed_first_line = get(g:, 'gitgutter_sign_removed_first_line', '‾')
 else
-  call s:set('g:gitgutter_sign_removed_first_line', '_^')
+  let g:gitgutter_sign_removed_first_line = get(g:, 'gitgutter_sign_removed_first_line', '_^')
 endif
 
-call s:set('g:gitgutter_sign_removed_above_and_below', '[')
-call s:set('g:gitgutter_sign_modified_removed',       '~_')
-call s:set('g:gitgutter_git_args',                      '')
-call s:set('g:gitgutter_diff_relative_to',         'index')
-call s:set('g:gitgutter_diff_args',                     '')
-call s:set('g:gitgutter_diff_base',                     '')
-call s:set('g:gitgutter_map_keys',                       1)
-call s:set('g:gitgutter_terminal_reports_focus',         1)
-call s:set('g:gitgutter_async',                          1)
-call s:set('g:gitgutter_log',                            0)
-call s:set('g:gitgutter_use_location_list',              0)
-
-call s:set('g:gitgutter_git_executable', 'git')
+let g:gitgutter_sign_removed_above_and_below = get(g:, 'gitgutter_sign_removed_above_and_below', '_¯')
+let g:gitgutter_sign_modified_removed        = get(g:, 'gitgutter_sign_modified_removed', '~_')
+let g:gitgutter_git_args                     = get(g:, 'gitgutter_git_args', '')
+let g:gitgutter_diff_relative_to             = get(g:, 'gitgutter_diff_relative_to', 'index')
+let g:gitgutter_diff_args                    = get(g:, 'gitgutter_diff_args', '')
+let g:gitgutter_diff_base                    = get(g:, 'gitgutter_diff_base', '')
+let g:gitgutter_map_keys                     = get(g:, 'gitgutter_map_keys', 1)
+let g:gitgutter_terminal_reports_focus       = get(g:, 'gitgutter_terminal_reports_focus', 1)
+let g:gitgutter_async                        = get(g:, 'gitgutter_async', 1)
+let g:gitgutter_log                          = get(g:, 'gitgutter_log', 0)
+let g:gitgutter_use_location_list            = get(g:, 'gitgutter_use_location_list', 0)
+let g:gitgutter_close_preview_on_escape      = get(g:, 'gitgutter_close_preview_on_escape', 0)
+let g:gitgutter_show_msg_on_hunk_jumping     = get(g:, 'gitgutter_show_msg_on_hunk_jumping', 1)
+
+let g:gitgutter_git_executable = get(g:, 'gitgutter_git_executable', 'git')
 if !executable(g:gitgutter_git_executable)
-  call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
+  if g:gitgutter_enabled
+    call gitgutter#utility#warn('Cannot find git. Please set g:gitgutter_git_executable.')
+  endif
+  finish
 endif
 
 let default_grep = 'grep'
-call s:set('g:gitgutter_grep', default_grep)
+let g:gitgutter_grep = get(g:, 'gitgutter_grep', default_grep)
 if !empty(g:gitgutter_grep)
   if executable(split(g:gitgutter_grep)[0])
     if $GREP_OPTIONS =~# '--color=always'
@@ -77,13 +99,12 @@ if !empty(g:gitgutter_grep)
     endif
   else
     if g:gitgutter_grep !=# default_grep
-      call gitgutter#utility#warn('cannot find '.g:gitgutter_grep.'. Please check g:gitgutter_grep.')
+      call gitgutter#utility#warn('Cannot find '.g:gitgutter_grep.'. Please check g:gitgutter_grep.')
     endif
     let g:gitgutter_grep = ''
   endif
 endif
 
-call gitgutter#highlight#define_sign_column_highlight()
 call gitgutter#highlight#define_highlights()
 call gitgutter#highlight#define_signs()
 
@@ -110,7 +131,10 @@ command! -bar GitGutterBufferDisable call gitgutter#buffer_disable()
 command! -bar GitGutterBufferEnable  call gitgutter#buffer_enable()
 command! -bar GitGutterBufferToggle  call gitgutter#buffer_toggle()
 
-command! -bar GitGutterQuickFix call gitgutter#quickfix()
+command! -bar GitGutterQuickFix call gitgutter#quickfix(0)
+command! -bar GitGutterQuickFixCurrentFile call gitgutter#quickfix(1)
+
+command! -bar GitGutterDiffOrig call gitgutter#difforig()
 
 " }}}
 
@@ -194,24 +218,41 @@ command! -bar GitGutterDebug call gitgutter#debug#debug()
 " Maps {{{
 
 nnoremap <silent> <expr> <Plug>(GitGutterNextHunk) &diff ? ']c' : ":\<C-U>execute v:count1 . 'GitGutterNextHunk'\<CR>"
-nnoremap <silent> <expr> <Plug>GitGutterNextHunk   &diff ? ']c' : ":\<C-U>call gitgutter#utility#warn('please change your map \<lt>Plug>GitGutterNextHunk to \<lt>Plug>(GitGutterNextHunk)')\<CR>"
+nnoremap <silent> <expr> <Plug>GitGutterNextHunk   &diff ? ']c' : ":\<C-U>call gitgutter#utility#warn('Please change your map \<lt>Plug>GitGutterNextHunk to \<lt>Plug>(GitGutterNextHunk)')\<CR>"
 nnoremap <silent> <expr> <Plug>(GitGutterPrevHunk) &diff ? '[c' : ":\<C-U>execute v:count1 . 'GitGutterPrevHunk'\<CR>"
-nnoremap <silent> <expr> <Plug>GitGutterPrevHunk   &diff ? '[c' : ":\<C-U>call gitgutter#utility#warn('please change your map \<lt>Plug>GitGutterPrevHunk to \<lt>Plug>(GitGutterPrevHunk)')\<CR>"
+nnoremap <silent> <expr> <Plug>GitGutterPrevHunk   &diff ? '[c' : ":\<C-U>call gitgutter#utility#warn('Please change your map \<lt>Plug>GitGutterPrevHunk to \<lt>Plug>(GitGutterPrevHunk)')\<CR>"
 
 xnoremap <silent> <Plug>(GitGutterStageHunk)   :GitGutterStageHunk<CR>
-xnoremap <silent> <Plug>GitGutterStageHunk     :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
+xnoremap <silent> <Plug>GitGutterStageHunk     :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
 nnoremap <silent> <Plug>(GitGutterStageHunk)   :GitGutterStageHunk<CR>
-nnoremap <silent> <Plug>GitGutterStageHunk     :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
+nnoremap <silent> <Plug>GitGutterStageHunk     :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
 nnoremap <silent> <Plug>(GitGutterUndoHunk)    :GitGutterUndoHunk<CR>
-nnoremap <silent> <Plug>GitGutterUndoHunk      :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterUndoHunk to <lt>Plug>(GitGutterUndoHunk)')<CR>
+nnoremap <silent> <Plug>GitGutterUndoHunk      :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterUndoHunk to <lt>Plug>(GitGutterUndoHunk)')<CR>
 nnoremap <silent> <Plug>(GitGutterPreviewHunk) :GitGutterPreviewHunk<CR>
-nnoremap <silent> <Plug>GitGutterPreviewHunk   :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterPreviewHunk to <lt>Plug>(GitGutterPreviewHunk)')<CR>
+nnoremap <silent> <Plug>GitGutterPreviewHunk   :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterPreviewHunk to <lt>Plug>(GitGutterPreviewHunk)')<CR>
 
 " }}}
 
 function! s:on_bufenter()
   call gitgutter#setup_maps()
 
+  " To keep vim's start-up fast, do not process the buffer when vim is starting.
+  " Instead process it a short time later.  Normally we would rely on our
+  " CursorHold autocommand to handle this but it turns out CursorHold is not
+  " guaranteed to fire if the user has not typed anything yet; so set up a
+  " timer instead.  The disadvantage is that if CursorHold does fire, the
+  " plugin will do a round of unnecessary work; but since there will not have
+  " been any changes to the buffer since the first round, the second round
+  " will be cheap.
+  if has('vim_starting') && !$VIM_GITGUTTER_TEST
+    if exists('*timer_start') && has('lambda')
+      call s:next_tick("call gitgutter#process_buffer(+".bufnr('').", 0)")
+    else
+      call gitgutter#process_buffer(bufnr(''), 0)
+    endif
+    return
+  endif
+
   if exists('t:gitgutter_didtabenter') && t:gitgutter_didtabenter
     let t:gitgutter_didtabenter = 0
     call gitgutter#all(!g:gitgutter_terminal_reports_focus)
@@ -220,6 +261,10 @@ function! s:on_bufenter()
   endif
 endfunction
 
+function! s:next_tick(cmd)
+  call timer_start(1, {-> execute(a:cmd)})
+endfunction
+
 " Autocommands {{{
 
 augroup gitgutter
@@ -229,11 +274,16 @@ augroup gitgutter
 
   autocmd BufEnter * call s:on_bufenter()
 
+  " Ensure Vim is always checking for CursorMoved to avoid CursorMoved
+  " being fired at the wrong time in floating preview window on Neovim.
+  " See vim/vim#2053.
+  autocmd CursorMoved * execute ''
+
   autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 0)
   if exists('*timer_start') && has('lambda')
-    autocmd FileChangedShellPost * call timer_start(1, {-> gitgutter#process_buffer(bufnr(''), 1)})
+    autocmd FileChangedShellPost * call s:next_tick("call gitgutter#process_buffer(+".expand('<abuf>').", 1)")
   else
-    autocmd FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 1)
+    autocmd FileChangedShellPost * call gitgutter#process_buffer(+expand('<abuf>'), 1)
   endif
 
   " Ensure that all buffers are processed when opening vim with multiple files, e.g.:
@@ -253,18 +303,18 @@ augroup gitgutter
   " FocusGained gets triggered on startup with Neovim at least already.
   " Therefore this tracks also if it was lost before.
   let s:focus_was_lost = 0
-  autocmd FocusGained * if s:focus_was_lost | let focus_was_lost = 0 | call gitgutter#all(1) | endif
+  autocmd FocusGained * if s:focus_was_lost | let s:focus_was_lost = 0 | call gitgutter#all(1) | endif
   autocmd FocusLost * let s:focus_was_lost = 1
 
   if exists('##VimResume')
     autocmd VimResume * call gitgutter#all(1)
   endif
 
-  autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
+  autocmd ColorScheme * call gitgutter#highlight#define_highlights()
 
   " Disable during :vimgrep
-  autocmd QuickFixCmdPre  *vimgrep* let g:gitgutter_enabled = 0
-  autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = 1
+  autocmd QuickFixCmdPre  *vimgrep* let [g:gitgutter_was_enabled, g:gitgutter_enabled] = [g:gitgutter_enabled, 0]
+  autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = g:gitgutter_was_enabled | unlet g:gitgutter_was_enabled
 augroup END
 
 " }}}
diff --git a/test/test_gitgutter.vim b/test/test_gitgutter.vim
index e75f21b..df527b8 100644
--- a/test/test_gitgutter.vim
+++ b/test/test_gitgutter.vim
@@ -205,6 +205,20 @@ function Test_filename_with_square_brackets()
 endfunction
 
 
+function Test_filename_with_space()
+  call system('touch fix\ ture.txt && git add fix\ ture.txt')
+  edit fix\ ture.txt
+  normal ggo*
+  call s:trigger_gitgutter()
+
+  let expected = [
+        \ {'lnum': 1, 'name': 'GitGutterLineAdded'},
+        \ {'lnum': 2, 'name': 'GitGutterLineAdded'}
+        \ ]
+  call s:assert_signs(expected, 'fix\ ture.txt')
+endfunction
+
+
 function Test_filename_leading_dash()
   call system('touch -- -fixture.txt && git add -- -fixture.txt')
   edit -fixture.txt
@@ -835,6 +849,9 @@ endfunction
 
 
 function Test_fix_file_references()
+  let sid = matchstr(execute('filter autoload/gitgutter/hunk.vim scriptnames'), '\d\+')
+  let FixFileReferences = function("<SNR>".sid."_fix_file_references")
+
   " No special characters
   let hunk_diff = join([
         \ 'diff --git a/fixture.txt b/fixture.txt',
@@ -855,7 +872,7 @@ function Test_fix_file_references()
         \ '+x'
         \ ], "\n")."\n"
 
-  call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
+  call assert_equal(expected, FixFileReferences(filepath, hunk_diff))
 
   " diff.mnemonicPrefix; spaces in filename
   let hunk_diff = join([
@@ -877,7 +894,7 @@ function Test_fix_file_references()
         \ '+x'
         \ ], "\n")."\n"
 
-  call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
+  call assert_equal(expected, FixFileReferences(filepath, hunk_diff))
 
   " Backslashes in filename; quotation marks
   let hunk_diff = join([
@@ -899,7 +916,7 @@ function Test_fix_file_references()
         \ '+x'
         \ ], "\n")."\n"
 
-  call assert_equal(expected, gitgutter#hunk#fix_file_references(filepath, hunk_diff))
+  call assert_equal(expected, FixFileReferences(filepath, hunk_diff))
 endfunction
 
 
@@ -947,12 +964,27 @@ function Test_quickfix()
   call setline(5, ['A', 'B'])
   call setline(9, ['C', 'D'])
   write
+  let bufnr1 = bufnr('')
+
+  edit fixture_dos.txt
+  call setline(2, ['A', 'B'])
+  write
+  let bufnr2 = bufnr('')
 
   GitGutterQuickFix
 
   let expected = [
-        \ {'lnum': 5, 'bufnr': bufnr(''), 'text': '-e'},
-        \ {'lnum': 9, 'bufnr': bufnr(''), 'text': '-i'}
+        \ {'lnum': 5, 'bufnr': bufnr1, 'text': '-e'},
+        \ {'lnum': 9, 'bufnr': bufnr1, 'text': '-i'},
+        \ {'lnum': 2, 'bufnr': bufnr2, 'text': "-b\r"}
+        \ ]
+
+  call s:assert_list_of_dicts(expected, getqflist())
+
+  GitGutterQuickFixCurrentFile
+
+  let expected = [
+        \ {'lnum': 2, 'bufnr': bufnr(''), 'text': "-b\r"},
         \ ]
 
   call s:assert_list_of_dicts(expected, getqflist())
@@ -960,39 +992,45 @@ endfunction
 
 
 function Test_common_prefix()
+  let sid = matchstr(execute('filter autoload/gitgutter/diff_highlight.vim scriptnames'), '\d\+')
+  let CommonPrefix = function("<SNR>".sid."_common_prefix")
+
   " zero length
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('', 'foo'))
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('foo', ''))
+  call assert_equal(-1, CommonPrefix('', 'foo'))
+  call assert_equal(-1, CommonPrefix('foo', ''))
   " nothing in common
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abcde', '+pqrst'))
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('abcde', 'pqrst'))
+  call assert_equal(-1, CommonPrefix('-abcde', '+pqrst'))
+  call assert_equal(-1, CommonPrefix('abcde', 'pqrst'))
   " something in common
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abcde', '+abcpq'))
-  call assert_equal(2, gitgutter#diff_highlight#common_prefix('abcde', 'abcpq'))
-  call assert_equal(0, gitgutter#diff_highlight#common_prefix('abc', 'apq'))
+  call assert_equal(-1, CommonPrefix('-abcde', '+abcpq'))
+  call assert_equal(2, CommonPrefix('abcde', 'abcpq'))
+  call assert_equal(0, CommonPrefix('abc', 'apq'))
   " everything in common
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abcde', '+abcde'))
-  call assert_equal(4, gitgutter#diff_highlight#common_prefix('abcde', 'abcde'))
+  call assert_equal(-1, CommonPrefix('-abcde', '+abcde'))
+  call assert_equal(4, CommonPrefix('abcde', 'abcde'))
   " different lengths
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abcde', '+abx'))
-  call assert_equal(1, gitgutter#diff_highlight#common_prefix('abcde', 'abx'))
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abx',   '+abcde'))
-  call assert_equal(1, gitgutter#diff_highlight#common_prefix('abx',   'abcde'))
-  call assert_equal(-1, gitgutter#diff_highlight#common_prefix('-abcde', '+abc'))
-  call assert_equal(2, gitgutter#diff_highlight#common_prefix('abcde', 'abc'))
+  call assert_equal(-1, CommonPrefix('-abcde', '+abx'))
+  call assert_equal(1, CommonPrefix('abcde', 'abx'))
+  call assert_equal(-1, CommonPrefix('-abx',   '+abcde'))
+  call assert_equal(1, CommonPrefix('abx',   'abcde'))
+  call assert_equal(-1, CommonPrefix('-abcde', '+abc'))
+  call assert_equal(2, CommonPrefix('abcde', 'abc'))
 endfunction
 
 
 function Test_common_suffix()
+  let sid = matchstr(execute('filter autoload/gitgutter/diff_highlight.vim scriptnames'), '\d\+')
+  let CommonSuffix = function("<SNR>".sid."_common_suffix")
+
   " nothing in common
-  call assert_equal([6,6], gitgutter#diff_highlight#common_suffix('-abcde', '+pqrst', 0))
+  call assert_equal([6,6], CommonSuffix('-abcde', '+pqrst', 0))
   " something in common
-  call assert_equal([3,3], gitgutter#diff_highlight#common_suffix('-abcde', '+pqcde', 0))
+  call assert_equal([3,3], CommonSuffix('-abcde', '+pqcde', 0))
   " everything in common
-  call assert_equal([5,5], gitgutter#diff_highlight#common_suffix('-abcde', '+abcde', 5))
+  call assert_equal([5,5], CommonSuffix('-abcde', '+abcde', 5))
   " different lengths
-  call assert_equal([4,2], gitgutter#diff_highlight#common_suffix('-abcde', '+xde', 0))
-  call assert_equal([2,4], gitgutter#diff_highlight#common_suffix('-xde',   '+abcde', 0))
+  call assert_equal([4,2], CommonSuffix('-abcde', '+xde', 0))
+  call assert_equal([2,4], CommonSuffix('-xde',   '+abcde', 0))
 endfunction
 
 
@@ -1081,18 +1119,24 @@ endfunction
 
 
 function Test_lcs()
-  call assert_equal('', gitgutter#diff_highlight#lcs('', 'foo'))
-  call assert_equal('', gitgutter#diff_highlight#lcs('foo', ''))
-  call assert_equal('bar', gitgutter#diff_highlight#lcs('foobarbaz', 'bbart'))
-  call assert_equal('transaction', gitgutter#diff_highlight#lcs('transaction.unexplained_amount', 'amount(transaction)'))
+  let sid = matchstr(execute('filter autoload/gitgutter/diff_highlight.vim scriptnames'), '\d\+')
+  let Lcs = function("<SNR>".sid."_lcs")
+
+  call assert_equal('', Lcs('', 'foo'))
+  call assert_equal('', Lcs('foo', ''))
+  call assert_equal('bar', Lcs('foobarbaz', 'bbart'))
+  call assert_equal('transaction', Lcs('transaction.unexplained_amount', 'amount(transaction)'))
 endfunction
 
 
 function Test_split()
-  call assert_equal(['foo', 'baz'], gitgutter#diff_highlight#split('foobarbaz', 'bar'))
-  call assert_equal(['', 'barbaz'], gitgutter#diff_highlight#split('foobarbaz', 'foo'))
-  call assert_equal(['foobar', ''], gitgutter#diff_highlight#split('foobarbaz', 'baz'))
-  call assert_equal(['1', '2'], gitgutter#diff_highlight#split('1~2', '~'))
+  let sid = matchstr(execute('filter autoload/gitgutter/diff_highlight.vim scriptnames'), '\d\+')
+  let Split = function("<SNR>".sid."_split")
+
+  call assert_equal(['foo', 'baz'], Split('foobarbaz', 'bar'))
+  call assert_equal(['', 'barbaz'], Split('foobarbaz', 'foo'))
+  call assert_equal(['foobar', ''], Split('foobarbaz', 'baz'))
+  call assert_equal(['1', '2'], Split('1~2', '~'))
 endfunction
 
 
@@ -1111,3 +1155,12 @@ function Test_foldtext()
   call assert_equal(0, gitgutter#fold#is_changed())
   call assert_equal('+-  3 lines: a', gitgutter#fold#foldtext())
 endfunction
+
+
+function Test_assume_unchanged()
+  call system("git update-index --assume-unchanged fixture.txt")
+  unlet b:gitgutter.path  " it was already set when fixture.txt was loaded in SetUp()
+  normal ggo*
+  call s:trigger_gitgutter()
+  call s:assert_signs([], 'fixture.txt')
+endfunction
diff --git a/unplace.vim b/unplace.vim
deleted file mode 100644
index a97993d..0000000
--- a/unplace.vim
+++ /dev/null
@@ -1,27 +0,0 @@
-" Measure how long it takes to unplace signs.
-"
-" Source this file with `:source %` or `vim -S unplace.vim`
-
-
-let num = 500
-sign define Foo text=*
-
-new
-
-call append(0, range(1, num))
-
-for i in range(1, num)
-  execute "sign place ".i." line=".i." name=Foo buffer=".bufnr('')
-endfor
-
-let start = reltime()
-for i in range(1, num)
-  execute "sign unplace ".i
-endfor
-let elapsed = reltime(start)
-
-bdelete!
-
-echom split(reltimestr(elapsed))[0]."s to remove ".num." signs"
-echom string(reltimefloat(elapsed) * 1000 / num).' ms/sign'
-echom string(float2nr(num / reltimefloat(elapsed))).' sign/s'

Debdiff

File lists identical (after any substitutions)

No differences were encountered in the control files

More details

Full run details