Codebase list vim-gitgutter / ad0c379d-90bf-4237-ad88-a640d8d45300/upstream
Import upstream version 0~20200414+git20220223.1.18d1298 Debian Janitor 2 years ago
12 changed file(s) with 695 addition(s) and 339 deletion(s). Raw diff Collapse all Expand all
00 ## vim-gitgutter
11
2 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.
2 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.
33
44 The signs are always up to date and the plugin never saves your buffer.
5
6 The name "gitgutter" comes from the Sublime Text 3 plugin which inspired this in 2013.
57
68 Features:
79
3234 * Supports git only. If you work with other version control systems, I recommend [vim-signify](https://github.com/mhinz/vim-signify).
3335 * 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.
3436
37 Compatibility:
38
39 Compatible back to Vim 7.4, and probably 7.3.
40
3541
3642 ### Screenshot
3743
7076
7177 ### Windows
7278
73 I recommend configuring vim-gitgutter with the full path to your git executable. For example:
74
75 ```viml
79 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.
80
81 You can avoid this risk by configuring the full path to your git executable. For example:
82
83 ```viml
84 " This path probably won't work
7685 let g:gitgutter_git_executable = 'C:\Program Files\Git\bin\git.exe'
7786 ```
7887
79 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.
88 Unfortunately I don't know the correct escaping for the path - if you do, please let me know!
8089
8190
8291 ### Getting started
8695 You can jump between hunks with `[c` and `]c`. You can preview, stage, and undo hunks with `<leader>hp`, `<leader>hs`, and `<leader>hu` respectively.
8796
8897 You cannot unstage a staged hunk.
98
99 After updating the signs, the plugin fires the `GitGutter` User autocommand.
100
101 After staging a hunk or part of a hunk, the plugin fires the `GitGutterStage` User autocommand.
89102
90103
91104 #### Activation
126139
127140 If you switch off both line highlighting and signs, you won't see the sign column.
128141
129 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:
130
131 ```viml
132 let g:gitgutter_max_signs = 500 " default value
133 ```
142 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:
143
144 ```viml
145 let g:gitgutter_max_signs = 500 " default value (Vim < 8.1.0614, Neovim < 0.4.0)
146 let g:gitgutter_max_signs = -1 " default value (otherwise)
147 ```
148
149 You can also remove the limit by setting `g:gitgutter_max_signs = -1`.
134150
135151 #### Hunks
136152
148164 nmap [h <Plug>(GitGutterPrevHunk)
149165 ```
150166
151 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.
167 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:
168
169 ```viml
170 let g:gitgutter_show_msg_on_hunk_jumping = 0
171 ```
172
173 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:
174
175 ```viml
176 command! Gqf GitGutterQuickFix | copen
177 ```
152178
153179 You can stage or undo an individual hunk when your cursor is in it:
154180
256282 * How to handle non-gitgutter signs
257283 * The signs' colours and symbols
258284 * Line highlights
285 * Line number highlights (only in Neovim 0.3.2 or higher)
286 * The diff syntax colours used in the preview window
287 * The intra-line diff highlights used in the preview window
259288 * Whether the diff is relative to the index (default) or working tree.
260289 * The base of the diff
261290 * Extra arguments for `git` when running `git diff`
269298 * Whether to clobber or preserve non-gitgutter signs
270299 * The priority of gitgutter's signs.
271300 * Whether to use a floating/popup window for hunk previews
301 * The appearance of a floating/popup window for hunk previews
272302 * Whether to populate the quickfix list or a location list with all hunks
273303
274304 Please note that vim-gitgutter won't override any colours or highlights you've set in your colorscheme.
276306
277307 #### Sign column
278308
279 By default vim-gitgutter will make the sign column look like the line number column.
280
281 To customise your sign column's background color, first tell vim-gitgutter to leave it alone:
282
283 ```viml
284 let g:gitgutter_override_sign_column_highlight = 0
285 ```
286
287 And then either update your colorscheme's `SignColumn` highlight group or set it in your vimrc:
288
289 ```viml
290 highlight SignColumn ctermbg=whatever " terminal Vim
291 highlight SignColumn guibg=whatever " gVim/MacVim
309 Set the `SignColumn` highlight group to change the sign column's colour. For example:
310
311 ```viml
312 " vim-gitgutter used to do this by default:
313 highlight! link SignColumn LineNr
314
315 " or you could do this:
316 highlight SignColumn guibg=whatever ctermbg=whatever
292317 ```
293318
294319 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:
307332
308333 #### Signs' colours and symbols
309334
310 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.
311
312 The signs' background colours will all be set to the sign column's background colour.
313
314 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:
315
316 ```viml
317 GitGutterAdd " an added line (default: links to DiffAdd)
318 GitGutterChange " a changed line (default: links to DiffChange)
319 GitGutterDelete " at least one removed line (default: links to DiffDelete)
320 GitGutterChangeDelete " a changed line followed by at least one removed line (default: links to GitGutterChange)
321 ```
322
323 You can either set these with `highlight GitGutterAdd {key}={arg}...` or link them to existing highlight groups with, say, `highlight link GitGutterAdd MyDiffAdd`.
324
325 To get vim-gitgutter's original colours (based on git-diff's colours in my terminal):
326
327 ```viml
328 highlight GitGutterAdd guifg=#009900 guibg=<X> ctermfg=2 ctermbg=<Y>
329 highlight GitGutterChange guifg=#bbbb00 guibg=<X> ctermfg=3 ctermbg=<Y>
330 highlight GitGutterDelete guifg=#ff2222 guibg=<X> ctermfg=1 ctermbg=<Y>
331 ```
332
333 – 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`.
335 If you or your colourscheme has defined `GitGutter*` highlight groups, the plugin will use them for the signs' colours.
336
337 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:
338
339 ```viml
340 let g:gitgutter_set_sign_backgrounds = 1
341 ```
342
343 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:
344
345 ```viml
346 highlight GitGutterAdd guifg=#009900 ctermfg=2
347 highlight GitGutterChange guifg=#bbbb00 ctermfg=3
348 highlight GitGutterDelete guifg=#ff2222 ctermfg=1
349 ```
334350
335351 To customise the symbols, add the following to your `~/.vimrc`:
336352
339355 let g:gitgutter_sign_modified = 'yy'
340356 let g:gitgutter_sign_removed = 'zz'
341357 let g:gitgutter_sign_removed_first_line = '^^'
358 let g:gitgutter_sign_removed_above_and_below = '{'
342359 let g:gitgutter_sign_modified_removed = 'ww'
343360 ```
344361
381398 ```
382399
383400
401 #### The diff syntax colours used in the preview window
402
403 To change the diff syntax colours used in the preview window, set up the `diff*` highlight groups in your colorscheme or `~/.vimrc`:
404
405 ```viml
406 diffAdded " if not set: use GitGutterAdd's foreground colour
407 diffChanged " if not set: use GitGutterChange's foreground colour
408 diffRemoved " if not set: use GitGutterDelete's foreground colour
409 ```
410
411 Note the `diff*` highlight groups are used in any buffer whose `'syntax'` is `diff`.
412
413
414 #### The intra-line diff highlights used in the preview window
415
416 To change the intra-line diff highlights used in the preview window, set up the following highlight groups in your colorscheme or `~/.vimrc`:
417
418 ```viml
419 GitGutterAddIntraLine " default: gui=reverse cterm=reverse
420 GitGutterDeleteIntraLine " default: gui=reverse cterm=reverse
421 ```
422
423 For example, to use `DiffAdd` for intra-line added regions:
424
425 ```viml
426 highlight link GitGutterAddIntraLine DiffAdd
427 ```
428
429
384430 #### Whether the diff is relative to the index or working tree
385431
386432 By default diffs are relative to the index. How you can make them relative to the working tree:
471517 #### To use floating/popup windows for hunk previews
472518
473519 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.
520
521
522 #### The appearance of a floating/popup window for hunk previews
523
524 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).
474525
475526
476527 #### To load all hunks into the current window's location list instead of the quickfix list
633684
634685 Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column.
635686
636 > Why are the colours in the preview window weird?
637
638 Probably because your colourscheme doesn't configure the `diff{Added,Changed,Removed}` highlight groups. Try this in `after/syntax/diff.vim`:
639
640 ```viml
641 highlight link diffAdded DiffAdd
642 highlight link diffChanged DiffChange
643 highlight link diffRemoved DiffDelete
644 ```
645
646687 > What happens if I also use another plugin which uses signs (e.g. Syntastic)?
647688
648689 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.
658699 * Verify `:echo system("git --version")` succeeds.
659700 * Verify your git config is compatible with the version of git returned by the command above.
660701 * Verify your Vim supports signs (`:echo has('signs')` should give `1`).
661 * Verify your file is being tracked by git and has unstaged changes.
702 * 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.
703 * Execute `:sign place group=gitgutter`; you should see a list of signs.
704 - If the signs are listed: this is a colorscheme / highlight problem. Compare `:highlight GitGutterAdd` with `:highlight SignColumn`.
705 - 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.
662706
663707 #### When the whole file is marked as added
664708
680724 * [Smash Into Vim][siv]
681725
682726 This was one of PeepCode's all-time top three bestsellers and is now available at Pluralsight.
683
684 You can read reviews on my [website][airblade].
685727
686728
687729 ### Intellectual Property
44 \ (has('patch-7-4-1832') && has('gui_macvim'))
55 \ )
66 \ )
7
8 let s:jobs = {}
79
810 function! gitgutter#async#available()
911 return s:available
2729 \ 'on_exit': function('s:on_exit_nvim')
2830 \ }))
2931 else
30 call job_start(command, {
32 let job = job_start(command, {
3133 \ 'out_cb': function('s:on_stdout_vim', options),
3234 \ 'err_cb': function('s:on_stderr_vim', options),
3335 \ 'close_cb': function('s:on_exit_vim', options)
3436 \ })
37 let s:jobs[s:job_id(job)] = 1
3538 endif
3639 endfunction
3740
8285
8386 function! s:on_exit_vim(channel) dict abort
8487 let job = ch_getjob(a:channel)
88 let jobid = s:job_id(job)
89 if has_key(s:jobs, jobid) | unlet s:jobs[jobid] | endif
8590 while 1
8691 if job_status(job) == 'dead'
8792 let exit_code = job_info(job).exitval
9499 call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
95100 endif
96101 endfunction
102
103 function! s:job_id(job)
104 " Vim
105 return job_info(a:job).process
106 endfunction
2121 call s:separator()
2222
2323 call s:option('updatetime')
24 call s:option('shell')
25 call s:option('shellcmdflag')
26 call s:option('shellpipe')
27 call s:option('shellquote')
28 call s:option('shellredir')
29 call s:option('shellslash')
30 call s:option('shelltemp')
31 call s:option('shelltype')
32 call s:option('shellxescape')
33 call s:option('shellxquote')
3424 endfunction
3525
3626
5141 endfunction
5242
5343 function! s:grep_version()
54 let v = system('grep --version')
44 let v = system(g:gitgutter_grep.' --version')
5545 call s:output( substitute(v, '\n$', '', '') )
5646
57 let v = system('grep --help')
47 let v = system(g:gitgutter_grep.' --help')
5848 call s:output( substitute(v, '\%x00', '', 'g') )
5949 endfunction
6050
1010 endfunction
1111
1212 let s:c_flag = s:git_supports_command_line_config_override()
13
1413
1514 let s:temp_from = tempname()
1615 let s:temp_buffer = tempname()
7069 " grep is available.
7170 function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort
7271 if gitgutter#utility#repo_path(a:bufnr, 0) == -1
73 throw 'gitgutter author fail'
72 throw 'gitgutter path not set'
7473 endif
7574
7675 if gitgutter#utility#repo_path(a:bufnr, 0) == -2
119118 endif
120119
121120 " Write file from index to temporary file.
122 let index_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1)
121 let index_name = gitgutter#utility#get_diff_base(a:bufnr).':'.gitgutter#utility#repo_path(a:bufnr, 1)
123122 let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager show '.index_name.' > '.from_file.' && '
124123
125124 elseif a:from ==# 'working_tree'
127126 endif
128127
129128 " Call git-diff.
130 let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager '.g:gitgutter_git_args
129 let cmd .= g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager'
131130 if s:c_flag
132131 let cmd .= ' -c "diff.autorefreshindex=0"'
133132 let cmd .= ' -c "diff.noprefix=false"'
181180 let modified_lines = gitgutter#diff#process_hunks(a:bufnr, gitgutter#hunk#hunks(a:bufnr))
182181
183182 let signs_count = len(modified_lines)
184 if signs_count > g:gitgutter_max_signs
183 if g:gitgutter_max_signs != -1 && signs_count > g:gitgutter_max_signs
185184 call gitgutter#utility#warn_once(a:bufnr, printf(
186185 \ 'exceeded maximum number of signs (%d > %d, configured by g:gitgutter_max_signs).',
187186 \ signs_count, g:gitgutter_max_signs), 'max_signs')
399398 let bufcontents[0]=''.bufcontents[0]
400399 endif
401400
402 call writefile(bufcontents, a:file, 'b')
401 " The file we are writing to is a temporary file. Sometimes the parent
402 " directory is deleted outside Vim but, because Vim caches the directory
403 " name at startup and does not check for its existence subsequently, Vim
404 " does not realise. This causes E482 errors.
405 try
406 call writefile(bufcontents, a:file, 'b')
407 catch /E482/
408 call mkdir(fnamemodify(a:file, ':h'), '', '0700')
409 call writefile(bufcontents, a:file, 'b')
410 endtry
403411 endfunction
404412
405413
6262 endif
6363 endfunction
6464
65
66 function! gitgutter#highlight#define_sign_column_highlight() abort
67 if g:gitgutter_override_sign_column_highlight
68 highlight! link SignColumn LineNr
69 else
70 highlight default link SignColumn LineNr
71 endif
72 endfunction
7365
7466 function! gitgutter#highlight#define_highlights() abort
7567 let [guibg, ctermbg] = s:get_background_colors('SignColumn')
8375 highlight default link GitGutterChangeDeleteInvisible GitGutterChangeInvisible
8476
8577 " When they are visible.
86 " By default use Diff* foreground colors with SignColumn's background.
87 for type in ['Add', 'Change', 'Delete']
88 let [guifg, ctermfg] = s:get_foreground_colors('Diff'.type)
89 execute "highlight GitGutter".type."Default guifg=".guifg." guibg=".guibg." ctermfg=".ctermfg." ctermbg=".ctermbg
90 execute "highlight default link GitGutter".type." GitGutter".type."Default"
78 for type in ["Add", "Change", "Delete"]
79 if hlexists("GitGutter".type) && s:get_foreground_colors("GitGutter".type) != ['NONE', 'NONE']
80 if g:gitgutter_set_sign_backgrounds
81 execute "highlight GitGutter".type." guibg=".guibg." ctermbg=".ctermbg
82 endif
83 continue
84 elseif s:useful_diff_colours()
85 let [guifg, ctermfg] = s:get_foreground_colors('Diff'.type)
86 else
87 let [guifg, ctermfg] = s:get_foreground_fallback_colors(type)
88 endif
89 execute "highlight GitGutter".type." guifg=".guifg." guibg=".guibg." ctermfg=".ctermfg." ctermbg=".ctermbg
9190 endfor
91
92 if hlexists("GitGutterChangeDelete") && g:gitgutter_set_sign_backgrounds
93 execute "highlight GitGutterChangeDelete guibg=".guibg." ctermbg=".ctermbg
94 endif
95
9296 highlight default link GitGutterChangeDelete GitGutterChange
9397
9498 " Highlights used for the whole line.
104108 highlight default link GitGutterChangeDeleteLineNr CursorLineNr
105109
106110 " Highlights used intra line.
107 highlight GitGutterAddIntraLine gui=reverse cterm=reverse
108 highlight GitGutterDeleteIntraLine gui=reverse cterm=reverse
111 highlight default GitGutterAddIntraLine gui=reverse cterm=reverse
112 highlight default GitGutterDeleteIntraLine gui=reverse cterm=reverse
113 " Set diff syntax colours (used in the preview window) - diffAdded,diffChanged,diffRemoved -
114 " to match the signs, if not set aleady.
115 for [dtype,type] in [['Added','Add'], ['Changed','Change'], ['Removed','Delete']]
116 if !hlexists('diff'.dtype)
117 let [guifg, ctermfg] = s:get_foreground_colors('GitGutter'.type)
118 execute "highlight diff".dtype." guifg=".guifg." ctermfg=".ctermfg." guibg=NONE ctermbg=NONE"
119 endif
120 endfor
109121 endfunction
110122
111123 function! gitgutter#highlight#define_signs() abort
162174 sign define GitGutterLineRemovedAboveAndBelow linehl=GitGutterDeleteLine
163175 sign define GitGutterLineModifiedRemoved linehl=GitGutterChangeDeleteLine
164176 else
165 sign define GitGutterLineAdded linehl=
166 sign define GitGutterLineModified linehl=
167 sign define GitGutterLineRemoved linehl=
168 sign define GitGutterLineRemovedFirstLine linehl=
169 sign define GitGutterLineRemovedAboveAndBelow linehl=
170 sign define GitGutterLineModifiedRemoved linehl=
177 sign define GitGutterLineAdded linehl=NONE
178 sign define GitGutterLineModified linehl=NONE
179 sign define GitGutterLineRemoved linehl=NONE
180 sign define GitGutterLineRemovedFirstLine linehl=NONE
181 sign define GitGutterLineRemovedAboveAndBelow linehl=NONE
182 sign define GitGutterLineModifiedRemoved linehl=NONE
171183 endif
172184 endfunction
173185
182194 sign define GitGutterLineRemovedAboveAndBelow numhl=GitGutterDeleteLineNr
183195 sign define GitGutterLineModifiedRemoved numhl=GitGutterChangeDeleteLineNr
184196 else
185 sign define GitGutterLineAdded numhl=
186 sign define GitGutterLineModified numhl=
187 sign define GitGutterLineRemoved numhl=
188 sign define GitGutterLineRemovedFirstLine numhl=
189 sign define GitGutterLineRemovedAboveAndBelow numhl=
190 sign define GitGutterLineModifiedRemoved numhl=
197 sign define GitGutterLineAdded numhl=NONE
198 sign define GitGutterLineModified numhl=NONE
199 sign define GitGutterLineRemoved numhl=NONE
200 sign define GitGutterLineRemovedFirstLine numhl=NONE
201 sign define GitGutterLineRemovedAboveAndBelow numhl=NONE
202 sign define GitGutterLineModifiedRemoved numhl=NONE
191203 endif
192204 catch /E475/
193205 endtry
213225 let guibg = s:get_hl(a:group, 'bg', 'gui')
214226 return [guibg, ctermbg]
215227 endfunction
228
229 function! s:useful_diff_colours()
230 let [guifg_add, ctermfg_add] = s:get_foreground_colors('DiffAdd')
231 let [guifg_del, ctermfg_del] = s:get_foreground_colors('DiffDelete')
232
233 return guifg_add != guifg_del && ctermfg_add != ctermfg_del
234 endfunction
235
236 function! s:get_foreground_fallback_colors(type)
237 if a:type == 'Add'
238 return ['#009900', '2']
239 elseif a:type == 'Change'
240 return ['#bbbb00', '3']
241 elseif a:type == 'Delete'
242 return ['#ff2222', '1']
243 endif
244 endfunction
00 let s:winid = 0
1 let s:preview_bufnr = 0
2 let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
13
24 function! gitgutter#hunk#set_hunks(bufnr, hunks) abort
35 call gitgutter#utility#setbufvar(a:bufnr, 'hunks', a:hunks)
4345
4446 function! gitgutter#hunk#next_hunk(count) abort
4547 let bufnr = bufnr('')
46 if gitgutter#utility#is_active(bufnr)
47 let current_line = line('.')
48 let hunk_count = 0
49 for hunk in gitgutter#hunk#hunks(bufnr)
50 if hunk[2] > current_line
51 let hunk_count += 1
52 if hunk_count == a:count
53 execute 'normal!' hunk[2] . 'Gzv'
54 return
48 if !gitgutter#utility#is_active(bufnr) | return | endif
49
50 let hunks = gitgutter#hunk#hunks(bufnr)
51 if empty(hunks)
52 call gitgutter#utility#warn('No hunks in file')
53 return
54 endif
55
56 let current_line = line('.')
57 let hunk_count = 0
58 for hunk in hunks
59 if hunk[2] > current_line
60 let hunk_count += 1
61 if hunk_count == a:count
62 execute 'normal!' hunk[2] . 'Gzv'
63 if g:gitgutter_show_msg_on_hunk_jumping
64 redraw | echo printf('Hunk %d of %d', index(hunks, hunk) + 1, len(hunks))
5565 endif
66 if gitgutter#hunk#is_preview_window_open()
67 call gitgutter#hunk#preview()
68 endif
69 return
5670 endif
57 endfor
58 call gitgutter#utility#warn('No more hunks')
59 endif
71 endif
72 endfor
73 call gitgutter#utility#warn('No more hunks')
6074 endfunction
6175
6276 function! gitgutter#hunk#prev_hunk(count) abort
6377 let bufnr = bufnr('')
64 if gitgutter#utility#is_active(bufnr)
65 let current_line = line('.')
66 let hunk_count = 0
67 for hunk in reverse(copy(gitgutter#hunk#hunks(bufnr)))
68 if hunk[2] < current_line
69 let hunk_count += 1
70 if hunk_count == a:count
71 let target = hunk[2] == 0 ? 1 : hunk[2]
72 execute 'normal!' target . 'Gzv'
73 return
78 if !gitgutter#utility#is_active(bufnr) | return | endif
79
80 let hunks = gitgutter#hunk#hunks(bufnr)
81 if empty(hunks)
82 call gitgutter#utility#warn('No hunks in file')
83 return
84 endif
85
86 let current_line = line('.')
87 let hunk_count = 0
88 for hunk in reverse(copy(hunks))
89 if hunk[2] < current_line
90 let hunk_count += 1
91 if hunk_count == a:count
92 let target = hunk[2] == 0 ? 1 : hunk[2]
93 execute 'normal!' target . 'Gzv'
94 if g:gitgutter_show_msg_on_hunk_jumping
95 redraw | echo printf('Hunk %d of %d', index(hunks, hunk) + 1, len(hunks))
7496 endif
97 if gitgutter#hunk#is_preview_window_open()
98 call gitgutter#hunk#preview()
99 endif
100 return
75101 endif
76 endfor
77 call gitgutter#utility#warn('No previous hunks')
78 endif
102 endif
103 endfor
104 call gitgutter#utility#warn('No previous hunks')
79105 endfunction
80106
81107 " Returns the hunk the cursor is currently in or an empty list if the cursor
222248 let hunk_diff = join(hunk_header + hunk_body, "\n")."\n"
223249
224250 call s:goto_original_window()
225 call s:close_hunk_preview_window()
251 call gitgutter#hunk#close_hunk_preview_window()
226252 call s:stage(hunk_diff)
227253 endif
228254
236262 let g:gitgutter_async = async
237263
238264 call gitgutter#hunk#set_hunks(bufnr, gitgutter#diff#parse_diff(diff))
265 call gitgutter#diff#process_hunks(bufnr, gitgutter#hunk#hunks(bufnr)) " so the hunk summary is updated
239266
240267 if empty(s:current_hunk())
241 call gitgutter#utility#warn('cursor is not in a hunk')
268 call gitgutter#utility#warn('Cursor is not in a hunk')
242269 elseif s:cursor_in_two_hunks()
243270 let choice = input('Choose hunk: upper or lower (u/l)? ')
244271 " Clear input
248275 elseif choice =~ 'l'
249276 call a:op(gitgutter#diff#hunk_diff(bufnr, diff, 1))
250277 else
251 call gitgutter#utility#warn('did not recognise your choice')
278 call gitgutter#utility#warn('Did not recognise your choice')
252279 endif
253280 else
254281 let hunk_diff = gitgutter#diff#hunk_diff(bufnr, diff)
272299 \ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' apply --cached --unidiff-zero - '),
273300 \ diff)
274301 if v:shell_error
275 call gitgutter#utility#warn('patch does not apply')
302 call gitgutter#utility#warn('Patch does not apply')
303 else
304 if exists('#User#GitGutterStage')
305 execute 'doautocmd' s:nomodeline 'User GitGutterStage'
306 endif
276307 endif
277308
278309 " Refresh gitgutter's view of buffer.
395426 function! s:open_hunk_preview_window()
396427 if g:gitgutter_preview_win_floating
397428 if exists('*nvim_open_win')
398 call s:close_hunk_preview_window()
429 call gitgutter#hunk#close_hunk_preview_window()
399430
400431 let buf = nvim_create_buf(v:false, v:false)
401432 " Set default width and height for now.
402 let s:winid = nvim_open_win(buf, v:false, {
403 \ 'relative': 'cursor',
404 \ 'row': 1,
405 \ 'col': 0,
406 \ 'width': 42,
407 \ 'height': &previewheight,
408 \ 'style': 'minimal'
409 \ })
433 let s:winid = nvim_open_win(buf, v:false, g:gitgutter_floating_window_options)
410434 call nvim_buf_set_option(buf, 'filetype', 'diff')
411435 call nvim_buf_set_option(buf, 'buftype', 'acwrite')
412436 call nvim_buf_set_option(buf, 'bufhidden', 'delete')
414438 call nvim_buf_set_name(buf, 'gitgutter://hunk-preview')
415439
416440 " Assumes cursor is in original window.
417 autocmd CursorMoved <buffer> ++once call s:close_hunk_preview_window()
441 autocmd CursorMoved <buffer> ++once call gitgutter#hunk#close_hunk_preview_window()
442
443 if g:gitgutter_close_preview_on_escape
444 " Map <Esc> to close the floating preview.
445 nnoremap <buffer> <silent> <Esc> :<C-U>call gitgutter#hunk#close_hunk_preview_window()<CR>
446 " Ensure that when the preview window is closed, the map is removed.
447 autocmd User GitGutterPreviewClosed silent! nunmap <buffer> <Esc>
448 autocmd CursorMoved <buffer> ++once silent! nunmap <buffer> <Esc>
449 execute "autocmd WinClosed <buffer=".winbufnr(s:winid)."> doautocmd" s:nomodeline "User GitGutterPreviewClosed"
450 endif
418451
419452 return
420453 endif
421454
422455 if exists('*popup_create')
423 let s:winid = popup_create('', {
424 \ 'line': 'cursor+1',
425 \ 'col': 'cursor',
426 \ 'moved': 'any',
427 \ })
456 if g:gitgutter_close_preview_on_escape
457 let g:gitgutter_floating_window_options.filter = function('s:close_popup_on_escape')
458 endif
459
460 let s:winid = popup_create('', g:gitgutter_floating_window_options)
428461
429462 call setbufvar(winbufnr(s:winid), '&filetype', 'diff')
430463
432465 endif
433466 endif
434467
468 if exists('&previewpopup')
469 let [previewpopup, &previewpopup] = [&previewpopup, '']
470 endif
471
472 " Specifying where to open the preview window can lead to the cursor going
473 " to an unexpected window when the preview window is closed (#769).
474 silent! noautocmd execute g:gitgutter_preview_win_location 'pedit gitgutter://hunk-preview'
435475 silent! wincmd P
436 if !&previewwindow
437 noautocmd execute g:gitgutter_preview_win_location &previewheight 'new gitgutter://hunk-preview'
438 doautocmd WinEnter
476 setlocal statusline=%{''}
477 doautocmd WinEnter
478 if exists('*win_getid')
439479 let s:winid = win_getid()
440 set previewwindow
441 setlocal filetype=diff buftype=acwrite bufhidden=delete
442 " Reset some defaults in case someone else has changed them.
443 setlocal noreadonly modifiable noswapfile
444 endif
480 else
481 let s:preview_bufnr = bufnr('')
482 endif
483 setlocal filetype=diff buftype=acwrite bufhidden=delete
484 " Reset some defaults in case someone else has changed them.
485 setlocal noreadonly modifiable noswapfile
486 if g:gitgutter_close_preview_on_escape
487 " Ensure cursor goes to the expected window.
488 nnoremap <buffer> <silent> <Esc> :<C-U>wincmd p<Bar>pclose<CR>
489 endif
490
491 if exists('&previewpopup')
492 let &previewpopup=previewpopup
493 endif
494 endfunction
495
496
497 function! s:close_popup_on_escape(winid, key)
498 if a:key == "\<Esc>"
499 call popup_close(a:winid)
500 return 1
501 endif
502 return 0
445503 endfunction
446504
447505
449507 " Preview window: assumes cursor is in preview window.
450508 function! s:populate_hunk_preview_window(header, body)
451509 let body_length = len(a:body)
452 let height = min([body_length, &previewheight])
453510
454511 if g:gitgutter_preview_win_floating
455512 if exists('*nvim_open_win')
513 let height = min([body_length, g:gitgutter_floating_window_options.height])
514
456515 " Assumes cursor is not in previewing window.
457516 call nvim_buf_set_var(winbufnr(s:winid), 'hunk_header', a:header)
517
518 let [_scrolloff, &scrolloff] = [&scrolloff, 0]
458519
459520 let width = max(map(copy(a:body), 'strdisplaywidth(v:val)'))
460521 call nvim_win_set_width(s:winid, width)
461522 call nvim_win_set_height(s:winid, height)
523
524 let &scrolloff=_scrolloff
462525
463526 call nvim_buf_set_lines(winbufnr(s:winid), 0, -1, v:false, [])
464527 call nvim_buf_set_lines(winbufnr(s:winid), 0, -1, v:false, a:body)
485548
486549 else
487550 let b:hunk_header = a:header
488 execute 'resize' height
489551
490552 %delete _
491553 call setline(1, a:body)
492554 setlocal nomodified
555
556 normal! G$
557 let hunk_height = max([body_length, winline()])
558 let height = min([hunk_height, &previewheight])
559 execute 'resize' height
560 1
493561
494562 call clearmatches()
495563 for region in gitgutter#diff_highlight#process(a:body)
505573 function! s:enable_staging_from_hunk_preview_window()
506574 augroup gitgutter_hunk_preview
507575 autocmd!
508 execute 'autocmd BufWriteCmd <buffer='.winbufnr(s:winid).'> GitGutterStageHunk'
576 let bufnr = s:winid != 0 ? winbufnr(s:winid) : s:preview_bufnr
577 execute 'autocmd BufWriteCmd <buffer='.bufnr.'> GitGutterStageHunk'
509578 augroup END
510579 endfunction
511580
516585 endfunction
517586
518587
519 function! s:close_hunk_preview_window()
520 call setbufvar(winbufnr(s:winid), '&modified', 0)
588 function! gitgutter#hunk#close_hunk_preview_window()
589 let bufnr = s:winid != 0 ? winbufnr(s:winid) : s:preview_bufnr
590 call setbufvar(bufnr, '&modified', 0)
521591
522592 if g:gitgutter_preview_win_floating
523593 if win_id2win(s:winid) > 0
528598 endif
529599
530600 let s:winid = 0
531 endfunction
601 let s:preview_bufnr = 0
602 endfunction
603
604
605 function gitgutter#hunk#is_preview_window_open()
606 if g:gitgutter_preview_win_floating
607 if win_id2win(s:winid) > 0
608 execute win_id2win(s:winid).'wincmd c'
609 endif
610 else
611 for i in range(1, winnr('$'))
612 if getwinvar(i, '&previewwindow')
613 return 1
614 endif
615 endfor
616 endif
617 return 0
618 endfunction
2929
3030 function! gitgutter#utility#warn(message) abort
3131 echohl WarningMsg
32 echo 'vim-gitgutter: ' . a:message
32 echo a:message
3333 echohl None
3434 let v:warningmsg = a:message
3535 endfunction
3838 if empty(gitgutter#utility#getbufvar(a:bufnr, a:key))
3939 call gitgutter#utility#setbufvar(a:bufnr, a:key, '1')
4040 echohl WarningMsg
41 redraw | echom 'vim-gitgutter: ' . a:message
41 redraw | echom a:message
4242 echohl None
4343 let v:warningmsg = a:message
4444 endif
4747 " Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
4848 " This function does not and should not make any system calls.
4949 function! gitgutter#utility#is_active(bufnr) abort
50 return g:gitgutter_enabled &&
51 \ gitgutter#utility#getbufvar(a:bufnr, 'enabled', 1) &&
50 return gitgutter#utility#getbufvar(a:bufnr, 'enabled') &&
5251 \ !pumvisible() &&
5352 \ s:is_file_buffer(a:bufnr) &&
5453 \ s:exists_file(a:bufnr) &&
161160
162161
163162 function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
164 let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() ? 'cd /d' : 'cd')
163 let cd = s:unc_path(a:bufnr) ? 'pushd' : (gitgutter#utility#windows() && s:dos_shell() ? 'cd /d' : 'cd')
165164 return cd.' '.s:dir(a:bufnr).' && '.a:cmd
166165 endfunction
167166
169168 return s:abs_path(a:bufnr, 0) =~ '^\\\\'
170169 endfunction
171170
171 function! s:dos_shell()
172 return &shell == 'cmd.exe' || &shell == 'command.com'
173 endfunction
174
172175 function! s:use_known_shell() abort
173176 if has('unix') && &shell !=# 'sh'
174 let [s:shell, s:shellcmdflag, s:shellredir] = [&shell, &shellcmdflag, &shellredir]
177 let [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote] = [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote]
175178 let &shell = 'sh'
176179 set shellcmdflag=-c shellredir=>%s\ 2>&1
177180 endif
181 if has('win32') && (&shell =~# 'pwsh' || &shell =~# 'powershell')
182 let [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote] = [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote]
183 let &shell = 'cmd.exe'
184 set shellcmdflag=/s\ /c shellredir=>%s\ 2>&1 shellpipe=>%s\ 2>&1 shellquote= shellxquote="
185 endif
178186 endfunction
179187
180188 function! s:restore_shell() abort
181 if has('unix') && exists('s:shell')
182 let [&shell, &shellcmdflag, &shellredir] = [s:shell, s:shellcmdflag, s:shellredir]
183 endif
184 endfunction
185
186 function! gitgutter#utility#set_diff_base_if_fugitive(bufnr)
189 if (has('unix') || has('win32')) && exists('s:shell')
190 let [&shell, &shellcmdflag, &shellredir, &shellpipe, &shellquote, &shellxquote] = [s:shell, s:shellcmdflag, s:shellredir, s:shellpipe, s:shellquote, s:shellxquote]
191 endif
192 endfunction
193
194 function! gitgutter#utility#get_diff_base(bufnr)
187195 let p = resolve(expand('#'.a:bufnr.':p'))
188196 let ml = matchlist(p, '\v^fugitive:/.*/(\x{40,})/')
189197 if !empty(ml) && !empty(ml[1])
190 let g:gitgutter_diff_base = ml[1].'^'
191 endif
198 return ml[1].'^'
199 endif
200 return g:gitgutter_diff_base
192201 endfunction
193202
194203 function! s:abs_path(bufnr, shellesc)
2020 function! gitgutter#process_buffer(bufnr, force) abort
2121 " NOTE a:bufnr is not necessarily the current buffer.
2222
23 if gitgutter#utility#getbufvar(a:bufnr, 'enabled', -1) == -1
24 call gitgutter#utility#setbufvar(a:bufnr, 'enabled', g:gitgutter_enabled)
25 endif
26
2327 if gitgutter#utility#is_active(a:bufnr)
2428
2529 if has('patch-7.4.1559')
3135 if [how] == ['async'] " avoid string-to-number conversion if how is a number
3236 return
3337 endif
34
35 call gitgutter#utility#set_diff_base_if_fugitive(a:bufnr)
3638
3739 if a:force || s:has_fresh_changes(a:bufnr)
3840
5658
5759
5860 function! gitgutter#disable() abort
59 " get list of all buffers (across all tabs)
61 call s:toggle_each_buffer(0)
62 let g:gitgutter_enabled = 0
63 endfunction
64
65 function! gitgutter#enable() abort
66 call s:toggle_each_buffer(1)
67 let g:gitgutter_enabled = 1
68 endfunction
69
70 function s:toggle_each_buffer(enable)
6071 for bufnr in range(1, bufnr('$') + 1)
6172 if buflisted(bufnr)
6273 let file = expand('#'.bufnr.':p')
6374 if !empty(file)
64 call s:clear(bufnr)
75 if a:enable
76 call gitgutter#buffer_enable(bufnr)
77 else
78 call gitgutter#buffer_disable(bufnr)
79 end
6580 endif
6681 endif
6782 endfor
68
69 let g:gitgutter_enabled = 0
70 endfunction
71
72 function! gitgutter#enable() abort
73 let g:gitgutter_enabled = 1
74 call gitgutter#all(1)
7583 endfunction
7684
7785 function! gitgutter#toggle() abort
8391 endfunction
8492
8593
86 function! gitgutter#buffer_disable() abort
87 let bufnr = bufnr('')
94 function! gitgutter#buffer_disable(...) abort
95 let bufnr = a:0 ? a:1 : bufnr('')
8896 call gitgutter#utility#setbufvar(bufnr, 'enabled', 0)
8997 call s:clear(bufnr)
9098 endfunction
9199
92 function! gitgutter#buffer_enable() abort
93 let bufnr = bufnr('')
100 function! gitgutter#buffer_enable(...) abort
101 let bufnr = a:0 ? a:1 : bufnr('')
94102 call gitgutter#utility#setbufvar(bufnr, 'enabled', 1)
95103 call gitgutter#process_buffer(bufnr, 1)
96104 endfunction
97105
98 function! gitgutter#buffer_toggle() abort
99 if gitgutter#utility#getbufvar(bufnr(''), 'enabled', 1)
100 call gitgutter#buffer_disable()
106 function! gitgutter#buffer_toggle(...) abort
107 let bufnr = a:0 ? a:1 : bufnr('')
108 if gitgutter#utility#getbufvar(bufnr, 'enabled', 1)
109 call gitgutter#buffer_disable(bufnr)
101110 else
102 call gitgutter#buffer_enable()
111 call gitgutter#buffer_enable(bufnr)
103112 endif
104113 endfunction
105114
180189 " - this runs synchronously
181190 " - it ignores unsaved changes in buffers
182191 " - it does not change to the repo root
183 function! gitgutter#quickfix()
192 function! gitgutter#quickfix(current_file)
193 let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' rev-parse --show-cdup'
194 let path_to_repo = get(systemlist(cmd), 0, '')
195 if !empty(path_to_repo) && path_to_repo[-1:] != '/'
196 let path_to_repo .= '/'
197 endif
198
184199 let locations = []
185 let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager '.g:gitgutter_git_args.
186 \ ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args. ' '. g:gitgutter_diff_base
200 let cmd = g:gitgutter_git_executable.' '.g:gitgutter_git_args.' --no-pager'.
201 \ ' diff --no-ext-diff --no-color -U0'.
202 \ ' --src-prefix=a/'.path_to_repo.' --dst-prefix=b/'.path_to_repo.' '.
203 \ g:gitgutter_diff_args. ' '. g:gitgutter_diff_base
204 if a:current_file
205 let cmd = cmd.' -- '.expand('%:p')
206 endif
187207 let diff = systemlist(cmd)
188208 let lnum = 0
189209 for line in diff
195215 elseif line =~ '^diff --git "'
196216 let [_, fnamel, _, fnamer] = split(line, '"')
197217 let fname = fnamel ==# fnamer ? fnamel : fnamel[2:]
218 elseif line =~ '^diff --cc [^"]'
219 let fname = line[10:]
220 elseif line =~ '^diff --cc "'
221 let [_, fname] = split(line, '"')
198222 elseif line =~ '^@@'
199223 let lnum = matchlist(line, '+\(\d\+\)')[1]
200224 elseif lnum > 0
00 *gitgutter.txt* A Vim plugin which shows a git diff in the gutter.
11
22
3 Vim Git Gutter
3 Vim GitGutter
44
55
66 Author: Andy Stewart <https://airbladesoftware.com/>
2626 ===============================================================================
2727 INTRODUCTION *gitgutter-introduction*
2828
29 GitGutter is a Vim plugin which shows a git diff in the 'gutter' (sign column).
29 GitGutter is a Vim plugin which shows a git diff in the sign column.
3030 It shows which lines have been added, modified, or removed. You can also
3131 preview, stage, and undo individual hunks. The plugin also provides a hunk
3232 text object.
3333
3434 The signs are always up to date and the plugin never saves your buffer.
35
36 The name "gitgutter" comes from the Sublime Text 3 plugin which inspired this
37 one in 2013.
3538
3639
3740 ===============================================================================
5962 ===============================================================================
6063 WINDOWS *gitgutter-windows*
6164
62 I recommend configuring vim-gitgutter with the full path to your git executable.
65 There is a potential risk on Windows due to `cmd.exe` prioritising the current
66 folder over folders in `PATH`. If you have a file named `git.*` (i.e. with
67 any extension in `PATHEXT`) in your current folder, it will be executed
68 instead of git whenever the plugin calls git.
69
70 You can avoid this risk by configuring the full path to your git executable.
6371 For example:
6472 >
73 " This path probably won't work
6574 let g:gitgutter_git_executable = 'C:\Program Files\Git\bin\git.exe'
6675 <
67 This is to avoid a problem which occurs if you have file named "git.*" (i.e.
68 with any extension in "PATHEXT") in your current folder. "cmd.exe" prioritises
69 the current folder over folders in 'PATH' and will try to execute your file
70 instead of the "git" binary.
76
77 Unfortunately I don't know the correct escaping for the path - if you do,
78 please let me know!
7179
7280
7381 ===============================================================================
8391
8492 *gitgutter-:GitGutterToggle*
8593 :GitGutterToggle Toggle vim-gitgutter on or off for all buffers.
94
95 *gitgutter-:GitGutterBufferDisable*
96 :GitGutterBufferDisable Turn vim-gitgutter off for current buffer.
97
98 *gitgutter-:GitGutterBufferEnable*
99 :GitGutterBufferEnable Turn vim-gitgutter on for current buffer.
100
101 *gitgutter-:GitGutterBufferToggle*
102 :GitGutterBufferToggle Toggle vim-gitgutter on or off for current buffer.
86103
87104 *gitgutter-:GitGutter*
88105 :GitGutter Update signs for the current buffer. You shouldn't
142159 :GitGutterQuickFix Load all hunks into the |quickfix| list. Note this
143160 ignores any unsaved changes in your buffers. The
144161 |g:gitgutter_use_location_list| option can be set to
145 populate the location list of the current window instead
162 populate the location list of the current window
163 instead. Use |:copen| (or |:lopen|) to open a buffer
164 containing the search results in linked form; or add a
165 custom command like this:
166 >
167 command! Gqf GitGutterQuickFix | copen
168 <
169 *gitgutter-:GitGutterQuickFixCurrentFile*
170 :GitGutterQuickFixCurrentFile Same as :GitGutterQuickFix, but only load hunks for
171 the file in the focused buffer. This has the same
172 functionality as :GitGutterQuickFix when the focused
173 buffer is empty.
146174
147175
148176 Commands for operating on a hunk:~
162190
163191 *gitgutter-:GitGutterPreviewHunk*
164192 :GitGutterPreviewHunk Preview the hunk the cursor is in.
165 Use |:pclose| or |CTRL-W_CTRL-Z| to close the preview
166 window.
167193
168194 To stage part of the hunk, move to the preview window,
169195 delete any lines you do not want to stage, and
170196 |GitGutterStageHunk|.
171197
198 To close a non-floating preview window use |:pclose|
199 or |CTRL-W_z| or |CTRL-W_CTRL-Z|; or normal window-
200 closing (|:quit| or |:close| or |CTRL-W_c|) if your cursor
201 is in the preview window.
202
203 To close a floating window when the cursor is in the
204 original buffer, move the cursor.
205
206 To close a floating window when the cursor is in the
207 floating window use normal window-closing, or move to
208 the original window with |CTRL-W_p|. Alternatively set
209 |g:gitgutter_close_preview_on_escape| and use <Esc>.
210
211 Two functions are available for your own logic:
212 >
213 gitgutter#hunk#is_preview_window_open()
214 gitgutter#hunk#close_hunk_preview_window()
215 <
216
172217 Commands for folds:~
173218
174219 *gitgutter-:GitGutterFold*
176221
177222
178223 ===============================================================================
179 AUTOCOMMAND *gitgutter-autocommand*
224 AUTOCOMMANDS *gitgutter-autocommands*
180225
181226 User GitGutter~
182227
188233 A dictionary `g:gitgutter_hook_context` is made available during its execution,
189234 which contains an entry `bufnr` that contains the buffer number being updated.
190235
236 User GitGutterStage~
237
238 After staging a hunk or part of a hunk vim-gitgutter fires a |User| |autocmd|
239 with the event GitGutterStage. Staging always happens in the current buffer.
191240
192241 ===============================================================================
193242 MAPPINGS *gitgutter-mappings*
298347 |g:gitgutter_sign_removed|
299348 |g:gitgutter_sign_removed_first_line|
300349 |g:gitgutter_sign_modified_removed|
301 |g:gitgutter_override_sign_column_highlight|
350 |g:gitgutter_set_sign_backgrounds|
351
352 Hunk jumping:~
353
354 |g:gitgutter_show_msg_on_hunk_jumping|
302355
303356 Hunk previews:~
304357
305358 |g:gitgutter_preview_win_floating|
359 |g:gitgutter_floating_window_options|
360 |g:gitgutter_close_preview_on_escape|
306361
307362 Terminal:~
308363
404459 Determines whether or not to show line number highlights.
405460
406461 *g:gitgutter_max_signs*
407 Default: 500
462 Default: 500 (Vim < 8.1.0614, Neovim < 0.4.0)
463 -1 (otherwise)
408464
409465 Sets the maximum number of signs to show in a buffer. Vim is slow at updating
410466 signs, so to avoid slowing down the GUI the number of signs is capped. When
411467 the number of changed lines exceeds this value, the plugin removes all signs
412468 and displays a warning message.
413469
470 When set to -1 the limit is not applied.
471
414472 *g:gitgutter_sign_priority*
415473 Default: 10
416474
427485 *g:gitgutter_sign_modified*
428486 *g:gitgutter_sign_removed*
429487 *g:gitgutter_sign_removed_first_line*
488 *g:gitgutter_sign_removed_above_and_below*
430489 *g:gitgutter_sign_modified_removed*
431490 Defaults:
432491 >
434493 let g:gitgutter_sign_modified = '~'
435494 let g:gitgutter_sign_removed = '_'
436495 let g:gitgutter_sign_removed_first_line = '‾'
496 let g:gitgutter_sign_removed_above_and_below = '_¯'
437497 let g:gitgutter_sign_modified_removed = '~_'
438498 <
439499 You can use unicode characters but not images. Signs must not take up more than
440500 2 columns.
441501
442 *g:gitgutter_override_sign_column_highlight*
443 Default: 1
444
445 Controls whether to make the sign column look like the line-number column (i.e.
446 the |hl-LineNr| highlight group).
447
448 To customise your sign column's background color, first tell vim-gitgutter to
449 leave it alone:
450 >
451 let g:gitgutter_override_sign_column_highlight = 0
452 <
453
454 And then either update your colorscheme's |hlSignColumn| highlight group or set
455 it in your |vimrc|:
456
457 Desired appearance Command ~
458 Same as line-number column highlight clear SignColumn
459 User-defined (terminal Vim) highlight SignColumn ctermbg={whatever}
460 User-defined (graphical Vim) highlight SignColumn guibg={whatever}
461
502 *g:gitgutter_set_sign_backgrounds*
503 Default: 0
504
505 Only applies to existing GitGutter* highlight groups. See
506 |gitgutter-highlights|.
507
508 Controls whether to override the signs' background colours to match the
509 |hl-SignColumn|.
462510
463511 *g:gitgutter_preview_win_floating*
464512 Default: 0 (Vim)
469517 popup windows on Vim you will not be able to stage partial hunks via the
470518 preview window.
471519
520 *g:gitgutter_floating_window_options*
521 Default:
522 >
523 " Vim
524 {
525 \ 'line': 'cursor+1',
526 \ 'col': 'cursor',
527 \ 'moved': 'any'
528 }
529
530 " Neovim
531 {
532 \ 'relative': 'cursor',
533 \ 'row': 1,
534 \ 'col': 0,
535 \ 'width': 42,
536 \ 'height': &previewheight,
537 \ 'style': 'minimal'
538 }
539 <
540 This dictionary is passed directly to |popup_create()| (Vim) or
541 |nvim_open_win()| (Neovim).
542
543 *g:gitgutter_close_preview_on_escape*
544 Default: 0
545
546 Whether pressing <Esc> in a preview window closes it.
547
472548 *g:gitgutter_terminal_reports_focus*
473549 Default: 1
474550
517593 When switched on, the :GitGutterQuickFix command populates the location list
518594 of the current window instead of the global quickfix list.
519595
596 *g:gitgutter_show_msg_on_hunk_jumping*
597 Default: 1
598
599 When switched on, a message like "Hunk 4 of 11" is shown on hunk jumping.
600
520601
521602 ===============================================================================
522603 HIGHLIGHTS *gitgutter-highlights*
523604
524 To change the signs' colours, set up the following highlight groups in your
525 colorscheme or |vimrc|:
526 >
527 GitGutterAdd " an added line
528 GitGutterChange " a changed line
529 GitGutterDelete " at least one removed line
530 GitGutterChangeDelete " a changed line followed by at least one removed line
531 <
532
533 You can either set these with `highlight GitGutterAdd {key}={arg}...` or link
534 them to existing highlight groups with, say:
535 >
536 highlight link GitGutterAdd MyDiffAdd
537 <
605 To change the signs' colours, specify these highlight groups in your |vimrc|:
606 >
607 highlight GitGutterAdd guifg=#009900 ctermfg=2
608 highlight GitGutterChange guifg=#bbbb00 ctermfg=3
609 highlight GitGutterDelete guifg=#ff2222 ctermfg=1
610 <
611
612 See |highlight-guifg| and |highlight-ctermfg| for the values you can use.
613
614 If you do not like the signs' background colours and you do not want to update
615 the GitGutter* highlight groups yourself, you can get the plugin to do it
616 |g:gitgutter_set_sign_backgrounds|.
538617
539618 To change the line highlights, set up the following highlight groups in your
540619 colorscheme or |vimrc|:
561640 >
562641 highlight link GitGutterChangeLineNr Underlined
563642 <
643 To change the diff syntax colours used in the preview window, set up the diff*
644 highlight groups in your colorscheme or |vimrc|:
645 >
646 diffAdded " if not set: use GitGutterAdd's foreground colour
647 diffChanged " if not set: use GitGutterChange's foreground colour
648 diffRemoved " if not set: use GitGutterDelete's foreground colour
649 <
650 Note the diff* highlight groups are used in any buffer whose 'syntax' is
651 "diff".
652
653 To change the intra-line diff highlights used in the preview window, set up
654 the following highlight groups in your colorscheme or |vimrc|:
655 >
656 GitGutterAddIntraLine " default: gui=reverse cterm=reverse
657 GitGutterDeleteIntraLine " default: gui=reverse cterm=reverse
658 <
659 For example, to use |hl-DiffAdd| for intra-line added regions:
660 >
661 highlight link GitGutterAddIntraLine DiffAdd
662 <
564663
565664
566665 ===============================================================================
591690 d. Why are the colours in the sign column weird?
592691
593692 Your colorscheme is configuring the |hl-SignColumn| highlight group weirdly.
594 Please see |g:gitgutter_override_sign_column_highlight| on customising the
595 sign column.
693 Here are two ways you could change the colours:
694 >
695 highlight! link SignColumn LineNr
696 highlight SignColumn guibg=whatever ctermbg=whatever
697 <
596698
597699 e. What happens if I also use another plugin which uses signs (e.g. Syntastic)?
598700
631733 <
632734 If the result is -2, the plugin thinks your file is not tracked by git.
633735
736 6. Check whether the signs have been placed:
737 >
738 :sign place group=gitgutter
739 <
740 If you see a list of signs, this is a colorscheme / highlight problem.
741 Compare these two highlight values:
742 >
743 :highlight GitGutterAdd
744 :highlight SignColumn
745 <
746 If no signs are listed, the call to git-diff is probably failing. Turn on
747 logging by adding the following to your vimrc, restart, reproduce the problem,
748 and examing the gitgutter.log file in the plugin's directory.
749 >
750 let g:gitgutter_log = 1
751 <
634752
635753 When the whole file is marked as added:~
636754
656774 let g:gitgutter_terminal_reports_focus = 0
657775 <
658776
777 vim:tw=78:et:ft=help:norl:
77 " Initialisation {{{
88
99 if v:version < 703 || (v:version == 703 && !has("patch105"))
10 call gitgutter#utility#warn('requires Vim 7.3.105')
10 call gitgutter#utility#warn('Requires Vim 7.3.105')
1111 finish
1212 endif
1313
14 function! s:set(var, default) abort
15 if !exists(a:var)
16 if type(a:default)
17 execute 'let' a:var '=' string(a:default)
18 else
19 execute 'let' a:var '=' a:default
20 endif
21 endif
22 endfunction
23
24 call s:set('g:gitgutter_preview_win_location', 'bo')
14 let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
15
16 function! s:obsolete(var)
17 if exists(a:var)
18 call gitgutter#utility#warn(a:var.' is obsolete and has no effect.')
19 endif
20 endfunction
21
22
23 let g:gitgutter_preview_win_location = get(g:, 'gitgutter_preview_win_location', 'bo')
2524 if exists('*nvim_open_win')
26 call s:set('g:gitgutter_preview_win_floating', 1)
25 let g:gitgutter_preview_win_floating = get(g:, 'gitgutter_preview_win_floating', 1)
26 let g:gitgutter_floating_window_options = get(g:, 'gitgutter_floating_window_options', {
27 \ 'relative': 'cursor',
28 \ 'row': 1,
29 \ 'col': 0,
30 \ 'width': 42,
31 \ 'height': &previewheight,
32 \ 'style': 'minimal'
33 \ })
2734 else
28 call s:set('g:gitgutter_preview_win_floating', 0)
29 endif
30 call s:set('g:gitgutter_enabled', 1)
31 call s:set('g:gitgutter_max_signs', 500)
32 call s:set('g:gitgutter_signs', 1)
33 call s:set('g:gitgutter_highlight_lines', 0)
34 call s:set('g:gitgutter_highlight_linenrs', 0)
35 call s:set('g:gitgutter_sign_priority', 10)
35 let default = exists('&previewpopup') ? !empty(&previewpopup) : 0
36 let g:gitgutter_preview_win_floating = get(g:, 'gitgutter_preview_win_floating', default)
37 let g:gitgutter_floating_window_options = get(g:, 'gitgutter_floating_window_options', {
38 \ 'line': 'cursor+1',
39 \ 'col': 'cursor',
40 \ 'moved': 'any'
41 \ })
42 endif
43 let g:gitgutter_enabled = get(g:, 'gitgutter_enabled', 1)
44 if exists('*sign_unplace')
45 let g:gitgutter_max_signs = get(g:, 'gitgutter_max_signs', -1)
46 else
47 let g:gitgutter_max_signs = get(g:, 'gitgutter_max_signs', 500)
48 endif
49 let g:gitgutter_signs = get(g:, 'gitgutter_signs', 1)
50 let g:gitgutter_highlight_lines = get(g:, 'gitgutter_highlight_lines', 0)
51 let g:gitgutter_highlight_linenrs = get(g:, 'gitgutter_highlight_linenrs', 0)
52 let g:gitgutter_sign_priority = get(g:, 'gitgutter_sign_priority', 10)
3653 " Nvim 0.4.0 has an expanding sign column
3754 " The sign_place() function supports sign priority.
3855 if (has('nvim-0.4.0') || exists('*sign_place')) && !exists('g:gitgutter_sign_allow_clobber')
3956 let g:gitgutter_sign_allow_clobber = 1
4057 endif
41 call s:set('g:gitgutter_sign_allow_clobber', 0)
42 call s:set('g:gitgutter_override_sign_column_highlight', 1)
43 call s:set('g:gitgutter_sign_added', '+')
44 call s:set('g:gitgutter_sign_modified', '~')
45 call s:set('g:gitgutter_sign_removed', '_')
58 let g:gitgutter_sign_allow_clobber = get(g:, 'gitgutter_sign_allow_clobber', 0)
59 let g:gitgutter_set_sign_backgrounds = get(g:, 'gitgutter_set_sign_backgrounds', 0)
60 let g:gitgutter_sign_added = get(g:, 'gitgutter_sign_added', '+')
61 let g:gitgutter_sign_modified = get(g:, 'gitgutter_sign_modified', '~')
62 let g:gitgutter_sign_removed = get(g:, 'gitgutter_sign_removed', '_')
4663
4764 if gitgutter#utility#supports_overscore_sign()
48 call s:set('g:gitgutter_sign_removed_first_line', '‾')
65 let g:gitgutter_sign_removed_first_line = get(g:, 'gitgutter_sign_removed_first_line', '‾')
4966 else
50 call s:set('g:gitgutter_sign_removed_first_line', '_^')
51 endif
52
53 call s:set('g:gitgutter_sign_removed_above_and_below', '[')
54 call s:set('g:gitgutter_sign_modified_removed', '~_')
55 call s:set('g:gitgutter_git_args', '')
56 call s:set('g:gitgutter_diff_relative_to', 'index')
57 call s:set('g:gitgutter_diff_args', '')
58 call s:set('g:gitgutter_diff_base', '')
59 call s:set('g:gitgutter_map_keys', 1)
60 call s:set('g:gitgutter_terminal_reports_focus', 1)
61 call s:set('g:gitgutter_async', 1)
62 call s:set('g:gitgutter_log', 0)
63 call s:set('g:gitgutter_use_location_list', 0)
64
65 call s:set('g:gitgutter_git_executable', 'git')
67 let g:gitgutter_sign_removed_first_line = get(g:, 'gitgutter_sign_removed_first_line', '_^')
68 endif
69
70 let g:gitgutter_sign_removed_above_and_below = get(g:, 'gitgutter_sign_removed_above_and_below', '_¯')
71 let g:gitgutter_sign_modified_removed = get(g:, 'gitgutter_sign_modified_removed', '~_')
72 let g:gitgutter_git_args = get(g:, 'gitgutter_git_args', '')
73 let g:gitgutter_diff_relative_to = get(g:, 'gitgutter_diff_relative_to', 'index')
74 let g:gitgutter_diff_args = get(g:, 'gitgutter_diff_args', '')
75 let g:gitgutter_diff_base = get(g:, 'gitgutter_diff_base', '')
76 let g:gitgutter_map_keys = get(g:, 'gitgutter_map_keys', 1)
77 let g:gitgutter_terminal_reports_focus = get(g:, 'gitgutter_terminal_reports_focus', 1)
78 let g:gitgutter_async = get(g:, 'gitgutter_async', 1)
79 let g:gitgutter_log = get(g:, 'gitgutter_log', 0)
80 let g:gitgutter_use_location_list = get(g:, 'gitgutter_use_location_list', 0)
81 let g:gitgutter_close_preview_on_escape = get(g:, 'gitgutter_close_preview_on_escape', 0)
82 let g:gitgutter_show_msg_on_hunk_jumping = get(g:, 'gitgutter_show_msg_on_hunk_jumping', 1)
83
84 let g:gitgutter_git_executable = get(g:, 'gitgutter_git_executable', 'git')
6685 if !executable(g:gitgutter_git_executable)
67 call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
86 if g:gitgutter_enabled
87 call gitgutter#utility#warn('Cannot find git. Please set g:gitgutter_git_executable.')
88 endif
89 finish
6890 endif
6991
7092 let default_grep = 'grep'
71 call s:set('g:gitgutter_grep', default_grep)
93 let g:gitgutter_grep = get(g:, 'gitgutter_grep', default_grep)
7294 if !empty(g:gitgutter_grep)
7395 if executable(split(g:gitgutter_grep)[0])
7496 if $GREP_OPTIONS =~# '--color=always'
7698 endif
7799 else
78100 if g:gitgutter_grep !=# default_grep
79 call gitgutter#utility#warn('cannot find '.g:gitgutter_grep.'. Please check g:gitgutter_grep.')
101 call gitgutter#utility#warn('Cannot find '.g:gitgutter_grep.'. Please check g:gitgutter_grep.')
80102 endif
81103 let g:gitgutter_grep = ''
82104 endif
83105 endif
84106
85 call gitgutter#highlight#define_sign_column_highlight()
86107 call gitgutter#highlight#define_highlights()
87108 call gitgutter#highlight#define_signs()
88109
109130 command! -bar GitGutterBufferEnable call gitgutter#buffer_enable()
110131 command! -bar GitGutterBufferToggle call gitgutter#buffer_toggle()
111132
112 command! -bar GitGutterQuickFix call gitgutter#quickfix()
133 command! -bar GitGutterQuickFix call gitgutter#quickfix(0)
134 command! -bar GitGutterQuickFixCurrentFile call gitgutter#quickfix(1)
113135
114136 " }}}
115137
193215 " Maps {{{
194216
195217 nnoremap <silent> <expr> <Plug>(GitGutterNextHunk) &diff ? ']c' : ":\<C-U>execute v:count1 . 'GitGutterNextHunk'\<CR>"
196 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>"
218 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>"
197219 nnoremap <silent> <expr> <Plug>(GitGutterPrevHunk) &diff ? '[c' : ":\<C-U>execute v:count1 . 'GitGutterPrevHunk'\<CR>"
198 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>"
220 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>"
199221
200222 xnoremap <silent> <Plug>(GitGutterStageHunk) :GitGutterStageHunk<CR>
201 xnoremap <silent> <Plug>GitGutterStageHunk :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
223 xnoremap <silent> <Plug>GitGutterStageHunk :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
202224 nnoremap <silent> <Plug>(GitGutterStageHunk) :GitGutterStageHunk<CR>
203 nnoremap <silent> <Plug>GitGutterStageHunk :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
225 nnoremap <silent> <Plug>GitGutterStageHunk :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterStageHunk to <lt>Plug>(GitGutterStageHunk)')<CR>
204226 nnoremap <silent> <Plug>(GitGutterUndoHunk) :GitGutterUndoHunk<CR>
205 nnoremap <silent> <Plug>GitGutterUndoHunk :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterUndoHunk to <lt>Plug>(GitGutterUndoHunk)')<CR>
227 nnoremap <silent> <Plug>GitGutterUndoHunk :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterUndoHunk to <lt>Plug>(GitGutterUndoHunk)')<CR>
206228 nnoremap <silent> <Plug>(GitGutterPreviewHunk) :GitGutterPreviewHunk<CR>
207 nnoremap <silent> <Plug>GitGutterPreviewHunk :call gitgutter#utility#warn('please change your map <lt>Plug>GitGutterPreviewHunk to <lt>Plug>(GitGutterPreviewHunk)')<CR>
229 nnoremap <silent> <Plug>GitGutterPreviewHunk :call gitgutter#utility#warn('Please change your map <lt>Plug>GitGutterPreviewHunk to <lt>Plug>(GitGutterPreviewHunk)')<CR>
208230
209231 " }}}
210232
211233 function! s:on_bufenter()
212234 call gitgutter#setup_maps()
235
236 " To keep vim's start-up fast, do not process the buffer when vim is starting.
237 " Instead process it a short time later. Normally we would rely on our
238 " CursorHold autocommand to handle this but it turns out CursorHold is not
239 " guaranteed to fire if the user has not typed anything yet; so set up a
240 " timer instead. The disadvantage is that if CursorHold does fire, the
241 " plugin will do a round of unnecessary work; but since there will not have
242 " been any changes to the buffer since the first round, the second round
243 " will be cheap.
244 if has('vim_starting') && !$VIM_GITGUTTER_TEST
245 if exists('*timer_start')
246 call timer_start(&updatetime, 'GitGutterCursorHold')
247 endif
248 return
249 endif
213250
214251 if exists('t:gitgutter_didtabenter') && t:gitgutter_didtabenter
215252 let t:gitgutter_didtabenter = 0
219256 endif
220257 endfunction
221258
259 function! GitGutterCursorHold(timer)
260 execute 'doautocmd' s:nomodeline 'gitgutter CursorHold'
261 endfunction
262
263 function! s:next_tick(cmd)
264 call timer_start(1, {-> execute(a:cmd)})
265 endfunction
266
222267 " Autocommands {{{
223268
224269 augroup gitgutter
228273
229274 autocmd BufEnter * call s:on_bufenter()
230275
276 " Ensure Vim is always checking for CursorMoved to avoid CursorMoved
277 " being fired at the wrong time in floating preview window on Neovim.
278 " See vim/vim#2053.
279 autocmd CursorMoved * execute ''
280
231281 autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 0)
232282 if exists('*timer_start') && has('lambda')
233 autocmd FileChangedShellPost * call timer_start(1, {-> gitgutter#process_buffer(bufnr(''), 1)})
283 autocmd FileChangedShellPost * call s:next_tick("call gitgutter#process_buffer(+".expand('<abuf>').", 1)")
234284 else
235 autocmd FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 1)
285 autocmd FileChangedShellPost * call gitgutter#process_buffer(+expand('<abuf>'), 1)
236286 endif
237287
238288 " Ensure that all buffers are processed when opening vim with multiple files, e.g.:
252302 " FocusGained gets triggered on startup with Neovim at least already.
253303 " Therefore this tracks also if it was lost before.
254304 let s:focus_was_lost = 0
255 autocmd FocusGained * if s:focus_was_lost | let focus_was_lost = 0 | call gitgutter#all(1) | endif
305 autocmd FocusGained * if s:focus_was_lost | let s:focus_was_lost = 0 | call gitgutter#all(1) | endif
256306 autocmd FocusLost * let s:focus_was_lost = 1
257307
258308 if exists('##VimResume')
259309 autocmd VimResume * call gitgutter#all(1)
260310 endif
261311
262 autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
312 autocmd ColorScheme * call gitgutter#highlight#define_highlights()
263313
264314 " Disable during :vimgrep
265 autocmd QuickFixCmdPre *vimgrep* let g:gitgutter_enabled = 0
266 autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = 1
315 autocmd QuickFixCmdPre *vimgrep* let [g:gitgutter_was_enabled, g:gitgutter_enabled] = [g:gitgutter_enabled, 0]
316 autocmd QuickFixCmdPost *vimgrep* let g:gitgutter_enabled = g:gitgutter_was_enabled | unlet g:gitgutter_was_enabled
267317 augroup END
268318
269319 " }}}
946946 call setline(5, ['A', 'B'])
947947 call setline(9, ['C', 'D'])
948948 write
949 let bufnr1 = bufnr('')
950
951 edit fixture_dos.txt
952 call setline(2, ['A', 'B'])
953 write
954 let bufnr2 = bufnr('')
949955
950956 GitGutterQuickFix
951957
952958 let expected = [
953 \ {'lnum': 5, 'bufnr': bufnr(''), 'text': '-e'},
954 \ {'lnum': 9, 'bufnr': bufnr(''), 'text': '-i'}
959 \ {'lnum': 5, 'bufnr': bufnr1, 'text': '-e'},
960 \ {'lnum': 9, 'bufnr': bufnr1, 'text': '-i'},
961 \ {'lnum': 2, 'bufnr': bufnr2, 'text': "-b\r"}
962 \ ]
963
964 call s:assert_list_of_dicts(expected, getqflist())
965
966 GitGutterQuickFixCurrentFile
967
968 let expected = [
969 \ {'lnum': 2, 'bufnr': bufnr(''), 'text': "-b\r"},
955970 \ ]
956971
957972 call s:assert_list_of_dicts(expected, getqflist())
+0
-27
unplace.vim less more
0 " Measure how long it takes to unplace signs.
1 "
2 " Source this file with `:source %` or `vim -S unplace.vim`
3
4
5 let num = 500
6 sign define Foo text=*
7
8 new
9
10 call append(0, range(1, num))
11
12 for i in range(1, num)
13 execute "sign place ".i." line=".i." name=Foo buffer=".bufnr('')
14 endfor
15
16 let start = reltime()
17 for i in range(1, num)
18 execute "sign unplace ".i
19 endfor
20 let elapsed = reltime(start)
21
22 bdelete!
23
24 echom split(reltimestr(elapsed))[0]."s to remove ".num." signs"
25 echom string(reltimefloat(elapsed) * 1000 / num).' ms/sign'
26 echom string(float2nr(num / reltimefloat(elapsed))).' sign/s'