diff --git a/autoload/mergetool.vim b/autoload/mergetool.vim index 2cb1c0a..630b28b 100644 --- a/autoload/mergetool.vim +++ b/autoload/mergetool.vim @@ -52,8 +52,34 @@ function! mergetool#start() "{{{ call mergetool#prefer_revision(g:mergetool_prefer_revision) call mergetool#set_layout(g:mergetool_layout) + call mergetool#bind_commands() endfunction "}}} +function! mergetool#bind_commands() + command! -nargs=0 MergetoolStop call mergetool#stop() + command! -nargs=1 MergetoolSetLayout call mergetool#set_layout() + command! -nargs=1 MergetoolToggleLayout call mergetool#toggle_layout() + command! -nargs=0 MergetoolPreferLocal call mergetool#prefer_revision('local') + command! -nargs=0 MergetoolPreferRemote call mergetool#prefer_revision('remote') + doautocmd User MergetoolStart +endf + +function! mergetool#unbind_commands() + delcommand MergetoolStop + delcommand MergetoolSetLayout + delcommand MergetoolToggleLayout + delcommand MergetoolPreferLocal + delcommand MergetoolPreferRemote + doautocmd User MergetoolStop +endf + +" Dummy autocmds to prevent errors. +augroup mergetool_dummy + au! + autocmd User MergetoolStart let s:mergetool_dummy = 1 + autocmd User MergetoolStop let s:mergetool_dummy = 0 +augroup END + " Stop mergetool effect depends on: " - when run as 'git mergetool' " - when run from Vim directly on file with conflict markers @@ -104,6 +130,7 @@ function! mergetool#stop() " {{{ endif let g:mergetool_in_merge_mode = 0 + call mergetool#unbind_commands() tabclose endif endfunction " }}} @@ -223,6 +250,57 @@ endfunction " }}} " }}} +" Diff exchange {{{ + +" Do either diffget or diffput, depending on given direction +" and whether the window has adjacent window in a given direction +" h| + window on right = diffget from right win +" h| + no window on right = diffput to left win +" l| + window on left = diffget from left win +" l| + no window on left = diffput to right win +" Same logic applies for vertical directions: 'j' and 'k' + +let s:directions = { + \ 'h': 'l', + \ 'l': 'h', + \ 'j': 'k', + \ 'k': 'j' } + +function mergetool#DiffExchange(dir) + let oppdir = s:directions[a:dir] + + let winoppdir = s:FindWindowOnDir(oppdir) + if (winoppdir != -1) + execute "diffget " . winbufnr(winoppdir) + else + let windir = s:FindWindowOnDir(a:dir) + if (windir != -1) + execute "diffput " . winbufnr(windir) + else + echohl WarningMsg + echo 'Cannot exchange diff. Found only single window' + echohl None + endif + endif +endfunction + +" Finds window in given direction and returns it win number +" If no window found, returns -1 +function s:FindWindowOnDir(dir) + let oldwin = winnr() + + execute "noautocmd wincmd " . a:dir + let curwin = winnr() + if (oldwin != curwin) + noautocmd wincmd p + return curwin + else + return -1 + endif +endfunction + +" }}} + " Private functions{{{ let s:markers = { diff --git a/plugin/mergetool.vim b/plugin/mergetool.vim index 522d260..f932375 100644 --- a/plugin/mergetool.vim +++ b/plugin/mergetool.vim @@ -7,74 +7,25 @@ let g:loaded_mergetool = 1 let g:mergetool_in_merge_mode = 0 +" Commands and mappings for mergetool state. Additional commands +" available during merging. command! -nargs=0 MergetoolStart call mergetool#start() -command! -nargs=0 MergetoolStop call mergetool#stop() command! -nargs=0 MergetoolToggle call mergetool#toggle() -command! -nargs=1 MergetoolSetLayout call mergetool#set_layout() -command! -nargs=1 MergetoolToggleLayout call mergetool#toggle_layout() -command! -nargs=0 MergetoolPreferLocal call mergetool#prefer_revision('local') -command! -nargs=0 MergetoolPreferRemote call mergetool#prefer_revision('remote') nnoremap (MergetoolToggle) :call mergetool#toggle() -" {{{ Diff exchange -" Do either diffget or diffput, depending on given direction -" and whether the window has adjacent window in a given direction -" h| + window on right = diffget from right win -" h| + no window on right = diffput to left win -" l| + window on left = diffget from left win -" l| + no window on left = diffput to right win -" Same logic applies for vertical directions: 'j' and 'k' -let s:directions = { - \ 'h': 'l', - \ 'l': 'h', - \ 'j': 'k', - \ 'k': 'j' } +" Commands and mappings for diff exchange commands. These can be used +" outside of merging (in any diff windows). +command! -nargs=0 MergetoolDiffExchangeLeft call mergetool#DiffExchange('h') +command! -nargs=0 MergetoolDiffExchangeRight call mergetool#DiffExchange('l') +command! -nargs=0 MergetoolDiffExchangeDown call mergetool#DiffExchange('j') +command! -nargs=0 MergetoolDiffExchangeUp call mergetool#DiffExchange('k') -function s:DiffExchange(dir) - let oppdir = s:directions[a:dir] - - let winoppdir = s:FindWindowOnDir(oppdir) - if (winoppdir != -1) - execute "diffget " . winbufnr(winoppdir) - else - let windir = s:FindWindowOnDir(a:dir) - if (windir != -1) - execute "diffput " . winbufnr(windir) - else - echohl WarningMsg - echo 'Cannot exchange diff. Found only single window' - echohl None - endif - endif -endfunction - -" Finds window in given direction and returns it win number -" If no window found, returns -1 -function s:FindWindowOnDir(dir) - let oldwin = winnr() - - execute "noautocmd wincmd " . a:dir - let curwin = winnr() - if (oldwin != curwin) - noautocmd wincmd p - return curwin - else - return -1 - endif -endfunction - -" Commands and mappings for diff exchange commands -command! -nargs=0 MergetoolDiffExchangeLeft call s:DiffExchange('h') -command! -nargs=0 MergetoolDiffExchangeRight call s:DiffExchange('l') -command! -nargs=0 MergetoolDiffExchangeDown call s:DiffExchange('j') -command! -nargs=0 MergetoolDiffExchangeUp call s:DiffExchange('k') - -nnoremap (MergetoolDiffExchangeLeft) :call DiffExchange('h') -nnoremap (MergetoolDiffExchangeRight) :call DiffExchange('l') -nnoremap (MergetoolDiffExchangeDown) :call DiffExchange('j') -nnoremap (MergetoolDiffExchangeUp) :call DiffExchange('k') +nnoremap (MergetoolDiffExchangeLeft) :call mergetool#DiffExchange('h') +nnoremap (MergetoolDiffExchangeRight) :call mergetool#DiffExchange('l') +nnoremap (MergetoolDiffExchangeDown) :call mergetool#DiffExchange('j') +nnoremap (MergetoolDiffExchangeUp) :call mergetool#DiffExchange('k') " }}} diff --git a/readme.md b/readme.md index baa254c..9599ce9 100644 --- a/readme.md +++ b/readme.md @@ -383,6 +383,18 @@ let g:airline_section_z = airline#section#create(['_diffmerge', ...other_parts]) ![Status line indicator](./screenshots/airline_merge_indicator.png) + +You can run vimscript when mergemode begins and ends: + +```vim +augroup your_mergetool + au! + autocmd User MergetoolStart set nospell + autocmd User MergetoolStop set spell +augroup END +``` + + ### Quitting merge mode When exiting merge mode, `vim-mergetool` would prompt you whether merge was successful. If not, it will rollback changes to the buffer, will not save `MERGED` file to disk, and exit with non-zero code, when running as a `git mergetool`.