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