# HG changeset patch # User Steve Losh # Date 1334931408 -3600 # Node ID 0013f7e01b6e834bd72a3e2f3cf818680c61d982 # Parent c3f318a26db29fcbb65da43dc31d214be3b3b242 Rename to Splice, and change default prefix. diff -r c3f318a26db2 -r 0013f7e01b6e LICENSE --- a/LICENSE Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ -Copyright (C) 2011 by Steve Losh and contributors - -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. - diff -r c3f318a26db2 -r 0013f7e01b6e LICENSE.markdown --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE.markdown Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Steve Losh and contributors + +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.** + diff -r c3f318a26db2 -r 0013f7e01b6e README.markdown --- a/README.markdown Tue Apr 10 10:19:23 2012 -0400 +++ b/README.markdown Fri Apr 20 15:16:48 2012 +0100 @@ -1,8 +1,8 @@ -Threesome +Splice ========= -Threesome is a Vim plugin for resolving conflicts during three-way merges. +Splice is a Vim plugin for resolving conflicts during three-way merges. -Visit [the site](http://sjl.bitbucket.org/threesome.vim/) for more information. +Visit [the site](http://sjl.bitbucket.org/splice.vim/) for more information. diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splice.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splice.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,74 @@ +import vim, os, sys + + +# Add the library to the Python path. +for p in vim.eval("&runtimepath").split(','): + plugin_dir = os.path.join(p, "autoload") + if os.path.exists(os.path.join(plugin_dir, "splicelib")): + if plugin_dir not in sys.path: + sys.path.append(plugin_dir) + break + + +import splicelib.init as splice + + +# Wrapper functions ---------------------------------------------------------------- + +def SpliceInit(): + splice.init() + + +def SpliceOriginal(): + splice.modes.current_mode.key_original() + +def SpliceOne(): + splice.modes.current_mode.key_one() + +def SpliceTwo(): + splice.modes.current_mode.key_two() + +def SpliceResult(): + splice.modes.current_mode.key_result() + + +def SpliceGrid(): + splice.modes.key_grid() + +def SpliceLoupe(): + splice.modes.key_loupe() + +def SpliceCompare(): + splice.modes.key_compare() + +def SplicePath(): + splice.modes.key_path() + + +def SpliceDiff(): + splice.modes.current_mode.key_diff() + +def SpliceDiffoff(): + splice.modes.current_mode.key_diffoff() + +def SpliceScroll(): + splice.modes.current_mode.key_scrollbind() + +def SpliceLayout(): + splice.modes.current_mode.key_layout() + +def SpliceNext(): + splice.modes.current_mode.key_next() + +def SplicePrev(): + splice.modes.current_mode.key_prev() + +def SpliceUse(): + splice.modes.current_mode.key_use() + +def SpliceUse1(): + splice.modes.current_mode.key_use1() + +def SpliceUse2(): + splice.modes.current_mode.key_use2() + diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splice.vim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splice.vim Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,153 @@ +" ============================================================================ +" File: splice.vim +" Description: vim global plugin for resolving three-way merge conflicts +" Maintainer: Steve Losh +" License: MIT X11 +" ============================================================================ + +" Init {{{ + +" Vim version check {{{ + +if v:version < '703' + function! s:SpliceDidNotLoad() + echohl WarningMsg|echomsg "Splice unavailable: requires Vim 7.3+"|echohl None + endfunction + command! -nargs=0 SpliceInit call s:SpliceDidNotLoad() + finish +endif + +"}}} +" Python version check {{{ + +if has('python') + let s:has_supported_python = 2 +python << ENDPYTHON +import sys, vim +if sys.version_info[:2] < (2, 5): + vim.command('let s:has_supported_python = 0') +ENDPYTHON +else + let s:has_supported_python = 0 +endif + +if !s:has_supported_python + function! s:SpliceDidNotLoad() + echohl WarningMsg|echomsg "Splice requires Vim to be compiled with Python 2.5+"|echohl None + endfunction + command! -nargs=0 SpliceInit call s:SpliceDidNotLoad() + finish +endif + +"}}} +" Configuration variables {{{ + +if !exists('g:splice_disable') "{{{ + let g:splice_disable = 0 +endif " }}} +if !exists('g:splice_initial_mode') "{{{ + let g:splice_initial_mode = 'grid' +endif "}}} +if !exists('g:splice_initial_layout_grid') "{{{ + let g:splice_initial_layout_grid = 0 +endif "}}} +if !exists('g:splice_initial_layout_loupe') "{{{ + let g:splice_initial_layout_loupe = 0 +endif "}}} +if !exists('g:splice_initial_layout_compare') "{{{ + let g:splice_initial_layout_compare = 0 +endif "}}} +if !exists('g:splice_initial_layout_path') "{{{ + let g:splice_initial_layout_path = 0 +endif "}}} +if !exists('g:splice_initial_diff_grid') "{{{ + let g:splice_initial_diff_grid = 0 +endif "}}} +if !exists('g:splice_initial_diff_loupe') "{{{ + let g:splice_initial_diff_loupe = 0 +endif "}}} +if !exists('g:splice_initial_diff_compare') "{{{ + let g:splice_initial_diff_compare = 0 +endif "}}} +if !exists('g:splice_initial_diff_path') "{{{ + let g:splice_initial_diff_path = 0 +endif "}}} +if !exists('g:splice_initial_scrollbind_grid') "{{{ + let g:splice_initial_scrollbind_grid = 0 +endif "}}} +if !exists('g:splice_initial_scrollbind_loupe') "{{{ + let g:splice_initial_scrollbind_loupe = 0 +endif "}}} +if !exists('g:splice_initial_scrollbind_compare') "{{{ + let g:splice_initial_scrollbind_compare = 0 +endif "}}} +if !exists('g:splice_initial_scrollbind_path') "{{{ + let g:splice_initial_scrollbind_path = 0 +endif "}}} + +" }}} + +" }}} +" Wrappers {{{ + +function! splice#SpliceInit() "{{{ + let python_module = fnameescape(globpath(&runtimepath, 'autoload/splice.py')) + exe 'pyfile ' . python_module + python SpliceInit() +endfunction "}}} + +function! splice#SpliceGrid() "{{{ + python SpliceGrid() +endfunction "}}} +function! splice#SpliceLoupe() "{{{ + python SpliceLoupe() +endfunction "}}} +function! splice#SpliceCompare() "{{{ + python SpliceCompare() +endfunction "}}} +function! splice#SplicePath() "{{{ + python SplicePath() +endfunction "}}} + +function! splice#SpliceOriginal() "{{{ + python SpliceOriginal() +endfunction "}}} +function! splice#SpliceOne() "{{{ + python SpliceOne() +endfunction "}}} +function! splice#SpliceTwo() "{{{ + python SpliceTwo() +endfunction "}}} +function! splice#SpliceResult() "{{{ + python SpliceResult() +endfunction "}}} + +function! splice#SpliceDiff() "{{{ + python SpliceDiff() +endfunction "}}} +function! splice#SpliceDiffoff() "{{{ + python SpliceDiffoff() +endfunction "}}} +function! splice#SpliceScroll() "{{{ + python SpliceScroll() +endfunction "}}} +function! splice#SpliceLayout() "{{{ + python SpliceLayout() +endfunction "}}} +function! splice#SpliceNext() "{{{ + python SpliceNext() +endfunction "}}} +function! splice#SplicePrev() "{{{ + python SplicePrev() +endfunction "}}} +function! splice#SpliceUse() "{{{ + python SpliceUse() +endfunction "}}} +function! splice#SpliceUse1() "{{{ + python SpliceUse1() +endfunction "}}} +function! splice#SpliceUse2() "{{{ + python SpliceUse2() +endfunction "}}} + +" }}} diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/__init__.py diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/init.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/init.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,108 @@ +import vim +import modes +from settings import setting +from util import buffers, keys, windows + + +CONFLICT_MARKER_START = '<<<<<<<' +CONFLICT_MARKER_MARK = '=======' +CONFLICT_MARKER_END = '>>>>>>>' + +def process_result(): + windows.close_all() + buffers.result.open() + + lines = [] + in_conflict = False + for line in buffers.result.lines: + if in_conflict: + if CONFLICT_MARKER_MARK in line: + lines.append(line) + if CONFLICT_MARKER_END in line: + in_conflict = False + continue + + if CONFLICT_MARKER_START in line: + in_conflict = True + continue + + lines.append(line) + + buffers.result.set_lines(lines) + +def bind_global_keys(): + keys.bind('g', ':SpliceGrid') + keys.bind('l', ':SpliceLoupe') + keys.bind('c', ':SpliceCompare') + keys.bind('p', ':SplicePath') + + keys.bind('o', ':SpliceOriginal') + keys.bind('1', ':SpliceOne') + keys.bind('2', ':SpliceTwo') + keys.bind('r', ':SpliceResult') + + keys.bind('d', ':SpliceDiff') + keys.bind('D', ':SpliceDiffoff') + keys.bind('s', ':SpliceScroll') + keys.bind('n', ':SpliceNext') + keys.bind('N', ':SplicePrev') + keys.bind('', ':SpliceLayout') + keys.bind('u', ':SpliceUse') + + keys.bind('q', ':wa:qa') + keys.bind('CC', ':cq') + +def setlocal_buffers(): + buffers.original.open() + vim.command('setlocal noswapfile') + vim.command('setlocal nomodifiable') + if setting('wrap'): + vim.command('setlocal ' + setting('wrap')) + + buffers.one.open() + vim.command('setlocal noswapfile') + vim.command('setlocal nomodifiable') + if setting('wrap'): + vim.command('setlocal ' + setting('wrap')) + + buffers.two.open() + vim.command('setlocal noswapfile') + vim.command('setlocal nomodifiable') + if setting('wrap'): + vim.command('setlocal ' + setting('wrap')) + + buffers.result.open() + if setting('wrap'): + vim.command('setlocal ' + setting('wrap')) + + buffers.hud.open() + vim.command('setlocal noswapfile') + vim.command('setlocal nomodifiable') + vim.command('setlocal nobuflisted') + vim.command('setlocal buftype=nofile') + vim.command('setlocal noundofile') + vim.command('setlocal nolist') + vim.command('setlocal ft=splice') + vim.command('setlocal nowrap') + vim.command('resize ' + setting('hud_size', '3')) + +def create_hud(): + vim.command('new __Splice_HUD__') + + +def init(): + process_result() + create_hud() + setlocal_buffers() + bind_global_keys() + + vim.command('set hidden') + + initial_mode = setting('initial_mode', 'grid').lower() + if initial_mode not in ['grid', 'loupe', 'compare', 'path']: + initial_mode = 'grid' + + modes.current_mode = getattr(modes, initial_mode) + modes.current_mode.activate() + + diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/modes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/modes.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,910 @@ +from __future__ import with_statement + +import vim +from util import buffers, keys, windows +from settings import boolsetting, setting + + +current_mode = None + +class Mode(object): + def __init__(self): + return super(Mode, self).__init__() + + + def diff(self, diffmode): + with windows.remain(): + getattr(self, '_diff_%d' % diffmode)() + + # Reset the scrollbind to whatever it was before we diffed. + if not diffmode: + self.scrollbind(self._current_scrollbind) + + def key_diff(self, diffmode=None): + next_diff_mode = self._current_diff_mode + 1 + if next_diff_mode >= self._number_of_diff_modes: + next_diff_mode = 0 + self.diff(next_diff_mode) + + + def diffoff(self): + with windows.remain(): + for winnr in range(2, 2 + self._number_of_windows): + windows.focus(winnr) + curbuffer = buffers.current + + for buffer in buffers.all: + buffer.open() + vim.command('diffoff') + if setting('wrap'): + vim.command('setlocal ' + setting('wrap')) + + curbuffer.open() + + + def key_diffoff(self): + self.diff(0) + + + def scrollbind(self, enabled): + if self._current_diff_mode: + return + + with windows.remain(): + self._current_scrollbind = enabled + + for winnr in range(2, 2 + self._number_of_windows): + windows.focus(winnr) + + if enabled: + vim.command('set scrollbind') + else: + vim.command('set noscrollbind') + + if enabled: + vim.command('syncbind') + + def key_scrollbind(self): + self.scrollbind(not self._current_scrollbind) + + + def layout(self, layoutnr): + getattr(self, '_layout_%d' % layoutnr)() + self.diff(self._current_diff_mode) + self.redraw_hud() + + def key_layout(self, diffmode=None): + next_layout = self._current_layout + 1 + if next_layout >= self._number_of_layouts: + next_layout = 0 + self.layout(next_layout) + + + def key_original(self): + pass + + def key_one(self): + pass + + def key_two(self): + pass + + def key_result(self): + pass + + + def key_use(self): + pass + + + def activate(self): + self.layout(self._current_layout) + self.diff(self._current_diff_mode) + self.scrollbind(self._current_scrollbind) + + def deactivate(self): + pass + + + def key_next(self): + self.goto_result() + vim.command(r'exe "silent! normal! /\\v^\\=\\=\\=\\=\\=\\=\\=*$\"') + + def key_prev(self): + self.goto_result() + vim.command(r'exe "silent! normal! ?\\v^\\=\\=\\=\\=\\=\\=\\=*$\"') + + + def open_hud(self, winnr): + windows.split() + windows.focus(winnr) + buffers.hud.open() + vim.command('wincmd K') + self.redraw_hud() + + def hud_lines(self): + def pad(lines): + l = max([len(line) for line in lines]) + return [line.ljust(l) for line in lines] + + sep = ' | ' + + modes = pad([ + r'Splice Modes', + r'x[g]rid y[c]ompare'.replace('x', self._id == 'grid' and '*' or ' ') + .replace('y', self._id == 'comp' and '*' or ' '), + r'x[l]oupe y[p]ath'.replace('x', self._id == 'loup' and '*' or ' ') + .replace('y', self._id == 'path' and '*' or ' '), + ]) + diagram = pad(self.hud_diagram()) + commands = pad([ + r'Splice Commands', + r'd: cycle diffs n: next conflict space: cycle layouts u: use hunk o: original 1: one q: save and quit', + r'D: diffs off N: prev conflict s: toggle scrollbind r: result 2: two CC: exit with error', + ]) + + lines = [] + for line in modes: + lines.append(line + sep) + for i, line in enumerate(diagram): + lines[i] += line + sep + for i, line in enumerate(commands): + lines[i] += line + sep + + for i, line in enumerate(lines): + lines[i] = line.rstrip() + + return lines + + def redraw_hud(self): + with windows.remain(): + windows.focus(1) + + vim.command('setlocal modifiable') + buffers.hud.set_lines(self.hud_lines()) + vim.command('setlocal nomodifiable') + + vim.command('set winfixheight') + vim.command('resize ' + setting('hud_size', '3')) + vim.command('wincmd =') + + +class GridMode(Mode): + """ + Layout 0 Layout 1 Layout 2 + +-------------------+ +--------------------------+ +---------------+ + | Original | | One | Result | Two | | One | + |2 | | | | | |2 | + +-------------------+ | | | | +---------------+ + | One | Two | | | | | | Result | + |3 |4 | | | | | |3 | + +-------------------+ | | | | +---------------+ + | Result | | | | | | Two | + |5 | |2 |3 |4 | |4 | + +-------------------+ +--------------------------+ +---------------+ + """ + + def __init__(self): + self._id = 'grid' + self._current_layout = int(setting('initial_layout_grid', 0)) + self._current_diff_mode = int(setting('initial_diff_grid', 0)) + self._current_scrollbind = boolsetting('initial_scrollbind_grid') + + self._number_of_diff_modes = 2 + self._number_of_layouts = 3 + + return super(GridMode, self).__init__() + + + def _layout_0(self): + self._number_of_windows = 4 + self._current_layout = 0 + + # Open the layout + windows.close_all() + windows.split() + windows.split() + windows.focus(2) + windows.vsplit() + + # Put the buffers in the appropriate windows + windows.focus(1) + buffers.original.open() + + windows.focus(2) + buffers.one.open() + + windows.focus(3) + buffers.two.open() + + windows.focus(4) + buffers.result.open() + + self.open_hud(5) + + windows.focus(5) + + def _layout_1(self): + self._number_of_windows = 3 + self._current_layout = 1 + + # Open the layout + windows.close_all() + windows.vsplit() + windows.vsplit() + + # Put the buffers in the appropriate windows + windows.focus(1) + buffers.one.open() + + windows.focus(2) + buffers.result.open() + + windows.focus(3) + buffers.two.open() + + self.open_hud(4) + + windows.focus(3) + + def _layout_2(self): + self._number_of_windows = 4 + self._current_layout = 2 + + # Open the layout + windows.close_all() + windows.split() + windows.split() + + # Put the buffers in the appropriate windows + windows.focus(1) + buffers.one.open() + + windows.focus(2) + buffers.result.open() + + windows.focus(3) + buffers.two.open() + + self.open_hud(4) + + windows.focus(3) + + + def _diff_0(self): + self.diffoff() + self._current_diff_mode = 0 + + def _diff_1(self): + self.diffoff() + self._current_diff_mode = 1 + + for i in range(2, self._number_of_windows + 2): + windows.focus(i) + vim.command('diffthis') + + + def key_original(self): + if self._current_layout == 0: + windows.focus(2) + elif self._current_layout == 1: + return + elif self._current_layout == 2: + return + + def key_one(self): + if self._current_layout == 0: + windows.focus(3) + elif self._current_layout == 1: + windows.focus(2) + elif self._current_layout == 2: + windows.focus(2) + + def key_two(self): + if self._current_layout == 0: + windows.focus(4) + elif self._current_layout == 1: + windows.focus(4) + elif self._current_layout == 2: + windows.focus(4) + + def key_result(self): + if self._current_layout == 0: + windows.focus(5) + elif self._current_layout == 1: + windows.focus(3) + elif self._current_layout == 2: + windows.focus(3) + + + def _key_use_0(self, target): + targetwin = 3 if target == 1 else 4 + + with windows.remain(): + self.diffoff() + + windows.focus(5) + vim.command('diffthis') + + windows.focus(targetwin) + vim.command('diffthis') + + def _key_use_12(self, target): + targetwin = 2 if target == 1 else 4 + + with windows.remain(): + self.diffoff() + + windows.focus(3) + vim.command('diffthis') + + windows.focus(targetwin) + vim.command('diffthis') + + + def key_use1(self): + current_diff = self._current_diff_mode + + if self._current_layout == 0: + self._key_use_0(1) + elif self._current_layout == 1: + self._key_use_12(1) + elif self._current_layout == 2: + self._key_use_12(1) + + if buffers.current == buffers.result: + vim.command('diffget') + elif buffers.current in (buffers.one, buffers.two): + vim.command('diffput') + + self.diff(current_diff) + + def key_use2(self): + current_diff = self._current_diff_mode + + if self._current_layout == 0: + self._key_use_0(2) + elif self._current_layout == 1: + self._key_use_12(2) + elif self._current_layout == 2: + self._key_use_12(2) + + if buffers.current == buffers.result: + vim.command('diffget') + elif buffers.current in (buffers.one, buffers.two): + vim.command('diffput') + + self.diff(current_diff) + + + def goto_result(self): + if self._current_layout == 0: + windows.focus(5) + elif self._current_layout == 1: + windows.focus(3) + elif self._current_layout == 2: + windows.focus(3) + + + def activate(self): + keys.unbind('u') + keys.bind('u1', ':SpliceUse1') + keys.bind('u2', ':SpliceUse2') + return super(GridMode, self).activate() + + def deactivate(self): + keys.unbind('u1') + keys.unbind('u2') + keys.bind('u', ':SpliceUse') + return super(GridMode, self).deactivate() + + + def hud_diagram(self): + if self._current_layout == 0: + return [ + r' Original', + r'Layout -> One Two', + r' Result', + ] + elif self._current_layout == 1: + return [ + r'', + r'Layout -> One Result Two', + r'', + ] + elif self._current_layout == 2: + return [ + r' One', + r'Layout -> Result', + r' Two', + ] + +class LoupeMode(Mode): + def __init__(self): + self._id = 'loup' + self._current_layout = int(setting('initial_layout_loupe', 0)) + self._current_diff_mode = int(setting('initial_diff_loupe', 0)) + self._current_scrollbind = boolsetting('initial_scrollbind_loupe') + + self._number_of_diff_modes = 1 + self._number_of_layouts = 1 + + self._current_buffer = buffers.result + + return super(LoupeMode, self).__init__() + + + def _diff_0(self): + self.diffoff() + self._current_diff_mode = 0 + + + def _layout_0(self): + self._number_of_windows = 1 + self._current_layout = 0 + + # Open the layout + windows.close_all() + + # Put the buffers in the appropriate windows + windows.focus(1) + self._current_buffer.open() + + self.open_hud(2) + + windows.focus(2) + + + def key_original(self): + windows.focus(2) + buffers.original.open() + self._current_buffer = buffers.original + self.redraw_hud() + + def key_one(self): + windows.focus(2) + buffers.one.open() + self._current_buffer = buffers.one + self.redraw_hud() + + def key_two(self): + windows.focus(2) + buffers.two.open() + self._current_buffer = buffers.two + self.redraw_hud() + + def key_result(self): + windows.focus(2) + buffers.result.open() + self._current_buffer = buffers.result + self.redraw_hud() + + + def key_use(self): + pass + + + def goto_result(self): + self.key_result() + + + def hud_diagram(self): + buf = buffers.labels[self._current_buffer.name] + + if self._current_layout == 0: + return [ + r'', + r'Layout -> %s ' % (buf,), + r'', + ] + +class CompareMode(Mode): + def __init__(self): + self._id = 'comp' + self._current_layout = int(setting('initial_layout_compare', 0)) + self._current_diff_mode = int(setting('initial_diff_compare', 0)) + self._current_scrollbind = boolsetting('initial_scrollbind_compare') + + self._number_of_diff_modes = 2 + self._number_of_layouts = 2 + + self._current_buffer_first = buffers.original + self._current_buffer_second = buffers.result + + return super(CompareMode, self).__init__() + + + def _diff_0(self): + self.diffoff() + self._current_diff_mode = 0 + + def _diff_1(self): + self.diffoff() + self._current_diff_mode = 1 + + windows.focus(2) + vim.command('diffthis') + + windows.focus(3) + vim.command('diffthis') + + + def _layout_0(self): + self._number_of_windows = 2 + self._current_layout = 0 + + # Open the layout + windows.close_all() + windows.vsplit() + + # Put the buffers in the appropriate windows + windows.focus(1) + self._current_buffer_first.open() + + windows.focus(2) + self._current_buffer_second.open() + + self.open_hud(3) + + windows.focus(3) + + def _layout_1(self): + self._number_of_windows = 2 + self._current_layout = 1 + + # Open the layout + windows.close_all() + windows.split() + + # Put the buffers in the appropriate windows + windows.focus(1) + self._current_buffer_first.open() + + windows.focus(2) + self._current_buffer_second.open() + + self.open_hud(3) + + windows.focus(3) + + + def key_original(self): + windows.focus(2) + buffers.original.open() + self._current_buffer_first = buffers.original + self.diff(self._current_diff_mode) + + self.redraw_hud() + + def key_one(self): + def open_one(winnr): + buffers.one.open(winnr) + if winnr == 2: + self._current_buffer_first = buffers.one + else: + self._current_buffer_second = buffers.one + self.diff(self._current_diff_mode) + self.redraw_hud() + + curwindow = windows.currentnr() + if curwindow == 1: + curwindow = 2 + + # If file one is showing, go to it. + windows.focus(2) + if buffers.current == buffers.one: + return + + windows.focus(3) + if buffers.current == buffers.one: + return + + # If both the original and result are showing, open file one in the + # current window. + windows.focus(2) + if buffers.current == buffers.original: + windows.focus(3) + if buffers.current == buffers.result: + open_one(curwindow) + return + + # If file two is in window 1, then we open file one in window 1. + windows.focus(2) + if buffers.current == buffers.two: + open_one(2) + return + + # Otherwise, open file one in the current window. + open_one(curwindow) + + def key_two(self): + def open_two(winnr): + buffers.two.open(winnr) + if winnr == 2: + self._current_buffer_first = buffers.two + else: + self._current_buffer_second = buffers.two + self.diff(self._current_diff_mode) + self.redraw_hud() + + curwindow = windows.currentnr() + if curwindow == 1: + curwindow = 2 + + # If file two is showing, go to it. + windows.focus(2) + if buffers.current == buffers.two: + return + + windows.focus(3) + if buffers.current == buffers.two: + return + + # If both the original and result are showing, open file two in the + # current window. + windows.focus(2) + if buffers.current == buffers.original: + windows.focus(3) + if buffers.current == buffers.result: + open_two(curwindow) + return + + # If file one is in window 2, then we open file two in window 2. + windows.focus(3) + if buffers.current == buffers.two: + open_two(3) + return + + # Otherwise, open file two in window 2. + open_two(3) + + def key_result(self): + windows.focus(3) + buffers.result.open() + self._current_buffer_second = buffers.result + self.diff(self._current_diff_mode) + + self.redraw_hud() + + + def key_use(self): + active = (self._current_buffer_first, self._current_buffer_second) + + if buffers.result not in active: + return + + if buffers.one not in active and buffers.two not in active: + return + + current_diff = self._current_diff_mode + with windows.remain(): + self._diff_1() # diff the windows + + if buffers.current == buffers.result: + vim.command('diffget') + elif buffers.current in (buffers.one, buffers.two): + vim.command('diffput') + + self.diff(current_diff) + + + def goto_result(self): + self.key_result() + + + def hud_diagram(self): + first = buffers.labels[self._current_buffer_first.name] + second = buffers.labels[self._current_buffer_second.name] + + if self._current_layout == 0: + return [ + r'', + r'Layout -> %s %s' % (first, second), + r'', + ] + elif self._current_layout == 1: + return [ + r'', + r'Layout -> %s' % first, + r' %s' % second, + ] + +class PathMode(Mode): + def __init__(self): + self._id = 'path' + self._current_layout = int(setting('initial_layout_path', 0)) + self._current_diff_mode = int(setting('initial_diff_path', 0)) + self._current_scrollbind = boolsetting('initial_scrollbind_path') + + self._number_of_diff_modes = 5 + self._number_of_layouts = 2 + + self._current_mid_buffer = buffers.one + + return super(PathMode, self).__init__() + + + def _diff_0(self): + self.diffoff() + self._current_diff_mode = 0 + + def _diff_1(self): + self.diffoff() + self._current_diff_mode = 1 + + windows.focus(2) + vim.command('diffthis') + + windows.focus(4) + vim.command('diffthis') + + def _diff_2(self): + self.diffoff() + self._current_diff_mode = 2 + + windows.focus(2) + vim.command('diffthis') + + windows.focus(3) + vim.command('diffthis') + + def _diff_3(self): + self.diffoff() + self._current_diff_mode = 3 + + windows.focus(3) + vim.command('diffthis') + + windows.focus(4) + vim.command('diffthis') + + def _diff_4(self): + self.diffoff() + self._current_diff_mode = 4 + + windows.focus(2) + vim.command('diffthis') + + windows.focus(3) + vim.command('diffthis') + + windows.focus(4) + vim.command('diffthis') + + + def _layout_0(self): + self._number_of_windows = 3 + self._current_layout = 0 + + # Open the layout + windows.close_all() + windows.vsplit() + windows.vsplit() + + # Put the buffers in the appropriate windows + windows.focus(1) + buffers.original.open() + + windows.focus(2) + self._current_mid_buffer.open() + + windows.focus(3) + buffers.result.open() + + self.open_hud(4) + + windows.focus(4) + + def _layout_1(self): + self._number_of_windows = 3 + self._current_layout = 1 + + # Open the layout + windows.close_all() + windows.split() + windows.split() + + # Put the buffers in the appropriate windows + windows.focus(1) + buffers.original.open() + + windows.focus(2) + self._current_mid_buffer.open() + + windows.focus(3) + buffers.result.open() + + self.open_hud(4) + + windows.focus(4) + + + def key_original(self): + windows.focus(2) + + def key_one(self): + windows.focus(3) + buffers.one.open() + self._current_mid_buffer = buffers.one + self.diff(self._current_diff_mode) + windows.focus(3) + self.redraw_hud() + + def key_two(self): + windows.focus(3) + buffers.two.open() + self._current_mid_buffer = buffers.two + self.diff(self._current_diff_mode) + windows.focus(3) + self.redraw_hud() + + def key_result(self): + windows.focus(4) + + + def key_use(self): + current_diff = self._current_diff_mode + with windows.remain(): + self._diff_3() # diff the middle and result windows + + if buffers.current == buffers.result: + vim.command('diffget') + elif buffers.current in (buffers.one, buffers.two): + vim.command('diffput') + + self.diff(current_diff) + + + def goto_result(self): + windows.focus(4) + + + def hud_diagram(self): + if self._current_mid_buffer == buffers.one: + buf = 'One' + else: + buf = 'Two' + + if self._current_layout == 0: + return [ + r'', + r'Layout -> Original %s Result' % buf, + r'', + ] + elif self._current_layout == 1: + return [ + r' Original', + r'Layout -> %s' % buf, + r' Result', + ] + + +grid = GridMode() +loupe = LoupeMode() +compare = CompareMode() +path = PathMode() + + +def key_grid(): + global current_mode + current_mode.deactivate() + current_mode = grid + grid.activate() + +def key_loupe(): + global current_mode + current_mode.deactivate() + current_mode = loupe + loupe.activate() + +def key_compare(): + global current_mode + current_mode.deactivate() + current_mode = compare + compare.activate() + +def key_path(): + global current_mode + current_mode.deactivate() + current_mode = path + path.activate() diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/settings.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,16 @@ +import vim + + +def setting(name, default=None): + full_name = 'g:splice_' + name + + if not int(vim.eval('exists("%s")' % full_name)): + return default + else: + return vim.eval(full_name) + +def boolsetting(name): + if int(setting(name, 0)): + return True + else: + False diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/util/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/util/__init__.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,2 @@ +# This is kind of a dirty hack. Feels bad, man. +from bufferlib import buffers diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/util/bufferlib.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/util/bufferlib.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,91 @@ +import os +import vim +import windows + +ap = os.path.abspath + +class Buffer(object): + def __init__(self, i): + self.number = i + 1 + self._buffer = vim.buffers[i] + self.name = self._buffer.name + + def open(self, winnr=None): + if winnr is not None: + windows.focus(winnr) + vim.command('%dbuffer' % self.number) + + def set_lines(self, lines): + self._buffer[:] = lines + + @property + def lines(self): + for line in self._buffer: + yield line + + + def __eq__(self, other): + return self.name == other.name + + def __ne__(self, other): + return self.name != other.name + + +class _BufferList(object): + @property + def original(self): + return Buffer(0) + + @property + def one(self): + return Buffer(1) + + @property + def two(self): + return Buffer(2) + + @property + def result(self): + return Buffer(3) + + @property + def hud(self): + return Buffer(int(vim.eval("bufnr('__Splice_HUD__')")) - 1) + + + @property + def current(self): + bufname = ap(vim.eval('bufname("%")')) + + if bufname == ap(self.original.name): + return self.original + elif bufname == ap(self.one.name): + return self.one + elif bufname == ap(self.two.name): + return self.two + elif bufname == ap(self.result.name): + return self.result + + @property + def all(self): + return [self.original, self.one, self.two, self.result] + + + @property + def labels(self): + return { buffers.original.name: 'Original', + buffers.one.name: 'One', + buffers.two.name: 'Two', + buffers.result.name: 'Result' } + + class remain: + def __enter__(self): + self.curbuf = vim.eval('bufnr(bufname("%"))') + self.pos = windows.pos() + + def __exit__(self, type, value, traceback): + vim.command('%dbuffer' % self.curbuf) + vim.current.window.cursor = self.pos + +buffers = _BufferList() + diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/util/io.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/util/io.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,5 @@ +import sys + + +def error(m): + sys.stderr.write(str(m) + '\n') diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/util/keys.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/util/keys.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,34 @@ +import vim +from bufferlib import buffers +from ..settings import setting + + +def bind(key, to, options='', mode=None, leader=None): + if not leader: + leader = setting('leader', '-') + + vim.command('nnoremap %s %s%s %s' % (options, leader, key, to)) + +def unbind(key, options='', leader=None): + if not leader: + leader = setting('leader', '-') + + vim.command('unmap %s %s%s' % (options, leader, key)) + +def bind_for_all(key, to, options='', mode=None, leader=None): + if not leader: + leader = setting('leader', '') + + with buffers.remain(): + for b in buffers.all: + b.open() + bind(key, to, options, mode, leader) + +def unbind_for_all(key, options='', leader=None): + if not leader: + leader = setting('leader', '') + + with buffers.remain(): + for b in buffers.all: + b.open() + unbind(key, options, leader) diff -r c3f318a26db2 -r 0013f7e01b6e autoload/splicelib/util/windows.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/autoload/splicelib/util/windows.py Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,36 @@ +import vim + + +def focus(winnr): + vim.command('%dwincmd w' % winnr) + +def close(winnr): + focus(winnr) + vim.command('wincmd c') + +def close_all(): + for winnr in range(len(vim.windows) - 1): + close(winnr) + +def split(): + vim.command('wincmd s') + +def vsplit(): + vim.command('wincmd v') + +def currentnr(): + return int(vim.eval('winnr()')) + +def pos(): + return vim.current.window.cursor + + +class remain: + def __enter__(self): + self.curwindow = currentnr() + self.pos = pos() + + def __exit__(self, type, value, traceback): + focus(self.curwindow) + vim.current.window.cursor = self.pos + diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesome.py --- a/autoload/threesome.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -import vim, os, sys - - -# Add the library to the Python path. -for p in vim.eval("&runtimepath").split(','): - plugin_dir = os.path.join(p, "autoload") - if os.path.exists(os.path.join(plugin_dir, "threesomelib")): - if plugin_dir not in sys.path: - sys.path.append(plugin_dir) - break - - -import threesomelib.init as threesome - - -# Wrapper functions ---------------------------------------------------------------- - -def ThreesomeInit(): - threesome.init() - - -def ThreesomeOriginal(): - threesome.modes.current_mode.key_original() - -def ThreesomeOne(): - threesome.modes.current_mode.key_one() - -def ThreesomeTwo(): - threesome.modes.current_mode.key_two() - -def ThreesomeResult(): - threesome.modes.current_mode.key_result() - - -def ThreesomeGrid(): - threesome.modes.key_grid() - -def ThreesomeLoupe(): - threesome.modes.key_loupe() - -def ThreesomeCompare(): - threesome.modes.key_compare() - -def ThreesomePath(): - threesome.modes.key_path() - - -def ThreesomeDiff(): - threesome.modes.current_mode.key_diff() - -def ThreesomeDiffoff(): - threesome.modes.current_mode.key_diffoff() - -def ThreesomeScroll(): - threesome.modes.current_mode.key_scrollbind() - -def ThreesomeLayout(): - threesome.modes.current_mode.key_layout() - -def ThreesomeNext(): - threesome.modes.current_mode.key_next() - -def ThreesomePrev(): - threesome.modes.current_mode.key_prev() - -def ThreesomeUse(): - threesome.modes.current_mode.key_use() - -def ThreesomeUse1(): - threesome.modes.current_mode.key_use1() - -def ThreesomeUse2(): - threesome.modes.current_mode.key_use2() - diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesome.vim --- a/autoload/threesome.vim Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,153 +0,0 @@ -" ============================================================================ -" File: threesome.vim -" Description: vim global plugin for resolving three-way merge conflicts -" Maintainer: Steve Losh -" License: MIT X11 -" ============================================================================ - -" Init {{{ - -" Vim version check {{{ - -if v:version < '703' - function! s:ThreesomeDidNotLoad() - echohl WarningMsg|echomsg "Threesome unavailable: requires Vim 7.3+"|echohl None - endfunction - command! -nargs=0 ThreesomeInit call s:ThreesomeDidNotLoad() - finish -endif - -"}}} -" Python version check {{{ - -if has('python') - let s:has_supported_python = 2 -python << ENDPYTHON -import sys, vim -if sys.version_info[:2] < (2, 5): - vim.command('let s:has_supported_python = 0') -ENDPYTHON -else - let s:has_supported_python = 0 -endif - -if !s:has_supported_python - function! s:ThreesomeDidNotLoad() - echohl WarningMsg|echomsg "Threesome requires Vim to be compiled with Python 2.5+"|echohl None - endfunction - command! -nargs=0 ThreesomeInit call s:ThreesomeDidNotLoad() - finish -endif - -"}}} -" Configuration variables {{{ - -if !exists('g:threesome_disable') "{{{ - let g:threesome_disable = 0 -endif " }}} -if !exists('g:threesome_initial_mode') "{{{ - let g:threesome_initial_mode = 'grid' -endif "}}} -if !exists('g:threesome_initial_layout_grid') "{{{ - let g:threesome_initial_layout_grid = 0 -endif "}}} -if !exists('g:threesome_initial_layout_loupe') "{{{ - let g:threesome_initial_layout_loupe = 0 -endif "}}} -if !exists('g:threesome_initial_layout_compare') "{{{ - let g:threesome_initial_layout_compare = 0 -endif "}}} -if !exists('g:threesome_initial_layout_path') "{{{ - let g:threesome_initial_layout_path = 0 -endif "}}} -if !exists('g:threesome_initial_diff_grid') "{{{ - let g:threesome_initial_diff_grid = 0 -endif "}}} -if !exists('g:threesome_initial_diff_loupe') "{{{ - let g:threesome_initial_diff_loupe = 0 -endif "}}} -if !exists('g:threesome_initial_diff_compare') "{{{ - let g:threesome_initial_diff_compare = 0 -endif "}}} -if !exists('g:threesome_initial_diff_path') "{{{ - let g:threesome_initial_diff_path = 0 -endif "}}} -if !exists('g:threesome_initial_scrollbind_grid') "{{{ - let g:threesome_initial_scrollbind_grid = 0 -endif "}}} -if !exists('g:threesome_initial_scrollbind_loupe') "{{{ - let g:threesome_initial_scrollbind_loupe = 0 -endif "}}} -if !exists('g:threesome_initial_scrollbind_compare') "{{{ - let g:threesome_initial_scrollbind_compare = 0 -endif "}}} -if !exists('g:threesome_initial_scrollbind_path') "{{{ - let g:threesome_initial_scrollbind_path = 0 -endif "}}} - -" }}} - -" }}} -" Wrappers {{{ - -function! threesome#ThreesomeInit() "{{{ - let python_module = fnameescape(globpath(&runtimepath, 'autoload/threesome.py')) - exe 'pyfile ' . python_module - python ThreesomeInit() -endfunction "}}} - -function! threesome#ThreesomeGrid() "{{{ - python ThreesomeGrid() -endfunction "}}} -function! threesome#ThreesomeLoupe() "{{{ - python ThreesomeLoupe() -endfunction "}}} -function! threesome#ThreesomeCompare() "{{{ - python ThreesomeCompare() -endfunction "}}} -function! threesome#ThreesomePath() "{{{ - python ThreesomePath() -endfunction "}}} - -function! threesome#ThreesomeOriginal() "{{{ - python ThreesomeOriginal() -endfunction "}}} -function! threesome#ThreesomeOne() "{{{ - python ThreesomeOne() -endfunction "}}} -function! threesome#ThreesomeTwo() "{{{ - python ThreesomeTwo() -endfunction "}}} -function! threesome#ThreesomeResult() "{{{ - python ThreesomeResult() -endfunction "}}} - -function! threesome#ThreesomeDiff() "{{{ - python ThreesomeDiff() -endfunction "}}} -function! threesome#ThreesomeDiffoff() "{{{ - python ThreesomeDiffoff() -endfunction "}}} -function! threesome#ThreesomeScroll() "{{{ - python ThreesomeScroll() -endfunction "}}} -function! threesome#ThreesomeLayout() "{{{ - python ThreesomeLayout() -endfunction "}}} -function! threesome#ThreesomeNext() "{{{ - python ThreesomeNext() -endfunction "}}} -function! threesome#ThreesomePrev() "{{{ - python ThreesomePrev() -endfunction "}}} -function! threesome#ThreesomeUse() "{{{ - python ThreesomeUse() -endfunction "}}} -function! threesome#ThreesomeUse1() "{{{ - python ThreesomeUse1() -endfunction "}}} -function! threesome#ThreesomeUse2() "{{{ - python ThreesomeUse2() -endfunction "}}} - -" }}} diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/__init__.py diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/init.py --- a/autoload/threesomelib/init.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -import vim -import modes -from settings import setting -from util import buffers, keys, windows - - -CONFLICT_MARKER_START = '<<<<<<<' -CONFLICT_MARKER_MARK = '=======' -CONFLICT_MARKER_END = '>>>>>>>' - -def process_result(): - windows.close_all() - buffers.result.open() - - lines = [] - in_conflict = False - for line in buffers.result.lines: - if in_conflict: - if CONFLICT_MARKER_MARK in line: - lines.append(line) - if CONFLICT_MARKER_END in line: - in_conflict = False - continue - - if CONFLICT_MARKER_START in line: - in_conflict = True - continue - - lines.append(line) - - buffers.result.set_lines(lines) - -def bind_global_keys(): - keys.bind('g', ':ThreesomeGrid') - keys.bind('l', ':ThreesomeLoupe') - keys.bind('c', ':ThreesomeCompare') - keys.bind('p', ':ThreesomePath') - - keys.bind('o', ':ThreesomeOriginal') - keys.bind('1', ':ThreesomeOne') - keys.bind('2', ':ThreesomeTwo') - keys.bind('r', ':ThreesomeResult') - - keys.bind('d', ':ThreesomeDiff') - keys.bind('D', ':ThreesomeDiffoff') - keys.bind('s', ':ThreesomeScroll') - keys.bind('n', ':ThreesomeNext') - keys.bind('N', ':ThreesomePrev') - keys.bind('', ':ThreesomeLayout') - keys.bind('u', ':ThreesomeUse') - - keys.bind('q', ':wa:qa') - keys.bind('CC', ':cq') - -def setlocal_buffers(): - buffers.original.open() - vim.command('setlocal noswapfile') - vim.command('setlocal nomodifiable') - if setting('wrap'): - vim.command('setlocal ' + setting('wrap')) - - buffers.one.open() - vim.command('setlocal noswapfile') - vim.command('setlocal nomodifiable') - if setting('wrap'): - vim.command('setlocal ' + setting('wrap')) - - buffers.two.open() - vim.command('setlocal noswapfile') - vim.command('setlocal nomodifiable') - if setting('wrap'): - vim.command('setlocal ' + setting('wrap')) - - buffers.result.open() - if setting('wrap'): - vim.command('setlocal ' + setting('wrap')) - - buffers.hud.open() - vim.command('setlocal noswapfile') - vim.command('setlocal nomodifiable') - vim.command('setlocal nobuflisted') - vim.command('setlocal buftype=nofile') - vim.command('setlocal noundofile') - vim.command('setlocal nolist') - vim.command('setlocal ft=threesome') - vim.command('setlocal nowrap') - vim.command('resize ' + setting('hud_size', '3')) - -def create_hud(): - vim.command('new __Threesome_HUD__') - - -def init(): - process_result() - create_hud() - setlocal_buffers() - bind_global_keys() - - vim.command('set hidden') - - initial_mode = setting('initial_mode', 'grid').lower() - if initial_mode not in ['grid', 'loupe', 'compare', 'path']: - initial_mode = 'grid' - - modes.current_mode = getattr(modes, initial_mode) - modes.current_mode.activate() - - diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/modes.py --- a/autoload/threesomelib/modes.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,910 +0,0 @@ -from __future__ import with_statement - -import vim -from util import buffers, keys, windows -from settings import boolsetting, setting - - -current_mode = None - -class Mode(object): - def __init__(self): - return super(Mode, self).__init__() - - - def diff(self, diffmode): - with windows.remain(): - getattr(self, '_diff_%d' % diffmode)() - - # Reset the scrollbind to whatever it was before we diffed. - if not diffmode: - self.scrollbind(self._current_scrollbind) - - def key_diff(self, diffmode=None): - next_diff_mode = self._current_diff_mode + 1 - if next_diff_mode >= self._number_of_diff_modes: - next_diff_mode = 0 - self.diff(next_diff_mode) - - - def diffoff(self): - with windows.remain(): - for winnr in range(2, 2 + self._number_of_windows): - windows.focus(winnr) - curbuffer = buffers.current - - for buffer in buffers.all: - buffer.open() - vim.command('diffoff') - if setting('wrap'): - vim.command('setlocal ' + setting('wrap')) - - curbuffer.open() - - - def key_diffoff(self): - self.diff(0) - - - def scrollbind(self, enabled): - if self._current_diff_mode: - return - - with windows.remain(): - self._current_scrollbind = enabled - - for winnr in range(2, 2 + self._number_of_windows): - windows.focus(winnr) - - if enabled: - vim.command('set scrollbind') - else: - vim.command('set noscrollbind') - - if enabled: - vim.command('syncbind') - - def key_scrollbind(self): - self.scrollbind(not self._current_scrollbind) - - - def layout(self, layoutnr): - getattr(self, '_layout_%d' % layoutnr)() - self.diff(self._current_diff_mode) - self.redraw_hud() - - def key_layout(self, diffmode=None): - next_layout = self._current_layout + 1 - if next_layout >= self._number_of_layouts: - next_layout = 0 - self.layout(next_layout) - - - def key_original(self): - pass - - def key_one(self): - pass - - def key_two(self): - pass - - def key_result(self): - pass - - - def key_use(self): - pass - - - def activate(self): - self.layout(self._current_layout) - self.diff(self._current_diff_mode) - self.scrollbind(self._current_scrollbind) - - def deactivate(self): - pass - - - def key_next(self): - self.goto_result() - vim.command(r'exe "silent! normal! /\\v^\\=\\=\\=\\=\\=\\=\\=*$\"') - - def key_prev(self): - self.goto_result() - vim.command(r'exe "silent! normal! ?\\v^\\=\\=\\=\\=\\=\\=\\=*$\"') - - - def open_hud(self, winnr): - windows.split() - windows.focus(winnr) - buffers.hud.open() - vim.command('wincmd K') - self.redraw_hud() - - def hud_lines(self): - def pad(lines): - l = max([len(line) for line in lines]) - return [line.ljust(l) for line in lines] - - sep = ' | ' - - modes = pad([ - r'Threesome Modes', - r'x[g]rid y[c]ompare'.replace('x', self._id == 'grid' and '*' or ' ') - .replace('y', self._id == 'comp' and '*' or ' '), - r'x[l]oupe y[p]ath'.replace('x', self._id == 'loup' and '*' or ' ') - .replace('y', self._id == 'path' and '*' or ' '), - ]) - diagram = pad(self.hud_diagram()) - commands = pad([ - r'Threesome Commands', - r'd: cycle diffs n: next conflict space: cycle layouts u: use hunk o: original 1: one q: save and quit', - r'D: diffs off N: prev conflict s: toggle scrollbind r: result 2: two CC: exit with error', - ]) - - lines = [] - for line in modes: - lines.append(line + sep) - for i, line in enumerate(diagram): - lines[i] += line + sep - for i, line in enumerate(commands): - lines[i] += line + sep - - for i, line in enumerate(lines): - lines[i] = line.rstrip() - - return lines - - def redraw_hud(self): - with windows.remain(): - windows.focus(1) - - vim.command('setlocal modifiable') - buffers.hud.set_lines(self.hud_lines()) - vim.command('setlocal nomodifiable') - - vim.command('set winfixheight') - vim.command('resize ' + setting('hud_size', '3')) - vim.command('wincmd =') - - -class GridMode(Mode): - """ - Layout 0 Layout 1 Layout 2 - +-------------------+ +--------------------------+ +---------------+ - | Original | | One | Result | Two | | One | - |2 | | | | | |2 | - +-------------------+ | | | | +---------------+ - | One | Two | | | | | | Result | - |3 |4 | | | | | |3 | - +-------------------+ | | | | +---------------+ - | Result | | | | | | Two | - |5 | |2 |3 |4 | |4 | - +-------------------+ +--------------------------+ +---------------+ - """ - - def __init__(self): - self._id = 'grid' - self._current_layout = int(setting('initial_layout_grid', 0)) - self._current_diff_mode = int(setting('initial_diff_grid', 0)) - self._current_scrollbind = boolsetting('initial_scrollbind_grid') - - self._number_of_diff_modes = 2 - self._number_of_layouts = 3 - - return super(GridMode, self).__init__() - - - def _layout_0(self): - self._number_of_windows = 4 - self._current_layout = 0 - - # Open the layout - windows.close_all() - windows.split() - windows.split() - windows.focus(2) - windows.vsplit() - - # Put the buffers in the appropriate windows - windows.focus(1) - buffers.original.open() - - windows.focus(2) - buffers.one.open() - - windows.focus(3) - buffers.two.open() - - windows.focus(4) - buffers.result.open() - - self.open_hud(5) - - windows.focus(5) - - def _layout_1(self): - self._number_of_windows = 3 - self._current_layout = 1 - - # Open the layout - windows.close_all() - windows.vsplit() - windows.vsplit() - - # Put the buffers in the appropriate windows - windows.focus(1) - buffers.one.open() - - windows.focus(2) - buffers.result.open() - - windows.focus(3) - buffers.two.open() - - self.open_hud(4) - - windows.focus(3) - - def _layout_2(self): - self._number_of_windows = 4 - self._current_layout = 2 - - # Open the layout - windows.close_all() - windows.split() - windows.split() - - # Put the buffers in the appropriate windows - windows.focus(1) - buffers.one.open() - - windows.focus(2) - buffers.result.open() - - windows.focus(3) - buffers.two.open() - - self.open_hud(4) - - windows.focus(3) - - - def _diff_0(self): - self.diffoff() - self._current_diff_mode = 0 - - def _diff_1(self): - self.diffoff() - self._current_diff_mode = 1 - - for i in range(2, self._number_of_windows + 2): - windows.focus(i) - vim.command('diffthis') - - - def key_original(self): - if self._current_layout == 0: - windows.focus(2) - elif self._current_layout == 1: - return - elif self._current_layout == 2: - return - - def key_one(self): - if self._current_layout == 0: - windows.focus(3) - elif self._current_layout == 1: - windows.focus(2) - elif self._current_layout == 2: - windows.focus(2) - - def key_two(self): - if self._current_layout == 0: - windows.focus(4) - elif self._current_layout == 1: - windows.focus(4) - elif self._current_layout == 2: - windows.focus(4) - - def key_result(self): - if self._current_layout == 0: - windows.focus(5) - elif self._current_layout == 1: - windows.focus(3) - elif self._current_layout == 2: - windows.focus(3) - - - def _key_use_0(self, target): - targetwin = 3 if target == 1 else 4 - - with windows.remain(): - self.diffoff() - - windows.focus(5) - vim.command('diffthis') - - windows.focus(targetwin) - vim.command('diffthis') - - def _key_use_12(self, target): - targetwin = 2 if target == 1 else 4 - - with windows.remain(): - self.diffoff() - - windows.focus(3) - vim.command('diffthis') - - windows.focus(targetwin) - vim.command('diffthis') - - - def key_use1(self): - current_diff = self._current_diff_mode - - if self._current_layout == 0: - self._key_use_0(1) - elif self._current_layout == 1: - self._key_use_12(1) - elif self._current_layout == 2: - self._key_use_12(1) - - if buffers.current == buffers.result: - vim.command('diffget') - elif buffers.current in (buffers.one, buffers.two): - vim.command('diffput') - - self.diff(current_diff) - - def key_use2(self): - current_diff = self._current_diff_mode - - if self._current_layout == 0: - self._key_use_0(2) - elif self._current_layout == 1: - self._key_use_12(2) - elif self._current_layout == 2: - self._key_use_12(2) - - if buffers.current == buffers.result: - vim.command('diffget') - elif buffers.current in (buffers.one, buffers.two): - vim.command('diffput') - - self.diff(current_diff) - - - def goto_result(self): - if self._current_layout == 0: - windows.focus(5) - elif self._current_layout == 1: - windows.focus(3) - elif self._current_layout == 2: - windows.focus(3) - - - def activate(self): - keys.unbind('u') - keys.bind('u1', ':ThreesomeUse1') - keys.bind('u2', ':ThreesomeUse2') - return super(GridMode, self).activate() - - def deactivate(self): - keys.unbind('u1') - keys.unbind('u2') - keys.bind('u', ':ThreesomeUse') - return super(GridMode, self).deactivate() - - - def hud_diagram(self): - if self._current_layout == 0: - return [ - r' Original', - r'Layout -> One Two', - r' Result', - ] - elif self._current_layout == 1: - return [ - r'', - r'Layout -> One Result Two', - r'', - ] - elif self._current_layout == 2: - return [ - r' One', - r'Layout -> Result', - r' Two', - ] - -class LoupeMode(Mode): - def __init__(self): - self._id = 'loup' - self._current_layout = int(setting('initial_layout_loupe', 0)) - self._current_diff_mode = int(setting('initial_diff_loupe', 0)) - self._current_scrollbind = boolsetting('initial_scrollbind_loupe') - - self._number_of_diff_modes = 1 - self._number_of_layouts = 1 - - self._current_buffer = buffers.result - - return super(LoupeMode, self).__init__() - - - def _diff_0(self): - self.diffoff() - self._current_diff_mode = 0 - - - def _layout_0(self): - self._number_of_windows = 1 - self._current_layout = 0 - - # Open the layout - windows.close_all() - - # Put the buffers in the appropriate windows - windows.focus(1) - self._current_buffer.open() - - self.open_hud(2) - - windows.focus(2) - - - def key_original(self): - windows.focus(2) - buffers.original.open() - self._current_buffer = buffers.original - self.redraw_hud() - - def key_one(self): - windows.focus(2) - buffers.one.open() - self._current_buffer = buffers.one - self.redraw_hud() - - def key_two(self): - windows.focus(2) - buffers.two.open() - self._current_buffer = buffers.two - self.redraw_hud() - - def key_result(self): - windows.focus(2) - buffers.result.open() - self._current_buffer = buffers.result - self.redraw_hud() - - - def key_use(self): - pass - - - def goto_result(self): - self.key_result() - - - def hud_diagram(self): - buf = buffers.labels[self._current_buffer.name] - - if self._current_layout == 0: - return [ - r'', - r'Layout -> %s ' % (buf,), - r'', - ] - -class CompareMode(Mode): - def __init__(self): - self._id = 'comp' - self._current_layout = int(setting('initial_layout_compare', 0)) - self._current_diff_mode = int(setting('initial_diff_compare', 0)) - self._current_scrollbind = boolsetting('initial_scrollbind_compare') - - self._number_of_diff_modes = 2 - self._number_of_layouts = 2 - - self._current_buffer_first = buffers.original - self._current_buffer_second = buffers.result - - return super(CompareMode, self).__init__() - - - def _diff_0(self): - self.diffoff() - self._current_diff_mode = 0 - - def _diff_1(self): - self.diffoff() - self._current_diff_mode = 1 - - windows.focus(2) - vim.command('diffthis') - - windows.focus(3) - vim.command('diffthis') - - - def _layout_0(self): - self._number_of_windows = 2 - self._current_layout = 0 - - # Open the layout - windows.close_all() - windows.vsplit() - - # Put the buffers in the appropriate windows - windows.focus(1) - self._current_buffer_first.open() - - windows.focus(2) - self._current_buffer_second.open() - - self.open_hud(3) - - windows.focus(3) - - def _layout_1(self): - self._number_of_windows = 2 - self._current_layout = 1 - - # Open the layout - windows.close_all() - windows.split() - - # Put the buffers in the appropriate windows - windows.focus(1) - self._current_buffer_first.open() - - windows.focus(2) - self._current_buffer_second.open() - - self.open_hud(3) - - windows.focus(3) - - - def key_original(self): - windows.focus(2) - buffers.original.open() - self._current_buffer_first = buffers.original - self.diff(self._current_diff_mode) - - self.redraw_hud() - - def key_one(self): - def open_one(winnr): - buffers.one.open(winnr) - if winnr == 2: - self._current_buffer_first = buffers.one - else: - self._current_buffer_second = buffers.one - self.diff(self._current_diff_mode) - self.redraw_hud() - - curwindow = windows.currentnr() - if curwindow == 1: - curwindow = 2 - - # If file one is showing, go to it. - windows.focus(2) - if buffers.current == buffers.one: - return - - windows.focus(3) - if buffers.current == buffers.one: - return - - # If both the original and result are showing, open file one in the - # current window. - windows.focus(2) - if buffers.current == buffers.original: - windows.focus(3) - if buffers.current == buffers.result: - open_one(curwindow) - return - - # If file two is in window 1, then we open file one in window 1. - windows.focus(2) - if buffers.current == buffers.two: - open_one(2) - return - - # Otherwise, open file one in the current window. - open_one(curwindow) - - def key_two(self): - def open_two(winnr): - buffers.two.open(winnr) - if winnr == 2: - self._current_buffer_first = buffers.two - else: - self._current_buffer_second = buffers.two - self.diff(self._current_diff_mode) - self.redraw_hud() - - curwindow = windows.currentnr() - if curwindow == 1: - curwindow = 2 - - # If file two is showing, go to it. - windows.focus(2) - if buffers.current == buffers.two: - return - - windows.focus(3) - if buffers.current == buffers.two: - return - - # If both the original and result are showing, open file two in the - # current window. - windows.focus(2) - if buffers.current == buffers.original: - windows.focus(3) - if buffers.current == buffers.result: - open_two(curwindow) - return - - # If file one is in window 2, then we open file two in window 2. - windows.focus(3) - if buffers.current == buffers.two: - open_two(3) - return - - # Otherwise, open file two in window 2. - open_two(curwindow) - - def key_result(self): - windows.focus(3) - buffers.result.open() - self._current_buffer_second = buffers.result - self.diff(self._current_diff_mode) - - self.redraw_hud() - - - def key_use(self): - active = (self._current_buffer_first, self._current_buffer_second) - - if buffers.result not in active: - return - - if buffers.one not in active and buffers.two not in active: - return - - current_diff = self._current_diff_mode - with windows.remain(): - self._diff_1() # diff the windows - - if buffers.current == buffers.result: - vim.command('diffget') - elif buffers.current in (buffers.one, buffers.two): - vim.command('diffput') - - self.diff(current_diff) - - - def goto_result(self): - self.key_result() - - - def hud_diagram(self): - first = buffers.labels[self._current_buffer_first.name] - second = buffers.labels[self._current_buffer_second.name] - - if self._current_layout == 0: - return [ - r'', - r'Layout -> %s %s' % (first, second), - r'', - ] - elif self._current_layout == 1: - return [ - r'', - r'Layout -> %s' % first, - r' %s' % second, - ] - -class PathMode(Mode): - def __init__(self): - self._id = 'path' - self._current_layout = int(setting('initial_layout_path', 0)) - self._current_diff_mode = int(setting('initial_diff_path', 0)) - self._current_scrollbind = boolsetting('initial_scrollbind_path') - - self._number_of_diff_modes = 5 - self._number_of_layouts = 2 - - self._current_mid_buffer = buffers.one - - return super(PathMode, self).__init__() - - - def _diff_0(self): - self.diffoff() - self._current_diff_mode = 0 - - def _diff_1(self): - self.diffoff() - self._current_diff_mode = 1 - - windows.focus(2) - vim.command('diffthis') - - windows.focus(4) - vim.command('diffthis') - - def _diff_2(self): - self.diffoff() - self._current_diff_mode = 2 - - windows.focus(2) - vim.command('diffthis') - - windows.focus(3) - vim.command('diffthis') - - def _diff_3(self): - self.diffoff() - self._current_diff_mode = 3 - - windows.focus(3) - vim.command('diffthis') - - windows.focus(4) - vim.command('diffthis') - - def _diff_4(self): - self.diffoff() - self._current_diff_mode = 4 - - windows.focus(2) - vim.command('diffthis') - - windows.focus(3) - vim.command('diffthis') - - windows.focus(4) - vim.command('diffthis') - - - def _layout_0(self): - self._number_of_windows = 3 - self._current_layout = 0 - - # Open the layout - windows.close_all() - windows.vsplit() - windows.vsplit() - - # Put the buffers in the appropriate windows - windows.focus(1) - buffers.original.open() - - windows.focus(2) - self._current_mid_buffer.open() - - windows.focus(3) - buffers.result.open() - - self.open_hud(4) - - windows.focus(4) - - def _layout_1(self): - self._number_of_windows = 3 - self._current_layout = 1 - - # Open the layout - windows.close_all() - windows.split() - windows.split() - - # Put the buffers in the appropriate windows - windows.focus(1) - buffers.original.open() - - windows.focus(2) - self._current_mid_buffer.open() - - windows.focus(3) - buffers.result.open() - - self.open_hud(4) - - windows.focus(4) - - - def key_original(self): - windows.focus(2) - - def key_one(self): - windows.focus(3) - buffers.one.open() - self._current_mid_buffer = buffers.one - self.diff(self._current_diff_mode) - windows.focus(3) - self.redraw_hud() - - def key_two(self): - windows.focus(3) - buffers.two.open() - self._current_mid_buffer = buffers.two - self.diff(self._current_diff_mode) - windows.focus(3) - self.redraw_hud() - - def key_result(self): - windows.focus(4) - - - def key_use(self): - current_diff = self._current_diff_mode - with windows.remain(): - self._diff_3() # diff the middle and result windows - - if buffers.current == buffers.result: - vim.command('diffget') - elif buffers.current in (buffers.one, buffers.two): - vim.command('diffput') - - self.diff(current_diff) - - - def goto_result(self): - windows.focus(4) - - - def hud_diagram(self): - if self._current_mid_buffer == buffers.one: - buf = 'One' - else: - buf = 'Two' - - if self._current_layout == 0: - return [ - r'', - r'Layout -> Original %s Result' % buf, - r'', - ] - elif self._current_layout == 1: - return [ - r' Original', - r'Layout -> %s' % buf, - r' Result', - ] - - -grid = GridMode() -loupe = LoupeMode() -compare = CompareMode() -path = PathMode() - - -def key_grid(): - global current_mode - current_mode.deactivate() - current_mode = grid - grid.activate() - -def key_loupe(): - global current_mode - current_mode.deactivate() - current_mode = loupe - loupe.activate() - -def key_compare(): - global current_mode - current_mode.deactivate() - current_mode = compare - compare.activate() - -def key_path(): - global current_mode - current_mode.deactivate() - current_mode = path - path.activate() diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/settings.py --- a/autoload/threesomelib/settings.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -import vim - - -def setting(name, default=None): - full_name = 'g:threesome_' + name - - if not int(vim.eval('exists("%s")' % full_name)): - return default - else: - return vim.eval(full_name) - -def boolsetting(name): - if int(setting(name, 0)): - return True - else: - False diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/util/__init__.py --- a/autoload/threesomelib/util/__init__.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -# This is kind of a dirty hack. Feels bad, man. -from bufferlib import buffers diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/util/bufferlib.py --- a/autoload/threesomelib/util/bufferlib.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -import os -import vim -import windows - -ap = os.path.abspath - -class Buffer(object): - def __init__(self, i): - self.number = i + 1 - self._buffer = vim.buffers[i] - self.name = self._buffer.name - - def open(self, winnr=None): - if winnr is not None: - windows.focus(winnr) - vim.command('%dbuffer' % self.number) - - def set_lines(self, lines): - self._buffer[:] = lines - - @property - def lines(self): - for line in self._buffer: - yield line - - - def __eq__(self, other): - return self.name == other.name - - def __ne__(self, other): - return self.name != other.name - - -class _BufferList(object): - @property - def original(self): - return Buffer(0) - - @property - def one(self): - return Buffer(1) - - @property - def two(self): - return Buffer(2) - - @property - def result(self): - return Buffer(3) - - @property - def hud(self): - return Buffer(int(vim.eval("bufnr('__Threesome_HUD__')")) - 1) - - - @property - def current(self): - bufname = ap(vim.eval('bufname("%")')) - - if bufname == ap(self.original.name): - return self.original - elif bufname == ap(self.one.name): - return self.one - elif bufname == ap(self.two.name): - return self.two - elif bufname == ap(self.result.name): - return self.result - - @property - def all(self): - return [self.original, self.one, self.two, self.result] - - - @property - def labels(self): - return { buffers.original.name: 'Original', - buffers.one.name: 'One', - buffers.two.name: 'Two', - buffers.result.name: 'Result' } - - class remain: - def __enter__(self): - self.curbuf = vim.eval('bufnr(bufname("%"))') - self.pos = windows.pos() - - def __exit__(self, type, value, traceback): - vim.command('%dbuffer' % self.curbuf) - vim.current.window.cursor = self.pos - -buffers = _BufferList() - diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/util/io.py --- a/autoload/threesomelib/util/io.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -import sys - - -def error(m): - sys.stderr.write(str(m) + '\n') diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/util/keys.py --- a/autoload/threesomelib/util/keys.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -import vim -from bufferlib import buffers -from ..settings import setting - - -def bind(key, to, options='', mode=None, leader=None): - if not leader: - leader = setting('leader', '') - - vim.command('nnoremap %s %s%s %s' % (options, leader, key, to)) - -def unbind(key, options='', leader=None): - if not leader: - leader = setting('leader', '') - - vim.command('unmap %s %s%s' % (options, leader, key)) - -def bind_for_all(key, to, options='', mode=None, leader=None): - if not leader: - leader = setting('leader', '') - - with buffers.remain(): - for b in buffers.all: - b.open() - bind(key, to, options, mode, leader) - -def unbind_for_all(key, options='', leader=None): - if not leader: - leader = setting('leader', '') - - with buffers.remain(): - for b in buffers.all: - b.open() - unbind(key, options, leader) diff -r c3f318a26db2 -r 0013f7e01b6e autoload/threesomelib/util/windows.py --- a/autoload/threesomelib/util/windows.py Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -import vim - - -def focus(winnr): - vim.command('%dwincmd w' % winnr) - -def close(winnr): - focus(winnr) - vim.command('wincmd c') - -def close_all(): - for winnr in range(len(vim.windows) - 1): - close(winnr) - -def split(): - vim.command('wincmd s') - -def vsplit(): - vim.command('wincmd v') - -def currentnr(): - return int(vim.eval('winnr()')) - -def pos(): - return vim.current.window.cursor - - -class remain: - def __enter__(self): - self.curwindow = currentnr() - self.pos = pos() - - def __exit__(self, type, value, traceback): - focus(self.curwindow) - vim.current.window.cursor = self.pos - diff -r c3f318a26db2 -r 0013f7e01b6e doc/splice.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/splice.txt Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,660 @@ +*splice.txt* A plugin for resolving three-way merge conflicts. + +Splice is a Vim plugin for resolving conflicts during three-way merges. +It's designed to be used as a merge tool for version control systems like +Mercurial, Git and Bazaar. + +============================================================================== +CONTENTS *Splice-contents* + + 1. Version Control Integration ............... |SpliceVCS| + 1.1 Mercurial ............................ |SpliceVCS_hg| + 1.2 Git .................................. |SpliceVCS_git| + 1.3 Bazaar ............................... |SpliceVCS_bzr| + 2. Basic Usage ............................... |SpliceUsage| + 2.1 Files ................................ |SpliceUsage_files| + 2.2 Modes ................................ |SpliceUsage_modes| + 3. Key Bindings .............................. |SpliceKeys| + 3.1 Mode Selection Keys .................. |SpliceKeys_mode| + 3.2 File Selection Keys .................. |SpliceKeys_file| + 3.3 Other Keys ........................... |SpliceKeys_other| + 4. Modes ..................................... |SpliceModes| + 4.1 Grid ................................. |SpliceModes_grid| + 4.2 Loupe ................................ |SpliceModes_loupe| + 4.3 Compare .............................. |SpliceModes_compare| + 4.4 Path ................................. |SpliceModes_path| + 5. Configuration ............................. |SpliceConfig| + 5.1 splice_debug ......................... |SpliceConfig_debug| + 5.2 splice_disable ....................... |SpliceConfig_disable| + 5.3 splice_initial_diff_grid ............. |SpliceConfig_id_grid| + 5.4 splice_initial_diff_loupe ............ |SpliceConfig_id_loupe| + 5.5 splice_initial_diff_compare .......... |SpliceConfig_id_compare| + 5.6 splice_initial_diff_path ............. |SpliceConfig_id_path| + 5.7 splice_initial_layout_grid ........... |SpliceConfig_il_grid| + 5.8 splice_initial_layout_loupe .......... |SpliceConfig_il_loupe| + 5.9 splice_initial_layout_compare ........ |SpliceConfig_il_compare| + 5.10 splice_initial_layout_path .......... |SpliceConfig_il_path| + 5.11 splice_initial_scrollbind_grid ...... |SpliceConfig_is_grid| + 5.12 splice_initial_scrollbind_loupe ..... |SpliceConfig_is_loupe| + 5.13 splice_initial_scrollbind_compare ... |SpliceConfig_is_compare| + 5.14 splice_initial_scrollbind_path ...... |SpliceConfig_is_path| + 5.15 splice_initial_mode ................. |SpliceConfig_im| + 5.16 splice_prefix ....................... |SpliceConfig_prefix| + 5.17 splice_wrap ......................... |SpliceConfig_wrap| + 6. License ................................... |SpliceLicense| + 7. Bugs ...................................... |SpliceBugs| + 8. Contributing .............................. |SpliceContributing| + 9. Changelog ................................. |SpliceChangelog| + 10. Credits ................................... |SpliceCredits| + + +============================================================================== +1. Version Control Integration *SpliceVCS* + +Splice is meant to be called by your version control system when it needs you +to resolve merge conflicts. You will need to configure your VCS to do this +before you can use Splice. + +*Note: If you'd like to use a Vim GUI instead of console vim, replace + "vim" in the following commands with your choice of "mvim" or "gvim". + +------------------------------------------------------------------------------ +1.1 Mercurial *SpliceVCS_hg* + +Add the following lines to "~/.hgrc": > + + [merge-tools] + splice.executable = vim + splice.args = -f $base $local $other $output -c 'SpliceInit' + splice.premerge = keep + splice.priority = 1 + +Mercurial will now open Vim with Splice whenever a file has merge conflicts +which need to be resolved. + +------------------------------------------------------------------------------ +1.2 Git *SpliceVCS_git* + +Add the following lines to "~/.gitconfig": > + + [merge] + tool = splice + + [mergetool "splice"] + cmd = "vim -f $BASE $LOCAL $REMOTE $MERGED -c 'SpliceInit'" + trustExitCode = true + +If a "git merge" or "git pull" fails with merge conflicts you can now run +"git mergetool". Git will loop over all the files with conflicts and allow +you to resolve them with Vim and Splice. + +------------------------------------------------------------------------------ +1.3 Bazaar *SpliceVCS_bzr* + +For Bazaar 2.4 or greater, add the following line to bazaar.conf: +> + bzr.mergetool.splice = vim {base} {this} {other} {result} -c 'SpliceInit' +< +Optionally, change the default merge tool by setting: +> + bzr.default_mergetool = splice +< +For earlier versions of Bazaar, set the following entry in bazaar.conf: +> + external_merge = vim %b %t %o %r -c 'SpliceInit' +< +You can now use Vim with Splice from "bzr qconflicts". + +============================================================================== +2. Basic Usage *SpliceUsage* + +Splice takes a lot of inspiration for its user interface from Adobe Lightroom, +a photo editing program. + +When resolving merge conflicts your goal is: + + - Examine the three files describing the changes being merged. + - Combine these changes into a fourth file (the "result"). + - Save the result to disk. + - Exit Vim with a non-error status code to tell the VCS the merge succeeded. + +Splice has several "modes" to help you work with the various files. + +------------------------------------------------------------------------------ +2.1 Files *SpliceUsage_files* + +When resolving a merge there are four files you will work with: + +Original *SpliceUsage_files_original* + The original file, as it appears in the parent revision of the two + revisions being merged. + +One *SpliceUsage_files_one* + The file as it appears in the first revision being merged. + + This is usually the "current" revision, or the one you are at when you + run "hg merge REV"). + +Two *SpliceUsage_files_two* + The file as it appears in the second revision being merged. + + This is usually the "target" revision, or the one you specify in the + "hg merge REV" command). + +Result *SpliceUsage_files_result* + The result of merging the two revisions of the file. + + This is the file that your version control system expects to contain the + final result once you're done. + +------------------------------------------------------------------------------ +2.2 Modes *SpliceUsage_modes* + +Splice has four "modes" or "views" for working with the files. + +Grid *SpliceUsage_modes_grid* + Shows all four files at once to give you an overview of the merge. + + See |SpliceModes-grid| for more information. + +Loupe *SpliceUsage_modes_loupe* + Shows a single file at a time for close examination of a single file. + + See |SpliceModes-loupe| for more information. + +Compare *SpliceUsage_modes_compare* + Shows two files at a time for examining the movement of changes between + pairs of files. + + See |SpliceModes-compare| for more information. + +Path *SpliceUsage_modes_path* + Shows three files at a time: + + - The original + - Either one or two + - The result + + Used for examining how a change moves through one "path" or "branch" + of the merge. + + See |SpliceModes-path| for more information. + + +============================================================================== +3. Key Bindings *SpliceKeys* + +All of Splice's key mappings are prefixed with a single key to group them +together and avoid shadowing other mappings. By default this key is '-' +(minus/hyphen). + +See the |SpliceConfig_prefix| setting if you'd like to change this prefix to +something else. + +All keybindings are used across (almost) all modes. + +The behavior of some of them changes depending on the current mode, but the +effects should be fairly intuitive. + +------------------------------------------------------------------------------ +3.1 Mode Selection Keys *SpliceKeys_mode* + +g *Grid* + Switch to grid view. + +l *Loupe* + Switch to loupe view. + +c *Compare* + Switch to compare view. + +p *Path* + Switch to path view. + +------------------------------------------------------------------------------ +3.2 File Selection Keys *SpliceKeys_file* + +o *Original* + Select the original file. + +1 *One* + Select file one. + +2 *Two* + Select file two. + +r *Result* + Select the result file. + +------------------------------------------------------------------------------ +3.3 Other Keys *SpliceKeys_other* + +d *Diff* + Cycle through various diff combinations. + +D *DiffOff* + Turn off all diffs. + +u *UseHunk* + Place a hunk from file one or two into + the result file. + +s *Scroll* + Toggle scroll locking on and off. + + *Layout* + Cycle through various layouts of the + current view. + +n *Next* + Move to the next unresolved conflict. + +N *Previous* + Move to the previous unresolved conflict. + +q *Quit* + Save the result file and exit Vim. + + Indicates to the VCS that the merge was + successful and it should use the current + contents of the result file as the result. + +CC *Cancel* + Exits Vim with an error code (like |:cquit|). + Indicates to the VCS that the merge was + NOT successful. + +============================================================================== +4. Modes *SpliceModes* + +This section describes each mode in detail. + +------------------------------------------------------------------------------ +4.1 Grid *SpliceModes_grid* + +The grid view is used to get an overview of all files at once to get a birds' +eye view of the merge. + +Grid Layouts *SpliceModes_grid_layouts* +------------ + + Layout 0 Layout 1 Layout 2 + +-------------------+ +--------------------------+ +---------------+ + | Original | | One | Result | Two | | One | + | | | | | | | | + +-------------------+ | | | | +---------------+ + | One | Two | | | | | | Result | + | | | | | | | | | + +-------------------+ | | | | +---------------+ + | Result | | | | | | Two | + | | | | | | | | + +-------------------+ +--------------------------+ +---------------+ + +Grid-Specific Key Bindings *SpliceModes_grid_keys* +-------------------------- + +o *Original-Grid* + Select the original file, but only in layout 1. + +u *UseHunk-Grid* + Disabled in this mode. + +u1 *UseHunk1-Grid* + Place a hunk from file one into the result file. + +u2 *UseHunk2-Grid* + Place a hunk from file two into the result file. + +Grid Diffs *SpliceModes_grid_diffs* +---------- + +1. No diff. +2. Diff all files. + +------------------------------------------------------------------------------ +4.2 Loupe *SpliceModes_loupe* + +The loupe view is used to focus on and examine a single file in detail. + +Loupe Layouts *SpliceModes_loupe_layouts* +------------- + + Layout 0 + +-----------------+ + | Any Single File | + | | + | | + | | + | | + | | + +-----------------+ + +Loupe-Specific Key Bindings *SpliceModes_loupe_keys* +--------------------------- + +u *UseHunk-Loupe* + Disabled in this mode. + +Loupe Diffs *SpliceModes_loupe_diffs* +----------- + +No diffs are possible in loupe mode. + +------------------------------------------------------------------------------ +4.3 Compare *SpliceModes_compare* + +The compare view is used to examine the differences between two files at +a time. + +Compare Layouts *SpliceModes_compare_layouts* +--------------- + + Layout 0 Layout 1 + +-------------------+ +-------------------+ + | Orig | Result | | Orig | + | | | | or One | + | or | or | | or Two | + | | | | | + | One | One | +-------------------+ + | | | | One | + | or | or | | or Two | + | | | | or Result | + | Two | Two | | | + +-------------------+ +-------------------+ + +Compare-Specific Key Bindings *SpliceModes_compare_keys* +----------------------------- + +u *UseHunk-Compare* + If the result file and file one/two are + both visible, place a hunk from one/two + into the result file. Otherwise: disabled. + +Compare Diffs *SpliceModes_compare_diffs* +------------- + +1. No diff. +2. Diff both files. + +------------------------------------------------------------------------------ +4.4 Path *SpliceModes_path* + +The path view is used to view the flow of changed through one "path" or +"branch" of the merge. + +Path Layouts *SpliceModes_path_layouts* +------------ + + Layout 0 Layout 1 + +--------------------------+ +-------------------+ + | Orig | | Result | | Orig | + | | One | | | | + | | | | +-------------------+ + | | or | | | One | + | | | | | or Two | + | | Two | | +-------------------+ + | | | | | Result | + | | | | | | + +--------------------------+ +-------------------+ + + +Path-Specific Key Bindings *SpliceModes_path_keys* +-------------------------- + +u *UseHunk-Path* + Place a hunk from file one or two (whichever + is currently in the center window) into the + result file. + +Path Diffs *SpliceModes_path_diffs* +---------- + +1. No diff. +2. Diff the original and center windows. +3. Diff the center and result windows. +4. Diff the original and result windows. + +============================================================================== +5. Configuration *SpliceConfig* + +You can tweak the behavior of Splice by setting a few variables in your +|vimrc| file. For example: > + + let g:splice_initial_mode = "compare" + let g:splice_initial_layout_grid = 2 + let g:splice_initial_layout_compare = 1 + +------------------------------------------------------------------------------ +5.1 g:splice_debug *SpliceConfig_debug* + +Set this to 1 to force Splice to reload every time its file is sourced. + +Options: 0 or 1 +Default: 0 (Splice is loaded only once) + +------------------------------------------------------------------------------ +5.2 g:splice_disable *SpliceConfig_disable* + +Set this to 1 to disable Splice entirely. + +Useful if you use the same ~/.vim folder on multiple machines and some of +them may not have Python support. + +Options: 0 or 1 +Default: 0 (Splice is enabled as usual) + +------------------------------------------------------------------------------ +5.3 g:splice_initial_diff_grid *SpliceConfig_id_grid* + +Set this to change the diff the grid mode starts in. + +See |SpliceModes-grid-diffs| for the list of diffs. + +Options: 0, or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.4 g:splice_initial_diff_loupe *SpliceConfig_id_loupe* + +Set this to change the diff the loupe mode starts in. + +See |SpliceModes-loupe-diffs| for the list of diffs. + +Options: 0 +Default: 0 + +------------------------------------------------------------------------------ +5.5 g:splice_initial_diff_compare *SpliceConfig_id_compare* + +Set this to change the diff the compare mode starts in. + +See |SpliceModes-compare-diffs| for the list of diffs. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.6 g:splice_initial_diff_path *SpliceConfig_id_path* + +Set this to change the diff the path mode starts in. + +See |SpliceModes-path-diffs| for the list of diffs. + +options: 0, 1, 2, 3, or 4 +Default: 0 + +------------------------------------------------------------------------------ +5.7 g:splice_initial_layout_grid *SpliceConfig_il_grid* + +Set this to change the layout the grid mode starts in. + +See |SpliceModes-grid-layouts| for the list of layouts. + +Options: 0, 1, or 2 +Default: 0 + +------------------------------------------------------------------------------ +5.8 g:splice_initial_layout_loupe *SpliceConfig_il_loupe* + +Set this to change the layout the loupe mode starts in. + +See |SpliceModes-loupe-layouts| for the list of layouts. + +Options: 0 +Default: 0 + +------------------------------------------------------------------------------ +5.9 g:splice_initial_layout_compare *SpliceConfig_il_compare* + +Set this to change the layout the compare mode starts in. + +See |SpliceModes-compare-layouts| for the list of layouts. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.10 g:splice_initial_layout_path *SpliceConfig_il_path* + +Set this to change the layout the path mode starts in. + +See |SpliceModes-path-layouts| for the list of layouts. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.11 g:splice_initial_scrollbind_grid *SpliceConfig_is_grid* + +Set this to 1 to enable |scrollbind| by default in grid mode. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.12 g:splice_initial_scrollbind_loupe *SpliceConfig_is_loupe* + +Set this to 1 to enable |scrollbind| by default in loupe mode. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.13 g:splice_initial_scrollbind_compare *SpliceConfig_is_compare* + +Set this to 1 to enable |scrollbind| by default in compare mode. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.14 g:splice_initial_scrollbind_path *SpliceConfig_is_path* + +Set this to 1 to enable |scrollbind| by default in path mode. + +Options: 0 or 1 +Default: 0 + +------------------------------------------------------------------------------ +5.15 g:splice_initial_mode *SpliceConfig_im* + +Set this to change the mode Splice initially starts up in. + +See |SpliceModes| for a description of each mode. + +Options: "grid", "loupe", "compare", or "path" +Default: "grid" + +------------------------------------------------------------------------------ +5.16 g:splice_prefix *SpliceConfig_prefix* + +Set this to change the prefix Splice will bind all of its mappings to. + +For example: > + + let g:splice_prefix = "t" + +Will make all Splice commands start with t instead of the default '-'. + +Options: Any valid key mapping string +Default: "-" + +------------------------------------------------------------------------------ +5.17 g:splice_wrap *SpliceConfig_wrap* + +Set this to "wrap" or "nowrap" to set |wrap| or |nowrap| on all windows by +default. + +By default Splice will use your default settings. + +Options: "wrap", "nowrap" +Default: None (use the default settings) + +============================================================================== +6. License *SpliceLicense* + +Splice is copyright Steve Losh & contributors, 2011+ and is licensed +under the MIT/X11 license. + +============================================================================== +7. Bugs *SpliceBugs* + +Please report any bugs you may find on the GitHub issue tracker: + + http://github.com/sjl/splice.vim/issues + +============================================================================== +8. Contributing *SpliceContributing* + +Think you can make Splice better? Awesome. New contributors are always +welcome. + +Fork the project on BitBucket or GitHub and send a pull request. + + BitBucket: http://bitbucket.org/sjl/splice.vim + GitHub: http://github.com/sjl/splice.vim + +============================================================================== +9. Changelog *SpliceChangelog* + +v1.0.0 + * Rename to Splice. + * Change the default prefix to '-' instead of . +v0.2.0 + * Add threesome_leader as a config option. +v0.1.1 + * Fix a bug when the user doesn't use :set hidden. +v0.1.0 + * Preliminary "it probably won't eat your data" release! +v0.0.8 + * A bunch of cleanup. +v0.0.7 + * Add use hunk functionality. +v0.0.6 + * Add the HUD. + * Configurable wrapping. +v0.0.5 + * Configurable scrollbinding. +v0.0.4 + * Basic configuration settings. +v0.0.3 + * Multiple layout support. +v0.0.2 + * There's still not much working, but at least there's some help now! +v0.0.1 + * Oh god nothing works please don't use this for real work yet. + +============================================================================== +10. Credits *SpliceCredits* + +Splice was originally written by Steve Losh after he got fed up with the lack +of a powerful, intuitive, beautiful three-way merge program on OS X. + +A lot of the inspiration for the layout of the code came from vim-orgmode. + +The UI is a combination of ideas from Conflict2Diff.vim, Fugitive.vim, and +Adobe Lightroom. + +============================================================================== + + vim:ts=4:et:ft=help: diff -r c3f318a26db2 -r 0013f7e01b6e doc/threesome.txt --- a/doc/threesome.txt Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,669 +0,0 @@ -*threesome.txt* A plugin for resolving three-way merge conflicts. - -============================================================================== -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -============================================================================== - - This plugin is still under active development. - - It probably won't eat your data, but don't hate me if it does. - -============================================================================== -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -============================================================================== - - -Threesome is a Vim plugin for resolving conflicts during three-way merges. -It's designed to be used as a merge tool for version control systems like -Mercurial, Git and Bazaar. - -============================================================================== -CONTENTS *Threesome-contents* - - 1. Version Control Integration ................. |ThreesomeVCS| - 1.1 Mercurial .............................. |ThreesomeVCS_hg| - 1.2 Git .................................... |ThreesomeVCS_git| - 1.3 Bazaar ................................. |ThreesomeVCS_bzr| - 2. Basic Usage ................................. |ThreesomeUsage| - 2.1 Files .................................. |ThreesomeUsage_files| - 2.2 Modes .................................. |ThreesomeUsage_modes| - 3. Key Bindings ................................ |ThreesomeKeys| - 3.1 Mode Selection Keys .................... |ThreesomeKeys_mode| - 3.2 File Selection Keys .................... |ThreesomeKeys_file| - 3.3 Other Keys ............................. |ThreesomeKeys_other| - 4. Modes ....................................... |ThreesomeModes| - 4.1 Grid ................................... |ThreesomeModes_grid| - 4.2 Loupe .................................. |ThreesomeModes_loupe| - 4.3 Compare ................................ |ThreesomeModes_compare| - 4.4 Path ................................... |ThreesomeModes_path| - 5. Configuration ............................... |ThreesomeConfig| - 5.1 threesome_debug ........................ |ThreesomeConfig_debug| - 5.2 threesome_disable ...................... |ThreesomeConfig_disable| - 5.3 threesome_initial_diff_grid ............ |ThreesomeConfig_id_grid| - 5.4 threesome_initial_diff_loupe ........... |ThreesomeConfig_id_loupe| - 5.5 threesome_initial_diff_compare ......... |ThreesomeConfig_id_compare| - 5.6 threesome_initial_diff_path ............ |ThreesomeConfig_id_path| - 5.7 threesome_initial_layout_grid .......... |ThreesomeConfig_il_grid| - 5.8 threesome_initial_layout_loupe ......... |ThreesomeConfig_il_loupe| - 5.9 threesome_initial_layout_compare ....... |ThreesomeConfig_il_compare| - 5.10 threesome_initial_layout_path ......... |ThreesomeConfig_il_path| - 5.11 threesome_initial_scrollbind_grid ..... |ThreesomeConfig_is_grid| - 5.12 threesome_initial_scrollbind_loupe .... |ThreesomeConfig_is_loupe| - 5.13 threesome_initial_scrollbind_compare .. |ThreesomeConfig_is_compare| - 5.14 threesome_initial_scrollbind_path ..... |ThreesomeConfig_is_path| - 5.15 threesome_initial_mode ................ |ThreesomeConfig_im| - 5.16 threesome_leader ...................... |ThreesomeConfig_leader| - 5.17 threesome_wrap ........................ |ThreesomeConfig_wrap| - 6. License ..................................... |ThreesomeLicense| - 7. Bugs ........................................ |ThreesomeBugs| - 8. Contributing ................................ |ThreesomeContributing| - 9. Changelog ................................... |ThreesomeChangelog| - 10. Credits ..................................... |ThreesomeCredits| - - -============================================================================== -1. Version Control Integration *ThreesomeVCS* - -Threesome is meant to be called by your version control system when it needs -you to resolve merge conflicts. You will need to configure your VCS to do -this before you can use Threesome. - -*Note: If you'd like to use a Vim GUI instead of console vim, replace - "vim" in the following commands with your choice of "mvim" or "gvim". - ------------------------------------------------------------------------------- -1.1 Mercurial *ThreesomeVCS_hg* - -Add the following lines to "~/.hgrc": > - - [merge-tools] - threesome.executable = vim - threesome.args = -f $base $local $other $output -c 'ThreesomeInit' - threesome.premerge = keep - threesome.priority = 1 - -Mercurial will now open Vim with Threesome whenever a file has merge conflicts -which need to be resolved. - ------------------------------------------------------------------------------- -1.2 Git *ThreesomeVCS_git* - -Add the following lines to "~/.gitconfig": > - - [merge] - tool = threesome - - [mergetool "threesome"] - cmd = "vim -f $BASE $LOCAL $REMOTE $MERGED -c 'ThreesomeInit'" - trustExitCode = true - -If a "git merge" or "git pull" fails with merge conflicts you can now run -"git mergetool". Git will loop over all the files with conflicts and allow -you to resolve them with Vim and Threesome. - ------------------------------------------------------------------------------- -1.3 Bazaar *ThreesomeVCS_bzr* - -For Bazaar 2.4 or greater, add the following line to bazaar.conf: -> - bzr.mergetool.threesome = vim {base} {this} {other} {result} -c 'ThreesomeInit' -< -Optionally, change the default merge tool by setting: -> - bzr.default_mergetool = threesome -< -For earlier versions of Bazaar, set the following entry in bazaar.conf: -> - external_merge = vim %b %t %o %r -c 'ThreesomeInit' -< -You can now use Vim with Threesome from "bzr qconflicts". - -============================================================================== -2. Basic Usage *ThreesomeUsage* - -Threesome takes a lot of inspiration for its user interface from Adobe -Lightroom, a photo editing program. - -When resolving merge conflicts your goal is: - - - Examine the three files describing the changes being merged. - - Combine these changes into a fourth file (the "result"). - - Save the result to disk. - - Exit Vim with a non-error status code to tell the VCS the merge succeeded. - -Threesome has several "modes" to help you work with the various files. - ------------------------------------------------------------------------------- -2.1 Files *ThreesomeUsage_files* - -When resolving a merge there are four files you will work with: - -Original *ThreesomeUsage_files_original* - The original file, as it appears in the parent revision of the two - revisions being merged. - -One *ThreesomeUsage_files_one* - The file as it appears in the first revision being merged. - - This is usually the "current" revision, or the one you are at when you - run "hg merge REV"). - -Two *ThreesomeUsage_files_two* - The file as it appears in the second revision being merged. - - This is usually the "target" revision, or the one you specify in the - "hg merge REV" command). - -Result *ThreesomeUsage_files_result* - The result of merging the two revisions of the file. - - This is the file that your version control system expects to contain the - final result once you're done. - ------------------------------------------------------------------------------- -2.2 Modes *ThreesomeUsage_modes* - -Threesome has four "modes" or "views" for working with the files. - -Grid *ThreesomeUsage_modes_grid* - Shows all four files at once to give you an overview of the merge. - - See |ThreesomeModes-grid| for more information. - -Loupe *ThreesomeUsage_modes_loupe* - Shows a single file at a time for close examination of a single file. - - See |ThreesomeModes-loupe| for more information. - -Compare *ThreesomeUsage_modes_compare* - Shows two files at a time for examining the movement of changes between - pairs of files. - - See |ThreesomeModes-compare| for more information. - -Path *ThreesomeUsage_modes_path* - Shows three files at a time: - - - The original - - Either one or two - - The result - - Used for examining how a change moves through one "path" or "branch" - of the merge. - - See |ThreesomeModes-path| for more information. - - -============================================================================== -3. Key Bindings *ThreesomeKeys* - -Threesome makes use of for all of its key bindings to avoid -clashing with global mappings. If you've never used now -would be a good time to read the |maplocalleader| documentation and -configure a key for it. - -All keybindings are used across (almost) all modes. - -The behavior of some of them changes depending on the current mode, but the -effects should be fairly intuitive. - ------------------------------------------------------------------------------- -3.1 Mode Selection Keys *ThreesomeKeys_mode* - -g *Grid* - Switch to grid view. - -l *Loupe* - Switch to loupe view. - -c *Compare* - Switch to compare view. - -p *Path* - Switch to path view. - ------------------------------------------------------------------------------- -3.2 File Selection Keys *ThreesomeKeys_file* - -o *Original* - Select the original file. - -1 *One* - Select file one. - -2 *Two* - Select file two. - -r *Result* - Select the result file. - ------------------------------------------------------------------------------- -3.3 Other Keys *ThreesomeKeys_other* - -d *Diff* - Cycle through various diff combinations. - -D *DiffOff* - Turn off all diffs. - -u *UseHunk* - Place a hunk from file one or two into - the result file. - -s *Scroll* - Toggle scroll locking on and off. - - *Layout* - Cycle through various layouts of the - current view. - -n *Next* - Move to the next unresolved conflict. - -N *Previous* - Move to the previous unresolved conflict. - -q *Quit* - Save the result file and exit Vim. - - Indicates to the VCS that the merge was - successful and it should use the current - contents of the result file as the result. - -CC *Cancel* - Exits Vim with an error code (like |:cquit|). - Indicates to the VCS that the merge was - NOT successful. - -============================================================================== -4. Modes *ThreesomeModes* - -This section describes each mode in detail. - ------------------------------------------------------------------------------- -4.1 Grid *ThreesomeModes_grid* - -The grid view is used to get an overview of all files at once to get a birds' -eye view of the merge. - -Grid Layouts *ThreesomeModes_grid_layouts* ------------- - - Layout 0 Layout 1 Layout 2 - +-------------------+ +--------------------------+ +---------------+ - | Original | | One | Result | Two | | One | - | | | | | | | | - +-------------------+ | | | | +---------------+ - | One | Two | | | | | | Result | - | | | | | | | | | - +-------------------+ | | | | +---------------+ - | Result | | | | | | Two | - | | | | | | | | - +-------------------+ +--------------------------+ +---------------+ - -Grid-Specific Key Bindings *ThreesomeModes_grid_keys* --------------------------- - -o *Original-Grid* - Select the original file, but only in layout 1. - -u *UseHunk-Grid* - Disabled in this mode. - -u1 *UseHunk1-Grid* - Place a hunk from file one into the result file. - -u2 *UseHunk2-Grid* - Place a hunk from file two into the result file. - -Grid Diffs *ThreesomeModes_grid_diffs* ----------- - -1. No diff. -2. Diff all files. - ------------------------------------------------------------------------------- -4.2 Loupe *ThreesomeModes_loupe* - -The loupe view is used to focus on and examine a single file in detail. - -Loupe Layouts *ThreesomeModes_loupe_layouts* -------------- - - Layout 0 - +-----------------+ - | Any Single File | - | | - | | - | | - | | - | | - +-----------------+ - -Loupe-Specific Key Bindings *ThreesomeModes_loupe_keys* ---------------------------- - -u *UseHunk-Loupe* - Disabled in this mode. - -Loupe Diffs *ThreesomeModes_loupe_diffs* ------------ - -No diffs are possible in loupe mode. - ------------------------------------------------------------------------------- -4.3 Compare *ThreesomeModes_compare* - -The compare view is used to examine the differences between two files at -a time. - -Compare Layouts *ThreesomeModes_compare_layouts* ---------------- - - Layout 0 Layout 1 - +-------------------+ +-------------------+ - | Orig | Result | | Orig | - | | | | or One | - | or | or | | or Two | - | | | | | - | One | One | +-------------------+ - | | | | One | - | or | or | | or Two | - | | | | or Result | - | Two | Two | | | - +-------------------+ +-------------------+ - -Compare-Specific Key Bindings *ThreesomeModes_compare_keys* ------------------------------ - -u *UseHunk-Compare* - If the result file and file one/two are - both visible, place a hunk from one/two - into the result file. Otherwise: disabled. - -Compare Diffs *ThreesomeModes_compare_diffs* -------------- - -1. No diff. -2. Diff both files. - ------------------------------------------------------------------------------- -4.4 Path *ThreesomeModes_path* - -The path view is used to view the flow of changed through one "path" or -"branch" of the merge. - -Path Layouts *ThreesomeModes_path_layouts* ------------- - - Layout 0 Layout 1 - +--------------------------+ +-------------------+ - | Orig | | Result | | Orig | - | | One | | | | - | | | | +-------------------+ - | | or | | | One | - | | | | | or Two | - | | Two | | +-------------------+ - | | | | | Result | - | | | | | | - +--------------------------+ +-------------------+ - - -Path-Specific Key Bindings *ThreesomeModes_path_keys* --------------------------- - -u *UseHunk-Path* - Place a hunk from file one or two (whichever - is currently in the center window) into the - result file. - -Path Diffs *ThreesomeModes_path_diffs* ----------- - -1. No diff. -2. Diff the original and center windows. -3. Diff the center and result windows. -4. Diff the original and result windows. - -============================================================================== -5. Configuration *ThreesomeConfig* - -You can tweak the behavior of Threesome by setting a few variables in your -|vimrc| file. For example: > - - let g:threesome_initial_mode = "compare" - let g:threesome_initial_layout_grid = 2 - let g:threesome_initial_layout_compare = 1 - ------------------------------------------------------------------------------- -5.1 g:threesome_debug *ThreesomeConfig_debug* - -Set this to 1 to force Threesome to reload every time its file is sourced. - -Options: 0 or 1 -Default: 0 (Threesome is loaded only once) - ------------------------------------------------------------------------------- -5.2 g:threesome_disable *ThreesomeConfig_disable* - -Set this to 1 to disable Threesome entirely. - -Useful if you use the same ~/.vim folder on multiple machines and some of -them may not have Python support. - -Options: 0 or 1 -Default: 0 (Threesome is enabled as usual) - ------------------------------------------------------------------------------- -5.3 g:threesome_initial_diff_grid *ThreesomeConfig_id_grid* - -Set this to change the diff the grid mode starts in. - -See |ThreesomeModes-grid-diffs| for the list of diffs. - -Options: 0, or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.4 g:threesome_initial_diff_loupe *ThreesomeConfig_id_loupe* - -Set this to change the diff the loupe mode starts in. - -See |ThreesomeModes-loupe-diffs| for the list of diffs. - -Options: 0 -Default: 0 - ------------------------------------------------------------------------------- -5.5 g:threesome_initial_diff_compare *ThreesomeConfig_id_compare* - -Set this to change the diff the compare mode starts in. - -See |ThreesomeModes-compare-diffs| for the list of diffs. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.6 g:threesome_initial_diff_path *ThreesomeConfig_id_path* - -Set this to change the diff the path mode starts in. - -See |ThreesomeModes-path-diffs| for the list of diffs. - -options: 0, 1, 2, 3, or 4 -Default: 0 - ------------------------------------------------------------------------------- -5.7 g:threesome_initial_layout_grid *ThreesomeConfig_il_grid* - -Set this to change the layout the grid mode starts in. - -See |ThreesomeModes-grid-layouts| for the list of layouts. - -Options: 0, 1, or 2 -Default: 0 - ------------------------------------------------------------------------------- -5.8 g:threesome_initial_layout_loupe *ThreesomeConfig_il_loupe* - -Set this to change the layout the loupe mode starts in. - -See |ThreesomeModes-loupe-layouts| for the list of layouts. - -Options: 0 -Default: 0 - ------------------------------------------------------------------------------- -5.9 g:threesome_initial_layout_compare *ThreesomeConfig_il_compare* - -Set this to change the layout the compare mode starts in. - -See |ThreesomeModes-compare-layouts| for the list of layouts. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.10 g:threesome_initial_layout_path *ThreesomeConfig_il_path* - -Set this to change the layout the path mode starts in. - -See |ThreesomeModes-path-layouts| for the list of layouts. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.11 g:threesome_initial_scrollbind_grid *ThreesomeConfig_is_grid* - -Set this to 1 to enable |scrollbind| by default in grid mode. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.12 g:threesome_initial_scrollbind_loupe *ThreesomeConfig_is_loupe* - -Set this to 1 to enable |scrollbind| by default in loupe mode. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.13 g:threesome_initial_scrollbind_compare *ThreesomeConfig_is_compare* - -Set this to 1 to enable |scrollbind| by default in compare mode. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.14 g:threesome_initial_scrollbind_path *ThreesomeConfig_is_path* - -Set this to 1 to enable |scrollbind| by default in path mode. - -Options: 0 or 1 -Default: 0 - ------------------------------------------------------------------------------- -5.15 g:threesome_initial_mode *ThreesomeConfig_im* - -Set this to change the mode Threesome initially starts up in. - -See |ThreesomeModes| for a description of each mode. - -Options: "grid", "loupe", "compare", or "path" -Default: "grid" - ------------------------------------------------------------------------------- -5.16 g:threesome_leader *ThreesomeConfig_leader* - -Set this to change the leader Threesome will bind all of its mappings to. - -For example: > - - let g:threesome_leader = "t" - -Will make all Threesome commands start with t instead of the default -. - -Options: Any valid key mapping string -Default: "" - ------------------------------------------------------------------------------- -5.17 g:threesome_wrap *ThreesomeConfig_wrap* - -Set this to "wrap" or "nowrap" to set |wrap| or |nowrap| on all windows by -default. - -By default Threesome will use your default settings. - -Options: "wrap", "nowrap" -Default: None (use the default settings) - -============================================================================== -6. License *ThreesomeLicense* - -Threesome is copyright Steve Losh & contributors, 2011+ and is licensed -under the MIT/X11 license. - -============================================================================== -7. Bugs *ThreesomeBugs* - -Please report any bugs you may find on the GitHub issue tracker: - - http://github.com/sjl/threesome.vim/issues - -============================================================================== -8. Contributing *ThreesomeContributing* - -Think you can make Threesome better? Awesome. New contributors are always -welcome. - -Fork the project on BitBucket or GitHub and send a pull request. - - BitBucket: http://bitbucket.org/sjl/threesome.vim - GitHub: http://github.com/sjl/threesome.vim - -============================================================================== -9. Changelog *ThreesomeChangelog* - -v0.2.0 - * Add threesome_leader as a config option. -v0.1.1 - * Fix a bug when the user doesn't use :set hidden. -v0.1.0 - * Preliminary "it probably won't eat your data" release! -v0.0.8 - * A bunch of cleanup. -v0.0.7 - * Add use hunk functionality. -v0.0.6 - * Add the HUD. - * Configurable wrapping. -v0.0.5 - * Configurable scrollbinding. -v0.0.4 - * Basic configuration settings. -v0.0.3 - * Multiple layout support. -v0.0.2 - * There's still not much working, but at least there's some help now! -v0.0.1 - * Oh god nothing works please don't use this for real work yet. - -============================================================================== -10. Credits *ThreesomeCredits* - -Threesome was originally written by Steve Losh after he got fed up with the -lack of a powerful, intuitive, beautiful three-way merge program on OS X. - -A lot of the inspiration for the layout of the code came from vim-orgmode. - -The UI is a combination of ideas from Conflict2Diff.vim, Fugitive.vim, and -Adobe Lightroom. - -============================================================================== - - vim:ts=4:et:ft=help: diff -r c3f318a26db2 -r 0013f7e01b6e package.sh --- a/package.sh Tue Apr 10 10:19:23 2012 -0400 +++ b/package.sh Fri Apr 20 15:16:48 2012 +0100 @@ -1,3 +1,3 @@ #!/usr/bin/env bash -hg archive ~/Desktop/threesome.zip -I 'doc' -I 'plugin' -I 'autoload' -I 'syntax' -I 'LICENSE' -I 'README.markdown' +hg archive ~/Desktop/splice.zip -I 'doc' -I 'plugin' -I 'autoload' -I 'syntax' -I 'LICENSE' -I 'README.markdown' diff -r c3f318a26db2 -r 0013f7e01b6e plugin/splice.vim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/plugin/splice.vim Fri Apr 20 15:16:48 2012 +0100 @@ -0,0 +1,40 @@ +" ============================================================================ +" File: splice.vim +" Description: vim global plugin for resolving three-way merge conflicts +" Maintainer: Steve Losh +" License: MIT X11 +" ============================================================================ + +" Init {{{ + +if !exists('g:splice_debug') && (exists('g:splice_disable') || exists('loaded_splice') || &cp) + finish +endif +let loaded_splice = 1 + +" }}} +" Commands {{{ + +command! -nargs=0 SpliceInit call splice#SpliceInit() + +command! -nargs=0 SpliceGrid call splice#SpliceGrid() +command! -nargs=0 SpliceLoupe call splice#SpliceLoupe() +command! -nargs=0 SpliceCompare call splice#SpliceCompare() +command! -nargs=0 SplicePath call splice#SplicePath() + +command! -nargs=0 SpliceOriginal call splice#SpliceOriginal() +command! -nargs=0 SpliceOne call splice#SpliceOne() +command! -nargs=0 SpliceTwo call splice#SpliceTwo() +command! -nargs=0 SpliceResult call splice#SpliceResult() + +command! -nargs=0 SpliceDiff call splice#SpliceDiff() +command! -nargs=0 SpliceDiffoff call splice#SpliceDiffoff() +command! -nargs=0 SpliceScroll call splice#SpliceScroll() +command! -nargs=0 SpliceLayout call splice#SpliceLayout() +command! -nargs=0 SpliceNext call splice#SpliceNext() +command! -nargs=0 SplicePrev call splice#SplicePrev() +command! -nargs=0 SpliceUse call splice#SpliceUse() +command! -nargs=0 SpliceUse1 call splice#SpliceUse1() +command! -nargs=0 SpliceUse2 call splice#SpliceUse2() + +" }}} diff -r c3f318a26db2 -r 0013f7e01b6e plugin/threesome.vim --- a/plugin/threesome.vim Tue Apr 10 10:19:23 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -" ============================================================================ -" File: threesome.vim -" Description: vim global plugin for resolving three-way merge conflicts -" Maintainer: Steve Losh -" License: MIT X11 -" ============================================================================ - -" Init {{{ - -if !exists('g:threesome_debug') && (exists('g:threesome_disable') || exists('loaded_threesome') || &cp) - finish -endif -let loaded_threesome = 1 - -" }}} -" Commands {{{ - -command! -nargs=0 ThreesomeInit call threesome#ThreesomeInit() - -command! -nargs=0 ThreesomeGrid call threesome#ThreesomeGrid() -command! -nargs=0 ThreesomeLoupe call threesome#ThreesomeLoupe() -command! -nargs=0 ThreesomeCompare call threesome#ThreesomeCompare() -command! -nargs=0 ThreesomePath call threesome#ThreesomePath() - -command! -nargs=0 ThreesomeOriginal call threesome#ThreesomeOriginal() -command! -nargs=0 ThreesomeOne call threesome#ThreesomeOne() -command! -nargs=0 ThreesomeTwo call threesome#ThreesomeTwo() -command! -nargs=0 ThreesomeResult call threesome#ThreesomeResult() - -command! -nargs=0 ThreesomeDiff call threesome#ThreesomeDiff() -command! -nargs=0 ThreesomeDiffoff call threesome#ThreesomeDiffoff() -command! -nargs=0 ThreesomeScroll call threesome#ThreesomeScroll() -command! -nargs=0 ThreesomeLayout call threesome#ThreesomeLayout() -command! -nargs=0 ThreesomeNext call threesome#ThreesomeNext() -command! -nargs=0 ThreesomePrev call threesome#ThreesomePrev() -command! -nargs=0 ThreesomeUse call threesome#ThreesomeUse() -command! -nargs=0 ThreesomeUse1 call threesome#ThreesomeUse1() -command! -nargs=0 ThreesomeUse2 call threesome#ThreesomeUse2() - -" }}} diff -r c3f318a26db2 -r 0013f7e01b6e site/index.markdown --- a/site/index.markdown Tue Apr 10 10:19:23 2012 -0400 +++ b/site/index.markdown Fri Apr 20 15:16:48 2012 +0100 @@ -1,4 +1,4 @@ -Threesome - a Vim plugin for resolving three-way merges- +Splice - a Vim plugin for resolving three-way merges- Demo ---- @@ -15,7 +15,7 @@ Yes, that's some (relatively) new stuff. No, I'm not going to support anything less than that. -Threesome is a merge tool which means you'll be working with it on your development +Splice is a merge tool which means you'll be working with it on your development machine, not over SSH on your servers. If you can't be bothered to run up-to-date versions of your tools on your main @@ -27,8 +27,8 @@ Use [Pathogen][] to install the plugin from your choice of repositories: - hg clone https://bitbucket.org/sjl/threesome.vim ~/.vim/bundle/threesome - git clone https://github.com/sjl/threesome.vim.git ~/.vim/bundle/threesome + hg clone https://bitbucket.org/sjl/splice.vim ~/.vim/bundle/splice + git clone https://github.com/sjl/splice.vim.git ~/.vim/bundle/splice [Pathogen]: http://www.vim.org/scripts/script.php?script_id=2332 @@ -43,10 +43,10 @@ Add the following lines to `~/.hgrc`: [merge-tools] - threesome.executable = mvim - threesome.args = -f $base $local $other $output -c 'ThreesomeInit' - threesome.premerge = keep - threesome.priority = 1 + splice.executable = mvim + splice.args = -f $base $local $other $output -c 'SpliceInit' + splice.premerge = keep + splice.priority = 1 **Note:** replace `mvim` with `gvim` if you're on Linux, or just plain `vim` if you prefer to keep the editor in the console. @@ -55,10 +55,10 @@ Add the following lines to `~/.gitconfig`: [merge] - tool = threesome + tool = splice - [mergetool "threesome"] - cmd = "mvim -f $BASE $LOCAL $REMOTE $MERGED -c 'ThreesomeInit'" + [mergetool "splice"] + cmd = "mvim -f $BASE $LOCAL $REMOTE $MERGED -c 'SpliceInit'" trustExitCode = true **Note:** replace `mvim` with `gvim` if you're on Linux, or just plain `vim` if you prefer to keep the editor in the console. @@ -67,25 +67,25 @@ For Bazaar 2.4 or greater, add the following line to bazaar.conf: - bzr.mergetool.threesome = mvim {base} {this} {other} {result} -c 'ThreesomeInit' + bzr.mergetool.splice = mvim {base} {this} {other} {result} -c 'SpliceInit' Optionally, change the default merge tool by setting: - bzr.default_mergetool = threesome + bzr.default_mergetool = splice For earlier versions of Bazaar, set the following entry in bazaar.conf: - external_merge = mvim %b %t %o %r -c 'ThreesomeInit' + external_merge = mvim %b %t %o %r -c 'SpliceInit' **Note:** replace `mvim` with `gvim` if you're on Linux, or just plain `vim` if you prefer to keep the editor in the console. More Information ---------------- -**Full Documentation:** `:help threesome` -**Source (Mercurial):** -**Source (Git):** -**Issues:** +**Full Documentation:** `:help splice` +**Source (Mercurial):** +**Source (Git):** +**Issues:** **License:** [MIT/X11][license] [license]: http://www.opensource.org/licenses/mit-license.php diff -r c3f318a26db2 -r 0013f7e01b6e site/layout.html --- a/site/layout.html Tue Apr 10 10:19:23 2012 -0400 +++ b/site/layout.html Fri Apr 20 15:16:48 2012 +0100 @@ -6,11 +6,11 @@ - + {{ title }} - +