5 changed files with 560 additions and 0 deletions
@ -0,0 +1,19 @@ |
|||||||
|
Copyright (c) 2014 rhysd |
||||||
|
|
||||||
|
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,121 @@ |
|||||||
|
More Pleasant Editing on Commit Message |
||||||
|
======================================= |
||||||
|
|
||||||
|
When you type `git commit`, Vim starts and opens a commit buffer. This plugin improves |
||||||
|
the commit buffer. |
||||||
|
|
||||||
|
committia.vim splits the buffer into 3 windows; edit window, status window and diff window. |
||||||
|
You no longer need to repeat moving to another window, scrolling and backing to the former |
||||||
|
position in order to see a long commit diff. |
||||||
|
|
||||||
|
If the width of Vim window is too narrow (160 characters by default), committia.vim falls back |
||||||
|
to single column mode, which has 2 windows; edit window and diff window. |
||||||
|
|
||||||
|
For wide window: |
||||||
|
|
||||||
|
 |
||||||
|
|
||||||
|
For narrow window: |
||||||
|
|
||||||
|
 |
||||||
|
|
||||||
|
## Hooks |
||||||
|
|
||||||
|
You can hook on opening the windows. |
||||||
|
|
||||||
|
Available hooks are: |
||||||
|
|
||||||
|
- `edit_open`: When opening a commit message window, this hook is called from the window. |
||||||
|
- `diff_open`: When opening a diff window, this hook is called from the window. |
||||||
|
- `status_open`: When opening a status window, this hook is called from the window. |
||||||
|
Please note that this hook is not called on single-column mode since it does not have a dedicated |
||||||
|
window for status. |
||||||
|
|
||||||
|
A vimrc example is below. |
||||||
|
|
||||||
|
```vim |
||||||
|
" You can get the information about the windows with first argument as a dictionary. |
||||||
|
" |
||||||
|
" KEY VALUE AVAILABILITY |
||||||
|
"----------------------------------------------------------------------------------- |
||||||
|
" vcs : vcs type (e.g. 'git') -> all hooks |
||||||
|
" edit_winnr : winnr of edit window -> ditto |
||||||
|
" edit_bufnr : bufnr of edit window -> ditto |
||||||
|
" diff_winnr : winnr of diff window -> ditto |
||||||
|
" diff_bufnr : bufnr of diff window -> ditto |
||||||
|
" status_winnr : winnr of status window -> all hooks except for 'diff_open' hook |
||||||
|
" status_bufnr : bufnr of status window -> ditto |
||||||
|
|
||||||
|
let g:committia_hooks = {} |
||||||
|
function! g:committia_hooks.edit_open(info) |
||||||
|
" Additional settings |
||||||
|
setlocal spell |
||||||
|
|
||||||
|
" If no commit message, start with insert mode |
||||||
|
if a:info.vcs ==# 'git' && getline(1) ==# '' |
||||||
|
startinsert |
||||||
|
endif |
||||||
|
|
||||||
|
" Scroll the diff window from insert mode |
||||||
|
" Map <C-n> and <C-p> |
||||||
|
imap <buffer><C-n> <Plug>(committia-scroll-diff-down-half) |
||||||
|
imap <buffer><C-p> <Plug>(committia-scroll-diff-up-half) |
||||||
|
endfunction |
||||||
|
``` |
||||||
|
|
||||||
|
## Mappings |
||||||
|
|
||||||
|
Mappings to scroll diff window for insert mode are available. |
||||||
|
|
||||||
|
| Mapping | Description | |
||||||
|
|-------------------------------------------|-----------------------------------------------| |
||||||
|
| `<Plug>(committia-scroll-diff-down-half)` | Scroll down the diff window by half a screen. | |
||||||
|
| `<Plug>(committia-scroll-diff-up-half)` | Scroll up the diff window by half a screen. | |
||||||
|
| `<Plug>(committia-scroll-diff-down-page)` | Scroll down the diff window by a screen. | |
||||||
|
| `<Plug>(committia-scroll-diff-up-page)` | Scroll up the diff window by a screen. | |
||||||
|
|
||||||
|
## Variables |
||||||
|
|
||||||
|
Some variables are available to control the behavior of committia.vim. |
||||||
|
|
||||||
|
### `g:committia_open_only_vim_starting` (default: `1`) |
||||||
|
|
||||||
|
If the value is `0`, committia.vim always attempts to open committia's buffer when `COMMIT_EDITMSG` |
||||||
|
buffer is opened. If you use [vim-fugitive](https://github.com/tpope/vim-fugitive), I recommend to |
||||||
|
set this value to `1`. |
||||||
|
|
||||||
|
### `g:committia_use_singlecolumn` (default: `'fallback'`) |
||||||
|
|
||||||
|
If the value is `'always'`, committia.vim always employs single column mode. |
||||||
|
|
||||||
|
### `g:committia_min_window_width` (default: `160`) |
||||||
|
|
||||||
|
If the width of window is narrower than the value, committia.vim employs single column mode. |
||||||
|
|
||||||
|
### `g:committia_status_window_opencmd` (default: `'belowright split'`) |
||||||
|
|
||||||
|
Vim command which opens a status window in multi-columns mode. |
||||||
|
|
||||||
|
### `g:committia_diff_window_opencmd` (default: `'botright vsplit'`) |
||||||
|
|
||||||
|
Vim command which opens a diff window in multi-columns mode. |
||||||
|
|
||||||
|
### `g:committia_singlecolumn_diff_window_opencmd` (default: `'belowright split'`) |
||||||
|
|
||||||
|
Vim command which opens a diff window in single-column mode. |
||||||
|
|
||||||
|
## Future |
||||||
|
|
||||||
|
- Cooperate with [vim-fugitive](https://github.com/tpope/vim-fugitive). |
||||||
|
- Add more VCS supports |
||||||
|
- Test all features |
||||||
|
|
||||||
|
## Contribution |
||||||
|
|
||||||
|
- [@uasi](https://github.com/uasi) : single column mode |
||||||
|
- [@anekos](https://github.com/uasi) : submodule and worktree support |
||||||
|
- [and more contributors who sent a patch](https://github.com/rhysd/committia.vim/graphs/contributors) |
||||||
|
|
||||||
|
## License |
||||||
|
|
||||||
|
[Distributed under the MIT license](LICENSE) |
@ -0,0 +1,196 @@ |
|||||||
|
let s:save_cpo = &cpo |
||||||
|
set cpo&vim |
||||||
|
|
||||||
|
let g:committia_use_singlecolumn = get(g:, 'committia_use_singlecolumn', 'fallback') |
||||||
|
let g:committia_min_window_width = get(g:, 'committia_min_window_width', 160) |
||||||
|
let g:committia_diff_window_opencmd = get(g:, 'committia_diff_window_opencmd', 'botright vsplit') |
||||||
|
let g:committia_status_window_opencmd = get(g:, 'committia_status_window_opencmd', 'belowright split') |
||||||
|
let g:committia_singlecolumn_diff_window_opencmd = get(g:, 'committia_singlecolumn_diff_window_opencmd', 'belowright split') |
||||||
|
let g:committia_hooks = get(g:, 'committia_hooks', {}) |
||||||
|
|
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-down-half) <C-o>:call committia#scroll_window('diff', 'C-d')<CR> |
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-up-half) <C-o>:call committia#scroll_window('diff', 'C-u')<CR> |
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-down-page) <C-o>:call committia#scroll_window('diff', 'C-f')<CR> |
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-up-page) <C-o>:call committia#scroll_window('diff', 'C-b')<CR> |
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-down) <C-o>:call committia#scroll_window('diff', 'j')<CR> |
||||||
|
inoremap <silent> <Plug>(committia-scroll-diff-up) <C-o>:call committia#scroll_window('diff', 'k')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-down-half) :<C-u>call committia#scroll_window('diff', 'C-d')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-up-half) :<C-u>call committia#scroll_window('diff', 'C-u')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-down-page) :<C-u>call committia#scroll_window('diff', 'C-f')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-up-page) :<C-u>call committia#scroll_window('diff', 'C-b')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-down) :<C-u>call committia#scroll_window('diff', 'j')<CR> |
||||||
|
nnoremap <silent> <Plug>(committia-scroll-diff-up) :<C-u>call committia#scroll_window('diff', 'k')<CR> |
||||||
|
|
||||||
|
let s:current_info = {} |
||||||
|
|
||||||
|
function! s:open_window(vcs, type, info, ft) abort |
||||||
|
let content = call('committia#' . a:vcs . '#' . a:type, []) |
||||||
|
|
||||||
|
let bufname = '__committia_' . a:type . '__' |
||||||
|
let coltype = a:info['singlecolumn'] ? 'singlecolumn_' : '' |
||||||
|
execute 'silent' g:committia_{coltype}{a:type}_window_opencmd bufname |
||||||
|
let a:info[a:type . '_winnr'] = bufwinnr(bufname) |
||||||
|
let a:info[a:type . '_bufnr'] = bufnr('%') |
||||||
|
call setline(1, content) |
||||||
|
execute 0 |
||||||
|
execute 'setlocal ft=' . a:ft |
||||||
|
setlocal nonumber bufhidden=wipe buftype=nofile readonly nolist nobuflisted noswapfile nomodifiable nomodified nofoldenable |
||||||
|
endfunction |
||||||
|
|
||||||
|
|
||||||
|
" Open diff window. If no diff is detected, close the window and return to |
||||||
|
" the original window. |
||||||
|
" It returns 0 if the window is not open, othewise 1 |
||||||
|
function! s:open_diff_window(vcs, info) abort |
||||||
|
call s:open_window(a:vcs, 'diff', a:info, 'git') |
||||||
|
if getline(1, '$') ==# [''] |
||||||
|
execute a:info.diff_winnr . 'wincmd c' |
||||||
|
wincmd p |
||||||
|
return 0 |
||||||
|
endif |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:open_status_window(vcs, info) abort |
||||||
|
call s:open_window(a:vcs, 'status', a:info, 'gitcommit') |
||||||
|
let status_winheight = winheight(a:info.status_bufnr) |
||||||
|
if line('$') < winheight(a:info.status_bufnr) |
||||||
|
execute 'resize' line('$') |
||||||
|
endif |
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:execute_hook(name, info) abort |
||||||
|
if has_key(g:committia_hooks, a:name) |
||||||
|
call call(g:committia_hooks[a:name], [a:info], g:committia_hooks) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:remove_all_contents_except_for_commit_message(vcs) abort |
||||||
|
1 |
||||||
|
" Handle squash message |
||||||
|
let line = call('committia#' . a:vcs . '#end_of_edit_region_line', []) |
||||||
|
if 0 < line && line <= line('$') |
||||||
|
execute 'silent' line . ',$delete _' |
||||||
|
endif |
||||||
|
1 |
||||||
|
vertical resize 80 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:callback_on_window_closed() abort |
||||||
|
if bufnr('%') == s:current_info.edit_bufnr |
||||||
|
for n in ['diff', 'status'] |
||||||
|
if has_key(s:current_info, n . '_bufnr') |
||||||
|
let winnr = bufwinnr(s:current_info[n . '_bufnr']) |
||||||
|
if winnr != -1 |
||||||
|
execute winnr . 'wincmd w' |
||||||
|
wincmd c |
||||||
|
endif |
||||||
|
endif |
||||||
|
endfor |
||||||
|
let s:current_info = {} |
||||||
|
autocmd! plugin-committia-winclosed |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:callback_on_window_closed_workaround() abort |
||||||
|
let edit_winnr = bufwinnr(s:current_info.edit_bufnr) |
||||||
|
if edit_winnr == -1 |
||||||
|
quit! |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:get_map_of(cmd) abort |
||||||
|
return eval('"\<' . a:cmd . '>"') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#scroll_window(type, cmd) abort |
||||||
|
let target_winnr = bufwinnr(s:current_info[a:type . '_bufnr']) |
||||||
|
if target_winnr == -1 |
||||||
|
return |
||||||
|
endif |
||||||
|
noautocmd execute target_winnr . 'wincmd w' |
||||||
|
noautocmd execute 'normal!' s:get_map_of(a:cmd) |
||||||
|
noautocmd wincmd p |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:set_callback_on_closed() abort |
||||||
|
augroup plugin-committia-winclosed |
||||||
|
if exists('##QuitPre') |
||||||
|
autocmd QuitPre COMMIT_EDITMSG,MERGE_MSG call s:callback_on_window_closed() |
||||||
|
else |
||||||
|
autocmd WinEnter __committia_diff__,__committia_status__ nested call s:callback_on_window_closed_workaround() |
||||||
|
end |
||||||
|
augroup END |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#open_multicolumn(vcs) abort |
||||||
|
let info = {'vcs' : a:vcs, 'edit_winnr' : winnr(), 'edit_bufnr' : bufnr('%'), 'singlecolumn' : 0} |
||||||
|
|
||||||
|
let diff_window_opened = s:open_diff_window(a:vcs, info) |
||||||
|
if !diff_window_opened |
||||||
|
return |
||||||
|
endif |
||||||
|
call s:execute_hook('diff_open', info) |
||||||
|
wincmd p |
||||||
|
|
||||||
|
call s:open_status_window(a:vcs, info) |
||||||
|
call s:execute_hook('status_open', info) |
||||||
|
wincmd p |
||||||
|
|
||||||
|
call s:remove_all_contents_except_for_commit_message(info.vcs) |
||||||
|
call s:execute_hook('edit_open', info) |
||||||
|
|
||||||
|
let s:current_info = info |
||||||
|
setlocal bufhidden=wipe |
||||||
|
let b:committia_opened = 1 |
||||||
|
call s:set_callback_on_closed() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#open_singlecolumn(vcs) abort |
||||||
|
let info = {'vcs' : a:vcs, 'edit_winnr' : winnr(), 'edit_bufnr' : bufnr('%'), 'singlecolumn' : 1} |
||||||
|
|
||||||
|
let diff_window_opened = s:open_diff_window(a:vcs, info) |
||||||
|
if !diff_window_opened |
||||||
|
return |
||||||
|
endif |
||||||
|
call s:execute_hook('diff_open', info) |
||||||
|
wincmd p |
||||||
|
|
||||||
|
let height = min([line('$') + 3, get(g:, 'committia_singlecolumn_edit_max_winheight', 16)]) |
||||||
|
execute 'resize' height |
||||||
|
call s:execute_hook('edit_open', info) |
||||||
|
|
||||||
|
let s:current_info = info |
||||||
|
setlocal bufhidden=wipe |
||||||
|
let b:committia_opened = 1 |
||||||
|
call s:set_callback_on_closed() |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#open(vcs) abort |
||||||
|
let is_narrow = winwidth(0) < g:committia_min_window_width |
||||||
|
let use_singlecolumn |
||||||
|
\ = g:committia_use_singlecolumn ==# 'always' |
||||||
|
\ || (is_narrow && g:committia_use_singlecolumn ==# 'fallback') |
||||||
|
|
||||||
|
if is_narrow && !use_singlecolumn |
||||||
|
call s:execute_hook('edit_open', {'vcs' : a:vcs}) |
||||||
|
return |
||||||
|
endif |
||||||
|
|
||||||
|
" When opening a commit buffer with --amend flag, Vim tries to move the |
||||||
|
" cursor to the previous position. Detect it and reset the cursor |
||||||
|
" position. |
||||||
|
if line('.') != 1 |
||||||
|
keepjumps call cursor(1, 1) |
||||||
|
endif |
||||||
|
|
||||||
|
if use_singlecolumn |
||||||
|
call committia#open_singlecolumn(a:vcs) |
||||||
|
else |
||||||
|
call committia#open_multicolumn(a:vcs) |
||||||
|
endif |
||||||
|
endfunction |
||||||
|
|
||||||
|
let &cpo = s:save_cpo |
||||||
|
unlet s:save_cpo |
@ -0,0 +1,206 @@ |
|||||||
|
if has('win32') || has('win64') |
||||||
|
let s:PATH_SEP = '\' |
||||||
|
function! s:is_absolute_path(path) abort |
||||||
|
return a:path =~# '^[a-zA-Z]:[/\\]' |
||||||
|
endfunction |
||||||
|
else |
||||||
|
let s:PATH_SEP = '/' |
||||||
|
function! s:is_absolute_path(path) abort |
||||||
|
return a:path[0] ==# '/' |
||||||
|
endfunction |
||||||
|
endif |
||||||
|
|
||||||
|
let g:committia#git#cmd = get(g:, 'committia#git#cmd', 'git') |
||||||
|
let g:committia#git#diff_cmd = get(g:, 'committia#git#diff_cmd', 'diff -u --cached --no-color --no-ext-diff') |
||||||
|
let g:committia#git#status_cmd = get(g:, 'committia#git#status_cmd', '-c color.status=false status -b') |
||||||
|
|
||||||
|
try |
||||||
|
silent call vimproc#version() |
||||||
|
|
||||||
|
" Note: vimproc exists |
||||||
|
function! s:system(cmd) abort |
||||||
|
let out = vimproc#system(a:cmd) |
||||||
|
if vimproc#get_last_status() |
||||||
|
throw printf("Failed to execute command '%s': %s", a:cmd, out) |
||||||
|
endif |
||||||
|
return out |
||||||
|
endfunction |
||||||
|
catch /^Vim\%((\a\+)\)\=:E117/ |
||||||
|
function! s:system(cmd) abort |
||||||
|
let out = system(a:cmd) |
||||||
|
if v:shell_error |
||||||
|
throw printf("Failed to execute command '%s': %s", a:cmd, out) |
||||||
|
endif |
||||||
|
return out |
||||||
|
endfunction |
||||||
|
endtry |
||||||
|
|
||||||
|
if !executable(g:committia#git#cmd) |
||||||
|
echoerr g:committia#git#cmd . ' command is not found. Please check g:committia#git#cmd' |
||||||
|
endif |
||||||
|
|
||||||
|
function! s:extract_first_line(str) abort |
||||||
|
let i = stridx(a:str, "\r") |
||||||
|
if i > 0 |
||||||
|
return a:str[: i - 1] |
||||||
|
endif |
||||||
|
let i = stridx(a:str, "\n") |
||||||
|
if i > 0 |
||||||
|
return a:str[: i - 1] |
||||||
|
endif |
||||||
|
return a:str |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:search_git_dir_and_work_tree() abort |
||||||
|
" Use environment variables if set |
||||||
|
if !empty($GIT_DIR) && !empty($GIT_WORK_TREE) |
||||||
|
if !isdirectory($GIT_WORK_TREE) |
||||||
|
throw 'Directory specified with $GIT_WORK_TREE does not exist: ' . $GIT_WORK_TREE |
||||||
|
endif |
||||||
|
return [$GIT_DIR, $GIT_WORK_TREE] |
||||||
|
endif |
||||||
|
|
||||||
|
" '/.git' is unnecessary under submodule directory. |
||||||
|
let matched = matchlist(expand('%:p'), '[\\/]\.git[\\/]\%(\(modules\|worktrees\)[\\/].\+[\\/]\)\?\%(COMMIT_EDITMSG\|MERGE_MSG\)$') |
||||||
|
if len(matched) > 1 |
||||||
|
let git_dir = expand('%:p:h') |
||||||
|
|
||||||
|
if matched[1] ==# 'worktrees' |
||||||
|
" Note: |
||||||
|
" This was added in #31. I'm not sure that the format of gitdir file |
||||||
|
" is fixed. Anyway, it works for now. |
||||||
|
let work_tree = fnamemodify(readfile(git_dir . '/gitdir')[0], ':h') |
||||||
|
return [git_dir, work_tree] |
||||||
|
endif |
||||||
|
|
||||||
|
" Avoid executing Git command in git-dir because `git rev-parse --show-toplevel` |
||||||
|
" does not return the repository root. To handle work-tree properly, |
||||||
|
" set $CWD to the parent of git-dir, which is outside of the |
||||||
|
" git-dir. (#39) |
||||||
|
let cwd_saved = getcwd() |
||||||
|
let cwd = fnamemodify(git_dir, ':h') |
||||||
|
if cwd_saved !=# cwd |
||||||
|
execute 'lcd' cwd |
||||||
|
endif |
||||||
|
try |
||||||
|
let cmd = printf('%s --git-dir="%s" rev-parse --show-toplevel', g:committia#git#cmd, escape(git_dir, '\')) |
||||||
|
let out = s:system(cmd) |
||||||
|
finally |
||||||
|
if cwd_saved !=# getcwd() |
||||||
|
execute 'lcd' cwd_saved |
||||||
|
endif |
||||||
|
endtry |
||||||
|
|
||||||
|
let work_tree = s:extract_first_line(out) |
||||||
|
return [git_dir, work_tree] |
||||||
|
endif |
||||||
|
|
||||||
|
if s:is_absolute_path($GIT_DIR) && isdirectory($GIT_DIR) |
||||||
|
let git_dir = $GIT_DIR |
||||||
|
else |
||||||
|
let root = s:extract_first_line(s:system(g:committia#git#cmd . ' rev-parse --show-cdup')) |
||||||
|
|
||||||
|
let git_dir = root . $GIT_DIR |
||||||
|
if !isdirectory(git_dir) |
||||||
|
throw 'Failed to get git-dir from $GIT_DIR' |
||||||
|
endif |
||||||
|
endif |
||||||
|
|
||||||
|
return [git_dir, fnamemodify(git_dir, ':h')] |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:execute_git(cmd) abort |
||||||
|
try |
||||||
|
let [git_dir, work_tree] = s:search_git_dir_and_work_tree() |
||||||
|
catch |
||||||
|
throw 'committia: git: Failed to retrieve git-dir or work-tree: ' . v:exception |
||||||
|
endtry |
||||||
|
|
||||||
|
if git_dir ==# '' || work_tree ==# '' |
||||||
|
throw 'committia: git: Failed to retrieve git-dir or work-tree' |
||||||
|
endif |
||||||
|
|
||||||
|
let index_file_was_set = s:ensure_index_file(git_dir) |
||||||
|
try |
||||||
|
let cmd = printf('%s --git-dir="%s" --work-tree="%s" %s', g:committia#git#cmd, escape(git_dir, '\'), escape(work_tree, '\'), a:cmd) |
||||||
|
try |
||||||
|
return s:system(cmd) |
||||||
|
catch |
||||||
|
throw 'committia: git: ' . v:exception |
||||||
|
endtry |
||||||
|
finally |
||||||
|
if index_file_was_set |
||||||
|
call s:unset_index_file() |
||||||
|
endif |
||||||
|
endtry |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:ensure_index_file(git_dir) abort |
||||||
|
if $GIT_INDEX_FILE !=# '' |
||||||
|
return 0 |
||||||
|
endif |
||||||
|
|
||||||
|
let lock_file = s:PATH_SEP . 'index.lock' |
||||||
|
if filereadable(lock_file) |
||||||
|
let $GIT_INDEX_FILE = lock_file |
||||||
|
else |
||||||
|
let $GIT_INDEX_FILE = a:git_dir . s:PATH_SEP . 'index' |
||||||
|
endif |
||||||
|
|
||||||
|
return 1 |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:unset_index_file() abort |
||||||
|
let $GIT_INDEX_FILE = '' |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#git#diff() abort |
||||||
|
let diff = s:execute_git(g:committia#git#diff_cmd) |
||||||
|
|
||||||
|
if diff !=# '' |
||||||
|
return split(diff, '\n') |
||||||
|
endif |
||||||
|
|
||||||
|
let line = s:diff_start_line() |
||||||
|
if line == 0 |
||||||
|
return [''] |
||||||
|
endif |
||||||
|
|
||||||
|
return getline(line, '$') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! s:diff_start_line() abort |
||||||
|
let re_start_diff_line = '# -\+ >8 -\+\n\%(#.*\n\)\+diff --git' |
||||||
|
return search(re_start_diff_line, 'cenW') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#git#status() abort |
||||||
|
try |
||||||
|
let status = s:execute_git(g:committia#git#status_cmd) |
||||||
|
catch /^committia: git: Failed to retrieve git-dir or work-tree/ |
||||||
|
" Leave status window empty when git-dir or work-tree not found |
||||||
|
return '' |
||||||
|
endtry |
||||||
|
return map(split(status, '\n'), 'substitute(v:val, "^", "# ", "g")') |
||||||
|
endfunction |
||||||
|
|
||||||
|
function! committia#git#end_of_edit_region_line() abort |
||||||
|
let line = s:diff_start_line() |
||||||
|
if line == 0 |
||||||
|
" If diff is not contained, assumes that the buffer ends with comment |
||||||
|
" block which was automatically inserted by Git. |
||||||
|
" Only the comment block will be removed from edit buffer. (#41) |
||||||
|
let line = line('$') + 1 |
||||||
|
endif |
||||||
|
while line > 1 |
||||||
|
if stridx(getline(line - 1), '#') != 0 |
||||||
|
break |
||||||
|
endif |
||||||
|
let line -= 1 |
||||||
|
endwhile |
||||||
|
if line > 1 && empty(getline(line - 1)) |
||||||
|
" Drop empty line before comment block. |
||||||
|
let line -= 1 |
||||||
|
endif |
||||||
|
return line |
||||||
|
endfunction |
@ -0,0 +1,18 @@ |
|||||||
|
if (exists('g:loaded_committia') && g:loaded_committia) || &cp |
||||||
|
finish |
||||||
|
endif |
||||||
|
|
||||||
|
let g:committia_open_only_vim_starting = get(g:, 'committia_open_only_vim_starting', 1) |
||||||
|
|
||||||
|
function! s:should_open(ft) abort |
||||||
|
return &ft ==# a:ft && (!g:committia_open_only_vim_starting || has('vim_starting')) && !exists('b:committia_opened') |
||||||
|
endfunction |
||||||
|
|
||||||
|
augroup plugin-committia |
||||||
|
autocmd! |
||||||
|
autocmd BufReadPost COMMIT_EDITMSG,MERGE_MSG if s:should_open('gitcommit') | call committia#open('git') | endif |
||||||
|
|
||||||
|
" ... Add other VCSs' commit editor filetypes |
||||||
|
augroup END |
||||||
|
|
||||||
|
let g:loaded_committia = 1 |
Loading…
Reference in new issue