From f3d20999d57ea1277355503961ea5b9d02fa9336 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Mon, 23 Dec 2019 15:17:36 -0800 Subject: [PATCH 1/3] Move diffexchange code to autoload --- autoload/mergetool.vim | 51 ++++++++++++++++++++++++++++++++ plugin/mergetool.vim | 66 +++++++----------------------------------- 2 files changed, 61 insertions(+), 56 deletions(-) diff --git a/autoload/mergetool.vim b/autoload/mergetool.vim index 2cb1c0a..c6d6cc9 100644 --- a/autoload/mergetool.vim +++ b/autoload/mergetool.vim @@ -223,6 +223,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..83e4b78 100644 --- a/plugin/mergetool.vim +++ b/plugin/mergetool.vim @@ -7,6 +7,7 @@ let g:loaded_mergetool = 1 let g:mergetool_in_merge_mode = 0 +" Commands and mappings for mergetool state command! -nargs=0 MergetoolStart call mergetool#start() command! -nargs=0 MergetoolStop call mergetool#stop() command! -nargs=0 MergetoolToggle call mergetool#toggle() @@ -17,64 +18,17 @@ 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' } - -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') +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') + +nnoremap (MergetoolDiffExchangeLeft) :call mergetool#DiffExchange('h') +nnoremap (MergetoolDiffExchangeRight) :call mergetool#DiffExchange('l') +nnoremap (MergetoolDiffExchangeDown) :call mergetool#DiffExchange('j') +nnoremap (MergetoolDiffExchangeUp) :call mergetool#DiffExchange('k') " }}} From b158916205bcda928bbfe2645e0964fe4d836070 Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Mon, 23 Dec 2019 15:22:24 -0800 Subject: [PATCH 2/3] Hide most commands when not merging It doesn't make sense to adjust our layout unless we're merging, so only define these commands while merge is active. This makes it easier to find the right mergetool commands. --- autoload/mergetool.vim | 18 ++++++++++++++++++ plugin/mergetool.vim | 11 ++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/autoload/mergetool.vim b/autoload/mergetool.vim index c6d6cc9..20eb4dc 100644 --- a/autoload/mergetool.vim +++ b/autoload/mergetool.vim @@ -52,8 +52,25 @@ 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') +endf + +function! mergetool#unbind_commands() + delcommand MergetoolStop + delcommand MergetoolSetLayout + delcommand MergetoolToggleLayout + delcommand MergetoolPreferLocal + delcommand MergetoolPreferRemote +endf + " Stop mergetool effect depends on: " - when run as 'git mergetool' " - when run from Vim directly on file with conflict markers @@ -104,6 +121,7 @@ function! mergetool#stop() " {{{ endif let g:mergetool_in_merge_mode = 0 + call mergetool#unbind_commands() tabclose endif endfunction " }}} diff --git a/plugin/mergetool.vim b/plugin/mergetool.vim index 83e4b78..f932375 100644 --- a/plugin/mergetool.vim +++ b/plugin/mergetool.vim @@ -7,20 +7,17 @@ let g:loaded_mergetool = 1 let g:mergetool_in_merge_mode = 0 -" Commands and mappings for mergetool state +" 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() -" Commands and mappings for diff exchange commands +" 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') From 34565185d21e60ecede66d0425c5f6a86d57136b Mon Sep 17 00:00:00 2001 From: David Briscoe Date: Mon, 23 Dec 2019 15:30:51 -0800 Subject: [PATCH 3/3] Add autocmds for defining commands when merging Allow users to define their own Mergetool commands. The best example I have is `:MergetoolDiffWithRemote` as an alias for `:MergetoolToggleLayout rlm` --- autoload/mergetool.vim | 9 +++++++++ readme.md | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/autoload/mergetool.vim b/autoload/mergetool.vim index 20eb4dc..630b28b 100644 --- a/autoload/mergetool.vim +++ b/autoload/mergetool.vim @@ -61,6 +61,7 @@ function! mergetool#bind_commands() 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() @@ -69,8 +70,16 @@ function! mergetool#unbind_commands() 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 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`.