3 changed files with 231 additions and 0 deletions
@ -0,0 +1,83 @@ |
|||||||
|
Show git diff for Git Rebase Interactive |
||||||
|
======================================= |
||||||
|
|
||||||
|
`auto-git-diff` is a vim plugin which shows git diff between each commit and |
||||||
|
its parent commit below the commit list window of git rebase interactive. |
||||||
|
|
||||||
|
When you move a text-cursor in `git-rebase-todo` file, `auto-git-diff` gets |
||||||
|
a commit hash of the line where the cursor exists and update the diff window. |
||||||
|
|
||||||
|
|
||||||
|
 |
||||||
|
|
||||||
|
## Variables |
||||||
|
|
||||||
|
- `g:auto_git_diff_disable_auto_update` |
||||||
|
|
||||||
|
If this variable is set to 1, the diff window won't update automatically. You |
||||||
|
can update the diff window manually with the following key mapping: |
||||||
|
`<Plug>(auto_git_diff_manual_update)`. |
||||||
|
|
||||||
|
- `g:auto_git_diff_show_window_at_right` |
||||||
|
|
||||||
|
If this variable is set to 1, the diff window will be created at right on the |
||||||
|
commit list window. |
||||||
|
|
||||||
|
- `g:auto_git_diff_command_options` |
||||||
|
|
||||||
|
The options passed to `git diff` command. If this variable is not defined, |
||||||
|
`--stat -p --submodule -C -C` will be used. |
||||||
|
|
||||||
|
## Mappings |
||||||
|
|
||||||
|
- `<Plug>(auto_git_diff_manual_update)` |
||||||
|
|
||||||
|
This key mapping updates the diff window manully. |
||||||
|
|
||||||
|
- `<Plug>(auto_git_diff_scroll_down_1)` |
||||||
|
- `<Plug>(auto_git_diff_scroll_up_1)` |
||||||
|
- `<Plug>(auto_git_diff_scroll_down_half)` |
||||||
|
- `<Plug>(auto_git_diff_scroll_up_half)` |
||||||
|
- `<Plug>(auto_git_diff_scroll_down_page)` |
||||||
|
- `<Plug>(auto_git_diff_scroll_up_page)` |
||||||
|
|
||||||
|
These key mappings scroll the diff window without moving the cursor into the |
||||||
|
window. `_1` means scrolling one line (`<C-e>` or `<C-y>`), `_half` means |
||||||
|
scrolling half a page (`<C-d>` or `<C-u>`) and `_page` means scrolling one page |
||||||
|
(`<C-f>` or `<C-b>`). |
||||||
|
|
||||||
|
Following is an example to configure the mappings in your `vimrc`. |
||||||
|
|
||||||
|
```vim |
||||||
|
function! s:setup_auto_git_diff() abort |
||||||
|
nmap <buffer><C-l> <Plug>(auto_git_diff_scroll_manual_update) |
||||||
|
nmap <buffer><C-n> <Plug>(auto_git_diff_scroll_down_half) |
||||||
|
nmap <buffer><C-p> <Plug>(auto_git_diff_scroll_up_half) |
||||||
|
endfunction |
||||||
|
autocmd FileType gitrebase call <SID>setup_auto_git_diff() |
||||||
|
``` |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
The MIT License (MIT) |
||||||
|
Copyright (c) 2015 hotwatermorning |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining |
||||||
|
a copy of this software and associated documentation files (the |
||||||
|
"Software"), to deal in the Software without restriction, including |
||||||
|
without limitation the rights to use, copy, modify, merge, publish, |
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to |
||||||
|
permit persons to whom the Software is furnished to do so, subject to |
||||||
|
the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be |
||||||
|
included in all copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||||
|
|
@ -0,0 +1,132 @@ |
|||||||
|
let s:save_cpo = &cpo |
||||||
|
let s:previous_hash_string = "" |
||||||
|
set cpo&vim |
||||||
|
|
||||||
|
nnoremap <silent> <Plug>(auto_git_diff_manual_update) :<C-u>call auto_git_diff#show_git_diff()<CR> |
||||||
|
|
||||||
|
" Get commit hash from current line. |
||||||
|
" The first colomn(pick, r, ...) can be empty. |
||||||
|
function! s:get_git_hash() abort |
||||||
|
return matchstr(getline('.'), '^\(\w\+\>\)\=\(\s*\)\zs\x\{4,40\}\>\ze') |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Find the preview window. |
||||||
|
" If not found, return zero. |
||||||
|
function! s:find_preview_window() abort |
||||||
|
for nr in range(1, winnr('$')) |
||||||
|
if getwinvar(nr, "&pvw") == 1 |
||||||
|
" found a preview |
||||||
|
return nr |
||||||
|
endif |
||||||
|
endfor |
||||||
|
return 0 |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Execute git diff between hash~1 and hash with options a:opts, |
||||||
|
" and show the result into the preview window. |
||||||
|
function! s:show_git_diff_impl(hash, vertsplit, opts) abort |
||||||
|
|
||||||
|
let wn = s:find_preview_window() |
||||||
|
|
||||||
|
if wn == 0 |
||||||
|
" The preview window is not found. |
||||||
|
" => Open new window |
||||||
|
|
||||||
|
if a:vertsplit |
||||||
|
rightbelow vnew |
||||||
|
else |
||||||
|
rightbelow new |
||||||
|
endif |
||||||
|
|
||||||
|
silent! setlocal previewwindow bufhidden=delete nobackup noswf nobuflisted nowrap buftype=nofile |
||||||
|
|
||||||
|
let wn = bufwinnr('%') |
||||||
|
else |
||||||
|
" Preview window is found" |
||||||
|
" Move to the window |
||||||
|
silent execute wn."wincmd w" |
||||||
|
endif |
||||||
|
|
||||||
|
let out = s:get_git_diff(a:hash, a:opts) |
||||||
|
|
||||||
|
if v:shell_error |
||||||
|
setlocal ft= |
||||||
|
else |
||||||
|
setlocal ft=diff |
||||||
|
endif |
||||||
|
|
||||||
|
setlocal modifiable |
||||||
|
|
||||||
|
silent! % delete _ |
||||||
|
silent! $ put=out |
||||||
|
silent! 1 delete _ |
||||||
|
|
||||||
|
setlocal nomodifiable |
||||||
|
|
||||||
|
noremap <buffer> q :bw<cr> |
||||||
|
|
||||||
|
silent wincmd p |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_git_diff(hash, opts) abort |
||||||
|
let prefix = has("win32") ? "set LANG=C & " : "env LANG=C " |
||||||
|
|
||||||
|
let diff_command = "git diff ".a:opts." ".a:hash."~1 ".a:hash |
||||||
|
silent let out = system(prefix.diff_command) |
||||||
|
if !v:shell_error |
||||||
|
return out |
||||||
|
endif |
||||||
|
let save_out = out |
||||||
|
|
||||||
|
let empty_tree_sha1_hex = "4b825dc642cb6eb9a060e54bf8d69288fbee4904" |
||||||
|
let diff_command = "git diff ".a:opts." ".empty_tree_sha1_hex." ".a:hash |
||||||
|
silent let out = system(prefix.diff_command) |
||||||
|
if !v:shell_error |
||||||
|
return out |
||||||
|
endif |
||||||
|
|
||||||
|
return save_out |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! auto_git_diff#show_git_diff() abort |
||||||
|
|
||||||
|
let hash_string = s:get_git_hash() |
||||||
|
if hash_string == "" || hash_string == s:previous_hash_string |
||||||
|
return |
||||||
|
else |
||||||
|
let s:previous_hash_string = hash_string |
||||||
|
endif |
||||||
|
|
||||||
|
call s:show_git_diff_impl( s:get_git_hash() |
||||||
|
\ , get(g:, "auto_git_diff_show_window_at_right", 0) |
||||||
|
\ , get(g:, "auto_git_diff_command_options", "--stat -p --submodule -C -C") |
||||||
|
\ ) |
||||||
|
endfunction |
||||||
|
|
||||||
|
" Called when text-cursor is moved. |
||||||
|
function! auto_git_diff#auto_update_git_diff() abort |
||||||
|
|
||||||
|
if get(g:, "auto_git_diff_disable_auto_update", 0) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
if mode() != "n" |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
call auto_git_diff#show_git_diff() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! auto_git_diff#scroll_in_preview_window(map) abort |
||||||
|
if s:find_preview_window() == 0 |
||||||
|
return |
||||||
|
endif |
||||||
|
wincmd P |
||||||
|
sandbox let input = eval('"\<'.a:map.'>"') |
||||||
|
execute "normal!" input |
||||||
|
wincmd p |
||||||
|
endfunction |
||||||
|
|
||||||
|
let &cpo = s:save_cpo |
||||||
|
unlet s:save_cpo |
||||||
|
|
@ -0,0 +1,16 @@ |
|||||||
|
if exists("g:did_auto_git_diff") | finish | endif |
||||||
|
let g:did_auto_git_diff = 1 |
||||||
|
|
||||||
|
augroup auto_git_diff_command_group |
||||||
|
autocmd! |
||||||
|
autocmd CursorMoved git-rebase-todo call auto_git_diff#auto_update_git_diff() |
||||||
|
autocmd FileType gitrebase setlocal nowarn nowb |
||||||
|
augroup END |
||||||
|
|
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_down_1) :<C-u>call auto_git_diff#scroll_in_preview_window("C-e")<CR> |
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_up_1) :<C-u>call auto_git_diff#scroll_in_preview_window("C-y")<CR> |
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_down_half) :<C-u>call auto_git_diff#scroll_in_preview_window("C-d")<CR> |
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_up_half) :<C-u>call auto_git_diff#scroll_in_preview_window("C-u")<CR> |
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_down_page) :<C-u>call auto_git_diff#scroll_in_preview_window("C-f")<CR> |
||||||
|
nnoremap <silent><Plug>(auto_git_diff_scroll_up_page) :<C-u>call auto_git_diff#scroll_in_preview_window("C-b")<CR> |
||||||
|
|
Loading…
Reference in new issue