mirror of
https://github.com/airblade/vim-gitgutter.git
synced 2025-11-08 11:33:48 -05:00
Big refactor.
- Hunk stage/undo/preview no longer saves the buffer.
- Hunk undo no longer makes locations go out of sync.
- Grep can be opted out of (grep output with ansi escapes is number one cause
of issues).
- Replaced g:gitgutter_grep_command with g:gitgutter_grep.
- Always runs git-diff the same way instead of in two possible ways.
- Separated detection of git tracking from diffing.
- Simplified path handling.
- Removed support for xolox shell: Windows taskbar does not flash with async
jobs.
- Removed g:gitgutter_{eager,realtime}.
- Simplified implementation generally.
This commit is contained in:
83
README.mkd
83
README.mkd
@@ -1,12 +1,14 @@
|
|||||||
## vim-gitgutter
|
## vim-gitgutter
|
||||||
|
|
||||||
A Vim plugin which shows a git diff in the 'gutter' (sign column). It shows whether each line has been added, modified, and where lines have been removed. You can also stage and undo individual hunks.
|
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.
|
||||||
|
|
||||||
|
The signs are always up to date and the plugin never saves your buffer.
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
* Shows signs for added, modified, and removed lines.
|
* Shows signs for added, modified, and removed lines.
|
||||||
* Runs the diffs asynchronously in terminal Vim/MacVim (7.4.1826+), gVim (7.4.1850+), MacVim GUI (7.4.1832+), and NeoVim.
|
* Runs the diffs asynchronously where possible.
|
||||||
* Ensures signs are always as up to date as possible (but without running more than necessary).
|
* Ensures signs are always up to date.
|
||||||
* Quick jumping between blocks of changed lines ("hunks").
|
* Quick jumping between blocks of changed lines ("hunks").
|
||||||
* Stage/undo/preview individual hunks.
|
* Stage/undo/preview individual hunks.
|
||||||
* Provides a hunk text object.
|
* Provides a hunk text object.
|
||||||
@@ -39,7 +41,7 @@ In the screenshot above you can see:
|
|||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
Before installation, please check your Vim supports signs by running `:echo has('signs')`. `1` means you're all set; `0` means you need to install a Vim with signs support. If you're compiling Vim yourself you need the 'big' or 'huge' feature set. [MacVim][] supports signs.
|
Before installation, please check your Vim supports signs by running `:echo has('signs')`. `1` means you're all set; `0` means you need to install a Vim with signs support. If you're compiling Vim yourself you need the 'big' or 'huge' feature set. MacVim supports signs.
|
||||||
|
|
||||||
You install vim-gitgutter like any other vim plugin.
|
You install vim-gitgutter like any other vim plugin.
|
||||||
|
|
||||||
@@ -100,12 +102,9 @@ cp -r vim-gitgutter/* ~/.vim/
|
|||||||
See `:help add-global-plugin`.
|
See `:help add-global-plugin`.
|
||||||
|
|
||||||
|
|
||||||
If you are on Windows you may find the command prompt pops up briefly every time vim-gitgutter runs. You can avoid this by installing both [vim-misc](https://github.com/xolox/vim-misc) and [vim-shell](https://github.com/xolox/vim-shell). If you have those two plugins but don't want vim-gitgutter to use them, you can opt out with `let g:gitgutter_avoid_cmd_prompt_on_windows = 0` in your `~/.vimrc`.
|
|
||||||
|
|
||||||
|
|
||||||
### Getting started
|
### Getting started
|
||||||
|
|
||||||
When you make a change to a file tracked by git, the diff markers should appear automatically. The delay is governed by vim's `updatetime` option; the default value is 4 seconds but I suggest reducing it to around 250ms (add `set updatetime=250` to your vimrc).
|
When you make a change to a file tracked by git, the diff markers should appear automatically. The delay is governed by vim's `updatetime` option; the default value is `4000`, i.e. 4 seconds, but I suggest reducing it to around 100ms (add `set updatetime=100` to your vimrc).
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@@ -136,7 +135,7 @@ Note that if you have line highlighting on and signs off, you will have an empty
|
|||||||
|
|
||||||
If you switch off both line highlighting and signs, you won't see the sign column. That is unless you configure the sign column always to be there (see Sign Column section).
|
If you switch off both line highlighting and signs, you won't see the sign column. That is unless you configure the sign column always to be there (see Sign Column section).
|
||||||
|
|
||||||
To keep your Vim snappy, vim-gitgutter will suppress itself 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:
|
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:
|
||||||
|
|
||||||
```viml
|
```viml
|
||||||
let g:gitgutter_max_signs = 500 " default value
|
let g:gitgutter_max_signs = 500 " default value
|
||||||
@@ -205,33 +204,6 @@ 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.
|
See the customisation section below for how to change the defaults.
|
||||||
|
|
||||||
|
|
||||||
### When are the signs updated?
|
|
||||||
|
|
||||||
By default the signs are updated as follows:
|
|
||||||
|
|
||||||
| Event | Reason for update | Configuration |
|
|
||||||
|---------------------------|--------------------------------------|------------------------|
|
|
||||||
| Stop typing | So the signs are real time | `g:gitgutter_realtime` |
|
|
||||||
| Switch buffer | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Switch tab | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Focus the GUI | To notice change to git index | `g:gitgutter_eager` (not gVim on Windows) |
|
|
||||||
| After shell command | To notice change to git index | `g:gitgutter_eager` |
|
|
||||||
| Read a file into a buffer | To display initial signs | [always] |
|
|
||||||
| Save a buffer | So non-realtime signs are up to date | [always] |
|
|
||||||
| Change a file outside Vim | To notice `git stash` | [always] |
|
|
||||||
|
|
||||||
The length of time Vim waits after you stop typing before it triggers the plugin is governed by the setting `updatetime`. This defaults to `4000` milliseconds which is rather too long. I recommend around `250` milliseconds but it depends on your system and your preferences. Note that in terminal Vim pre-7.4.427 an `updatetime` of less than approximately `1000` milliseconds can lead to random highlighting glitches; the lower the `updatetime`, the more glitches.
|
|
||||||
|
|
||||||
If you experience a lag, you can trade speed for accuracy:
|
|
||||||
|
|
||||||
```viml
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the realtime updating requires Vim 7.3.105 or higher.
|
|
||||||
|
|
||||||
|
|
||||||
### Customisation
|
### Customisation
|
||||||
|
|
||||||
You can customise:
|
You can customise:
|
||||||
@@ -351,7 +323,7 @@ If you use an alternative to grep, you can tell vim-gitgutter to use it here.
|
|||||||
|
|
||||||
```viml
|
```viml
|
||||||
" Default:
|
" Default:
|
||||||
let g:gitgutter_grep_command = 'grep'
|
let g:gitgutter_grep = 'grep'
|
||||||
```
|
```
|
||||||
|
|
||||||
#### To turn off vim-gitgutter by default
|
#### To turn off vim-gitgutter by default
|
||||||
@@ -498,13 +470,13 @@ Unstaging staged hunks is feasible but not quite as easy as it sounds. There ar
|
|||||||
2. The version staged in the index.
|
2. The version staged in the index.
|
||||||
3. The version in the working tree, in your vim buffer.
|
3. The version in the working tree, in your vim buffer.
|
||||||
|
|
||||||
`git-diff` without arguments shows you how 3 and 2 differ; this is what vim-gitgutter shows too.
|
`git-diff` without arguments shows you how 2 and 3 differ; this is what vim-gitgutter shows too.
|
||||||
|
|
||||||
`git-diff --staged` shows you how 2 and 1 differ.
|
`git-diff --staged` shows you how 1 and 2 differ.
|
||||||
|
|
||||||
Let's say you are looking at a file in vim which has some unstaged changes. Now you stage a hunk, either via vim-gitgutter or another means. The hunk is no longer marked in vim-gitgutter because it is the same in 3 and 2.
|
Let's say you are looking at a file in vim which has some unstaged changes. Now you stage a hunk, either via vim-gitgutter or another means. The hunk is no longer marked in vim-gitgutter because it is the same in 2 and 3.
|
||||||
|
|
||||||
Now you want to unstage that hunk. To see it, you need the difference between 2 and 1. For vim-gitgutter to show those differences, it would need to show you 2 instead of 3 in your vim buffer. But 2 is virtual so vim-gitgutter would need to handle it without touching 3.
|
Now you want to unstage that hunk. To see it, you need the difference between 1 and 2. For vim-gitgutter to show those differences, it would need to show you 2 instead of 3 in your vim buffer. But 2 is virtual so vim-gitgutter would need to handle it without touching 3.
|
||||||
|
|
||||||
I intend to implement this but I can't commit to any deadline.
|
I intend to implement this but I can't commit to any deadline.
|
||||||
|
|
||||||
@@ -512,32 +484,24 @@ I intend to implement this but I can't commit to any deadline.
|
|||||||
|
|
||||||
Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column.
|
Your colorscheme is configuring the `SignColumn` highlight group weirdly. Please see the section above on customising the sign column.
|
||||||
|
|
||||||
> There's a noticeable lag when vim-gitter runs; how can I avoid it?
|
|
||||||
|
|
||||||
By default vim-gitgutter runs often so the signs are as accurate as possible. The delay is governed by `updatetime`; see [above](#when-are-the-signs-updated) for more information.
|
|
||||||
|
|
||||||
If you don't want realtime updates and would like to trade a little accuracy for speed, add this to your `~/.vimrc`:
|
|
||||||
|
|
||||||
```viml
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
> What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
> What happens if I also use another plugin which uses signs (e.g. Syntastic)?
|
||||||
|
|
||||||
Vim only allows one sign per line. Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else. If so it doesn't do anything. In other words vim-gitgutter won't overwrite another plugin's signs. It also won't remove another plugin's signs.
|
Vim only allows one sign per line. Before adding a sign to a line, vim-gitgutter checks whether a sign has already been added by somebody else. If so it doesn't do anything. In other words vim-gitgutter won't overwrite another plugin's signs. It also won't remove another plugin's signs.
|
||||||
|
|
||||||
> Why aren't any signs showing at all?
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
#### When no signs are showing at all
|
||||||
|
|
||||||
Here are some things you can check:
|
Here are some things you can check:
|
||||||
|
|
||||||
* `:echo system("git --version")` succeeds.
|
* Try adding `let g:gitgutter_grep=''` to your vimrc. If it works, the problem is grep producing non-plain output; e.g. ANSI escape codes or colours.
|
||||||
* Your git config is compatible with the version of git returned by the command above.
|
* Verify `:echo system("git --version")` succeeds.
|
||||||
* Your Vim supports signs (`:echo has('signs')` should give `1`).
|
* Verify your git config is compatible with the version of git returned by the command above.
|
||||||
* Your file is being tracked by git and has unstaged changes.
|
* Verify your Vim supports signs (`:echo has('signs')` should give `1`).
|
||||||
* If you have aliased or configured `grep` to use any flags, add `let g:gitgutter_grep_command = 'grep'` to your `~/.vimrc`.
|
* Verify your file is being tracked by git and has unstaged changes.
|
||||||
|
|
||||||
> Why is the whole file marked as added when I edit it?
|
#### When the whole file is marked as added
|
||||||
|
|
||||||
* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory.
|
* If you use zsh, and you set `CDPATH`, make sure `CDPATH` doesn't include the current directory.
|
||||||
|
|
||||||
@@ -561,4 +525,3 @@ Copyright Andrew Stewart, AirBlade Software Ltd. Released under the MIT licence
|
|||||||
[pathogen]: https://github.com/tpope/vim-pathogen
|
[pathogen]: https://github.com/tpope/vim-pathogen
|
||||||
[siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim
|
[siv]: http://pluralsight.com/training/Courses/TableOfContents/smash-into-vim
|
||||||
[airblade]: http://airbladesoftware.com/peepcode-vim
|
[airblade]: http://airbladesoftware.com/peepcode-vim
|
||||||
[macvim]: http://code.google.com/p/macvim/
|
|
||||||
|
|||||||
@@ -1,67 +1,50 @@
|
|||||||
let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
|
|
||||||
|
|
||||||
" Primary functions {{{
|
" Primary functions {{{
|
||||||
|
|
||||||
function! gitgutter#all() abort
|
function! gitgutter#all(force) abort
|
||||||
for buffer_id in gitgutter#utility#dedup(tabpagebuflist())
|
for bufnr in tabpagebuflist()
|
||||||
let file = expand('#' . buffer_id . ':p')
|
let file = expand('#'.bufnr.':p')
|
||||||
if !empty(file)
|
if !empty(file)
|
||||||
call gitgutter#process_buffer(buffer_id, 0)
|
call gitgutter#init_buffer(bufnr)
|
||||||
|
call gitgutter#process_buffer(bufnr, a:force)
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" bufnr: (integer) the buffer to process.
|
|
||||||
" realtime: (boolean) when truthy, do a realtime diff; otherwise do a disk-based diff.
|
|
||||||
function! gitgutter#process_buffer(bufnr, realtime) abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
|
|
||||||
call gitgutter#utility#set_buffer(a:bufnr)
|
" Finds the file's path relative to the repo root.
|
||||||
if gitgutter#utility#is_active()
|
function! gitgutter#init_buffer(bufnr)
|
||||||
if g:gitgutter_sign_column_always
|
let p = gitgutter#utility#repo_path(a:bufnr, 0)
|
||||||
call gitgutter#sign#add_dummy_sign()
|
if type(p) != v:t_string || empty(p)
|
||||||
endif
|
call gitgutter#utility#set_repo_path(a:bufnr)
|
||||||
try
|
endif
|
||||||
if !a:realtime || gitgutter#utility#has_fresh_changes()
|
endfunction
|
||||||
let diff = gitgutter#diff#run_diff(a:realtime || gitgutter#utility#has_unsaved_changes(), 0)
|
|
||||||
if diff != 'async'
|
|
||||||
call gitgutter#handle_diff(diff)
|
function! gitgutter#process_buffer(bufnr, force) abort
|
||||||
endif
|
" NOTE a:bufnr is not necessarily the current buffer.
|
||||||
|
|
||||||
|
if gitgutter#utility#is_active(a:bufnr)
|
||||||
|
if a:force || s:has_fresh_changes(a:bufnr)
|
||||||
|
|
||||||
|
let diff = ''
|
||||||
|
try
|
||||||
|
let diff = gitgutter#diff#run_diff(a:bufnr, 0)
|
||||||
|
catch /gitgutter not tracked/
|
||||||
|
call gitgutter#debug#log('Not tracked: '.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)
|
||||||
|
endtry
|
||||||
|
|
||||||
|
if diff != 'async'
|
||||||
|
call gitgutter#diff#handler(a:bufnr, diff)
|
||||||
endif
|
endif
|
||||||
catch /diff failed/
|
|
||||||
call gitgutter#debug#log('diff failed')
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endtry
|
|
||||||
execute "silent doautocmd" s:nomodeline "User GitGutter"
|
|
||||||
else
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endif
|
|
||||||
|
|
||||||
call gitgutter#utility#restore_shell()
|
endif
|
||||||
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#handle_diff(diff) abort
|
|
||||||
call gitgutter#debug#log(a:diff)
|
|
||||||
|
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'tracked', 1)
|
|
||||||
|
|
||||||
call gitgutter#hunk#set_hunks(gitgutter#diff#parse_diff(a:diff))
|
|
||||||
let modified_lines = gitgutter#diff#process_hunks(gitgutter#hunk#hunks())
|
|
||||||
|
|
||||||
if len(modified_lines) > g:gitgutter_max_signs
|
|
||||||
call gitgutter#utility#warn_once('exceeded maximum number of signs (configured by g:gitgutter_max_signs).', 'max_signs')
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if g:gitgutter_signs || g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#sign#update_signs(modified_lines)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call gitgutter#utility#save_last_seen_change()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#disable() abort
|
function! gitgutter#disable() abort
|
||||||
" get list of all buffers (across all tabs)
|
" get list of all buffers (across all tabs)
|
||||||
let buflist = []
|
let buflist = []
|
||||||
@@ -69,13 +52,12 @@ function! gitgutter#disable() abort
|
|||||||
call extend(buflist, tabpagebuflist(i + 1))
|
call extend(buflist, tabpagebuflist(i + 1))
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
for buffer_id in gitgutter#utility#dedup(buflist)
|
for bufnr in buflist
|
||||||
let file = expand('#' . buffer_id . ':p')
|
let file = expand('#'.bufnr.':p')
|
||||||
if !empty(file)
|
if !empty(file)
|
||||||
call gitgutter#utility#set_buffer(buffer_id)
|
call gitgutter#sign#clear_signs(bufnr)
|
||||||
call gitgutter#sign#clear_signs()
|
call gitgutter#sign#remove_dummy_sign(bufnr, 1)
|
||||||
call gitgutter#sign#remove_dummy_sign(1)
|
call gitgutter#hunk#reset(bufnr)
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
@@ -84,7 +66,7 @@ endfunction
|
|||||||
|
|
||||||
function! gitgutter#enable() abort
|
function! gitgutter#enable() abort
|
||||||
let g:gitgutter_enabled = 1
|
let g:gitgutter_enabled = 1
|
||||||
call gitgutter#all()
|
call gitgutter#all(1)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#toggle() abort
|
function! gitgutter#toggle() abort
|
||||||
@@ -97,163 +79,7 @@ endfunction
|
|||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Line highlights {{{
|
function! s:has_fresh_changes(bufnr) abort
|
||||||
|
return getbufvar(a:bufnr, 'changedtick') != gitgutter#utility#getbufvar(a:bufnr, 'tick')
|
||||||
function! gitgutter#line_highlights_disable() abort
|
|
||||||
let g:gitgutter_highlight_lines = 0
|
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
|
||||||
|
|
||||||
if !g:gitgutter_signs
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
|
||||||
endif
|
|
||||||
|
|
||||||
redraw!
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#line_highlights_enable() abort
|
|
||||||
let old_highlight_lines = g:gitgutter_highlight_lines
|
|
||||||
|
|
||||||
let g:gitgutter_highlight_lines = 1
|
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
|
||||||
|
|
||||||
if !old_highlight_lines && !g:gitgutter_signs
|
|
||||||
call gitgutter#all()
|
|
||||||
endif
|
|
||||||
|
|
||||||
redraw!
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#line_highlights_toggle() abort
|
|
||||||
if g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#line_highlights_disable()
|
|
||||||
else
|
|
||||||
call gitgutter#line_highlights_enable()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}
|
|
||||||
|
|
||||||
" Signs {{{
|
|
||||||
|
|
||||||
function! gitgutter#signs_enable() abort
|
|
||||||
let old_signs = g:gitgutter_signs
|
|
||||||
|
|
||||||
let g:gitgutter_signs = 1
|
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
|
||||||
|
|
||||||
if !old_signs && !g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#all()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#signs_disable() abort
|
|
||||||
let g:gitgutter_signs = 0
|
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
|
||||||
|
|
||||||
if !g:gitgutter_highlight_lines
|
|
||||||
call gitgutter#sign#clear_signs()
|
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#signs_toggle() abort
|
|
||||||
if g:gitgutter_signs
|
|
||||||
call gitgutter#signs_disable()
|
|
||||||
else
|
|
||||||
call gitgutter#signs_enable()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}
|
|
||||||
|
|
||||||
" Hunks {{{
|
|
||||||
|
|
||||||
function! gitgutter#stage_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'stage')
|
|
||||||
call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --cached --unidiff-zero - '), diff_for_hunk)
|
|
||||||
|
|
||||||
" refresh gitgutter's view of buffer
|
|
||||||
silent execute "GitGutter"
|
|
||||||
endif
|
|
||||||
|
|
||||||
silent! call repeat#set("\<Plug>GitGutterStageHunk", -1)<CR>
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#undo_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'undo')
|
|
||||||
call gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' apply --reverse --unidiff-zero - '), diff_for_hunk)
|
|
||||||
|
|
||||||
" reload file preserving screen line position
|
|
||||||
" CTRL-Y and CTRL-E treat negative counts as positive counts.
|
|
||||||
let x = line('w0')
|
|
||||||
silent edit
|
|
||||||
let y = line('w0')
|
|
||||||
let z = x - y
|
|
||||||
if z > 0
|
|
||||||
execute "normal! ".z."\<C-E>"
|
|
||||||
else
|
|
||||||
execute "normal! ".z."\<C-Y>"
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
silent! call repeat#set("\<Plug>GitGutterUndoHunk", -1)<CR>
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#preview_hunk() abort
|
|
||||||
call gitgutter#utility#use_known_shell()
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
" Ensure the working copy of the file is up to date.
|
|
||||||
" It doesn't make sense to stage a hunk otherwise.
|
|
||||||
noautocmd silent write
|
|
||||||
let diff = gitgutter#diff#run_diff(0, 1)
|
|
||||||
call gitgutter#handle_diff(diff)
|
|
||||||
|
|
||||||
if empty(gitgutter#hunk#current_hunk())
|
|
||||||
call gitgutter#utility#warn('cursor is not in a hunk')
|
|
||||||
else
|
|
||||||
let diff_for_hunk = gitgutter#diff#generate_diff_for_hunk(diff, 'preview')
|
|
||||||
|
|
||||||
silent! wincmd P
|
|
||||||
if !&previewwindow
|
|
||||||
noautocmd execute 'bo' &previewheight 'new'
|
|
||||||
set previewwindow
|
|
||||||
endif
|
|
||||||
|
|
||||||
setlocal noro modifiable filetype=diff buftype=nofile bufhidden=delete noswapfile
|
|
||||||
execute "%delete_"
|
|
||||||
call append(0, split(diff_for_hunk, "\n"))
|
|
||||||
|
|
||||||
noautocmd wincmd p
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#restore_shell()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}
|
|
||||||
|
|||||||
@@ -11,10 +11,13 @@ function! gitgutter#async#available()
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#async#execute(cmd) abort
|
function! gitgutter#async#execute(cmd, bufnr, handler) abort
|
||||||
|
call gitgutter#debug#log('[async] '.a:cmd)
|
||||||
|
|
||||||
let options = {
|
let options = {
|
||||||
\ 'stdoutbuffer': [],
|
\ 'stdoutbuffer': [],
|
||||||
\ 'buffer': gitgutter#utility#bufnr()
|
\ 'buffer': a:bufnr,
|
||||||
|
\ 'handler': a:handler
|
||||||
\ }
|
\ }
|
||||||
let command = s:build_command(a:cmd)
|
let command = s:build_command(a:cmd)
|
||||||
|
|
||||||
@@ -58,33 +61,13 @@ function! s:on_stdout_nvim(_job_id, data, _event) dict abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stderr_nvim(_job_id, _data, _event) dict abort
|
function! s:on_stderr_nvim(_job_id, _data, _event) dict abort
|
||||||
" Backward compatibility for nvim < 0.2.0
|
call self.handler.err(self.buffer)
|
||||||
if !has('nvim-0.2.0')
|
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(self.buffer)
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call gitgutter#hunk#reset()
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#hunk#reset'))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit_nvim(_job_id, _data, _event) dict abort
|
function! s:on_exit_nvim(_job_id, exit_code, _event) dict abort
|
||||||
" Backward compatibility for nvim < 0.2.0
|
if !a:exit_code
|
||||||
if !has('nvim-0.2.0')
|
call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(self.buffer)
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call gitgutter#handle_diff(gitgutter#utility#stringify(self.stdoutbuffer))
|
|
||||||
endif
|
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
return
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#handle_diff', [gitgutter#utility#stringify(self.stdoutbuffer)]))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@@ -92,22 +75,15 @@ function! s:on_stdout_vim(_channel, data) dict abort
|
|||||||
call add(self.stdoutbuffer, a:data)
|
call add(self.stdoutbuffer, a:data)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_stderr_vim(_channel, _data) dict abort
|
function! s:on_stderr_vim(channel, _data) dict abort
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#hunk#reset'))
|
call self.handler.err(self.buffer)
|
||||||
|
try
|
||||||
|
call ch_close(a:channel) " so close_cb and its 'out' handler are not triggered
|
||||||
|
catch /E906/
|
||||||
|
" noop
|
||||||
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:on_exit_vim(_channel) dict abort
|
function! s:on_exit_vim(_channel) dict abort
|
||||||
call s:buffer_exec(self.buffer, function('gitgutter#handle_diff', [gitgutter#utility#stringify(self.stdoutbuffer)]))
|
call self.handler.out(self.buffer, join(self.stdoutbuffer, "\n"))
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function! s:buffer_exec(buffer, fn)
|
|
||||||
let current_buffer = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#utility#set_buffer(a:buffer)
|
|
||||||
|
|
||||||
if gitgutter#utility#is_active()
|
|
||||||
call a:fn()
|
|
||||||
endif
|
|
||||||
|
|
||||||
call gitgutter#utility#set_buffer(current_buffer)
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
@@ -12,67 +12,67 @@ function! gitgutter#debug#debug()
|
|||||||
setlocal bufhidden=delete
|
setlocal bufhidden=delete
|
||||||
setlocal noswapfile
|
setlocal noswapfile
|
||||||
|
|
||||||
call gitgutter#debug#vim_version()
|
call s:vim_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#git_version()
|
call s:git_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#grep_version()
|
call s:grep_version()
|
||||||
call gitgutter#debug#separator()
|
call s:separator()
|
||||||
|
|
||||||
call gitgutter#debug#option('updatetime')
|
call s:option('updatetime')
|
||||||
call gitgutter#debug#option('shell')
|
call s:option('shell')
|
||||||
call gitgutter#debug#option('shellcmdflag')
|
call s:option('shellcmdflag')
|
||||||
call gitgutter#debug#option('shellpipe')
|
call s:option('shellpipe')
|
||||||
call gitgutter#debug#option('shellquote')
|
call s:option('shellquote')
|
||||||
call gitgutter#debug#option('shellredir')
|
call s:option('shellredir')
|
||||||
call gitgutter#debug#option('shellslash')
|
call s:option('shellslash')
|
||||||
call gitgutter#debug#option('shelltemp')
|
call s:option('shelltemp')
|
||||||
call gitgutter#debug#option('shelltype')
|
call s:option('shelltype')
|
||||||
call gitgutter#debug#option('shellxescape')
|
call s:option('shellxescape')
|
||||||
call gitgutter#debug#option('shellxquote')
|
call s:option('shellxquote')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#debug#separator()
|
function! s:separator()
|
||||||
call gitgutter#debug#output('')
|
call s:output('')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#vim_version()
|
function! s:vim_version()
|
||||||
redir => version_info
|
redir => version_info
|
||||||
silent execute 'version'
|
silent execute 'version'
|
||||||
redir END
|
redir END
|
||||||
call gitgutter#debug#output(split(version_info, '\n')[0:2])
|
call s:output(split(version_info, '\n')[0:2])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#git_version()
|
function! s:git_version()
|
||||||
let v = system(g:gitgutter_git_executable.' --version')
|
let v = system(g:gitgutter_git_executable.' --version')
|
||||||
call gitgutter#debug#output( substitute(v, '\n$', '', '') )
|
call s:output( substitute(v, '\n$', '', '') )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#grep_version()
|
function! s:grep_version()
|
||||||
let v = system('grep --version')
|
let v = system('grep --version')
|
||||||
call gitgutter#debug#output( substitute(v, '\n$', '', '') )
|
call s:output( substitute(v, '\n$', '', '') )
|
||||||
|
|
||||||
let v = system('grep --help')
|
let v = system('grep --help')
|
||||||
call gitgutter#debug#output( substitute(v, '\%x00', '', 'g') )
|
call s:output( substitute(v, '\%x00', '', 'g') )
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#option(name)
|
function! s:option(name)
|
||||||
if exists('+' . a:name)
|
if exists('+' . a:name)
|
||||||
let v = eval('&' . a:name)
|
let v = eval('&' . a:name)
|
||||||
call gitgutter#debug#output(a:name . '=' . v)
|
call s:output(a:name . '=' . v)
|
||||||
" redir => output
|
" redir => output
|
||||||
" silent execute "verbose set " . a:name . "?"
|
" silent execute "verbose set " . a:name . "?"
|
||||||
" redir END
|
" redir END
|
||||||
" call gitgutter#debug#output(a:name . '=' . output)
|
" call s:output(a:name . '=' . output)
|
||||||
else
|
else
|
||||||
call gitgutter#debug#output(a:name . ' [n/a]')
|
call s:output(a:name . ' [n/a]')
|
||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#debug#output(text)
|
function! s:output(text)
|
||||||
call append(line('$'), a:text)
|
call append(line('$'), a:text)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +1,137 @@
|
|||||||
if exists('g:gitgutter_grep_command')
|
let s:nomodeline = (v:version > 703 || (v:version == 703 && has('patch442'))) ? '<nomodeline>' : ''
|
||||||
let s:grep_available = 1
|
|
||||||
let s:grep_command = g:gitgutter_grep_command
|
|
||||||
else
|
|
||||||
let s:grep_available = executable('grep')
|
|
||||||
if s:grep_available
|
|
||||||
let s:grep_command = 'grep'
|
|
||||||
if $GREP_OPTIONS =~# '--color=always'
|
|
||||||
let s:grep_command .= ' --color=never'
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
|
let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
|
||||||
|
|
||||||
let s:c_flag = gitgutter#utility#git_supports_command_line_config_override()
|
" True for git v1.7.2+.
|
||||||
|
function! s:git_supports_command_line_config_override() abort
|
||||||
|
call system(g:gitgutter_git_executable.' -c foo.bar=baz --version')
|
||||||
|
return !v:shell_error
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let s:c_flag = s:git_supports_command_line_config_override()
|
||||||
|
|
||||||
|
|
||||||
let s:temp_index = tempname()
|
let s:temp_index = tempname()
|
||||||
let s:temp_buffer = tempname()
|
let s:temp_buffer = tempname()
|
||||||
|
|
||||||
" Returns a diff of the buffer.
|
" Returns a diff of the buffer.
|
||||||
"
|
"
|
||||||
" The way to get the diff depends on whether the buffer is saved or unsaved.
|
" The buffer contents is not the same as the file on disk so we need to pass
|
||||||
|
" two instances of the file to git-diff:
|
||||||
"
|
"
|
||||||
" * Saved: the buffer contents is the same as the file on disk in the working
|
" git diff myfileA myfileB
|
||||||
" tree so we simply do:
|
|
||||||
"
|
"
|
||||||
" git diff myfile
|
" where myfileA comes from
|
||||||
"
|
"
|
||||||
" * Unsaved: the buffer contents is not the same as the file on disk so we
|
" git show :myfile > myfileA
|
||||||
" need to pass two instances of the file to git-diff:
|
|
||||||
"
|
"
|
||||||
" git diff myfileA myfileB
|
" and myfileB is the buffer contents. Ideally we would pass this to
|
||||||
|
" git-diff on stdin via the second argument to vim's system() function.
|
||||||
|
" Unfortunately git-diff does not do CRLF conversion for input received on
|
||||||
|
" stdin, and git-show never performs CRLF conversion, so repos with CRLF
|
||||||
|
" conversion report that every line is modified due to mismatching EOLs.
|
||||||
"
|
"
|
||||||
" The first instance is the file in the index which we obtain with:
|
" Instead, we write the buffer contents to a temporary file - myfileB in this
|
||||||
"
|
" example. Note the file extension must be preserved for the CRLF
|
||||||
" git show :myfile > myfileA
|
" conversion to work.
|
||||||
"
|
|
||||||
" The second instance is the buffer contents. Ideally we would pass this to
|
|
||||||
" git-diff on stdin via the second argument to vim's system() function.
|
|
||||||
" Unfortunately git-diff does not do CRLF conversion for input received on
|
|
||||||
" stdin, and git-show never performs CRLF conversion, so repos with CRLF
|
|
||||||
" conversion report that every line is modified due to mismatching EOLs.
|
|
||||||
"
|
|
||||||
" Instead, we write the buffer contents to a temporary file - myfileB in this
|
|
||||||
" example. Note the file extension must be preserved for the CRLF
|
|
||||||
" conversion to work.
|
|
||||||
"
|
|
||||||
" Before diffing a buffer for the first time, we check whether git knows about
|
|
||||||
" the file:
|
|
||||||
"
|
|
||||||
" git ls-files --error-unmatch myfile
|
|
||||||
"
|
"
|
||||||
" After running the diff we pass it through grep where available to reduce
|
" After running the diff we pass it through grep where available to reduce
|
||||||
" subsequent processing by the plugin. If grep is not available the plugin
|
" subsequent processing by the plugin. If grep is not available the plugin
|
||||||
" does the filtering instead.
|
" does the filtering instead.
|
||||||
function! gitgutter#diff#run_diff(realtime, preserve_full_diff) abort
|
function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort
|
||||||
|
while gitgutter#utility#repo_path(a:bufnr, 0) == -1
|
||||||
|
sleep 5m
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
if gitgutter#utility#repo_path(a:bufnr, 0) == -2
|
||||||
|
throw 'gitgutter not tracked'
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
" Wrap compound commands in parentheses to make Windows happy.
|
" Wrap compound commands in parentheses to make Windows happy.
|
||||||
" bash doesn't mind the parentheses.
|
" bash doesn't mind the parentheses.
|
||||||
let cmd = '('
|
let cmd = '('
|
||||||
|
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let blob_file = s:temp_index
|
||||||
let tracked = gitgutter#utility#getbufvar(bufnr, 'tracked', 0) " i.e. tracked by git
|
let buff_file = s:temp_buffer
|
||||||
if !tracked
|
|
||||||
" Don't bother trying to realtime-diff an untracked file.
|
let extension = gitgutter#utility#extension(a:bufnr)
|
||||||
" NOTE: perhaps we should pull this guard up to the caller?
|
if !empty(extension)
|
||||||
if a:realtime
|
let blob_file .= '.'.extension
|
||||||
throw 'diff failed'
|
let buff_file .= '.'.extension
|
||||||
else
|
|
||||||
let cmd .= g:gitgutter_git_executable.' ls-files --error-unmatch '.gitgutter#utility#shellescape(gitgutter#utility#filename()).' && ('
|
|
||||||
endif
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if a:realtime
|
" Write file from index to temporary file.
|
||||||
let blob_name = g:gitgutter_diff_base.':'.gitgutter#utility#shellescape(gitgutter#utility#file_relative_to_repo_root())
|
let blob_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1)
|
||||||
let blob_file = s:temp_index
|
let cmd .= g:gitgutter_git_executable.' show '.blob_name.' > '.blob_file.' && '
|
||||||
let buff_file = s:temp_buffer
|
|
||||||
let extension = gitgutter#utility#extension()
|
|
||||||
if !empty(extension)
|
|
||||||
let blob_file .= '.'.extension
|
|
||||||
let buff_file .= '.'.extension
|
|
||||||
endif
|
|
||||||
let cmd .= g:gitgutter_git_executable.' show '.blob_name.' > '.blob_file.' && '
|
|
||||||
|
|
||||||
" Writing the whole buffer resets the '[ and '] marks and also the
|
" Write buffer to temporary file.
|
||||||
" 'modified' flag (if &cpoptions includes '+'). These are unwanted
|
call s:write_buffer(a:bufnr, buff_file)
|
||||||
" side-effects so we save and restore the values ourselves.
|
|
||||||
let modified = getbufvar(bufnr, "&mod")
|
|
||||||
let op_mark_start = getpos("'[")
|
|
||||||
let op_mark_end = getpos("']")
|
|
||||||
|
|
||||||
let current_buffer = bufnr('')
|
|
||||||
execute 'buffer '.bufnr
|
|
||||||
execute 'keepalt noautocmd silent write!' buff_file
|
|
||||||
execute 'buffer '.current_buffer
|
|
||||||
|
|
||||||
call setbufvar(bufnr, "&mod", modified)
|
|
||||||
call setpos("'[", op_mark_start)
|
|
||||||
call setpos("']", op_mark_end)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
" Call git-diff with the temporary files.
|
||||||
let cmd .= g:gitgutter_git_executable
|
let cmd .= g:gitgutter_git_executable
|
||||||
if s:c_flag
|
if s:c_flag
|
||||||
let cmd .= ' -c "diff.autorefreshindex=0"'
|
let cmd .= ' -c "diff.autorefreshindex=0"'
|
||||||
let cmd .= ' -c "diff.noprefix=false"'
|
let cmd .= ' -c "diff.noprefix=false"'
|
||||||
endif
|
endif
|
||||||
let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' '
|
let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' -- '.blob_file.' '.buff_file
|
||||||
|
|
||||||
if a:realtime
|
" Pipe git-diff output into grep.
|
||||||
let cmd .= ' -- '.blob_file.' '.buff_file
|
if !a:preserve_full_diff && !empty(g:gitgutter_grep)
|
||||||
else
|
let cmd .= ' | '.g:gitgutter_grep.' '.gitgutter#utility#shellescape('^@@ ')
|
||||||
let cmd .= g:gitgutter_diff_base.' -- '.gitgutter#utility#shellescape(gitgutter#utility#filename())
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !a:preserve_full_diff && s:grep_available
|
" grep exits with 1 when no matches are found; git-diff exits with 1 when
|
||||||
let cmd .= ' | '.s:grep_command.' '.gitgutter#utility#shellescape('^@@ ')
|
" differences are found. However we want to treat non-matches and
|
||||||
endif
|
" differences as non-erroneous behaviour; so we OR the command with one
|
||||||
|
" which always exits with success (0).
|
||||||
if (!a:preserve_full_diff && s:grep_available) || a:realtime
|
let cmd .= ' || exit 0'
|
||||||
" grep exits with 1 when no matches are found; diff exits with 1 when
|
|
||||||
" differences are found. However we want to treat non-matches and
|
|
||||||
" differences as non-erroneous behaviour; so we OR the command with one
|
|
||||||
" which always exits with success (0).
|
|
||||||
let cmd .= ' || exit 0'
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd .= ')'
|
let cmd .= ')'
|
||||||
|
|
||||||
if !tracked
|
let cmd = gitgutter#utility#cd_cmd(a:bufnr, cmd)
|
||||||
let cmd .= ')'
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd = gitgutter#utility#command_in_directory_of_file(cmd)
|
if g:gitgutter_async && gitgutter#async#available()
|
||||||
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
if g:gitgutter_async && gitgutter#async#available() && !a:preserve_full_diff
|
\ 'out': function('gitgutter#diff#handler'),
|
||||||
call gitgutter#async#execute(cmd)
|
\ 'err': function('gitgutter#hunk#reset'),
|
||||||
|
\ })
|
||||||
return 'async'
|
return 'async'
|
||||||
|
|
||||||
else
|
else
|
||||||
let diff = gitgutter#utility#system(cmd)
|
let diff = gitgutter#utility#system(cmd)
|
||||||
|
|
||||||
if gitgutter#utility#shell_error()
|
if v:shell_error
|
||||||
" A shell error indicates the file is not tracked by git (unless something bizarre is going on).
|
call gitgutter#debug#log(diff)
|
||||||
throw 'diff failed'
|
throw 'gitgutter diff failed'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! gitgutter#diff#handler(bufnr, diff) abort
|
||||||
|
call gitgutter#debug#log(a:diff)
|
||||||
|
|
||||||
|
call gitgutter#hunk#set_hunks(a:bufnr, gitgutter#diff#parse_diff(a:diff))
|
||||||
|
let modified_lines = s:process_hunks(a:bufnr, gitgutter#hunk#hunks(a:bufnr))
|
||||||
|
|
||||||
|
if len(modified_lines) > g:gitgutter_max_signs
|
||||||
|
call gitgutter#utility#warn_once('exceeded maximum number of signs (configured by g:gitgutter_max_signs).', 'max_signs')
|
||||||
|
call gitgutter#sign#clear_signs(a:bufnr)
|
||||||
|
|
||||||
|
else
|
||||||
|
if g:gitgutter_signs || g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#sign#update_signs(a:bufnr, modified_lines)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:save_last_seen_change(a:bufnr)
|
||||||
|
execute "silent doautocmd" s:nomodeline "User GitGutter"
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#diff#parse_diff(diff) abort
|
function! gitgutter#diff#parse_diff(diff) abort
|
||||||
let hunks = []
|
let hunks = []
|
||||||
for line in split(a:diff, '\n')
|
for line in split(a:diff, '\n')
|
||||||
@@ -171,69 +156,69 @@ function! gitgutter#diff#parse_hunk(line) abort
|
|||||||
end
|
end
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_hunks(hunks) abort
|
function! s:process_hunks(bufnr, hunks) abort
|
||||||
let modified_lines = []
|
let modified_lines = []
|
||||||
for hunk in a:hunks
|
for hunk in a:hunks
|
||||||
call extend(modified_lines, gitgutter#diff#process_hunk(hunk))
|
call extend(modified_lines, s:process_hunk(a:bufnr, hunk))
|
||||||
endfor
|
endfor
|
||||||
return modified_lines
|
return modified_lines
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns [ [<line_number (number)>, <name (string)>], ...]
|
" Returns [ [<line_number (number)>, <name (string)>], ...]
|
||||||
function! gitgutter#diff#process_hunk(hunk) abort
|
function! s:process_hunk(bufnr, hunk) abort
|
||||||
let modifications = []
|
let modifications = []
|
||||||
let from_line = a:hunk[0]
|
let from_line = a:hunk[0]
|
||||||
let from_count = a:hunk[1]
|
let from_count = a:hunk[1]
|
||||||
let to_line = a:hunk[2]
|
let to_line = a:hunk[2]
|
||||||
let to_count = a:hunk[3]
|
let to_count = a:hunk[3]
|
||||||
|
|
||||||
if gitgutter#diff#is_added(from_count, to_count)
|
if s:is_added(from_count, to_count)
|
||||||
call gitgutter#diff#process_added(modifications, from_count, to_count, to_line)
|
call s:process_added(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_added(to_count)
|
call gitgutter#hunk#increment_lines_added(a:bufnr, to_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_removed(from_count, to_count)
|
elseif s:is_removed(from_count, to_count)
|
||||||
call gitgutter#diff#process_removed(modifications, from_count, to_count, to_line)
|
call s:process_removed(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_removed(from_count)
|
call gitgutter#hunk#increment_lines_removed(a:bufnr, from_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified(from_count, to_count)
|
elseif s:is_modified(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified(modifications, from_count, to_count, to_line)
|
call s:process_modified(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_modified(to_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, to_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified_and_added(from_count, to_count)
|
elseif s:is_modified_and_added(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line)
|
call s:process_modified_and_added(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_added(to_count - from_count)
|
call gitgutter#hunk#increment_lines_added(a:bufnr, to_count - from_count)
|
||||||
call gitgutter#hunk#increment_lines_modified(from_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, from_count)
|
||||||
|
|
||||||
elseif gitgutter#diff#is_modified_and_removed(from_count, to_count)
|
elseif s:is_modified_and_removed(from_count, to_count)
|
||||||
call gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line)
|
call s:process_modified_and_removed(modifications, from_count, to_count, to_line)
|
||||||
call gitgutter#hunk#increment_lines_modified(to_count)
|
call gitgutter#hunk#increment_lines_modified(a:bufnr, to_count)
|
||||||
call gitgutter#hunk#increment_lines_removed(from_count - to_count)
|
call gitgutter#hunk#increment_lines_removed(a:bufnr, from_count - to_count)
|
||||||
|
|
||||||
endif
|
endif
|
||||||
return modifications
|
return modifications
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_added(from_count, to_count) abort
|
function! s:is_added(from_count, to_count) abort
|
||||||
return a:from_count == 0 && a:to_count > 0
|
return a:from_count == 0 && a:to_count > 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_removed(from_count, to_count) abort
|
function! s:is_removed(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count == 0
|
return a:from_count > 0 && a:to_count == 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified(from_count, to_count) abort
|
function! s:is_modified(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count == a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified_and_added(from_count, to_count) abort
|
function! s:is_modified_and_added(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count < a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#is_modified_and_removed(from_count, to_count) abort
|
function! s:is_modified_and_removed(from_count, to_count) abort
|
||||||
return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count
|
return a:from_count > 0 && a:to_count > 0 && a:from_count > a:to_count
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_added(modifications, from_count, to_count, to_line) abort
|
function! s:process_added(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
@@ -242,7 +227,7 @@ function! gitgutter#diff#process_added(modifications, from_count, to_count, to_l
|
|||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_removed(modifications, from_count, to_count, to_line) abort
|
function! s:process_removed(modifications, from_count, to_count, to_line) abort
|
||||||
if a:to_line == 0
|
if a:to_line == 0
|
||||||
call add(a:modifications, [1, 'removed_first_line'])
|
call add(a:modifications, [1, 'removed_first_line'])
|
||||||
else
|
else
|
||||||
@@ -250,7 +235,7 @@ function! gitgutter#diff#process_removed(modifications, from_count, to_count, to
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
@@ -259,7 +244,7 @@ function! gitgutter#diff#process_modified(modifications, from_count, to_count, t
|
|||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified_and_added(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified_and_added(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:from_count
|
while offset < a:from_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
@@ -273,7 +258,7 @@ function! gitgutter#diff#process_modified_and_added(modifications, from_count, t
|
|||||||
endwhile
|
endwhile
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#diff#process_modified_and_removed(modifications, from_count, to_count, to_line) abort
|
function! s:process_modified_and_removed(modifications, from_count, to_count, to_line) abort
|
||||||
let offset = 0
|
let offset = 0
|
||||||
while offset < a:to_count
|
while offset < a:to_count
|
||||||
let line_number = a:to_line + offset
|
let line_number = a:to_line + offset
|
||||||
@@ -283,28 +268,14 @@ function! gitgutter#diff#process_modified_and_removed(modifications, from_count,
|
|||||||
let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed']
|
let a:modifications[-1] = [a:to_line + offset - 1, 'modified_removed']
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Generates a zero-context diff for the current hunk.
|
|
||||||
"
|
|
||||||
" diff - the full diff for the buffer
|
|
||||||
" type - stage | undo | preview
|
|
||||||
function! gitgutter#diff#generate_diff_for_hunk(diff, type) abort
|
|
||||||
let diff_for_hunk = gitgutter#diff#discard_hunks(a:diff, a:type == 'stage' || a:type == 'undo')
|
|
||||||
|
|
||||||
if a:type == 'stage' || a:type == 'undo'
|
" Returns a diff for the current hunk.
|
||||||
let diff_for_hunk = gitgutter#diff#adjust_hunk_summary(diff_for_hunk, a:type == 'stage')
|
function! gitgutter#diff#hunk_diff(bufnr, full_diff)
|
||||||
endif
|
|
||||||
|
|
||||||
return diff_for_hunk
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Returns the diff with all hunks discarded except the current.
|
|
||||||
"
|
|
||||||
" diff - the diff to process
|
|
||||||
" keep_header - truthy to keep the diff header and hunk summary, falsy to discard it
|
|
||||||
function! gitgutter#diff#discard_hunks(diff, keep_header) abort
|
|
||||||
let modified_diff = []
|
let modified_diff = []
|
||||||
let keep_line = a:keep_header
|
let keep_line = 1
|
||||||
for line in split(a:diff, '\n')
|
" Don't keepempty when splitting because the diff we want may not be the
|
||||||
|
" final one. Instead add trailing NL at end of function.
|
||||||
|
for line in split(a:full_diff, '\n')
|
||||||
let hunk_info = gitgutter#diff#parse_hunk(line)
|
let hunk_info = gitgutter#diff#parse_hunk(line)
|
||||||
if len(hunk_info) == 4 " start of new hunk
|
if len(hunk_info) == 4 " start of new hunk
|
||||||
let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info)
|
let keep_line = gitgutter#hunk#cursor_in_hunk(hunk_info)
|
||||||
@@ -313,36 +284,36 @@ function! gitgutter#diff#discard_hunks(diff, keep_header) abort
|
|||||||
call add(modified_diff, line)
|
call add(modified_diff, line)
|
||||||
endif
|
endif
|
||||||
endfor
|
endfor
|
||||||
|
return join(modified_diff, "\n")."\n"
|
||||||
if a:keep_header
|
|
||||||
return gitgutter#utility#stringify(modified_diff)
|
|
||||||
else
|
|
||||||
" Discard hunk summary too.
|
|
||||||
return gitgutter#utility#stringify(modified_diff[1:])
|
|
||||||
endif
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Adjust hunk summary (from's / to's line number) to ignore changes above/before this one.
|
|
||||||
"
|
function! s:write_buffer(bufnr, file)
|
||||||
" diff_for_hunk - a diff containing only the hunk of interest
|
" Write specified buffer (which may not be the current buffer) to buff_file.
|
||||||
" staging - truthy if the hunk is to be staged, falsy if it is to be undone
|
" There doesn't seem to be a clean way to write a buffer that isn't the current
|
||||||
"
|
" to a file; we have to switch to it, write it, then switch back.
|
||||||
" TODO: push this down to #discard_hunks?
|
let current_buffer = bufnr('')
|
||||||
function! gitgutter#diff#adjust_hunk_summary(diff_for_hunk, staging) abort
|
execute 'buffer '.a:bufnr
|
||||||
let line_adjustment = gitgutter#hunk#line_adjustment_for_current_hunk()
|
|
||||||
let adj_diff = []
|
" Writing the whole buffer resets the '[ and '] marks and also the
|
||||||
for line in split(a:diff_for_hunk, '\n')
|
" 'modified' flag (if &cpoptions includes '+'). These are unwanted
|
||||||
if match(line, s:hunk_re) != -1
|
" side-effects so we save and restore the values ourselves.
|
||||||
if a:staging
|
let modified = getbufvar(a:bufnr, "&mod")
|
||||||
" increment 'to' line number
|
let op_mark_start = getpos("'[")
|
||||||
let line = substitute(line, '+\@<=\(\d\+\)', '\=submatch(1)+line_adjustment', '')
|
let op_mark_end = getpos("']")
|
||||||
else
|
|
||||||
" decrement 'from' line number
|
execute 'keepalt noautocmd silent write!' a:file
|
||||||
let line = substitute(line, '-\@<=\(\d\+\)', '\=submatch(1)-line_adjustment', '')
|
|
||||||
endif
|
call setbufvar(a:bufnr, "&mod", modified)
|
||||||
endif
|
call setpos("'[", op_mark_start)
|
||||||
call add(adj_diff, line)
|
call setpos("']", op_mark_end)
|
||||||
endfor
|
|
||||||
return gitgutter#utility#stringify(adj_diff)
|
execute 'buffer '.current_buffer
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:save_last_seen_change(bufnr) abort
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'tick', getbufvar(a:bufnr, 'changedtick'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,37 @@
|
|||||||
|
function! gitgutter#highlight#line_disable() abort
|
||||||
|
let g:gitgutter_highlight_lines = 0
|
||||||
|
call s:define_sign_line_highlights()
|
||||||
|
|
||||||
|
if !g:gitgutter_signs
|
||||||
|
call gitgutter#sign#clear_signs(bufnr(''))
|
||||||
|
call gitgutter#sign#remove_dummy_sign(bufnr(''), 0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
redraw!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#highlight#line_enable() abort
|
||||||
|
let old_highlight_lines = g:gitgutter_highlight_lines
|
||||||
|
|
||||||
|
let g:gitgutter_highlight_lines = 1
|
||||||
|
call s:define_sign_line_highlights()
|
||||||
|
|
||||||
|
if !old_highlight_lines && !g:gitgutter_signs
|
||||||
|
call gitgutter#all(1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
redraw!
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#highlight#line_toggle() abort
|
||||||
|
if g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#highlight#line_disable()
|
||||||
|
else
|
||||||
|
call gitgutter#highlight#line_enable()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_column_highlight() abort
|
function! gitgutter#highlight#define_sign_column_highlight() abort
|
||||||
if g:gitgutter_override_sign_column_highlight
|
if g:gitgutter_override_sign_column_highlight
|
||||||
highlight! link SignColumn LineNr
|
highlight! link SignColumn LineNr
|
||||||
@@ -7,7 +41,7 @@ function! gitgutter#highlight#define_sign_column_highlight() abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_highlights() abort
|
function! gitgutter#highlight#define_highlights() abort
|
||||||
let [guibg, ctermbg] = gitgutter#highlight#get_background_colors('SignColumn')
|
let [guibg, ctermbg] = s:get_background_colors('SignColumn')
|
||||||
|
|
||||||
" Highlights used by the signs.
|
" Highlights used by the signs.
|
||||||
|
|
||||||
@@ -42,12 +76,12 @@ function! gitgutter#highlight#define_signs() abort
|
|||||||
sign define GitGutterLineModifiedRemoved
|
sign define GitGutterLineModifiedRemoved
|
||||||
sign define GitGutterDummy
|
sign define GitGutterDummy
|
||||||
|
|
||||||
call gitgutter#highlight#define_sign_text()
|
call s:define_sign_text()
|
||||||
call gitgutter#highlight#define_sign_text_highlights()
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
call gitgutter#highlight#define_sign_line_highlights()
|
call s:define_sign_line_highlights()
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_text() abort
|
function! s:define_sign_text() abort
|
||||||
execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added
|
execute "sign define GitGutterLineAdded text=" . g:gitgutter_sign_added
|
||||||
execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified
|
execute "sign define GitGutterLineModified text=" . g:gitgutter_sign_modified
|
||||||
execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed
|
execute "sign define GitGutterLineRemoved text=" . g:gitgutter_sign_removed
|
||||||
@@ -75,7 +109,7 @@ function! gitgutter#highlight#define_sign_text_highlights() abort
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#define_sign_line_highlights() abort
|
function! s:define_sign_line_highlights() abort
|
||||||
if g:gitgutter_highlight_lines
|
if g:gitgutter_highlight_lines
|
||||||
sign define GitGutterLineAdded linehl=GitGutterAddLine
|
sign define GitGutterLineAdded linehl=GitGutterAddLine
|
||||||
sign define GitGutterLineModified linehl=GitGutterChangeLine
|
sign define GitGutterLineModified linehl=GitGutterChangeLine
|
||||||
@@ -91,22 +125,22 @@ function! gitgutter#highlight#define_sign_line_highlights() abort
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#get_background_colors(group) abort
|
function! s:get_background_colors(group) abort
|
||||||
redir => highlight
|
redir => highlight
|
||||||
silent execute 'silent highlight ' . a:group
|
silent execute 'silent highlight ' . a:group
|
||||||
redir END
|
redir END
|
||||||
|
|
||||||
let link_matches = matchlist(highlight, 'links to \(\S\+\)')
|
let link_matches = matchlist(highlight, 'links to \(\S\+\)')
|
||||||
if len(link_matches) > 0 " follow the link
|
if len(link_matches) > 0 " follow the link
|
||||||
return gitgutter#highlight#get_background_colors(link_matches[1])
|
return s:get_background_colors(link_matches[1])
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let ctermbg = gitgutter#highlight#match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)')
|
let ctermbg = s:match_highlight(highlight, 'ctermbg=\([0-9A-Za-z]\+\)')
|
||||||
let guibg = gitgutter#highlight#match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)')
|
let guibg = s:match_highlight(highlight, 'guibg=\([#0-9A-Za-z]\+\)')
|
||||||
return [guibg, ctermbg]
|
return [guibg, ctermbg]
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#highlight#match_highlight(highlight, pattern) abort
|
function! s:match_highlight(highlight, pattern) abort
|
||||||
let matches = matchlist(a:highlight, a:pattern)
|
let matches = matchlist(a:highlight, a:pattern)
|
||||||
if len(matches) == 0
|
if len(matches) == 0
|
||||||
return 'NONE'
|
return 'NONE'
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
function! gitgutter#hunk#set_hunks(hunks) abort
|
function! gitgutter#hunk#set_hunks(bufnr, hunks) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', a:hunks)
|
call gitgutter#utility#setbufvar(a:bufnr, 'hunks', a:hunks)
|
||||||
call s:reset_summary()
|
call s:reset_summary(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#hunks() abort
|
function! gitgutter#hunk#hunks(bufnr) abort
|
||||||
return gitgutter#utility#getbufvar(gitgutter#utility#bufnr(), 'hunks', [])
|
return gitgutter#utility#getbufvar(a:bufnr, 'hunks', [])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#reset() abort
|
function! gitgutter#hunk#reset(bufnr) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'hunks', [])
|
call gitgutter#utility#setbufvar(a:bufnr, 'hunks', [])
|
||||||
call s:reset_summary()
|
call s:reset_summary(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@@ -17,37 +17,35 @@ function! gitgutter#hunk#summary(bufnr) abort
|
|||||||
return gitgutter#utility#getbufvar(a:bufnr, 'summary', [0,0,0])
|
return gitgutter#utility#getbufvar(a:bufnr, 'summary', [0,0,0])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:reset_summary() abort
|
function! s:reset_summary(bufnr) abort
|
||||||
call gitgutter#utility#setbufvar(gitgutter#utility#bufnr(), 'summary', [0,0,0])
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', [0,0,0])
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_added(count) abort
|
function! gitgutter#hunk#increment_lines_added(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[0] += a:count
|
let summary[0] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_modified(count) abort
|
function! gitgutter#hunk#increment_lines_modified(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[1] += a:count
|
let summary[1] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#increment_lines_removed(count) abort
|
function! gitgutter#hunk#increment_lines_removed(bufnr, count) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let summary = gitgutter#hunk#summary(a:bufnr)
|
||||||
let summary = gitgutter#hunk#summary(bufnr)
|
|
||||||
let summary[2] += a:count
|
let summary[2] += a:count
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'summary', summary)
|
call gitgutter#utility#setbufvar(a:bufnr, 'summary', summary)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#hunk#next_hunk(count) abort
|
function! gitgutter#hunk#next_hunk(count) abort
|
||||||
if gitgutter#utility#is_active()
|
let bufnr = bufnr('')
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
let current_line = line('.')
|
let current_line = line('.')
|
||||||
let hunk_count = 0
|
let hunk_count = 0
|
||||||
for hunk in gitgutter#hunk#hunks()
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
if hunk[2] > current_line
|
if hunk[2] > current_line
|
||||||
let hunk_count += 1
|
let hunk_count += 1
|
||||||
if hunk_count == a:count
|
if hunk_count == a:count
|
||||||
@@ -61,10 +59,11 @@ function! gitgutter#hunk#next_hunk(count) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#hunk#prev_hunk(count) abort
|
function! gitgutter#hunk#prev_hunk(count) abort
|
||||||
if gitgutter#utility#is_active()
|
let bufnr = bufnr('')
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
let current_line = line('.')
|
let current_line = line('.')
|
||||||
let hunk_count = 0
|
let hunk_count = 0
|
||||||
for hunk in reverse(copy(gitgutter#hunk#hunks()))
|
for hunk in reverse(copy(gitgutter#hunk#hunks(bufnr)))
|
||||||
if hunk[2] < current_line
|
if hunk[2] < current_line
|
||||||
let hunk_count += 1
|
let hunk_count += 1
|
||||||
if hunk_count == a:count
|
if hunk_count == a:count
|
||||||
@@ -80,10 +79,11 @@ endfunction
|
|||||||
|
|
||||||
" Returns the hunk the cursor is currently in or an empty list if the cursor
|
" Returns the hunk the cursor is currently in or an empty list if the cursor
|
||||||
" isn't in a hunk.
|
" isn't in a hunk.
|
||||||
function! gitgutter#hunk#current_hunk() abort
|
function! s:current_hunk() abort
|
||||||
|
let bufnr = bufnr('')
|
||||||
let current_hunk = []
|
let current_hunk = []
|
||||||
|
|
||||||
for hunk in gitgutter#hunk#hunks()
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
if gitgutter#hunk#cursor_in_hunk(hunk)
|
if gitgutter#hunk#cursor_in_hunk(hunk)
|
||||||
let current_hunk = hunk
|
let current_hunk = hunk
|
||||||
break
|
break
|
||||||
@@ -107,22 +107,9 @@ function! gitgutter#hunk#cursor_in_hunk(hunk) abort
|
|||||||
return 0
|
return 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns the number of lines the current hunk is offset from where it would
|
|
||||||
" be if any changes above it in the file didn't exist.
|
|
||||||
function! gitgutter#hunk#line_adjustment_for_current_hunk() abort
|
|
||||||
let adj = 0
|
|
||||||
for hunk in gitgutter#hunk#hunks()
|
|
||||||
if gitgutter#hunk#cursor_in_hunk(hunk)
|
|
||||||
break
|
|
||||||
else
|
|
||||||
let adj += hunk[1] - hunk[3]
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return adj
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#hunk#text_object(inner) abort
|
function! gitgutter#hunk#text_object(inner) abort
|
||||||
let hunk = gitgutter#hunk#current_hunk()
|
let bufnr = bufnr('')
|
||||||
|
let hunk = s:current_hunk(bufnr)
|
||||||
|
|
||||||
if empty(hunk)
|
if empty(hunk)
|
||||||
return
|
return
|
||||||
@@ -141,3 +128,129 @@ function! gitgutter#hunk#text_object(inner) abort
|
|||||||
|
|
||||||
execute 'normal! 'first_line.'GV'.last_line.'G'
|
execute 'normal! 'first_line.'GV'.last_line.'G'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! gitgutter#hunk#stage() abort
|
||||||
|
call s:hunk_op(function('s:stage'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#hunk#undo() abort
|
||||||
|
call s:hunk_op(function('s:undo'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#hunk#preview() abort
|
||||||
|
call s:hunk_op(function('s:preview'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:hunk_op(op)
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
|
||||||
|
if gitgutter#utility#is_active(bufnr)
|
||||||
|
" Get a (synchronous) diff.
|
||||||
|
let [async, g:gitgutter_async] = [g:gitgutter_async, 0]
|
||||||
|
let diff = gitgutter#diff#run_diff(bufnr, 1)
|
||||||
|
let g:gitgutter_async = async
|
||||||
|
|
||||||
|
call gitgutter#hunk#set_hunks(bufnr, gitgutter#diff#parse_diff(diff))
|
||||||
|
|
||||||
|
if empty(s:current_hunk())
|
||||||
|
call gitgutter#utility#warn('cursor is not in a hunk')
|
||||||
|
else
|
||||||
|
call a:op(gitgutter#diff#hunk_diff(bufnr, diff))
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:stage(hunk_diff)
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
let diff = s:adjust_header(bufnr, a:hunk_diff)
|
||||||
|
" Apply patch to index.
|
||||||
|
call gitgutter#utility#system(
|
||||||
|
\ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' apply --cached --unidiff-zero - '),
|
||||||
|
\ diff)
|
||||||
|
|
||||||
|
" Refresh gitgutter's view of buffer.
|
||||||
|
call gitgutter#process_buffer(bufnr, 1)
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:undo(hunk_diff)
|
||||||
|
" Apply reverse patch to buffer.
|
||||||
|
let hunk = gitgutter#diff#parse_hunk(split(a:hunk_diff, '\n')[4])
|
||||||
|
let lines = map(split(a:hunk_diff, '\n')[5:], 'v:val[1:]')
|
||||||
|
let lnum = hunk[2]
|
||||||
|
let added_only = hunk[1] == 0 && hunk[3] > 0
|
||||||
|
let removed_only = hunk[1] > 0 && hunk[3] == 0
|
||||||
|
|
||||||
|
if removed_only
|
||||||
|
call append(lnum, lines)
|
||||||
|
elseif added_only
|
||||||
|
execute lnum .','. (lnum+len(lines)-1) .'d'
|
||||||
|
else
|
||||||
|
call append(lnum-1, lines[0:hunk[1]])
|
||||||
|
execute (lnum+hunk[1]) .','. (lnum+hunk[1]+hunk[3]) .'d'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:preview(hunk_diff)
|
||||||
|
silent! wincmd P
|
||||||
|
if !&previewwindow
|
||||||
|
noautocmd execute 'bo' &previewheight 'new'
|
||||||
|
set previewwindow
|
||||||
|
endif
|
||||||
|
|
||||||
|
setlocal noro modifiable filetype=diff buftype=nofile bufhidden=delete noswapfile
|
||||||
|
execute "%delete_"
|
||||||
|
call append(0, split(s:discard_header(a:hunk_diff), "\n"))
|
||||||
|
|
||||||
|
noautocmd wincmd p
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:adjust_header(bufnr, hunk_diff)
|
||||||
|
return s:adjust_hunk_summary(s:fix_file_references(a:bufnr, a:hunk_diff))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Replaces references to temp files with the actual file.
|
||||||
|
function! s:fix_file_references(bufnr, hunk_diff)
|
||||||
|
let filepath = gitgutter#utility#repo_path(a:bufnr, 0)
|
||||||
|
let diff = a:hunk_diff
|
||||||
|
for tmp in matchlist(diff, '\vdiff --git a/(\S+) b/(\S+)\n')[1:2]
|
||||||
|
let diff = substitute(diff, tmp, filepath, 'g')
|
||||||
|
endfor
|
||||||
|
return diff
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:adjust_hunk_summary(hunk_diff) abort
|
||||||
|
let line_adjustment = s:line_adjustment_for_current_hunk()
|
||||||
|
let diff = split(a:hunk_diff, '\n', 1)
|
||||||
|
let diff[4] = substitute(diff[4], '+\@<=\(\d\+\)', '\=submatch(1)+line_adjustment', '')
|
||||||
|
return join(diff, "\n")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:discard_header(hunk_diff)
|
||||||
|
return join(split(a:hunk_diff, '\n', 1)[5:], "\n")
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Returns the number of lines the current hunk is offset from where it would
|
||||||
|
" be if any changes above it in the file didn't exist.
|
||||||
|
function! s:line_adjustment_for_current_hunk() abort
|
||||||
|
let bufnr = bufnr('')
|
||||||
|
let adj = 0
|
||||||
|
for hunk in gitgutter#hunk#hunks(bufnr)
|
||||||
|
if gitgutter#hunk#cursor_in_hunk(hunk)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
let adj += hunk[1] - hunk[3]
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
return adj
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,43 @@ let s:dummy_sign_id = s:first_sign_id - 1
|
|||||||
let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596"))
|
let s:supports_star = v:version > 703 || (v:version == 703 && has("patch596"))
|
||||||
|
|
||||||
|
|
||||||
" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed.
|
function! gitgutter#sign#enable() abort
|
||||||
function! gitgutter#sign#clear_signs() abort
|
let old_signs = g:gitgutter_signs
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
call gitgutter#sign#find_current_signs()
|
|
||||||
|
|
||||||
let sign_ids = map(values(gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')), 'v:val.id')
|
let g:gitgutter_signs = 1
|
||||||
call gitgutter#sign#remove_signs(sign_ids, 1)
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', {})
|
|
||||||
|
if !old_signs && !g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#all(1)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#sign#disable() abort
|
||||||
|
let g:gitgutter_signs = 0
|
||||||
|
call gitgutter#highlight#define_sign_text_highlights()
|
||||||
|
|
||||||
|
if !g:gitgutter_highlight_lines
|
||||||
|
call gitgutter#sign#clear_signs(bufnr(''))
|
||||||
|
call gitgutter#sign#remove_dummy_sign(bufnr(''), 0)
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! gitgutter#sign#toggle() abort
|
||||||
|
if g:gitgutter_signs
|
||||||
|
call gitgutter#sign#disable()
|
||||||
|
else
|
||||||
|
call gitgutter#sign#enable()
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
" Removes gitgutter's signs (excluding dummy sign) from the buffer being processed.
|
||||||
|
function! gitgutter#sign#clear_signs(bufnr) abort
|
||||||
|
call s:find_current_signs(a:bufnr)
|
||||||
|
|
||||||
|
let sign_ids = map(values(gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')), 'v:val.id')
|
||||||
|
call s:remove_signs(a:bufnr, sign_ids, 1)
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'gitgutter_signs', {})
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@@ -25,39 +54,37 @@ endfunction
|
|||||||
"
|
"
|
||||||
" modified_lines: list of [<line_number (number)>, <name (string)>]
|
" modified_lines: list of [<line_number (number)>, <name (string)>]
|
||||||
" where name = 'added|removed|modified|modified_removed'
|
" where name = 'added|removed|modified|modified_removed'
|
||||||
function! gitgutter#sign#update_signs(modified_lines) abort
|
function! gitgutter#sign#update_signs(bufnr, modified_lines) abort
|
||||||
call gitgutter#sign#find_current_signs()
|
call s:find_current_signs(a:bufnr)
|
||||||
|
|
||||||
let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]')
|
let new_gitgutter_signs_line_numbers = map(copy(a:modified_lines), 'v:val[0]')
|
||||||
let obsolete_signs = gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers)
|
let obsolete_signs = s:obsolete_gitgutter_signs_to_remove(a:bufnr, new_gitgutter_signs_line_numbers)
|
||||||
|
|
||||||
let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines)
|
let flicker_possible = s:remove_all_old_signs && !empty(a:modified_lines)
|
||||||
if flicker_possible
|
if flicker_possible
|
||||||
call gitgutter#sign#add_dummy_sign()
|
call s:add_dummy_sign(a:bufnr)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call gitgutter#sign#remove_signs(obsolete_signs, s:remove_all_old_signs)
|
call s:remove_signs(a:bufnr, obsolete_signs, s:remove_all_old_signs)
|
||||||
call gitgutter#sign#upsert_new_gitgutter_signs(a:modified_lines)
|
call s:upsert_new_gitgutter_signs(a:bufnr, a:modified_lines)
|
||||||
|
|
||||||
if flicker_possible
|
if flicker_possible
|
||||||
call gitgutter#sign#remove_dummy_sign(0)
|
call gitgutter#sign#remove_dummy_sign(a:bufnr, 0)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#add_dummy_sign() abort
|
function! s:add_dummy_sign(bufnr) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if !gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign')
|
||||||
if !gitgutter#utility#getbufvar(bufnr, 'dummy_sign')
|
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . a:bufnr
|
||||||
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', 1)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 1)
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#sign#remove_dummy_sign(force) abort
|
function! gitgutter#sign#remove_dummy_sign(bufnr, force) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign') && (a:force || !g:gitgutter_sign_column_always)
|
||||||
if gitgutter#utility#getbufvar(bufnr, 'dummy_sign') && (a:force || !g:gitgutter_sign_column_always)
|
execute "sign unplace" s:dummy_sign_id "buffer=" . a:bufnr
|
||||||
execute "sign unplace" s:dummy_sign_id "buffer=" . bufnr
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', 0)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', 0)
|
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@@ -67,14 +94,13 @@ endfunction
|
|||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#find_current_signs() abort
|
function! s:find_current_signs(bufnr) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
let gitgutter_signs = {} " <line_number (string)>: {'id': <id (number)>, 'name': <name (string)>}
|
let gitgutter_signs = {} " <line_number (string)>: {'id': <id (number)>, 'name': <name (string)>}
|
||||||
let other_signs = [] " [<line_number (number),...]
|
let other_signs = [] " [<line_number (number),...]
|
||||||
let dummy_sign_placed = 0
|
let dummy_sign_placed = 0
|
||||||
|
|
||||||
redir => signs
|
redir => signs
|
||||||
silent execute "sign place buffer=" . bufnr
|
silent execute "sign place buffer=" . a:bufnr
|
||||||
redir END
|
redir END
|
||||||
|
|
||||||
for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="')
|
for sign_line in filter(split(signs, '\n')[2:], 'v:val =~# "="')
|
||||||
@@ -101,19 +127,18 @@ function! gitgutter#sign#find_current_signs() abort
|
|||||||
end
|
end
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'dummy_sign', dummy_sign_placed)
|
call gitgutter#utility#setbufvar(a:bufnr, 'dummy_sign', dummy_sign_placed)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'gitgutter_signs', gitgutter_signs)
|
call gitgutter#utility#setbufvar(a:bufnr, 'gitgutter_signs', gitgutter_signs)
|
||||||
call gitgutter#utility#setbufvar(bufnr, 'other_signs', other_signs)
|
call gitgutter#utility#setbufvar(a:bufnr, 'other_signs', other_signs)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
" Returns a list of [<id (number)>, ...]
|
" Returns a list of [<id (number)>, ...]
|
||||||
" Sets `s:remove_all_old_signs` as a side-effect.
|
" Sets `s:remove_all_old_signs` as a side-effect.
|
||||||
function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_line_numbers) abort
|
function! s:obsolete_gitgutter_signs_to_remove(bufnr, new_gitgutter_signs_line_numbers) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
|
||||||
let signs_to_remove = [] " list of [<id (number)>, ...]
|
let signs_to_remove = [] " list of [<id (number)>, ...]
|
||||||
let remove_all_signs = 1
|
let remove_all_signs = 1
|
||||||
let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')
|
let old_gitgutter_signs = gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')
|
||||||
for line_number in keys(old_gitgutter_signs)
|
for line_number in keys(old_gitgutter_signs)
|
||||||
if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1
|
if index(a:new_gitgutter_signs_line_numbers, str2nr(line_number)) == -1
|
||||||
call add(signs_to_remove, old_gitgutter_signs[line_number].id)
|
call add(signs_to_remove, old_gitgutter_signs[line_number].id)
|
||||||
@@ -126,13 +151,12 @@ function! gitgutter#sign#obsolete_gitgutter_signs_to_remove(new_gitgutter_signs_
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort
|
function! s:remove_signs(bufnr, sign_ids, all_signs) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
if a:all_signs && s:supports_star && empty(gitgutter#utility#getbufvar(a:bufnr, 'other_signs'))
|
||||||
if a:all_signs && s:supports_star && empty(gitgutter#utility#getbufvar(bufnr, 'other_signs'))
|
let dummy_sign_present = gitgutter#utility#getbufvar(a:bufnr, 'dummy_sign')
|
||||||
let dummy_sign_present = gitgutter#utility#getbufvar(bufnr, 'dummy_sign')
|
execute "sign unplace * buffer=" . a:bufnr
|
||||||
execute "sign unplace * buffer=" . bufnr
|
|
||||||
if dummy_sign_present
|
if dummy_sign_present
|
||||||
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . bufnr
|
execute "sign place" s:dummy_sign_id "line=" . 9999 "name=GitGutterDummy buffer=" . a:bufnr
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
for id in a:sign_ids
|
for id in a:sign_ids
|
||||||
@@ -142,22 +166,21 @@ function! gitgutter#sign#remove_signs(sign_ids, all_signs) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort
|
function! s:upsert_new_gitgutter_signs(bufnr, modified_lines) abort
|
||||||
let bufnr = gitgutter#utility#bufnr()
|
let other_signs = gitgutter#utility#getbufvar(a:bufnr, 'other_signs')
|
||||||
let other_signs = gitgutter#utility#getbufvar(bufnr, 'other_signs')
|
let old_gitgutter_signs = gitgutter#utility#getbufvar(a:bufnr, 'gitgutter_signs')
|
||||||
let old_gitgutter_signs = gitgutter#utility#getbufvar(bufnr, 'gitgutter_signs')
|
|
||||||
|
|
||||||
for line in a:modified_lines
|
for line in a:modified_lines
|
||||||
let line_number = line[0] " <number>
|
let line_number = line[0] " <number>
|
||||||
if index(other_signs, line_number) == -1 " don't clobber others' signs
|
if index(other_signs, line_number) == -1 " don't clobber others' signs
|
||||||
let name = gitgutter#utility#highlight_name_for_change(line[1])
|
let name = s:highlight_name_for_change(line[1])
|
||||||
if !has_key(old_gitgutter_signs, line_number) " insert
|
if !has_key(old_gitgutter_signs, line_number) " insert
|
||||||
let id = gitgutter#sign#next_sign_id()
|
let id = s:next_sign_id()
|
||||||
execute "sign place" id "line=" . line_number "name=" . name "buffer=" . bufnr
|
execute "sign place" id "line=" . line_number "name=" . name "buffer=" . a:bufnr
|
||||||
else " update if sign has changed
|
else " update if sign has changed
|
||||||
let old_sign = old_gitgutter_signs[line_number]
|
let old_sign = old_gitgutter_signs[line_number]
|
||||||
if old_sign.name !=# name
|
if old_sign.name !=# name
|
||||||
execute "sign place" old_sign.id "name=" . name "buffer=" . bufnr
|
execute "sign place" old_sign.id "name=" . name "buffer=" . a:bufnr
|
||||||
end
|
end
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -166,7 +189,7 @@ function! gitgutter#sign#upsert_new_gitgutter_signs(modified_lines) abort
|
|||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function! gitgutter#sign#next_sign_id() abort
|
function! s:next_sign_id() abort
|
||||||
let next_id = s:next_sign_id
|
let next_id = s:next_sign_id
|
||||||
let s:next_sign_id += 1
|
let s:next_sign_id += 1
|
||||||
return next_id
|
return next_id
|
||||||
@@ -177,3 +200,20 @@ endfunction
|
|||||||
function! gitgutter#sign#reset()
|
function! gitgutter#sign#reset()
|
||||||
let s:next_sign_id = s:first_sign_id
|
let s:next_sign_id = s:first_sign_id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
function! s:highlight_name_for_change(text) abort
|
||||||
|
if a:text ==# 'added'
|
||||||
|
return 'GitGutterLineAdded'
|
||||||
|
elseif a:text ==# 'removed'
|
||||||
|
return 'GitGutterLineRemoved'
|
||||||
|
elseif a:text ==# 'removed_first_line'
|
||||||
|
return 'GitGutterLineRemovedFirstLine'
|
||||||
|
elseif a:text ==# 'modified'
|
||||||
|
return 'GitGutterLineModified'
|
||||||
|
elseif a:text ==# 'modified_removed'
|
||||||
|
return 'GitGutterLineModifiedRemoved'
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
let s:file = ''
|
|
||||||
let s:using_xolox_shell = -1
|
|
||||||
let s:exit_code = 0
|
|
||||||
|
|
||||||
function! gitgutter#utility#setbufvar(buffer, varname, val)
|
function! gitgutter#utility#setbufvar(buffer, varname, val)
|
||||||
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
let dict = get(getbufvar(a:buffer, ''), 'gitgutter', {})
|
||||||
let dict[a:varname] = a:val
|
let dict[a:varname] = a:val
|
||||||
@@ -38,188 +34,128 @@ endfunction
|
|||||||
|
|
||||||
" Returns truthy when the buffer's file should be processed; and falsey when it shouldn't.
|
" 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.
|
" This function does not and should not make any system calls.
|
||||||
function! gitgutter#utility#is_active() abort
|
function! gitgutter#utility#is_active(bufnr) abort
|
||||||
return g:gitgutter_enabled &&
|
return g:gitgutter_enabled &&
|
||||||
\ !pumvisible() &&
|
\ !pumvisible() &&
|
||||||
\ gitgutter#utility#is_file_buffer() &&
|
\ s:is_file_buffer(a:bufnr) &&
|
||||||
\ gitgutter#utility#exists_file() &&
|
\ s:exists_file(a:bufnr) &&
|
||||||
\ gitgutter#utility#not_git_dir()
|
\ s:not_git_dir(a:bufnr)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#not_git_dir() abort
|
function! s:not_git_dir(bufnr) abort
|
||||||
return gitgutter#utility#full_path_to_directory_of_file() !~ '[/\\]\.git\($\|[/\\]\)'
|
return s:dir(a:bufnr) !~ '[/\\]\.git\($\|[/\\]\)'
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#is_file_buffer() abort
|
function! s:is_file_buffer(bufnr) abort
|
||||||
return empty(getbufvar(s:bufnr, '&buftype'))
|
return empty(getbufvar(a:bufnr, '&buftype'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" A replacement for the built-in `shellescape(arg)`.
|
" From tpope/vim-fugitive
|
||||||
"
|
function! s:winshell()
|
||||||
" Recent versions of Vim handle shell escaping pretty well. However older
|
return &shell =~? 'cmd' || exists('+shellslash') && !&shellslash
|
||||||
" versions aren't as good. This attempts to do the right thing.
|
endfunction
|
||||||
"
|
|
||||||
" See:
|
" From tpope/vim-fugitive
|
||||||
" https://github.com/tpope/vim-fugitive/blob/8f0b8edfbd246c0026b7a2388e1d883d579ac7f6/plugin/fugitive.vim#L29-L37
|
|
||||||
function! gitgutter#utility#shellescape(arg) abort
|
function! gitgutter#utility#shellescape(arg) abort
|
||||||
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
||||||
return a:arg
|
return a:arg
|
||||||
elseif &shell =~# 'cmd' || gitgutter#utility#using_xolox_shell()
|
elseif s:winshell()
|
||||||
return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"'
|
return '"' . substitute(substitute(a:arg, '"', '""', 'g'), '%', '"%"', 'g') . '"'
|
||||||
else
|
else
|
||||||
return shellescape(a:arg)
|
return shellescape(a:arg)
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#set_buffer(bufnr) abort
|
function! gitgutter#utility#file(bufnr)
|
||||||
let s:bufnr = a:bufnr
|
return s:abs_path(a:bufnr, 1)
|
||||||
let s:file = resolve(bufname(a:bufnr))
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#bufnr()
|
" Not shellescaped
|
||||||
return s:bufnr
|
function! gitgutter#utility#extension(bufnr) abort
|
||||||
endfunction
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':e')
|
||||||
|
|
||||||
function! gitgutter#utility#file()
|
|
||||||
return s:file
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#filename() abort
|
|
||||||
return fnamemodify(s:file, ':t')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#extension() abort
|
|
||||||
return fnamemodify(s:file, ':e')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#full_path_to_directory_of_file() abort
|
|
||||||
return fnamemodify(s:file, ':p:h')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#directory_of_file() abort
|
|
||||||
return fnamemodify(s:file, ':h')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#exists_file() abort
|
|
||||||
return filereadable(s:file)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#has_unsaved_changes() abort
|
|
||||||
return getbufvar(s:bufnr, "&mod")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#has_fresh_changes() abort
|
|
||||||
return getbufvar(s:bufnr, 'changedtick') != gitgutter#utility#getbufvar(s:bufnr, 'last_tick')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#save_last_seen_change() abort
|
|
||||||
call gitgutter#utility#setbufvar(s:bufnr, 'last_tick', getbufvar(s:bufnr, 'changedtick'))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#shell_error() abort
|
|
||||||
return gitgutter#utility#using_xolox_shell() ? s:exit_code : v:shell_error
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#using_xolox_shell() abort
|
|
||||||
if s:using_xolox_shell == -1
|
|
||||||
if !g:gitgutter_avoid_cmd_prompt_on_windows
|
|
||||||
let s:using_xolox_shell = 0
|
|
||||||
" Although xolox/vim-shell works on both windows and unix we only want to use
|
|
||||||
" it on windows.
|
|
||||||
elseif has('win32') || has('win64') || has('win32unix')
|
|
||||||
let s:using_xolox_shell = exists('g:xolox#misc#version') && exists('g:xolox#shell#version')
|
|
||||||
else
|
|
||||||
let s:using_xolox_shell = 0
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:using_xolox_shell
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#system(cmd, ...) abort
|
function! gitgutter#utility#system(cmd, ...) abort
|
||||||
call gitgutter#debug#log(a:cmd, a:000)
|
call gitgutter#debug#log(a:cmd, a:000)
|
||||||
|
|
||||||
if gitgutter#utility#using_xolox_shell()
|
call s:use_known_shell()
|
||||||
let options = {'command': a:cmd, 'check': 0}
|
silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1)
|
||||||
if a:0 > 0
|
call s:restore_shell()
|
||||||
let options['stdin'] = a:1
|
|
||||||
endif
|
|
||||||
let ret = xolox#misc#os#exec(options)
|
|
||||||
let output = join(ret.stdout, "\n")
|
|
||||||
let s:exit_code = ret.exit_code
|
|
||||||
else
|
|
||||||
silent let output = (a:0 == 0) ? system(a:cmd) : system(a:cmd, a:1)
|
|
||||||
endif
|
|
||||||
return output
|
return output
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#file_relative_to_repo_root() abort
|
" Path of file relative to repo root.
|
||||||
let file_path_relative_to_repo_root = gitgutter#utility#getbufvar(s:bufnr, 'repo_relative_path')
|
"
|
||||||
if empty(file_path_relative_to_repo_root)
|
" * empty string - not set
|
||||||
let dir_path_relative_to_repo_root = gitgutter#utility#system(gitgutter#utility#command_in_directory_of_file(g:gitgutter_git_executable.' rev-parse --show-prefix'))
|
" * non-empty string - path
|
||||||
let dir_path_relative_to_repo_root = gitgutter#utility#strip_trailing_new_line(dir_path_relative_to_repo_root)
|
" * -1 - pending
|
||||||
let file_path_relative_to_repo_root = dir_path_relative_to_repo_root . gitgutter#utility#filename()
|
" * -2 - not tracked by git
|
||||||
call gitgutter#utility#setbufvar(s:bufnr, 'repo_relative_path', file_path_relative_to_repo_root)
|
function! gitgutter#utility#repo_path(bufnr, shellesc) abort
|
||||||
endif
|
let p = gitgutter#utility#getbufvar(a:bufnr, 'path')
|
||||||
return file_path_relative_to_repo_root
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#command_in_directory_of_file(cmd) abort
|
function! gitgutter#utility#set_repo_path(bufnr) abort
|
||||||
return 'cd '.gitgutter#utility#shellescape(gitgutter#utility#directory_of_file()).' && '.a:cmd
|
" Values of path:
|
||||||
endfunction
|
" * non-empty string - path
|
||||||
|
" * -1 - pending
|
||||||
|
" * -2 - not tracked by git
|
||||||
|
|
||||||
function! gitgutter#utility#highlight_name_for_change(text) abort
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -1)
|
||||||
if a:text ==# 'added'
|
let cmd = gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' ls-files --error-unmatch --full-name '.gitgutter#utility#shellescape(s:filename(a:bufnr)))
|
||||||
return 'GitGutterLineAdded'
|
|
||||||
elseif a:text ==# 'removed'
|
if g:gitgutter_async && gitgutter#async#available()
|
||||||
return 'GitGutterLineRemoved'
|
call gitgutter#async#execute(cmd, a:bufnr, {
|
||||||
elseif a:text ==# 'removed_first_line'
|
\ 'out': {bufnr, path -> gitgutter#utility#setbufvar(bufnr, 'path', s:strip_trailing_new_line(path))},
|
||||||
return 'GitGutterLineRemovedFirstLine'
|
\ 'err': {bufnr -> gitgutter#utility#setbufvar(bufnr, 'path', -2)},
|
||||||
elseif a:text ==# 'modified'
|
\ })
|
||||||
return 'GitGutterLineModified'
|
else
|
||||||
elseif a:text ==# 'modified_removed'
|
let path = gitgutter#utility#system(cmd)
|
||||||
return 'GitGutterLineModifiedRemoved'
|
if v:shell_error
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', -2)
|
||||||
|
else
|
||||||
|
call gitgutter#utility#setbufvar(a:bufnr, 'path', s:strip_trailing_new_line(path))
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Dedups list in-place.
|
function! gitgutter#utility#cd_cmd(bufnr, cmd) abort
|
||||||
" Assumes list has no empty entries.
|
return 'cd '.s:dir(a:bufnr).' && '.a:cmd
|
||||||
function! gitgutter#utility#dedup(list)
|
|
||||||
return filter(sort(a:list), 'index(a:list, v:val, v:key + 1) == -1')
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! gitgutter#utility#strip_trailing_new_line(line) abort
|
function! s:use_known_shell() abort
|
||||||
|
if has('unix') && &shell !=# 'sh'
|
||||||
|
let [s:shell, s:shellcmdflag, s:shellredir] = [&shell, &shellcmdflag, &shellredir]
|
||||||
|
let &shell = 'sh'
|
||||||
|
set shellcmdflag=-c shellredir=>%s\ 2>&1
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:restore_shell() abort
|
||||||
|
if has('unix') && exists('s:shell')
|
||||||
|
let [&shell, &shellcmdflag, &shellredir] = [s:shell, s:shellcmdflag, s:shellredir]
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:abs_path(bufnr, shellesc)
|
||||||
|
let p = resolve(expand('#'.a:bufnr.':p'))
|
||||||
|
return a:shellesc ? gitgutter#utility#shellescape(p) : p
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:dir(bufnr) abort
|
||||||
|
return gitgutter#utility#shellescape(fnamemodify(s:abs_path(a:bufnr, 0), ':h'))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
" Not shellescaped.
|
||||||
|
function! s:filename(bufnr) abort
|
||||||
|
return fnamemodify(s:abs_path(a:bufnr, 0), ':t')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:exists_file(bufnr) abort
|
||||||
|
return filereadable(s:abs_path(a:bufnr, 0))
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! s:strip_trailing_new_line(line) abort
|
||||||
return substitute(a:line, '\n$', '', '')
|
return substitute(a:line, '\n$', '', '')
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" True for git v1.7.2+.
|
|
||||||
function! gitgutter#utility#git_supports_command_line_config_override() abort
|
|
||||||
call system(g:gitgutter_git_executable.' -c foo.bar=baz --version')
|
|
||||||
return !v:shell_error
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#stringify(list) abort
|
|
||||||
return join(a:list, "\n")."\n"
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#use_known_shell() abort
|
|
||||||
if has('unix')
|
|
||||||
if &shell !=# 'sh'
|
|
||||||
let s:shell = &shell
|
|
||||||
let s:shellcmdflag = &shellcmdflag
|
|
||||||
let s:shellredir = &shellredir
|
|
||||||
let &shell = 'sh'
|
|
||||||
set shellcmdflag=-c
|
|
||||||
set shellredir=>%s\ 2>&1
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! gitgutter#utility#restore_shell() abort
|
|
||||||
if has('unix')
|
|
||||||
if exists('s:shell')
|
|
||||||
let &shell = s:shell
|
|
||||||
let &shellcmdflag = s:shellcmdflag
|
|
||||||
let &shellredir = s:shellredir
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ CONTENTS *GitGutterContents*
|
|||||||
1. INTRODUCTION *GitGutterIntroduction*
|
1. INTRODUCTION *GitGutterIntroduction*
|
||||||
*GitGutter*
|
*GitGutter*
|
||||||
|
|
||||||
Vim Git Gutter is a Vim plugin which shows a git diff in the 'gutter' (sign
|
GitGutter is a Vim plugin which shows a git diff in the 'gutter' (sign
|
||||||
column). It shows whether each line has been added, modified, and where lines
|
column). It shows whether each line has been added, modified, and where lines
|
||||||
have been removed.
|
have been removed.
|
||||||
|
|
||||||
This is a port of the Git Gutter plugin for Sublime Text 2.
|
This is a port of the GitGutter plugin for Sublime Text 2.
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
2. INSTALLATION *GitGutterInstallation*
|
2. INSTALLATION *GitGutterInstallation*
|
||||||
@@ -301,20 +301,6 @@ Add to your |vimrc|
|
|||||||
let g:gitgutter_highlight_lines = 1
|
let g:gitgutter_highlight_lines = 1
|
||||||
<
|
<
|
||||||
|
|
||||||
TO STOP VIM-GITGUTTER RUNNING IN REALTIME
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_realtime = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
TO STOP VIM-GITGUTTER RUNNING EAGERLY
|
|
||||||
|
|
||||||
Add to your |vimrc|
|
|
||||||
>
|
|
||||||
let g:gitgutter_eager = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
TO TURN OFF ASYNCHRONOUS UPDATES
|
TO TURN OFF ASYNCHRONOUS UPDATES
|
||||||
|
|
||||||
By default diffs are run asynchronously. To run diffs synchronously
|
By default diffs are run asynchronously. To run diffs synchronously
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ call s:set('g:gitgutter_signs', 1)
|
|||||||
call s:set('g:gitgutter_highlight_lines', 0)
|
call s:set('g:gitgutter_highlight_lines', 0)
|
||||||
call s:set('g:gitgutter_sign_column_always', 0)
|
call s:set('g:gitgutter_sign_column_always', 0)
|
||||||
if g:gitgutter_sign_column_always && exists('&signcolumn')
|
if g:gitgutter_sign_column_always && exists('&signcolumn')
|
||||||
|
" Vim 7.4.2201.
|
||||||
set signcolumn=yes
|
set signcolumn=yes
|
||||||
let g:gitgutter_sign_column_always = 0
|
let g:gitgutter_sign_column_always = 0
|
||||||
call gitgutter#utility#warn('please replace "let g:gitgutter_sign_column_always=1" with "set signcolumn=yes"')
|
call gitgutter#utility#warn('please replace "let g:gitgutter_sign_column_always=1" with "set signcolumn=yes"')
|
||||||
endif
|
endif
|
||||||
call s:set('g:gitgutter_override_sign_column_highlight', 1)
|
call s:set('g:gitgutter_override_sign_column_highlight', 1)
|
||||||
call s:set('g:gitgutter_realtime', 1)
|
|
||||||
call s:set('g:gitgutter_eager', 1)
|
|
||||||
call s:set('g:gitgutter_sign_added', '+')
|
call s:set('g:gitgutter_sign_added', '+')
|
||||||
call s:set('g:gitgutter_sign_modified', '~')
|
call s:set('g:gitgutter_sign_modified', '~')
|
||||||
call s:set('g:gitgutter_sign_removed', '_')
|
call s:set('g:gitgutter_sign_removed', '_')
|
||||||
@@ -53,15 +52,26 @@ call s:set('g:gitgutter_sign_modified_removed', '~_')
|
|||||||
call s:set('g:gitgutter_diff_args', '')
|
call s:set('g:gitgutter_diff_args', '')
|
||||||
call s:set('g:gitgutter_diff_base', '')
|
call s:set('g:gitgutter_diff_base', '')
|
||||||
call s:set('g:gitgutter_map_keys', 1)
|
call s:set('g:gitgutter_map_keys', 1)
|
||||||
call s:set('g:gitgutter_avoid_cmd_prompt_on_windows', 1)
|
|
||||||
call s:set('g:gitgutter_async', 1)
|
call s:set('g:gitgutter_async', 1)
|
||||||
call s:set('g:gitgutter_log', 0)
|
call s:set('g:gitgutter_log', 0)
|
||||||
call s:set('g:gitgutter_git_executable', 'git')
|
|
||||||
|
|
||||||
|
call s:set('g:gitgutter_git_executable', 'git')
|
||||||
if !executable(g:gitgutter_git_executable)
|
if !executable(g:gitgutter_git_executable)
|
||||||
call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
|
call gitgutter#utility#warn('cannot find git. Please set g:gitgutter_git_executable.')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
call s:set('g:gitgutter_grep', 'grep')
|
||||||
|
if !empty(g:gitgutter_grep)
|
||||||
|
if !executable(g:gitgutter_grep)
|
||||||
|
call gitgutter#utility#warn('cannot find '.g:gitgutter_grep.'. Please set g:gitgutter_grep.')
|
||||||
|
let g:gitgutter_grep = ''
|
||||||
|
else
|
||||||
|
if $GREP_OPTIONS =~# '--color=always'
|
||||||
|
let g:gitgutter_grep .= ' --color=never'
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
call gitgutter#highlight#define_sign_column_highlight()
|
call gitgutter#highlight#define_sign_column_highlight()
|
||||||
call gitgutter#highlight#define_highlights()
|
call gitgutter#highlight#define_highlights()
|
||||||
call gitgutter#highlight#define_signs()
|
call gitgutter#highlight#define_signs()
|
||||||
@@ -70,8 +80,8 @@ call gitgutter#highlight#define_signs()
|
|||||||
|
|
||||||
" Primary functions {{{
|
" Primary functions {{{
|
||||||
|
|
||||||
command -bar GitGutterAll call gitgutter#all()
|
command -bar GitGutterAll call gitgutter#all(1)
|
||||||
command -bar GitGutter call gitgutter#process_buffer(bufnr(''), 0)
|
command -bar GitGutter call gitgutter#process_buffer(bufnr(''), 1)
|
||||||
|
|
||||||
command -bar GitGutterDisable call gitgutter#disable()
|
command -bar GitGutterDisable call gitgutter#disable()
|
||||||
command -bar GitGutterEnable call gitgutter#enable()
|
command -bar GitGutterEnable call gitgutter#enable()
|
||||||
@@ -81,17 +91,17 @@ command -bar GitGutterToggle call gitgutter#toggle()
|
|||||||
|
|
||||||
" Line highlights {{{
|
" Line highlights {{{
|
||||||
|
|
||||||
command -bar GitGutterLineHighlightsDisable call gitgutter#line_highlights_disable()
|
command -bar GitGutterLineHighlightsDisable call gitgutter#highlight#line_disable()
|
||||||
command -bar GitGutterLineHighlightsEnable call gitgutter#line_highlights_enable()
|
command -bar GitGutterLineHighlightsEnable call gitgutter#highlight#line_enable()
|
||||||
command -bar GitGutterLineHighlightsToggle call gitgutter#line_highlights_toggle()
|
command -bar GitGutterLineHighlightsToggle call gitgutter#highlight#line_toggle()
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
" Signs {{{
|
" Signs {{{
|
||||||
|
|
||||||
command -bar GitGutterSignsEnable call gitgutter#signs_enable()
|
command -bar GitGutterSignsEnable call gitgutter#sign#enable()
|
||||||
command -bar GitGutterSignsDisable call gitgutter#signs_disable()
|
command -bar GitGutterSignsDisable call gitgutter#sign#disable()
|
||||||
command -bar GitGutterSignsToggle call gitgutter#signs_toggle()
|
command -bar GitGutterSignsToggle call gitgutter#sign#toggle()
|
||||||
|
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
@@ -100,10 +110,10 @@ command -bar GitGutterSignsToggle call gitgutter#signs_toggle()
|
|||||||
command -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk(<count>)
|
command -bar -count=1 GitGutterNextHunk call gitgutter#hunk#next_hunk(<count>)
|
||||||
command -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk(<count>)
|
command -bar -count=1 GitGutterPrevHunk call gitgutter#hunk#prev_hunk(<count>)
|
||||||
|
|
||||||
command -bar GitGutterStageHunk call gitgutter#stage_hunk()
|
command -bar GitGutterStageHunk call gitgutter#hunk#stage()
|
||||||
command -bar GitGutterUndoHunk call gitgutter#undo_hunk()
|
command -bar GitGutterUndoHunk call gitgutter#hunk#undo()
|
||||||
command -bar GitGutterRevertHunk echomsg 'GitGutterRevertHunk is deprecated. Use GitGutterUndoHunk'<Bar>call gitgutter#undo_hunk()
|
command -bar GitGutterRevertHunk echomsg 'GitGutterRevertHunk is deprecated. Use GitGutterUndoHunk'<Bar>call gitgutter#hunk#undo()
|
||||||
command -bar GitGutterPreviewHunk call gitgutter#preview_hunk()
|
command -bar GitGutterPreviewHunk call gitgutter#hunk#preview()
|
||||||
|
|
||||||
" Hunk text object
|
" Hunk text object
|
||||||
onoremap <silent> <Plug>GitGutterTextObjectInnerPending :<C-U>call gitgutter#hunk#text_object(1)<CR>
|
onoremap <silent> <Plug>GitGutterTextObjectInnerPending :<C-U>call gitgutter#hunk#text_object(1)<CR>
|
||||||
@@ -130,7 +140,8 @@ xnoremap <silent> <Plug>GitGutterTextObjectOuterVisual :<C-U>call gitgutter#hun
|
|||||||
" `line` - refers to the line number where the change starts
|
" `line` - refers to the line number where the change starts
|
||||||
" `count` - refers to the number of lines the change covers
|
" `count` - refers to the number of lines the change covers
|
||||||
function! GitGutterGetHunks()
|
function! GitGutterGetHunks()
|
||||||
return gitgutter#utility#is_active() ? gitgutter#hunk#hunks() : []
|
let bufnr = bufnr('')
|
||||||
|
return gitgutter#utility#is_active(bufnr) ? gitgutter#hunk#hunks(bufnr) : []
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Returns an array that contains a summary of the hunk status for the current
|
" Returns an array that contains a summary of the hunk status for the current
|
||||||
@@ -196,34 +207,27 @@ endif
|
|||||||
augroup gitgutter
|
augroup gitgutter
|
||||||
autocmd!
|
autocmd!
|
||||||
|
|
||||||
if g:gitgutter_realtime
|
autocmd TabEnter * call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1)
|
||||||
autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 1)
|
|
||||||
endif
|
|
||||||
|
|
||||||
if g:gitgutter_eager
|
autocmd BufEnter *
|
||||||
autocmd BufWritePost,FileChangedShellPost,ShellCmdPost * call gitgutter#process_buffer(bufnr(''), 0)
|
\ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') |
|
||||||
|
\ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) |
|
||||||
|
\ call gitgutter#all(0) |
|
||||||
|
\ else |
|
||||||
|
\ call gitgutter#init_buffer(bufnr('')) |
|
||||||
|
\ call gitgutter#process_buffer(bufnr(''), 0) |
|
||||||
|
\ endif
|
||||||
|
|
||||||
autocmd BufEnter *
|
autocmd CursorHold,CursorHoldI * call gitgutter#process_buffer(bufnr(''), 0)
|
||||||
\ if gettabvar(tabpagenr(), 'gitgutter_didtabenter') |
|
autocmd FileChangedShellPost,ShellCmdPost * call gitgutter#process_buffer(bufnr(''), 1)
|
||||||
\ call settabvar(tabpagenr(), 'gitgutter_didtabenter', 0) |
|
|
||||||
\ call gitgutter#all() |
|
|
||||||
\ else |
|
|
||||||
\ call gitgutter#process_buffer(bufnr(''), 0) |
|
|
||||||
\ endif
|
|
||||||
|
|
||||||
autocmd TabEnter * call settabvar(tabpagenr(), 'gitgutter_didtabenter', 1)
|
" Ensure that all buffers are processed when opening vim with multiple files, e.g.:
|
||||||
|
"
|
||||||
|
" vim -o file1 file2
|
||||||
|
autocmd VimEnter * if winnr() != winnr('$') | call gitgutter#all(0) | endif
|
||||||
|
|
||||||
" Ensure that all buffers are processed when opening vim with multiple files, e.g.:
|
if !has('gui_win32')
|
||||||
"
|
autocmd FocusGained * call gitgutter#all(1)
|
||||||
" vim -o file1 file2
|
|
||||||
autocmd VimEnter * if winnr() != winnr('$') | :GitGutterAll | endif
|
|
||||||
|
|
||||||
if !has('gui_win32')
|
|
||||||
autocmd FocusGained * call gitgutter#all()
|
|
||||||
endif
|
|
||||||
|
|
||||||
else
|
|
||||||
autocmd BufRead,BufWritePost,FileChangedShellPost * call gitgutter#process_buffer(bufnr(''), 0)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
|
autocmd ColorScheme * call gitgutter#highlight#define_sign_column_highlight() | call gitgutter#highlight#define_highlights()
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ endfunction
|
|||||||
|
|
||||||
function Test_add_lines()
|
function Test_add_lines()
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -76,7 +76,7 @@ function Test_add_lines_fish()
|
|||||||
set shell=/usr/local/bin/fish
|
set shell=/usr/local/bin/fish
|
||||||
|
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=2 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -87,7 +87,7 @@ endfunction
|
|||||||
|
|
||||||
function Test_modify_lines()
|
function Test_modify_lines()
|
||||||
normal ggi*
|
normal ggi*
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineModified"]
|
let expected = ["line=1 id=3000 name=GitGutterLineModified"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -96,7 +96,7 @@ endfunction
|
|||||||
|
|
||||||
function Test_remove_lines()
|
function Test_remove_lines()
|
||||||
execute '5d'
|
execute '5d'
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=4 id=3000 name=GitGutterLineRemoved"]
|
let expected = ["line=4 id=3000 name=GitGutterLineRemoved"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -105,7 +105,7 @@ endfunction
|
|||||||
|
|
||||||
function Test_remove_first_lines()
|
function Test_remove_first_lines()
|
||||||
execute '1d'
|
execute '1d'
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"]
|
let expected = ["line=1 id=3000 name=GitGutterLineRemovedFirstLine"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -115,7 +115,7 @@ endfunction
|
|||||||
function Test_edit_file_with_same_name_as_a_branch()
|
function Test_edit_file_with_same_name_as_a_branch()
|
||||||
normal 5Gi*
|
normal 5Gi*
|
||||||
call system('git checkout -b fixture.txt')
|
call system('git checkout -b fixture.txt')
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=5 id=3000 name=GitGutterLineModified"]
|
let expected = ["line=5 id=3000 name=GitGutterLineModified"]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
@@ -127,7 +127,7 @@ function Test_file_added_to_git()
|
|||||||
call system('touch '.tmpfile.' && git add '.tmpfile)
|
call system('touch '.tmpfile.' && git add '.tmpfile)
|
||||||
execute 'edit '.tmpfile
|
execute 'edit '.tmpfile
|
||||||
normal ihello
|
normal ihello
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ["line=1 id=3000 name=GitGutterLineAdded"]
|
let expected = ["line=1 id=3000 name=GitGutterLineAdded"]
|
||||||
call assert_equal(expected, s:signs('fileAddedToGit.tmp'))
|
call assert_equal(expected, s:signs('fileAddedToGit.tmp'))
|
||||||
@@ -138,7 +138,7 @@ function Test_filename_with_equals()
|
|||||||
call system('touch =fixture=.txt && git add =fixture=.txt')
|
call system('touch =fixture=.txt && git add =fixture=.txt')
|
||||||
edit =fixture=.txt
|
edit =fixture=.txt
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
||||||
@@ -152,7 +152,7 @@ function Test_filename_with_square_brackets()
|
|||||||
call system('touch fix[tu]re.txt && git add fix[tu]re.txt')
|
call system('touch fix[tu]re.txt && git add fix[tu]re.txt')
|
||||||
edit fix[tu]re.txt
|
edit fix[tu]re.txt
|
||||||
normal ggo*
|
normal ggo*
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
\ 'line=1 id=3000 name=GitGutterLineAdded',
|
||||||
@@ -168,7 +168,7 @@ function Test_follow_symlink()
|
|||||||
call system('ln -nfs fixture.txt '.tmp)
|
call system('ln -nfs fixture.txt '.tmp)
|
||||||
execute 'edit '.tmp
|
execute 'edit '.tmp
|
||||||
6d
|
6d
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ['line=5 id=3000 name=GitGutterLineRemoved']
|
let expected = ['line=5 id=3000 name=GitGutterLineRemoved']
|
||||||
call assert_equal(expected, s:signs('symlink'))
|
call assert_equal(expected, s:signs('symlink'))
|
||||||
@@ -218,26 +218,15 @@ endfunction
|
|||||||
|
|
||||||
function Test_orphaned_signs()
|
function Test_orphaned_signs()
|
||||||
execute "normal 5GoX\<CR>Y"
|
execute "normal 5GoX\<CR>Y"
|
||||||
write
|
doautocmd CursorHold
|
||||||
6d
|
6d
|
||||||
write
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = ['line=6 id=3001 name=GitGutterLineAdded']
|
let expected = ['line=6 id=3001 name=GitGutterLineAdded']
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
function Test_sign_column_always()
|
|
||||||
let g:gitgutter_sign_column_always=1
|
|
||||||
write
|
|
||||||
|
|
||||||
let expected = ['line=9999 id=2999 name=GitGutterDummy']
|
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
|
||||||
|
|
||||||
let g:gitgutter_sign_column_always=0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
function Test_untracked_file_outside_repo()
|
function Test_untracked_file_outside_repo()
|
||||||
let tmp = tempname()
|
let tmp = tempname()
|
||||||
call system('touch '.tmp)
|
call system('touch '.tmp)
|
||||||
@@ -301,8 +290,19 @@ function Test_hunk_stage()
|
|||||||
|
|
||||||
call assert_equal([], s:signs('fixture.txt'))
|
call assert_equal([], s:signs('fixture.txt'))
|
||||||
|
|
||||||
call assert_equal([], s:git_diff())
|
" Buffer is unsaved
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index ae8e546..f5c6aff 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -5 +5 @@ d',
|
||||||
|
\ '-*e',
|
||||||
|
\ '+e'
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
|
" Index has been updated
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index f5c6aff..ae8e546 100644',
|
\ 'index f5c6aff..ae8e546 100644',
|
||||||
@@ -313,6 +313,11 @@ function Test_hunk_stage()
|
|||||||
\ '+*e'
|
\ '+*e'
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff_staged())
|
call assert_equal(expected, s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff())
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@@ -329,6 +334,31 @@ function Test_hunk_stage_nearby_hunk()
|
|||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
|
||||||
|
" Buffer is unsaved
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index 53b13df..f5c6aff 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -3,0 +4 @@ c',
|
||||||
|
\ '+d',
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
|
" Index has been updated
|
||||||
|
let expected = [
|
||||||
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
|
\ 'index f5c6aff..53b13df 100644',
|
||||||
|
\ '--- a/fixture.txt',
|
||||||
|
\ '+++ b/fixture.txt',
|
||||||
|
\ '@@ -4 +3,0 @@ c',
|
||||||
|
\ '-d',
|
||||||
|
\ ]
|
||||||
|
call assert_equal(expected, s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index 53b13df..8fdfda7 100644',
|
\ 'index 53b13df..8fdfda7 100644',
|
||||||
@@ -340,16 +370,6 @@ function Test_hunk_stage_nearby_hunk()
|
|||||||
\ '+z',
|
\ '+z',
|
||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff())
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
let expected = [
|
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
|
||||||
\ 'index f5c6aff..53b13df 100644',
|
|
||||||
\ '--- a/fixture.txt',
|
|
||||||
\ '+++ b/fixture.txt',
|
|
||||||
\ '@@ -4 +3,0 @@ c',
|
|
||||||
\ '-d',
|
|
||||||
\ ]
|
|
||||||
call assert_equal(expected, s:git_diff_staged())
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
|
||||||
@@ -359,7 +379,6 @@ function Test_hunk_undo()
|
|||||||
|
|
||||||
normal 5Gi*
|
normal 5Gi*
|
||||||
GitGutterUndoHunk
|
GitGutterUndoHunk
|
||||||
write " write file so we can verify git diff (--staged)
|
|
||||||
|
|
||||||
call assert_equal('foo', &shell)
|
call assert_equal('foo', &shell)
|
||||||
let &shell = _shell
|
let &shell = _shell
|
||||||
@@ -374,8 +393,9 @@ function Test_undo_nearby_hunk()
|
|||||||
execute "normal! 2Gox\<CR>y\<CR>z"
|
execute "normal! 2Gox\<CR>y\<CR>z"
|
||||||
normal 2jdd
|
normal 2jdd
|
||||||
normal k
|
normal k
|
||||||
|
doautocmd CursorHold
|
||||||
GitGutterUndoHunk
|
GitGutterUndoHunk
|
||||||
write " write file so we can verify git diff (--staged)
|
doautocmd CursorHold
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'line=3 id=3000 name=GitGutterLineAdded',
|
\ 'line=3 id=3000 name=GitGutterLineAdded',
|
||||||
@@ -384,6 +404,13 @@ function Test_undo_nearby_hunk()
|
|||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:signs('fixture.txt'))
|
call assert_equal(expected, s:signs('fixture.txt'))
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff())
|
||||||
|
|
||||||
|
call assert_equal([], s:git_diff_staged())
|
||||||
|
|
||||||
|
" Save the buffer
|
||||||
|
write
|
||||||
|
|
||||||
let expected = [
|
let expected = [
|
||||||
\ 'diff --git a/fixture.txt b/fixture.txt',
|
\ 'diff --git a/fixture.txt b/fixture.txt',
|
||||||
\ 'index f5c6aff..3fbde56 100644',
|
\ 'index f5c6aff..3fbde56 100644',
|
||||||
@@ -396,5 +423,4 @@ function Test_undo_nearby_hunk()
|
|||||||
\ ]
|
\ ]
|
||||||
call assert_equal(expected, s:git_diff())
|
call assert_equal(expected, s:git_diff())
|
||||||
|
|
||||||
call assert_equal([], s:git_diff_staged())
|
|
||||||
endfunction
|
endfunction
|
||||||
|
|||||||
Reference in New Issue
Block a user