def MundoRenderPreview(): # {{{ """ Opens the preview window if necessary and renders a preview diff. """ if not _check_sanity(): return target_state = MundoGetTargetState() target_n = int(vim.eval('g:mundo_target_n')) # If there's no target state or the buffer has changed, update the cached # undo tree data, redraw the graph and abort preview rendering if target_state is None or nodesData.target_n != target_n: nodesData.make_nodes() MundoRenderGraph(True) return util._goto_window_for_buffer(target_n) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = node_after.parent vim.command('call s:MundoOpenPreview()') util._output_preview_text(nodesData.preview_diff(node_before, node_after)) # Mark the preview as up-to-date vim.command('call mundo#MundoPreviewOutdated(0)')
def MundoRenderPreview():# {{{ """ Opens the preview window if necessary and renders a preview diff. """ if not _check_sanity(): return target_state = MundoGetTargetState() target_n = int(vim.eval('g:mundo_target_n')) # If there's no target state or the buffer has changed, update the cached # undo tree data, redraw the graph and abort preview rendering if target_state is None or nodesData.target_n != target_n: nodesData.make_nodes() MundoRenderGraph(True) return util._goto_window_for_buffer(target_n) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = node_after.parent vim.command('call s:MundoOpenPreview()') util._output_preview_text(nodesData.preview_diff(node_before, node_after)) # Mark the preview as up-to-date vim.command('call mundo#MundoPreviewOutdated(0)')
def MundoGetTargetState(): # {{{ """ Get the current undo number that mundo is at. """ util._goto_window_for_buffer('__Mundo__') target_line = vim.eval("getline('.')") matches = re.match('^[^\[]* \[([0-9]+)\] .*$', target_line) if matches: return int(matches.group(1)) return 0
def MundoGetTargetState():# {{{ """ Get the current undo number that mundo is at. """ util._goto_window_for_buffer('__Mundo__') target_line = vim.eval("getline('.')") matches = re.match('^[^\[]* \[([0-9]+)\] .*$', target_line) if matches: return int(matches.group(1)) return 0
def MundoPlayTo(): # {{{ """ Replays changes between the current state and a selected state in real-time. """ if not _check_sanity(): return target_n = MundoGetTargetState() back = int(vim.eval('g:mundo_target_n')) delay = int(vim.eval('g:mundo_playback_delay')) util._goto_window_for_buffer(back) util.normal('zn') nodes, nmap = nodesData.make_nodes() start = nmap[nodesData.current()] end = nmap[target_n] def _walk_branch(origin, dest): # {{{ rev = origin.n < dest.n nodes = [] if origin.n > dest.n: current, final = origin, dest else: current, final = dest, origin while current.n > final.n: nodes.append(current) current = current.parent if current.n != final.n: return None nodes.append(current) if rev: return reversed(nodes) else: return nodes # }}} branch = _walk_branch(start, end) if not branch: vim.command('unsilent echo "No path to that node from here!"') util.normal('zN') return for node in branch: util._undo_to(node.n) MundoRenderGraph() util.normal('zz') util._goto_window_for_buffer(back) vim.command('redraw | sleep %dm' % delay) util.normal('zN')
def MundoPlayTo():# {{{ """ Replays changes between the current state and a selected state in real-time. """ if not _check_sanity(): return target_n = MundoGetTargetState() back = int(vim.eval('g:mundo_target_n')) delay = int(vim.eval('g:mundo_playback_delay')) util._goto_window_for_buffer(back) util.normal('zn') nodes, nmap = nodesData.make_nodes() start = nmap[nodesData.current()] end = nmap[target_n] def _walk_branch(origin, dest):# {{{ rev = origin.n < dest.n nodes = [] if origin.n > dest.n: current, final = origin, dest else: current, final = dest, origin while current.n > final.n: nodes.append(current) current = current.parent if current.n != final.n: return None nodes.append(current) if rev: return reversed(nodes) else: return nodes # }}} branch = _walk_branch(start, end) if not branch: vim.command('unsilent echo "No path to that node from here!"') util.normal('zN') return for node in branch: util._undo_to(node.n) MundoRenderGraph() util.normal('zz') util._goto_window_for_buffer(back) vim.command('redraw | sleep %dm' % delay) util.normal('zN')
def MundoPlayTo(): if not _check_sanity(): return target_n = MundoGetTargetState() back = int(vim.eval("g:mundo_target_n")) delay = int(vim.eval("g:mundo_playback_delay")) vim.command('echo "%s"' % back) util._goto_window_for_buffer(back) util.normal("zR") nodes, nmap = nodesData.make_nodes() start = nmap[nodesData.current()] end = nmap[target_n] def _walk_branch(origin, dest): rev = origin.n < dest.n nodes = [] if origin.n > dest.n: current, final = origin, dest else: current, final = dest, origin while current.n >= final.n: if current.n == final.n: break nodes.append(current) current = current.parent else: return None nodes.append(current) if rev: return reversed(nodes) else: return nodes branch = _walk_branch(start, end) if not branch: vim.command('unsilent echo "No path to that node from here!"') return for node in branch: util._undo_to(node.n) vim.command("MundoRenderGraph") util.normal("zz") util._goto_window_for_buffer(back) vim.command("redraw") vim.command("sleep %dm" % delay)
def GundoPlayTo(): if not _check_sanity(): return target_n = GundoGetTargetState() back = int(vim.eval('g:mundo_target_n')) delay = int(vim.eval('g:mundo_playback_delay')) vim.command('echo "%s"' % back) util._goto_window_for_buffer(back) util.normal('zR') nodes, nmap = nodesData.make_nodes() start = nmap[nodesData.current()] end = nmap[target_n] def _walk_branch(origin, dest): rev = origin.n < dest.n nodes = [] if origin.n > dest.n: current, final = origin, dest else: current, final = dest, origin while current.n >= final.n: if current.n == final.n: break nodes.append(current) current = current.parent else: return None nodes.append(current) if rev: return reversed(nodes) else: return nodes branch = _walk_branch(start, end) if not branch: vim.command('unsilent echo "No path to that node from here!"') return for node in branch: util._undo_to(node.n) vim.command('GundoRenderGraph') util.normal('zz') util._goto_window_for_buffer(back) vim.command('redraw') vim.command('sleep %dm' % delay)
def MundoRenderPatchdiff(): # {{{ """ Call MundoRenderChangePreview and display a vert diffpatch with the current file. """ if MundoRenderChangePreview(): # if there are no lines, do nothing (show a warning). util._goto_window_for_buffer('__Mundo_Preview__') if vim.current.buffer[:] == ['']: # restore the cursor position before exiting. util._goto_window_for_buffer('__Mundo__') vim.command( 'unsilent echo "No difference between current file and undo number!"' ) return False # quit out of mundo main screen util._goto_window_for_buffer('__Mundo__') vim.command('quit') # save the __Mundo_Preview__ buffer to a temp file. util._goto_window_for_buffer('__Mundo_Preview__') (handle, filename) = tempfile.mkstemp() vim.command('silent! w %s' % (filename)) # exit the __Mundo_Preview__ window vim.command('bdelete') # diff the temp file vim.command('silent! keepalt vert diffpatch %s' % (filename)) vim.command('set buftype=nofile bufhidden=delete') return True return False
def MundoRenderPatchdiff():# {{{ """ Call MundoRenderChangePreview and display a vert diffpatch with the current file. """ if MundoRenderChangePreview(): # if there are no lines, do nothing (show a warning). util._goto_window_for_buffer('__Mundo_Preview__') if vim.current.buffer[:] == ['']: # restore the cursor position before exiting. util._goto_window_for_buffer('__Mundo__') vim.command('unsilent echo "No difference between current file and undo number!"') return False # quit out of mundo main screen util._goto_window_for_buffer('__Mundo__') vim.command('quit') # save the __Mundo_Preview__ buffer to a temp file. util._goto_window_for_buffer('__Mundo_Preview__') (handle,filename) = tempfile.mkstemp() vim.command('silent! w %s' % (filename)) # exit the __Mundo_Preview__ window vim.command('bdelete') # diff the temp file vim.command('silent! keepalt vert diffpatch %s' % (filename)) vim.command('set buftype=nofile bufhidden=delete') return True return False
def MundoRenderChangePreview():# {{{ """ Render a diff of the target buffer and the selected undo tree node. Returns True on success, False otherwise. """ if not _check_sanity(): return vim.command('call s:MundoOpenPreview()') util._output_preview_text(MundoGetChangesForLine()) util._goto_window_for_buffer('__Mundo__') # Mark the preview as up-to-date vim.command('call mundo#MundoPreviewOutdated(0)') return True
def MundoRenderChangePreview(): # {{{ """ Render a diff of the target buffer and the selected undo tree node. Returns True on success, False otherwise. """ if not _check_sanity(): return vim.command('call s:MundoOpenPreview()') util._output_preview_text(MundoGetChangesForLine()) util._goto_window_for_buffer('__Mundo__') # Mark the preview as up-to-date vim.command('call mundo#MundoPreviewOutdated(0)') return True
def GundoRevert(): if not _check_sanity(): return target_n = GundoGetTargetState() back = vim.eval('g:mundo_target_n') util._goto_window_for_buffer(back) util._undo_to(target_n) vim.command('GundoRenderGraph') if int(vim.eval('g:mundo_return_on_revert')): util._goto_window_for_buffer(back) if int(vim.eval('g:mundo_close_on_revert')): vim.command('GundoToggle')
def MundoRevert(): if not _check_sanity(): return target_n = MundoGetTargetState() back = vim.eval("g:mundo_target_n") util._goto_window_for_buffer(back) util._undo_to(target_n) vim.command("MundoRenderGraph") if int(vim.eval("g:mundo_return_on_revert")): util._goto_window_for_buffer(back) if int(vim.eval("g:mundo_close_on_revert")): vim.command("MundoToggle")
def GundoMatch(down): """ Jump to the next node that matches the current pattern. If there is a next node, search from the next node to the end of the list of changes. Stop on a match. """ if not _check_sanity(): return # save the current window number (should be the navigation window) # then generate the undo nodes, and then go back to the current window. util._goto_window_for_buffer(vim.eval('g:mundo_target_n')) nodes, nmap = nodesData.make_nodes() total = len(nodes) - 1 util._goto_window_for_buffer_name('__Mundo__') curline = int(vim.eval("line('.')")) gundo_node = GundoGetTargetState() found_version = -1 if total > 0: therange = range(gundo_node - 1, -1, -1) if down < 0: therange = range(gundo_node + 1, total + 1) for version in therange: util._goto_window_for_buffer_name('__Mundo__') undochanges = nodesData.preview_diff(nmap[version].parent, nmap[version]) # Look thru all of the changes, ignore the first two b/c those are the # diff timestamp fields (not relevent): for change in undochanges[3:]: match_index = vim.eval( 'match("%s",@/)' % change.replace("\\", "\\\\").replace('"', '\\"')) # only consider the matches that are actual additions or # subtractions if int(match_index) >= 0 and (change.startswith('-') or change.startswith('+')): found_version = version break # found something, lets get out of here: if found_version != -1: break util._goto_window_for_buffer_name('__Mundo__') if found_version >= 0: GundoMove(found_version, 1, False)
def MundoRevert():# {{{ """ Reverts the target buffer to the state associated with a selected node in the undo graph. """ if not _check_sanity(): return target_n = MundoGetTargetState() back = int(vim.eval('g:mundo_target_n')) util._goto_window_for_buffer(back) util._undo_to(target_n) MundoRenderGraph() if int(vim.eval('g:mundo_return_on_revert')): util._goto_window_for_buffer(back) if int(vim.eval('g:mundo_close_on_revert')): vim.command('MundoToggle')
def MundoRevert(): # {{{ """ Reverts the target buffer to the state associated with a selected node in the undo graph. """ if not _check_sanity(): return target_n = MundoGetTargetState() back = int(vim.eval('g:mundo_target_n')) util._goto_window_for_buffer(back) util._undo_to(target_n) MundoRenderGraph() if int(vim.eval('g:mundo_return_on_revert')): util._goto_window_for_buffer(back) if int(vim.eval('g:mundo_close_on_revert')): vim.command('MundoToggle')
def MundoMatch(down): """ Jump to the next node that matches the current pattern. If there is a next node, search from the next node to the end of the list of changes. Stop on a match. """ if not _check_sanity(): return # save the current window number (should be the navigation window) # then generate the undo nodes, and then go back to the current window. util._goto_window_for_buffer(vim.eval("g:mundo_target_n")) nodes, nmap = nodesData.make_nodes() total = len(nodes) - 1 util._goto_window_for_buffer_name("__Mundo__") curline = int(vim.eval("line('.')")) mundo_node = MundoGetTargetState() found_version = -1 if total > 0: therange = range(mundo_node - 1, -1, -1) if down < 0: therange = range(mundo_node + 1, total + 1) for version in therange: util._goto_window_for_buffer_name("__Mundo__") undochanges = nodesData.preview_diff(nmap[version].parent, nmap[version]) # Look thru all of the changes, ignore the first two b/c those are the # diff timestamp fields (not relevent): for change in undochanges[3:]: match_index = vim.eval('match("%s",@/)' % change.replace("\\", "\\\\").replace('"', '\\"')) # only consider the matches that are actual additions or # subtractions if int(match_index) >= 0 and (change.startswith("-") or change.startswith("+")): found_version = version break # found something, lets get out of here: if found_version != -1: break util._goto_window_for_buffer_name("__Mundo__") if found_version >= 0: MundoMove(found_version, 1, False)
def MundoGetChangesForLine(): # {{{ if not _check_sanity(): return False target_state = MundoGetTargetState() # Check that there's an undo state. There may not be if we're talking about # a buffer with no changes yet. if target_state == None: util._goto_window_for_buffer('__Mundo__') return False else: target_state = int(target_state) util._goto_window_for_buffer(int(vim.eval('g:mundo_target_n'))) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = nmap[nodesData.current()] return nodesData.change_preview_diff(node_before, node_after)
def MundoGetChangesForLine(): if not _check_sanity(): return False target_state = MundoGetTargetState() # Check that there's an undo state. There may not be if we're talking about # a buffer with no changes yet. if target_state == None: util._goto_window_for_buffer_name("__Mundo__") return False else: target_state = int(target_state) util._goto_window_for_buffer(vim.eval("g:mundo_target_n")) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = nmap[nodesData.current()] return nodesData.change_preview_diff(node_before, node_after)
def GundoRenderPreview(): if not _check_sanity(): return target_state = GundoGetTargetState() # Check that there's an undo state. There may not be if we're talking about # a buffer with no changes yet. if target_state == None: util._goto_window_for_buffer_name('__Mundo__') return else: target_state = int(target_state) util._goto_window_for_buffer(vim.eval('g:mundo_target_n')) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = node_after.parent vim.command('call s:GundoOpenPreview()') util._output_preview_text(nodesData.preview_diff(node_before, node_after)) util._goto_window_for_buffer_name('__Mundo__')
def MundoRenderPreview(): if not _check_sanity(): return target_state = MundoGetTargetState() # Check that there's an undo state. There may not be if we're talking about # a buffer with no changes yet. if target_state == None: util._goto_window_for_buffer_name("__Mundo__") return else: target_state = int(target_state) util._goto_window_for_buffer(vim.eval("g:mundo_target_n")) nodes, nmap = nodesData.make_nodes() node_after = nmap[target_state] node_before = node_after.parent vim.command("call s:MundoOpenPreview()") util._output_preview_text(nodesData.preview_diff(node_before, node_after)) util._goto_window_for_buffer_name("__Mundo__")
def MundoRenderGraph(force=False): # {{{ """ Renders the undo graph if necessary, updating it to reflect changes in the target buffer's undo tree. Arguments --------- force : bool If True, the graph will always be rendered. If False, then the graph may not be rendered - when is already current for example. """ if not _check_sanity(): return util._goto_window_for_buffer('__Mundo__') first_visible_line = int(vim.eval("line('w0')")) last_visible_line = int(vim.eval("line('w$')")) verbose = vim.eval('g:mundo_verbose_graph') == "1" target = int(vim.eval('g:mundo_target_n')) if int(vim.eval('g:mundo_help')): header = (INLINE_HELP % target).splitlines() else: header = [(INLINE_HELP % target).splitlines()[0], '\n'] show_inline_undo = int(vim.eval("g:mundo_inline_undo")) == 1 mundo_last_visible_line = int(vim.eval("g:mundo_last_visible_line")) mundo_first_visible_line = int(vim.eval("g:mundo_first_visible_line")) if not force and not nodesData.is_outdated() and ( not show_inline_undo or (mundo_first_visible_line == first_visible_line and mundo_last_visible_line == last_visible_line)): return result = graphlog.generate(verbose, len(header) + 1, first_visible_line, last_visible_line, show_inline_undo, nodesData) vim.command("let g:mundo_last_visible_line=%s" % last_visible_line) vim.command("let g:mundo_first_visible_line=%s" % first_visible_line) output = [] # right align the dag and flip over the y axis: flip_dag = int(vim.eval("g:mundo_mirror_graph")) == 1 dag_width = 1 for line in result: if len(line[0]) > dag_width: dag_width = len(line[0]) for line in result: if flip_dag: dag_line = (line[0][::-1]).replace("/", "\\") output.append("%*s %s" % (dag_width, dag_line, line[1])) else: output.append("%-*s %s" % (dag_width, line[0], line[1])) vim.command('call s:MundoOpenGraph()') vim.command('setlocal modifiable') lines = (header + output) lines = [line.rstrip('\n') for line in lines] vim.current.buffer[:] = lines vim.command('setlocal nomodifiable') i = 1 for line in output: try: line.split('[')[0].index('@') i += 1 break except ValueError: pass i += 1 vim.command('%d' % (i + len(header) - 1))
def MundoRenderGraph(force=False):# {{{ """ Renders the undo graph if necessary, updating it to reflect changes in the target buffer's undo tree. Arguments --------- force : bool If True, the graph will always be rendered. If False, then the graph may not be rendered - when is already current for example. """ if not _check_sanity(): return util._goto_window_for_buffer('__Mundo__') first_visible_line = int(vim.eval("line('w0')")) last_visible_line = int(vim.eval("line('w$')")) verbose = vim.eval('g:mundo_verbose_graph') == "1" target = int(vim.eval('g:mundo_target_n')) if int(vim.eval('g:mundo_help')): header = (INLINE_HELP % target).splitlines() else: header = [(INLINE_HELP % target).splitlines()[0], '\n'] show_inline_undo = int(vim.eval("g:mundo_inline_undo")) == 1 mundo_last_visible_line = int(vim.eval("g:mundo_last_visible_line")) mundo_first_visible_line = int(vim.eval("g:mundo_first_visible_line")) if not force and not nodesData.is_outdated() and ( not show_inline_undo or ( mundo_first_visible_line == first_visible_line and mundo_last_visible_line == last_visible_line ) ): return result = graphlog.generate( verbose, len(header)+1, first_visible_line, last_visible_line, show_inline_undo, nodesData ) vim.command("let g:mundo_last_visible_line=%s"%last_visible_line) vim.command("let g:mundo_first_visible_line=%s"%first_visible_line) output = [] # right align the dag and flip over the y axis: flip_dag = int(vim.eval("g:mundo_mirror_graph")) == 1 dag_width = 1 for line in result: if len(line[0]) > dag_width: dag_width = len(line[0]) for line in result: if flip_dag: dag_line = (line[0][::-1]).replace("/","\\") output.append("%*s %s"% (dag_width,dag_line,line[1])) else: output.append("%-*s %s"% (dag_width,line[0],line[1])) vim.command('call s:MundoOpenGraph()') vim.command('setlocal modifiable') lines = (header + output) lines = [line.rstrip('\n') for line in lines] vim.current.buffer[:] = lines vim.command('setlocal nomodifiable') i = 1 for line in output: try: line.split('[')[0].index('@') i += 1 break except ValueError: pass i += 1 vim.command('%d' % (i+len(header)-1))