Skip to content

Commit

Permalink
Support any scm by assigning args at startup
Browse files Browse the repository at this point in the history
Fix #13: add g:mergetool_args_order.

Add g:mergetool_args_order to renames arguments as hidden files with the
same names as git (BASE, REMOTE, LOCAL). This allows mergetool to behave
as if invoked by git-mergetool for any scm.
  • Loading branch information
idbrii committed Apr 18, 2020
1 parent 0275a85 commit fd51120
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
43 changes: 43 additions & 0 deletions autoload/mergetool.vim
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ endfunction
let g:mergetool_layout = get(g:, 'mergetool_layout', 'mr')
let g:mergetool_prefer_revision = get(g:, 'mergetool_prefer_revision', 'local')
let g:MergetoolSetLayoutCallback = get(g:, 'MergetoolSetLayoutCallback', function('s:noop'))
let g:mergetool_args_order = get(g:, 'mergetool_args_order', '')

" {{{ Public exports

Expand Down Expand Up @@ -38,6 +39,16 @@ function! mergetool#start() "{{{
let s:mergedfile_fileformat = &fileformat
let s:mergedfile_filetype = &filetype

if !empty(g:mergetool_args_order)
let success = s:apply_args_order(s:mergedfile_bufnr, g:mergetool_args_order)
if !success
echohl WarningMsg
echo "g:mergetool_args_order didn't use the current file as MERGED. Ensure you're using the order as seen in :args."
echohl None
return
endif
endif

" Detect if we're run as 'git mergetool' by presence of BASE|LOCAL|REMOTE buf names
let s:run_as_git_mergetool = bufnr('BASE') != -1 &&
\ bufnr('LOCAL') != -1 &&
Expand Down Expand Up @@ -117,6 +128,38 @@ function! mergetool#toggle() " {{{
endif
endfunction " }}}

" Create hidden buffers that use git's special buffer names to support any
" scm. We never create a MERGED buffer. Instead, return it so we can validate
" it's as expected.
function! s:apply_args_order(merged_bufnr, arg_order) " {{{
let abbrevs = {
\ 'M': 'MERGED',
\ 'B': 'BASE',
\ 'R': 'REMOTE',
\ 'L': 'LOCAL' }

let i = 1
for labbr in split(a:arg_order, '\zs')
if labbr ==# 'M'
let current_arg_bufnr = bufnr(argv(i - 1))
if a:merged_bufnr != current_arg_bufnr
" Fail -- input merged buffer number doesn't match arg order.
return 0
endif
else
execute 'silent' i 'argument'
execute 'silent file' abbrevs[labbr]
setlocal buftype=nofile
setlocal bufhidden=hide
endif
let i += 1
endfor

execute "buffer " . a:merged_bufnr
" Success
return 1
endfunction " }}}

" Opens set of windows with merged file and various file revisions
" Supported layout options:
" - w, 'MERGED' revision as passed by Git, or working tree version of merged file
Expand Down
35 changes: 35 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,41 @@ Git detects whether merge was successful or not in two ways:
`vim-mergetool` supports both options. On quit, if merge was unsuccessful, it both discards any unsaved changes to buffer without touching file's `ctime` and returns non-zero exit code.


### Running as other scm mergetool

You can set the g:mergetool_args_order variable when you start vim to tell vim-mergetool that your arguments are the files to use for merging. Setup your scm to start vim like this:

gvim --nofork -c "let g:mergetool_args_order = 'MBRL'" -c "MergetoolStart" $MERGED $BASE $REMOTE $LOCAL

**MERGED should be the first file** because MergetoolStart is only valid in a file with conflict markers.

Your scm likely has its own names for these filenames. Check your documentation.


#### Example: Subversion

Subversion names the files something like this:

* MERGED --> file.vim
* BASE --> file.vim.r404217
* REMOTE --> file.vim.r404563
* LOCAL --> file.vim.mine

So you'd start a merge like this:

gvim --nofork -c "let g:mergetool_args_order = 'MBRL'" -c "MergetoolStart" file.vim file.vim.r404217 file.vim.r404563 file.vim.mine

vim-mergetool will act like it does as a git-mergetool (no extra tab and won't try to access git to load other files).

For TortoiseSVN, create a batchfile like this and set it as your mergetool:

set LOCAL=%1
set REMOTE=%2
set BASE=%3
set MERGED=%4
gvim --nofork -c "let g:mergetool_args_order = 'MBLR'" -c "Merge" "%MERGED%" "%BASE%" "%LOCAL%" "%REMOTE%"


### Running directly from running Vim instance
You can enter and exit merge mode from running Vim instance by opening a file with conflict markers, and running one of the commands:

Expand Down

0 comments on commit fd51120

Please sign in to comment.