From 1ba215e8bf5df74b1c71ea7b7308041517df8601 Mon Sep 17 00:00:00 2001 From: shaggyrogers Date: Thu, 22 Feb 2018 23:07:16 +1100 Subject: [PATCH 01/16] Added delay for automatic previews, added option to also delay inline diffs, added options for each, updated docs --- autoload/mundo.py | 5 +++-- autoload/mundo.vim | 43 +++++++++++++++++++++++++++++++++++++++++-- doc/mundo.txt | 41 +++++++++++++++++++++++++++++++---------- 3 files changed, 75 insertions(+), 14 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index 25387b0..a7c93c1 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -90,7 +90,7 @@ def MundoRenderGraph(force=False): 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 + not show_inline_undo or ( mundo_first_visible_line == first_visible_line and mundo_last_visible_line == last_visible_line @@ -262,7 +262,8 @@ def MundoMove(direction,move_count=1,relative=True,write=False): else: vim.command("call cursor(0, %d + 1)" % idx3) - if vim.eval('g:mundo_auto_preview') == '1': + if (vim.eval('g:mundo_auto_preview') == '1' and + vim.eval("get(g:, 'mundo_auto_preview_delay', 0)") == 0): MundoRenderPreview() diff --git a/autoload/mundo.vim b/autoload/mundo.vim index 0729cb5..f667f59 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -42,6 +42,7 @@ endif"}}} let s:plugin_path = escape(expand(':p:h'), '\') +let s:auto_preview_timer = -1 "}}} "{{{ Mundo utility functions @@ -409,12 +410,50 @@ function! s:MundoRefresh()"{{{ call winrestview(winView) endfunction"}}} +function! s:MundoUpdateCursor()"{{{ + if !get(g:, 'mundo_auto_preview_delay_refresh', 0) + call s:MundoRefresh() + endif + + if !g:mundo_auto_preview || !get(g:, 'mundo_auto_preview_delay', 0) + return + endif + + call s:MundoRestartCursorTimer() +endfunction"}}} + +function! s:MundoRestartCursorTimer()"{{{ + call s:MundoStopCursorTimer() + let s:auto_preview_timer = timer_start( + \ get(g:, 'mundo_auto_preview_delay', 0), + \ function('s:MundoRenderPreviewDelayed')) +endfunction"}}} + +function! s:MundoStopCursorTimer()"{{{ + if s:auto_preview_timer != -1 + call timer_stop(s:auto_preview_timer) + let s:auto_preview_timer = -1 + endif +endfunction"}}} + +function! s:MundoRenderPreviewDelayed(...)"{{{ + if mode() != 'n' + return s:MundoRestartCursorTimer() + endif + + if get(g:, 'mundo_auto_preview_delay_refresh', 0) + call s:MundoRefresh() + endif + + call s:MundoPython('MundoRenderPreview()') +endfunction"}}} + augroup MundoAug autocmd! autocmd BufNewFile __Mundo__ call s:MundoSettingsGraph() autocmd BufNewFile __Mundo_Preview__ call s:MundoSettingsPreview() - autocmd CursorHold * call s:MundoRefresh() - autocmd CursorMoved * call s:MundoRefresh() + autocmd CursorMoved __Mundo__ call s:MundoUpdateCursor() + autocmd BufLeave __Mundo__ call s:MundoStopCursorTimer() autocmd BufEnter * let b:mundoChangedtick = 0 augroup END diff --git a/doc/mundo.txt b/doc/mundo.txt index 458e7ad..a419fc8 100644 --- a/doc/mundo.txt +++ b/doc/mundo.txt @@ -20,11 +20,13 @@ CONTENTS *Mundo-contents* 3.9 mundo_preview_statusline .. |mundo_preview_statusline| mundo_tree_statusline ..... |mundo_tree_statusline| 3.10 mundo_auto_preview ........ |mundo_auto_preview| - 3.11 mundo_verbose_graph ....... |mundo_verbose_graph| - 3.12 mundo_playback_delay ...... |mundo_playback_delay| - 3.13 mundo_mirror_graph ........ |mundo_mirror_graph| - 3.14 mundo_inline_undo ......... |mundo_inline_undo| - 3.15 mundo_return_on_revert .... |mundo_return_on_revert| + 3.11 mundo_auto_preview_delay .. |mundo_auto_preview_delay| + 3.12 mundo_verbose_graph ....... |mundo_verbose_graph| + 3.13 mundo_playback_delay ...... |mundo_playback_delay| + 3.14 mundo_mirror_graph ........ |mundo_mirror_graph| + 3.15 mundo_inline_undo ......... |mundo_inline_undo| + 3.16 mundo_inline_undo_delay ... |mundo_inline_undo_delay| + 3.17 mundo_return_on_revert .... |mundo_return_on_revert| 4. License ......................... |MundoLicense| 5. Bugs ............................ |MundoBugs| 6. Contributing .................... |MundoContributing| @@ -223,7 +225,17 @@ be useful on large files and undo trees to speed up Mundo. Default: 1 (automatically preview diffs) ------------------------------------------------------------------------------ -3.11 g:mundo_verbose_graph *mundo_verbose_graph* + +3.11 g:mundo_auto_preview_delay *mundo_auto_preview_delay* + +This is the delay in milliseconds before a preview diff is automatically +rendered. The delay is reset whenever the cursor moves. Use this to speed up +undo tree traversal when automatic previews are enabled. + +Default: 0 (no delay) + +------------------------------------------------------------------------------ +3.12 g:mundo_verbose_graph *mundo_verbose_graph* Set this to 0 to create shorter graphs: the 'o' characters will only be used when multiple branches exist, and extra lines of '|' are suppressed making for @@ -232,7 +244,7 @@ a graph half as long. Default: 1 (verbose graphs) ------------------------------------------------------------------------------ -3.12 g:mundo_playback_delay *mundo_playback_delay* +3.13 g:mundo_playback_delay *mundo_playback_delay* This is the delay in milliseconds between each change when running 'play to' mode. Set this to a higher number for a slower playback or to a lower number @@ -241,14 +253,14 @@ for a faster playback. Default: 60 ------------------------------------------------------------------------------ -3.13 g:mundo_mirror_graph *mundo_mirror_graph* +3.14 g:mundo_mirror_graph *mundo_mirror_graph* Set this to 0 to align the graph to the left; set to 1 to align to the right. Default: 1 (mirror graph) ------------------------------------------------------------------------------ -3.14 g:mundo_inline_undo *mundo_inline_undo* +3.15 g:mundo_inline_undo *mundo_inline_undo* When enabled, a small one line diff is displayed to the right of the graph undo. Although not as detailed as a full diff provided in the preview window, it @@ -256,8 +268,17 @@ provides a quick summary of the diff w/o having to navigate. Default: 0 (no inline graph) +----------------------------------------------------------------------------- +3.16 g:mundo_inline_undo_delay *mundo_inline_undo_delay* + +When this option is set, inline diff rendering will be delayed until a preview +diff is rendered. Use this to speed up undo tree traversal when inline diffs +are enabled. + +Default: 0 (disabled) + ------------------------------------------------------------------------------ -3.15 g:mundo_return_on_revert *mundo_return_on_revert* +3.17 g:mundo_return_on_revert *mundo_return_on_revert* Set this to 0 to keep focus in the Mundo window after a revert. From 2571fa6e388a26d8199c15716494c87c09477706 Mon Sep 17 00:00:00 2001 From: shaggyrogers Date: Fri, 23 Feb 2018 02:20:03 +1100 Subject: [PATCH 02/16] Fixed g:mundo_auto_preview not being respected, fixed delayed auto preview triggering multiple times for the same node --- autoload/mundo.py | 4 ++-- autoload/mundo.vim | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index a7c93c1..ea92685 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -262,8 +262,8 @@ def MundoMove(direction,move_count=1,relative=True,write=False): else: vim.command("call cursor(0, %d + 1)" % idx3) - if (vim.eval('g:mundo_auto_preview') == '1' and - vim.eval("get(g:, 'mundo_auto_preview_delay', 0)") == 0): + if (vim.eval('g:mundo_auto_preview') != '0' and + int(vim.eval("get(g:, 'mundo_auto_preview_delay', 0)")) <= 0): MundoRenderPreview() diff --git a/autoload/mundo.vim b/autoload/mundo.vim index f667f59..0357040 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -411,12 +411,16 @@ function! s:MundoRefresh()"{{{ endfunction"}}} function! s:MundoUpdateCursor()"{{{ - if !get(g:, 'mundo_auto_preview_delay_refresh', 0) + if !g:mundo_auto_preview + return s:MundoRefresh() + endif + + if !get(g:, 'mundo_inline_undo_delay', 0) call s:MundoRefresh() endif - if !g:mundo_auto_preview || !get(g:, 'mundo_auto_preview_delay', 0) - return + if get(g:, 'mundo_auto_preview_delay', 0) <= 0 + return s:MundoPython('MundoRenderPreview()') endif call s:MundoRestartCursorTimer() @@ -437,14 +441,19 @@ function! s:MundoStopCursorTimer()"{{{ endfunction"}}} function! s:MundoRenderPreviewDelayed(...)"{{{ + if s:auto_preview_line == line('.') + return + endif + if mode() != 'n' return s:MundoRestartCursorTimer() endif - if get(g:, 'mundo_auto_preview_delay_refresh', 0) + if get(g:, 'mundo_inline_undo_delay', 0) call s:MundoRefresh() endif + let s:auto_preview_line = line('.') call s:MundoPython('MundoRenderPreview()') endfunction"}}} From a3597b0146af980a46fd96c7dfcd81be57a1deb2 Mon Sep 17 00:00:00 2001 From: shaggyrogers Date: Fri, 23 Feb 2018 02:25:59 +1100 Subject: [PATCH 03/16] Clarified documentation for mundo_inline_undo_delay option --- doc/mundo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/mundo.txt b/doc/mundo.txt index a419fc8..299eb5f 100644 --- a/doc/mundo.txt +++ b/doc/mundo.txt @@ -273,7 +273,7 @@ Default: 0 (no inline graph) When this option is set, inline diff rendering will be delayed until a preview diff is rendered. Use this to speed up undo tree traversal when inline diffs -are enabled. +and delayed automatic previews are both enabled. Default: 0 (disabled) From 3bf4e97c40bcb186ae391a8fa4b497fd46907e7f Mon Sep 17 00:00:00 2001 From: shaggyrogers Date: Fri, 23 Feb 2018 02:30:55 +1100 Subject: [PATCH 04/16] Fixed line I accidentally deleted... --- autoload/mundo.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/mundo.vim b/autoload/mundo.vim index 0357040..b66730d 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -43,6 +43,7 @@ endif"}}} let s:plugin_path = escape(expand(':p:h'), '\') let s:auto_preview_timer = -1 +let s:auto_preview_line = -1 "}}} "{{{ Mundo utility functions From edb5e8244f30b72c90ddfd3ecbe3c281cc1cbb97 Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Mon, 2 Apr 2018 01:31:16 +1000 Subject: [PATCH 05/16] changed g:mundo_inline_undo_delay to g:mundo_enable_inline_delay, fixed graph not updating when editing buffer with mundo open, fixed cursor/window focus issues with delayed previews, fixed bug occuring when auto preview delay is set and auto preview is disabled, updated vim documentation --- autoload/mundo.py | 2 +- autoload/mundo.vim | 92 ++++++++++++++++++++++++++-------------------- doc/mundo.txt | 4 +- 3 files changed, 56 insertions(+), 42 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index ea92685..5b5fb7b 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -262,7 +262,7 @@ def MundoMove(direction,move_count=1,relative=True,write=False): else: vim.command("call cursor(0, %d + 1)" % idx3) - if (vim.eval('g:mundo_auto_preview') != '0' and + if (vim.eval('g:mundo_auto_preview') != '0' or int(vim.eval("get(g:, 'mundo_auto_preview_delay', 0)")) <= 0): MundoRenderPreview() diff --git a/autoload/mundo.vim b/autoload/mundo.vim index b66730d..ac358ff 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -387,51 +387,48 @@ function! mundo#MundoHide()"{{{ endfunction"}}} function! mundo#MundoRenderGraph()"{{{ - call s:MundoPython('MundoRenderGraph()') + " Save window view information and buffer number + let currentWin = bufwinnr('%') + let winView = winsaveview() + + call s:MundoPython('MundoRenderGraph()') + + " Return to buffer and restore window view + execute currentWin .'wincmd w' + call winrestview(winView) endfunction"}}} " automatically reload Mundo buffer if open function! s:MundoRefresh()"{{{ - " abort when there were no changes - + " abort if Mundo is closed or cursor is in the preview window let mundoWin = bufwinnr('__Mundo__') let mundoPreWin = bufwinnr('__Mundo_Preview__') let currentWin = bufwinnr('%') - " abort if Mundo is closed or is current window if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) return endif - let winView = winsaveview() - :MundoRenderGraph - - " switch back to previous window - execute currentWin .'wincmd w' - call winrestview(winView) -endfunction"}}} - -function! s:MundoUpdateCursor()"{{{ - if !g:mundo_auto_preview - return s:MundoRefresh() - endif - - if !get(g:, 'mundo_inline_undo_delay', 0) - call s:MundoRefresh() - endif + " Normal refresh + if !get(g:, 'mundo_auto_preview', 0) || + \ get(g:, 'mundo_auto_preview_delay', 0) <= 0 + return mundo#MundoRenderGraph() + endif - if get(g:, 'mundo_auto_preview_delay', 0) <= 0 - return s:MundoPython('MundoRenderPreview()') - endif + " Delayed refresh + if !get(g:, 'mundo_enable_inline_delay', 0) || + \ !get(g:, 'mundo_inline_undo') + call mundo#MundoRenderGraph() + endif - call s:MundoRestartCursorTimer() + call s:MundoRestartRefreshTimer() endfunction"}}} -function! s:MundoRestartCursorTimer()"{{{ +function! s:MundoRestartRefreshTimer()"{{{ call s:MundoStopCursorTimer() let s:auto_preview_timer = timer_start( \ get(g:, 'mundo_auto_preview_delay', 0), - \ function('s:MundoRenderPreviewDelayed')) + \ function('s:MundoRefreshDelayed')) endfunction"}}} function! s:MundoStopCursorTimer()"{{{ @@ -441,28 +438,45 @@ function! s:MundoStopCursorTimer()"{{{ endif endfunction"}}} -function! s:MundoRenderPreviewDelayed(...)"{{{ - if s:auto_preview_line == line('.') - return - endif +function! s:MundoRefreshDelayed(...)"{{{ + " abort if Mundo is closed or cursor is in the preview window + let mundoWin = bufwinnr('__Mundo__') + let mundoPreWin = bufwinnr('__Mundo_Preview__') + let currentWin = bufwinnr('%') - if mode() != 'n' - return s:MundoRestartCursorTimer() - endif + if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) + return + endif - if get(g:, 'mundo_inline_undo_delay', 0) - call s:MundoRefresh() - endif + " Handle other windows + if currentWin != mundoWin + return mundo#MundoRenderGraph() + endif - let s:auto_preview_line = line('.') - call s:MundoPython('MundoRenderPreview()') + " Handle graph window (__Mundo__) + if s:auto_preview_line == line('.') + return + endif + + if mode() != 'n' + return s:MundoRestartRefreshTimer() + endif + + if get(g:, 'mundo_enable_inline_delay', 0) && get(g:, 'mundo_inline_undo') + call mundo#MundoRenderGraph() + endif + + let s:auto_preview_line = line('.') + call s:MundoPython('MundoRenderPreview()') endfunction"}}} augroup MundoAug autocmd! autocmd BufNewFile __Mundo__ call s:MundoSettingsGraph() autocmd BufNewFile __Mundo_Preview__ call s:MundoSettingsPreview() - autocmd CursorMoved __Mundo__ call s:MundoUpdateCursor() + autocmd CursorHold __Mundo__ call s:MundoRefresh() + autocmd CursorMoved __Mundo__ call s:MundoRefresh() + autocmd TextChanged * call s:MundoRefresh() autocmd BufLeave __Mundo__ call s:MundoStopCursorTimer() autocmd BufEnter * let b:mundoChangedtick = 0 augroup END diff --git a/doc/mundo.txt b/doc/mundo.txt index 299eb5f..f4d7201 100644 --- a/doc/mundo.txt +++ b/doc/mundo.txt @@ -25,7 +25,7 @@ CONTENTS *Mundo-contents* 3.13 mundo_playback_delay ...... |mundo_playback_delay| 3.14 mundo_mirror_graph ........ |mundo_mirror_graph| 3.15 mundo_inline_undo ......... |mundo_inline_undo| - 3.16 mundo_inline_undo_delay ... |mundo_inline_undo_delay| + 3.16 mundo_enable_inline_delay ... |mundo_enable_inline_delay| 3.17 mundo_return_on_revert .... |mundo_return_on_revert| 4. License ......................... |MundoLicense| 5. Bugs ............................ |MundoBugs| @@ -269,7 +269,7 @@ provides a quick summary of the diff w/o having to navigate. Default: 0 (no inline graph) ----------------------------------------------------------------------------- -3.16 g:mundo_inline_undo_delay *mundo_inline_undo_delay* +3.16 g:mundo_enable_inline_delay *mundo_enable_inline_delay* When this option is set, inline diff rendering will be delayed until a preview diff is rendered. Use this to speed up undo tree traversal when inline diffs From 7dafb5274cbd0dd0658ffbce3e70f4c8e951f95c Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Mon, 2 Apr 2018 17:49:48 +1000 Subject: [PATCH 06/16] Fixed graph updates when editing with mundo open --- autoload/mundo.py | 2 +- autoload/mundo.vim | 133 +++++++++++++++++++++++---------------------- 2 files changed, 68 insertions(+), 67 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index 5b5fb7b..5dc7dd9 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -262,7 +262,7 @@ def MundoMove(direction,move_count=1,relative=True,write=False): else: vim.command("call cursor(0, %d + 1)" % idx3) - if (vim.eval('g:mundo_auto_preview') != '0' or + if (vim.eval('g:mundo_auto_preview') == '0' or int(vim.eval("get(g:, 'mundo_auto_preview_delay', 0)")) <= 0): MundoRenderPreview() diff --git a/autoload/mundo.vim b/autoload/mundo.vim index ac358ff..23379be 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -272,7 +272,8 @@ endfunction"}}} function! s:InitPythonModule(python) exe a:python .' import sys' - exe a:python .' if sys.version_info[:2] < (2, 4): vim.command("let s:has_supported_python = 0")' + exe a:python .' if sys.version_info[:2] < (2, 4): '. + \ 'vim.command("let s:has_supported_python = 0")' endfunction @@ -387,51 +388,52 @@ function! mundo#MundoHide()"{{{ endfunction"}}} function! mundo#MundoRenderGraph()"{{{ - " Save window view information and buffer number - let currentWin = bufwinnr('%') - let winView = winsaveview() + " Save window view information and buffer number + let currentWin = bufwinnr('%') + let winView = winsaveview() - call s:MundoPython('MundoRenderGraph()') + call s:MundoPython('MundoRenderGraph()') - " Return to buffer and restore window view - execute currentWin .'wincmd w' - call winrestview(winView) + " Return to buffer and restore window view + execute currentWin .'wincmd w' + call winrestview(winView) endfunction"}}} " automatically reload Mundo buffer if open function! s:MundoRefresh()"{{{ - " abort if Mundo is closed or cursor is in the preview window - let mundoWin = bufwinnr('__Mundo__') - let mundoPreWin = bufwinnr('__Mundo_Preview__') - let currentWin = bufwinnr('%') - - if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) - return - endif - - " Normal refresh - if !get(g:, 'mundo_auto_preview', 0) || - \ get(g:, 'mundo_auto_preview_delay', 0) <= 0 - return mundo#MundoRenderGraph() - endif - - " Delayed refresh - if !get(g:, 'mundo_enable_inline_delay', 0) || - \ !get(g:, 'mundo_inline_undo') - call mundo#MundoRenderGraph() - endif - - call s:MundoRestartRefreshTimer() + " abort if Mundo is closed or cursor is in the preview window + let mundoWin = bufwinnr('__Mundo__') + let mundoPreWin = bufwinnr('__Mundo_Preview__') + let currentWin = bufwinnr('%') + + if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) + return + endif + + " Normal refresh + if !get(g:, 'mundo_auto_preview', 0) || + \ get(g:, 'mundo_auto_preview_delay', 0) <= 0 + return mundo#MundoRenderGraph() + endif + + " Delayed refresh + if !get(g:, 'mundo_enable_inline_delay', 0) || + \ !get(g:, 'mundo_inline_undo') + call mundo#MundoRenderGraph() + endif + + call s:MundoRestartRefreshTimer() endfunction"}}} function! s:MundoRestartRefreshTimer()"{{{ - call s:MundoStopCursorTimer() + call s:MundoStopRefreshTimer() let s:auto_preview_timer = timer_start( \ get(g:, 'mundo_auto_preview_delay', 0), - \ function('s:MundoRefreshDelayed')) + \ function('s:MundoRefreshDelayed') + \ ) endfunction"}}} -function! s:MundoStopCursorTimer()"{{{ +function! s:MundoStopRefreshTimer()"{{{ if s:auto_preview_timer != -1 call timer_stop(s:auto_preview_timer) let s:auto_preview_timer = -1 @@ -439,45 +441,44 @@ function! s:MundoStopCursorTimer()"{{{ endfunction"}}} function! s:MundoRefreshDelayed(...)"{{{ - " abort if Mundo is closed or cursor is in the preview window - let mundoWin = bufwinnr('__Mundo__') - let mundoPreWin = bufwinnr('__Mundo_Preview__') - let currentWin = bufwinnr('%') - - if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) - return - endif - - " Handle other windows - if currentWin != mundoWin - return mundo#MundoRenderGraph() - endif - - " Handle graph window (__Mundo__) - if s:auto_preview_line == line('.') - return - endif - - if mode() != 'n' - return s:MundoRestartRefreshTimer() - endif - - if get(g:, 'mundo_enable_inline_delay', 0) && get(g:, 'mundo_inline_undo') - call mundo#MundoRenderGraph() - endif - - let s:auto_preview_line = line('.') - call s:MundoPython('MundoRenderPreview()') + " abort if Mundo is closed or cursor is in the preview window + let mundoWin = bufwinnr('__Mundo__') + let mundoPreWin = bufwinnr('__Mundo_Preview__') + let currentWin = bufwinnr('%') + + if (mundoWin == -1) || (mundoPreWin == -1) || (mundoPreWin == currentWin) + return + endif + + " Handle other windows + if currentWin != mundoWin + return mundo#MundoRenderGraph() + endif + + " Handle graph window (__Mundo__) + if s:auto_preview_line == line('.') + return + endif + + if mode() != 'n' + return s:MundoRestartRefreshTimer() + endif + + if get(g:, 'mundo_enable_inline_delay', 0) && get(g:, 'mundo_inline_undo') + call mundo#MundoRenderGraph() + endif + + let s:auto_preview_line = line('.') + call s:MundoPython('MundoRenderPreview()') endfunction"}}} augroup MundoAug autocmd! autocmd BufNewFile __Mundo__ call s:MundoSettingsGraph() autocmd BufNewFile __Mundo_Preview__ call s:MundoSettingsPreview() - autocmd CursorHold __Mundo__ call s:MundoRefresh() - autocmd CursorMoved __Mundo__ call s:MundoRefresh() - autocmd TextChanged * call s:MundoRefresh() - autocmd BufLeave __Mundo__ call s:MundoStopCursorTimer() + autocmd CursorHold * call s:MundoRefresh() + autocmd CursorMoved * call s:MundoRefresh() + autocmd BufLeave __Mundo__ call s:MundoStopRefreshTimer() autocmd BufEnter * let b:mundoChangedtick = 0 augroup END From 41c165026033294f72e7b95ffba08d5ef0c0bf47 Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Mon, 2 Apr 2018 18:29:37 +1000 Subject: [PATCH 07/16] Fixed auto preview option logic error --- autoload/mundo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index 5dc7dd9..ea92685 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -262,7 +262,7 @@ def MundoMove(direction,move_count=1,relative=True,write=False): else: vim.command("call cursor(0, %d + 1)" % idx3) - if (vim.eval('g:mundo_auto_preview') == '0' or + if (vim.eval('g:mundo_auto_preview') != '0' and int(vim.eval("get(g:, 'mundo_auto_preview_delay', 0)")) <= 0): MundoRenderPreview() From 296bbd82150ebbb023d50ece2f8a074c9b01bade Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Wed, 2 May 2018 18:26:42 +1000 Subject: [PATCH 08/16] Fixed inline preview diffs not updating for some buffer changes, fixed issues associated with neovim terminal windows, mundo windows in other tabs now are closed when opening mundo in another tab, added and expanded function comments, some code cleanup, updated vim doc changelog --- autoload/mundo.py | 152 ++++++++++++++++++----------- autoload/mundo.vim | 209 +++++++++++++++++++++++++++------------- autoload/mundo/node.py | 20 ++-- autoload/mundo/util.py | 35 +++++-- autoload/mundo/util.vim | 2 + doc/mundo.txt | 36 +++---- 6 files changed, 296 insertions(+), 158 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index ea92685..1393e1a 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -18,21 +18,24 @@ import mundo.util as util import mundo.graphlog as graphlog -# Python Vim utility functions -----------------------------------------------------#{{{ +# Python Vim utility functions --------------------------------------------#{{{ MISSING_BUFFER = "Cannot find Mundo's target buffer (%s)" MISSING_WINDOW = "Cannot find window (%s) for Mundo's target buffer (%s)" def _check_sanity(): - '''Check to make sure we're not crazy. + """ Check to make sure we're not crazy. - Does the following things: - - * Make sure the target buffer still exists. - ''' + Ensures that: + * The target buffer exists, is loaded and is present in the tab. + * That neovim is not in terminal mode. + """ global nodesData + if not nodesData: nodesData = Nodes() + + # Check that the target buffer exists, is loaded and is present in the tab b = int(vim.eval('g:mundo_target_n')) if not vim.eval('bufloaded(%d)' % int(b)): @@ -40,10 +43,17 @@ def _check_sanity(): return False w = int(vim.eval('bufwinnr(%d)' % int(b))) + if w == -1: vim.command('echo "%s"' % (MISSING_WINDOW % (w, b))) return False + # Check if we are in terminal mode. + mode = vim.eval('mode()') + + if mode == 't': + return False + return True INLINE_HELP = '''\ @@ -68,10 +78,21 @@ def _check_sanity(): # from profilehooks import profile # @profile(immediate=True) -def MundoRenderGraph(force=False): +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$')")) @@ -140,8 +161,10 @@ def MundoRenderGraph(force=False): pass i += 1 vim.command('%d' % (i+len(header)-1)) +# }}} -def MundoRenderPreview(): +def MundoRenderPreview():# {{{ + """ Opens the preview window if necessary and renders a preview diff. """ if not _check_sanity(): return @@ -149,12 +172,12 @@ def MundoRenderPreview(): # 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 is None: - util._goto_window_for_buffer_name('__Mundo__') + util._goto_window_for_buffer('__Mundo__') return else: target_state = int(target_state) - util._goto_window_for_buffer(vim.eval('g:mundo_target_n')) + util._goto_window_for_buffer(int(vim.eval('g:mundo_target_n'))) nodes, nmap = nodesData.make_nodes() @@ -163,19 +186,22 @@ def MundoRenderPreview(): vim.command('call s:MundoOpenPreview()') util._output_preview_text(nodesData.preview_diff(node_before, node_after)) +# }}} - util._goto_window_for_buffer_name('__Mundo__') - -def MundoGetTargetState(): - """ Get the current undo number that mundo is at. """ - util._goto_window_for_buffer_name('__Mundo__') +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 GetNextLine(direction,move_count,write,start="line('.')"): +def GetNextLine(direction,move_count,write,start="line('.')"):# {{{ + """ Recursively finds the line number resulting from undo graph traversal + according to the given parameters. + """ start_line_no = int(vim.eval(start)) start_line = vim.eval("getline(%d)" % start_line_no) mundo_verbose_graph = vim.eval('g:mundo_verbose_graph') @@ -208,8 +234,9 @@ def GetNextLine(direction,move_count,write,start="line('.')"): return next_line return GetNextLine(direction,1,write,str(next_line)) return next_line +# }}} -def MundoMove(direction,move_count=1,relative=True,write=False): +def MundoMove(direction,move_count=1,relative=True,write=False):# {{{ """ Move within the undo graph in the direction specified (or to the specific undo node specified). @@ -261,40 +288,36 @@ def MundoMove(direction,move_count=1,relative=True,write=False): vim.command("call cursor(0, %d + 1)" % idx2) else: vim.command("call cursor(0, %d + 1)" % idx3) +# }}} - if (vim.eval('g:mundo_auto_preview') != '0' and - int(vim.eval("get(g:, 'mundo_auto_preview_delay', 0)")) <= 0): - MundoRenderPreview() - - -def MundoSearch(): +def MundoSearch():# {{{ search = vim.eval("input('/')") vim.command('let @/="%s"' % search.replace("\\", "\\\\").replace('"', '\\"')) MundoNextMatch() +# }}} - -def MundoPrevMatch(): +def MundoPrevMatch():# {{{ MundoMatch(-1) +# }}} - -def MundoNextMatch(): +def MundoNextMatch():# {{{ MundoMatch(1) +# }}} -def MundoMatch(down): +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. """ + 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')) + util._goto_window_for_buffer(int(vim.eval('g:mundo_target_n'))) nodes, nmap = nodesData.make_nodes() total = len(nodes) - 1 - util._goto_window_for_buffer_name('__Mundo__') + util._goto_window_for_buffer('__Mundo__') mundo_node = MundoGetTargetState() found_version = -1 @@ -303,7 +326,7 @@ def MundoMatch(down): if down < 0: therange = range(mundo_node+1,total+1) for version in therange: - util._goto_window_for_buffer_name('__Mundo__') + util._goto_window_for_buffer('__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): @@ -317,28 +340,29 @@ def MundoMatch(down): # found something, lets get out of here: if found_version != -1: break - util._goto_window_for_buffer_name('__Mundo__') + util._goto_window_for_buffer('__Mundo__') if found_version >= 0: MundoMove(found_version,1,False) +# }}} -def MundoRenderPatchdiff(): +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_name('__Mundo_Preview__') + util._goto_window_for_buffer('__Mundo_Preview__') if vim.current.buffer[:] == ['']: # restore the cursor position before exiting. - util._goto_window_for_buffer_name('__Mundo__') + 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_name('__Mundo__') + util._goto_window_for_buffer('__Mundo__') vim.command('quit') # save the __Mundo_Preview__ buffer to a temp file. - util._goto_window_for_buffer_name('__Mundo_Preview__') + util._goto_window_for_buffer('__Mundo_Preview__') (handle,filename) = tempfile.mkstemp() vim.command('silent! w %s' % (filename)) # exit the __Mundo_Preview__ window @@ -348,8 +372,9 @@ def MundoRenderPatchdiff(): vim.command('set buftype=nofile bufhidden=delete') return True return False +# }}} -def MundoGetChangesForLine(): +def MundoGetChangesForLine():# {{{ if not _check_sanity(): return False @@ -358,20 +383,21 @@ def MundoGetChangesForLine(): # 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__') + util._goto_window_for_buffer('__Mundo__') return False else: target_state = int(target_state) - util._goto_window_for_buffer(vim.eval('g:mundo_target_n')) + 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 MundoRenderChangePreview(): +def MundoRenderChangePreview():# {{{ """ Render the selected undo level with the current file. Return True on success, False on failure. """ if not _check_sanity(): @@ -380,11 +406,13 @@ def MundoRenderChangePreview(): vim.command('call s:MundoOpenPreview()') util._output_preview_text(MundoGetChangesForLine()) - util._goto_window_for_buffer_name('__Mundo__') + util._goto_window_for_buffer('__Mundo__') return True +# }}} -def MundoRenderToggleInlineDiff(): +def MundoRenderToggleInlineDiff():# {{{ + """ Toggles g:mundo_inline_undo and redraws the graph window. """ show_inline = int(vim.eval('g:mundo_inline_undo')) if show_inline == 0: vim.command("let g:mundo_inline_undo=1") @@ -394,8 +422,10 @@ def MundoRenderToggleInlineDiff(): nodesData.clear_oneline_diffs() MundoRenderGraph(True) vim.command("call cursor(%d,0)" % line) +# }}} -def MundoToggleHelp(): +def MundoToggleHelp():# {{{ + """ Toggles g:mundo_help and redraws the graph window. """ show_help = int(vim.eval('g:mundo_help')) if show_help == 0: vim.command("let g:mundo_help=1") @@ -406,15 +436,22 @@ def MundoToggleHelp(): old_line_count = int(vim.eval("line('$')")) MundoRenderGraph(True) new_line_count = int(vim.eval("line('$')")) - vim.command("call cursor(%d, %d)" % (line + new_line_count - old_line_count, column)) + vim.command( + "call cursor(%d, %d)" % (line + new_line_count - old_line_count, + column) + ) + +# Mundo undo/redo}}} -# Mundo undo/redo -def MundoRevert(): +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 = vim.eval('g:mundo_target_n') + back = int(vim.eval('g:mundo_target_n')) util._goto_window_for_buffer(back) util._undo_to(target_n) @@ -425,8 +462,12 @@ def MundoRevert(): if int(vim.eval('g:mundo_close_on_revert')): vim.command('MundoToggle') +# }}} -def MundoPlayTo(): +def MundoPlayTo():# {{{ + """ Replays changes between the current state and a selected state in + real-time. + """ if not _check_sanity(): return @@ -443,8 +484,7 @@ def MundoPlayTo(): start = nmap[nodesData.current()] end = nmap[target_n] - - def _walk_branch(origin, dest): + def _walk_branch(origin, dest):# {{{ rev = origin.n < dest.n nodes = [] @@ -466,6 +506,7 @@ def _walk_branch(origin, dest): return reversed(nodes) else: return nodes + # }}} branch = _walk_branch(start, end) @@ -480,3 +521,6 @@ def _walk_branch(origin, dest): util._goto_window_for_buffer(back) vim.command('redraw') vim.command('sleep %dm' % delay) +# }}} + +# vim: set ts=4 sw=4 tw=79 fdm=marker et : diff --git a/autoload/mundo.vim b/autoload/mundo.vim index 23379be..f6ef814 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -56,21 +56,39 @@ function! s:MundoSetupPythonPath()"{{{ end endfunction"}}} -function! s:MundoGoToWindowForBufferName(name)"{{{ - if bufwinnr(bufnr(a:name)) != -1 - exe bufwinnr(bufnr(a:name)) . "wincmd w" +" Moves to the first window in the current tab corresponding to expr. Accepts +" an integer buffer number or a string file-pattern; for a detailed description +" see :h bufname. Returns 1 if successful, 0 otherwise. +function! s:MundoGoToWindowForBuffer(expr)"{{{ + if bufwinnr(bufnr(a:expr)) != -1 + exe bufwinnr(bufnr(a:expr)) . "wincmd w" return 1 - else - return 0 endif + + return 0 endfunction"}}} -function! s:MundoIsVisible()"{{{ - if bufwinnr(bufnr("__Mundo__")) != -1 || bufwinnr(bufnr("__Mundo_Preview__")) != -1 +" Similar to MundoGoToWindowForBuffer, but considers windows in all tabs. +" Prioritises matches in the current tab. +function! s:MundoGoToWindowForBufferGlobal(expr)"{{{ + if s:MundoGoToWindowForBuffer(a:expr) return 1 - else + endif + + let l:bufWinIDs = win_findbuf(bufnr(a:expr)) + + if len(l:bufWinIDs) <= 0 return 0 endif + + call win_gotoid(l:bufWinIDs[0]) + return 1 +endfunction"}}} + +" Returns True if the graph or preview windows are open in the current tab. +function! s:MundoIsVisible()"{{{ + return bufwinnr(bufnr("__Mundo__")) != -1 || + \ bufwinnr(bufnr("__Mundo_Preview__")) != -1 endfunction"}}} function! s:MundoInlineHelpLength()"{{{ @@ -79,9 +97,7 @@ function! s:MundoInlineHelpLength()"{{{ else return 0 endif -endfunction"}}} - -"}}} +endfunction"}}}}} "{{{ Mundo buffer settings @@ -171,10 +187,10 @@ endfunction"}}} "{{{ Mundo buffer/window management function! s:MundoResizeBuffers(backto)"{{{ - call s:MundoGoToWindowForBufferName('__Mundo__') + call s:MundoGoToWindowForBuffer('__Mundo__') exe "vertical resize " . g:mundo_width - call s:MundoGoToWindowForBufferName('__Mundo_Preview__') + call s:MundoGoToWindowForBuffer('__Mundo_Preview__') exe "resize " . g:mundo_preview_height exe a:backto . "wincmd w" @@ -184,7 +200,7 @@ function! s:MundoOpenGraph()"{{{ let existing_mundo_buffer = bufnr("__Mundo__") if existing_mundo_buffer == -1 - call s:MundoGoToWindowForBufferName('__Mundo_Preview__') + call assert_true(s:MundoGoToWindowForBuffer('__Mundo_Preview__')) exe "new __Mundo__" set fdm=manual if g:mundo_preview_bottom @@ -203,7 +219,7 @@ function! s:MundoOpenGraph()"{{{ exe existing_mundo_window . "wincmd w" endif else - call s:MundoGoToWindowForBufferName('__Mundo_Preview__') + call s:MundoGoToWindowForBuffer('__Mundo_Preview__') if g:mundo_preview_bottom if g:mundo_right exe "botright vsplit +buffer" . existing_mundo_buffer @@ -258,27 +274,69 @@ function! s:MundoOpenPreview()"{{{ endif endfunction"}}} -function! s:MundoClose()"{{{ - if s:MundoGoToWindowForBufferName('__Mundo__') +" Quits *all* open Mundo graph and preview windows. +function! s:MundoClose() abort "{{{ + let [l:tabid, l:winid] = win_id2tabwin(win_getid()) + + while s:MundoGoToWindowForBufferGlobal('__Mundo__') quit - endif + endwhile - if s:MundoGoToWindowForBufferName('__Mundo_Preview__') + while s:MundoGoToWindowForBufferGlobal('__Mundo_Preview__') quit + endwhile + + if win_gotoid(l:winid) + return + elseif l:tabid != 0 && l:tabid <= tabpagenr('$') + execute 'normal! ' . l:tabid . 'gt' endif - exe bufwinnr(g:mundo_target_n) . "wincmd w" + call s:MundoGoToWindowForBuffer(get(g:, 'mundo_target_n', -1)) endfunction"}}} -function! s:InitPythonModule(python) +function! s:InitPythonModule(python)"{{{ exe a:python .' import sys' exe a:python .' if sys.version_info[:2] < (2, 4): '. \ 'vim.command("let s:has_supported_python = 0")' -endfunction +endfunction"}}} + +" Returns 1 if the current buffer is a valid target buffer for Mundo, or a +" (falsy) string indicating the reason if otherwise. +function! s:MundoIsValidBuffer()"{{{ + if !&modifiable | return 'is not modifiable' | endif + if &previewwindow | return 'is preview window' | endif + if &buftype != '' && &buftype != 'acwrite' | + \ return 'invalid buffer type "'.&buftype.'"' | endif + return 1 +endfunction "}}} + +" }}} + +" Open/reopen Mundo for the current buffer, initialising the python module if +" necessary. +function! s:MundoOpen() abort "{{{ + " Validate and target buffer, store buffer number & file + let is_valid_reason = s:MundoIsValidBuffer() + + if ! is_valid_reason + echom 'Current buffer ('.bufnr('').') is not a valid target for Mundo'. + \ ' (Reason: '.is_valid_reason.')' + return + endif + + let g:mundo_target_n = bufnr('') + let g:mundo_target_f = @% + " Close *all* existing Mundo windows + call s:MundoClose() -function! s:MundoOpen()"{{{ + " Load python if !exists('g:mundo_py_loaded') + " Add Mundo to python path + call s:MundoSetupPythonPath() + + " Initialise python module if s:has_supported_python == 2 exe 'py3file ' . escape(s:plugin_path, ' ') . '/mundo.py' call s:InitPythonModule('python3') @@ -289,8 +347,11 @@ function! s:MundoOpen()"{{{ if !s:has_supported_python function! s:MundoDidNotLoad() - echohl WarningMsg|echomsg "Mundo unavailable: requires Vim 7.3+"|echohl None + echohl WarningMsg + echomsg "Mundo unavailable: requires Vim 7.3+" + echohl None endfunction + command! -nargs=0 MundoToggle call s:MundoDidNotLoad() call s:MundoDidNotLoad() return @@ -305,11 +366,18 @@ function! s:MundoOpen()"{{{ let &splitbelow = 0 call s:MundoOpenPreview() - exe bufwinnr(g:mundo_target_n) . "wincmd w" +" exe bufwinnr(g:mundo_target_n) . "wincmd w" + call s:MundoGoToWindowForBuffer(g:mundo_target_n) call s:MundoOpenGraph() - call s:MundoPython('MundoRenderGraph()') - call s:MundoPython('MundoRenderPreview()') + call mundo#MundoRenderGraph() + + " Move cursor to the graph if the window was created + if line('.') == 1 + call s:MundoPython('MundoMove(1, 1)') + endif + + call mundo#MundoRenderPreview() " Restore `splitbelow` value. let &splitbelow = saved_splitbelow @@ -319,21 +387,15 @@ endfunction"}}} let s:mundo_path = escape( expand( ':p:h' ), '\' ) function! s:MundoToggle()"{{{ - call s:MundoSetupPythonPath() if s:MundoIsVisible() call s:MundoClose() else - let g:mundo_target_n = bufnr('') - let g:mundo_target_f = @% call s:MundoOpen() endif endfunction"}}} function! s:MundoShow()"{{{ - call s:MundoSetupPythonPath() if !s:MundoIsVisible() - let g:mundo_target_n = bufnr('') - let g:mundo_target_f = @% call s:MundoOpen() endif endfunction"}}} @@ -371,6 +433,32 @@ function! s:MundoPython(fn)"{{{ endif endfunction"}}} +" Wrapper for MundoPython() that restores the window state and prevents other +" Mundo autocommands (with the exception of BufNewFile) from triggering. +function! s:MundoPythonRestoreView(fn)"{{{ + " Save current window and view information, ignore autocommands + let currentWin = winnr() + let winView = winsaveview() + let eventignorePrev = &eventignore + set eventignore=CursorHold,CursorMoved,TextChanged,InsertLeave,BufLeave, + \BufEnter + + call s:MundoPython(a:fn) + + " Restore ignored autocommands, window and view information + silent exec 'set eventignore='.eventignorePrev + execute currentWin .'wincmd w' + call winrestview(winView) +endfunction"}}} + +function! mundo#MundoRenderGraph()"{{{ + call s:MundoPythonRestoreView('MundoRenderGraph()') +endfunction"}}} + +function! mundo#MundoRenderPreview()"{{{ + call s:MundoPythonRestoreView('MundoRenderPreview()') +endfunction"}}} + "}}} "{{{ Misc @@ -387,18 +475,6 @@ function! mundo#MundoHide()"{{{ call s:MundoHide() endfunction"}}} -function! mundo#MundoRenderGraph()"{{{ - " Save window view information and buffer number - let currentWin = bufwinnr('%') - let winView = winsaveview() - - call s:MundoPython('MundoRenderGraph()') - - " Return to buffer and restore window view - execute currentWin .'wincmd w' - call winrestview(winView) -endfunction"}}} - " automatically reload Mundo buffer if open function! s:MundoRefresh()"{{{ " abort if Mundo is closed or cursor is in the preview window @@ -410,18 +486,18 @@ function! s:MundoRefresh()"{{{ return endif - " Normal refresh - if !get(g:, 'mundo_auto_preview', 0) || - \ get(g:, 'mundo_auto_preview_delay', 0) <= 0 - return mundo#MundoRenderGraph() - endif - - " Delayed refresh - if !get(g:, 'mundo_enable_inline_delay', 0) || - \ !get(g:, 'mundo_inline_undo') + " Handle normal refresh + if get(g:, 'mundo_auto_preview_delay', 0) <= 0 call mundo#MundoRenderGraph() + + if get(g:, 'mundo_auto_preview', 0) && (currentWin == mundoWin) + \ && mode() == 'n' + call mundo#MundoRenderPreview() + endif + return endif + " Handle delayed refresh call s:MundoRestartRefreshTimer() endfunction"}}} @@ -429,7 +505,7 @@ function! s:MundoRestartRefreshTimer()"{{{ call s:MundoStopRefreshTimer() let s:auto_preview_timer = timer_start( \ get(g:, 'mundo_auto_preview_delay', 0), - \ function('s:MundoRefreshDelayed') + \ function('s:MundoRefreshDelayed') \ ) endfunction"}}} @@ -450,9 +526,11 @@ function! s:MundoRefreshDelayed(...)"{{{ return endif + call mundo#MundoRenderGraph() + " Handle other windows if currentWin != mundoWin - return mundo#MundoRenderGraph() + return endif " Handle graph window (__Mundo__) @@ -461,26 +539,23 @@ function! s:MundoRefreshDelayed(...)"{{{ endif if mode() != 'n' - return s:MundoRestartRefreshTimer() - endif - - if get(g:, 'mundo_enable_inline_delay', 0) && get(g:, 'mundo_inline_undo') - call mundo#MundoRenderGraph() + call s:MundoRestartRefreshTimer() + return endif let s:auto_preview_line = line('.') - call s:MundoPython('MundoRenderPreview()') + call mundo#MundoRenderPreview() endfunction"}}} -augroup MundoAug +augroup MundoAug"{{{ autocmd! autocmd BufNewFile __Mundo__ call s:MundoSettingsGraph() autocmd BufNewFile __Mundo_Preview__ call s:MundoSettingsPreview() - autocmd CursorHold * call s:MundoRefresh() - autocmd CursorMoved * call s:MundoRefresh() + autocmd CursorHold,CursorMoved,TextChanged,InsertLeave * + \ call s:MundoRefresh() autocmd BufLeave __Mundo__ call s:MundoStopRefreshTimer() - autocmd BufEnter * let b:mundoChangedtick = 0 -augroup END + autocmd BufEnter __Mundo__ let s:auto_preview_line = -1 +augroup END"}}} "}}} diff --git a/autoload/mundo/node.py b/autoload/mundo/node.py index 3b6b64d..2e0388f 100644 --- a/autoload/mundo/node.py +++ b/autoload/mundo/node.py @@ -34,7 +34,7 @@ def clear_oneline_diffs(self): self.diff_has_oneline = {} def _check_version_location(self): - util._goto_window_for_buffer(util.vim().eval('g:mundo_target_n')) + util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) target_f = util.vim().eval('g:mundo_target_f') if target_f != self.target_f: self._clear_cache() @@ -46,14 +46,15 @@ def _make_nodes(self,alts, nodes, parent=None): if alt: curhead = 'curhead' in alt saved = 'save' in alt - node = Node(n=alt['seq'], parent=p, time=alt['time'], curhead=curhead, saved=saved) + node = Node(n=alt['seq'], parent=p, time=alt['time'], + curhead=curhead, saved=saved) nodes.append(node) if alt.get('alt'): self._make_nodes(alt['alt'], nodes, p) p = node def is_outdated(self): - util._goto_window_for_buffer(util.vim().eval('g:mundo_target_n')) + util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) current_changedtick = util.vim().eval('b:changedtick') return self.changedtick != current_changedtick @@ -114,7 +115,7 @@ def change_preview_diff(self,before,after): if key in self.diffs: return self.diffs[key] - util._goto_window_for_buffer(util.vim().eval('g:mundo_target_n')) + util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) before_lines = self._get_lines(before) after_lines = self._get_lines(after) @@ -183,12 +184,15 @@ def preview_diff(self, before, after, unified=True, inline=False): after_time = self._fmt_time(after.time) if unified: - self.diffs[key] = list(difflib.unified_diff(before_lines, after_lines, - before_name, after_name, - before_time, after_time)) + self.diffs[key] = list( + difflib.unified_diff(before_lines, after_lines, before_name, + after_name, before_time, after_time) + ) elif inline: maxwidth = int(util.vim().eval("winwidth(0)")) - self.diffs[key] = diff.one_line_diff_str('\n'.join(before_lines),'\n'.join(after_lines),maxwidth) + self.diffs[key] = diff.one_line_diff_str( + '\n'.join(before_lines),'\n'.join(after_lines), maxwidth + ) self.diff_has_oneline[key] = True else: self.diffs[key] = "" diff --git a/autoload/mundo/util.py b/autoload/mundo/util.py index 548be34..e121d5b 100644 --- a/autoload/mundo/util.py +++ b/autoload/mundo/util.py @@ -3,29 +3,46 @@ normal = lambda s: vim().command('normal %s' % s) normal_silent = lambda s: vim().command('silent! normal %s' % s) + def vim(): """ call Vim. - - This is wrapped so that it can easily be mocked. + + This is wrapped so that it can easily be mocked. """ import vim return vim -def _goto_window_for_buffer(b): - w = int(vim().eval('bufwinnr(%d)' % int(b))) - vim().command('%dwincmd w' % int(w)) -def _goto_window_for_buffer_name(bn): - b = vim().eval('bufnr("%s")' % bn) - return _goto_window_for_buffer(b) +def _goto_window_for_buffer(expr): + """ Moves the cursor to the first window associated with buffer b in the + current tab page (only). + + Arguments + --------- + expr : int or str + The target buffer - either a buffer number (int) or a file-pattern + (str). See :h bufwinnr for a more detailed description. + """ + if not isinstance(expr, int) and not isinstance(expr, str): + raise TypeError('b has invalid type, str or int expected.') + + if isinstance(expr, str): + expr = "'{0}'".format(expr) + + winnr = int(vim().eval('bufwinnr({0})'.format(expr))) + assert winnr != -1 + vim().command('%dwincmd w' % int(winnr)) + # Rendering utility functions def _output_preview_text(lines): - _goto_window_for_buffer_name('__Mundo_Preview__') + """ Output a list of lines to the mundo preview window. """ + _goto_window_for_buffer('__Mundo_Preview__') vim().command('setlocal modifiable') vim().current.buffer[:] = [line.rstrip() for line in lines] vim().command('setlocal nomodifiable') + def _undo_to(n): n = int(n) if n == 0: diff --git a/autoload/mundo/util.vim b/autoload/mundo/util.vim index 0fb9649..b76f8c2 100644 --- a/autoload/mundo/util.vim +++ b/autoload/mundo/util.vim @@ -93,6 +93,8 @@ call mundo#util#set_default( \ 'g:mundo_return_on_revert', 1, \ 'g:gundo_return_on_revert') +call mundo#util#set_default('g:mundo_auto_preview_delay', 250) + function! mundo#util#init() abort endfunction diff --git a/doc/mundo.txt b/doc/mundo.txt index f4d7201..b696fc6 100644 --- a/doc/mundo.txt +++ b/doc/mundo.txt @@ -25,8 +25,7 @@ CONTENTS *Mundo-contents* 3.13 mundo_playback_delay ...... |mundo_playback_delay| 3.14 mundo_mirror_graph ........ |mundo_mirror_graph| 3.15 mundo_inline_undo ......... |mundo_inline_undo| - 3.16 mundo_enable_inline_delay ... |mundo_enable_inline_delay| - 3.17 mundo_return_on_revert .... |mundo_return_on_revert| + 3.16 mundo_return_on_revert .... |mundo_return_on_revert| 4. License ......................... |MundoLicense| 5. Bugs ............................ |MundoBugs| 6. Contributing .................... |MundoContributing| @@ -230,9 +229,10 @@ Default: 1 (automatically preview diffs) This is the delay in milliseconds before a preview diff is automatically rendered. The delay is reset whenever the cursor moves. Use this to speed up -undo tree traversal when automatic previews are enabled. +undo tree traversal when automatic previews are enabled. Set this to 0 to +disable the feature. -Default: 0 (no delay) +Default: 250 ------------------------------------------------------------------------------ 3.12 g:mundo_verbose_graph *mundo_verbose_graph* @@ -253,32 +253,23 @@ for a faster playback. Default: 60 ------------------------------------------------------------------------------ -3.14 g:mundo_mirror_graph *mundo_mirror_graph* +3.14 g:mundo_mirror_graph *mundo_mirror_graph* Set this to 0 to align the graph to the left; set to 1 to align to the right. Default: 1 (mirror graph) ------------------------------------------------------------------------------ -3.15 g:mundo_inline_undo *mundo_inline_undo* +3.15 g:mundo_inline_undo *mundo_inline_undo* -When enabled, a small one line diff is displayed to the right of the graph undo. -Although not as detailed as a full diff provided in the preview window, it -provides a quick summary of the diff w/o having to navigate. +When enabled, a small one line diff is displayed to the right of the graph +undo. Although not as detailed as a full diff provided in the preview window, +it provides a quick summary of the diff w/o having to navigate. Default: 0 (no inline graph) ------------------------------------------------------------------------------ -3.16 g:mundo_enable_inline_delay *mundo_enable_inline_delay* - -When this option is set, inline diff rendering will be delayed until a preview -diff is rendered. Use this to speed up undo tree traversal when inline diffs -and delayed automatic previews are both enabled. - -Default: 0 (disabled) - ------------------------------------------------------------------------------ -3.17 g:mundo_return_on_revert *mundo_return_on_revert* +3.16 g:mundo_return_on_revert *mundo_return_on_revert* Set this to 0 to keep focus in the Mundo window after a revert. @@ -302,11 +293,16 @@ https://github.com/simnalamburt/vim-mundo/issues Think you can make this plugin better? Awesome. Fork it on BitBucket or GitHub and send a pull request. +Version numbers should roughly follow Semantic Versioning. + GitHub: https://github.com/simnalamburt/vim-mundo ============================================================================== 7. Changelog *MundoChangelog* + +v3.1.0 + * Added g:mundo_auto_preview_delay setting. v3.0.1 * Made inline diff mode much faster(e.g. 300x) * Fix inline diffs not updating after scroll. @@ -341,8 +337,8 @@ v2.2.0 * Fix a bug with the splitbelow setting. v2.1.1 * Fix a bug with the movement key mappings. -v2.1.0 * Warnings about having an incompatible Vim and/or Python installation +v2.1.0 are now deferred until the first time you try to use Mundo, instead of being displayed on launch. * The and mappings are now configurable with From aa5c3a03b5e314a05da44abcc81a522065c942fc Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Fri, 4 May 2018 12:17:17 +1000 Subject: [PATCH 09/16] Fixed issue with Nodes not detecting target file or buffer changes --- autoload/mundo.py | 1 - autoload/mundo.vim | 19 +++++++------- autoload/mundo/node.py | 59 ++++++++++++++++++++++++++++-------------- autoload/mundo/util.py | 1 - 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index 1393e1a..d3af285 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -10,7 +10,6 @@ # ============================================================================ import re -import sys import tempfile import vim diff --git a/autoload/mundo.vim b/autoload/mundo.vim index f6ef814..dbb836e 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -60,12 +60,15 @@ endfunction"}}} " an integer buffer number or a string file-pattern; for a detailed description " see :h bufname. Returns 1 if successful, 0 otherwise. function! s:MundoGoToWindowForBuffer(expr)"{{{ - if bufwinnr(bufnr(a:expr)) != -1 - exe bufwinnr(bufnr(a:expr)) . "wincmd w" - return 1 + let l:winnr = bufwinnr(bufnr(a:expr)) + + if l:winnr == -1 + return 0 + elseif l:winnr != winnr() + exe l:winnr . "wincmd w" endif - return 0 + return 1 endfunction"}}} " Similar to MundoGoToWindowForBuffer, but considers windows in all tabs. @@ -319,7 +322,7 @@ function! s:MundoOpen() abort "{{{ " Validate and target buffer, store buffer number & file let is_valid_reason = s:MundoIsValidBuffer() - if ! is_valid_reason + if !is_valid_reason echom 'Current buffer ('.bufnr('').') is not a valid target for Mundo'. \ ' (Reason: '.is_valid_reason.')' return @@ -366,20 +369,18 @@ function! s:MundoOpen() abort "{{{ let &splitbelow = 0 call s:MundoOpenPreview() -" exe bufwinnr(g:mundo_target_n) . "wincmd w" call s:MundoGoToWindowForBuffer(g:mundo_target_n) call s:MundoOpenGraph() - call mundo#MundoRenderGraph() - " Move cursor to the graph if the window was created + " If necessary, move the graph window cursor to the first node if line('.') == 1 call s:MundoPython('MundoMove(1, 1)') endif call mundo#MundoRenderPreview() - " Restore `splitbelow` value. + " Restore `splitbelow` let &splitbelow = saved_splitbelow endfunction"}}} diff --git a/autoload/mundo/node.py b/autoload/mundo/node.py index 2e0388f..444f638 100644 --- a/autoload/mundo/node.py +++ b/autoload/mundo/node.py @@ -20,6 +20,7 @@ def __repr__(self): class Nodes(object): def __init__(self): + self.target_n_last = None self._clear_cache() def _clear_cache(self): @@ -33,25 +34,34 @@ def clear_oneline_diffs(self): self.diffs = {} self.diff_has_oneline = {} - def _check_version_location(self): - util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) + def _validate_cache(self): + """ Checks if the target file or buffer has changed, and if so + clears all cached data. + """ + target_n = int(util.vim().eval('g:mundo_target_n')) target_f = util.vim().eval('g:mundo_target_f') - if target_f != self.target_f: + + if self.target_n_last != target_n or target_f != self.target_f: self._clear_cache() + self.target_n_last = target_n def _make_nodes(self,alts, nodes, parent=None): p = parent for alt in alts: - if alt: - curhead = 'curhead' in alt - saved = 'save' in alt - node = Node(n=alt['seq'], parent=p, time=alt['time'], - curhead=curhead, saved=saved) - nodes.append(node) - if alt.get('alt'): - self._make_nodes(alt['alt'], nodes, p) - p = node + if not alt: + continue + + curhead = 'curhead' in alt + saved = 'save' in alt + node = Node(n=alt['seq'], parent=p, time=alt['time'], + curhead=curhead, saved=saved) + nodes.append(node) + + if alt.get('alt'): + self._make_nodes(alt['alt'], nodes, p) + + p = node def is_outdated(self): util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) @@ -59,12 +69,14 @@ def is_outdated(self): return self.changedtick != current_changedtick def make_nodes(self): + # Clear cache if it is invalid + self._validate_cache() + # If the current changedtick is unchanged, we don't need to do # anything: if not self.is_outdated(): return self.nodes_made - self._check_version_location() target_f = util.vim().eval('g:mundo_target_f') ut = util.vim().eval('undotree()') entries = ut['entries'] @@ -88,13 +100,15 @@ def make_nodes(self): def current(self): """ Return the number of the current change. """ - self._check_version_location() + self._validate_cache() nodes, nmap = self.make_nodes() _curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes)) + if _curhead_l: current = _curhead_l[0].parent.n else: current = int(util.vim().eval('changenr()')) + return current def _fmt_time(self,t): @@ -102,16 +116,19 @@ def _fmt_time(self,t): def _get_lines(self,node): n = 0 + if node: n = node.n if n not in self.lines: util._undo_to(n) self.lines[n] = util.vim().current.buffer[:] + return self.lines[n] - def change_preview_diff(self,before,after): - self._check_version_location() + def change_preview_diff(self, before, after): + self._validate_cache() key = "%s-%s-cpd"%(before.n,after.n) + if key in self.diffs: return self.diffs[key] @@ -127,8 +144,8 @@ def change_preview_diff(self,before,after): util._undo_to(self.current()) self.diffs[key] = list(difflib.unified_diff(before_lines, after_lines, - before_name, after_name, - before_time, after_time)) + before_name, after_name, + before_time, after_time)) return self.diffs[key] def preview_diff(self, before, after, unified=True, inline=False): @@ -143,9 +160,11 @@ def preview_diff(self, before, after, unified=True, inline=False): unified - If True, generate a unified diff inline - Generate a one line summary line. """ - self._check_version_location() + self._validate_cache() + bn = 0 an = 0 + if not after.n: # we're at the original file pass elif not before.n: # we're at a pseudo-root state @@ -153,8 +172,10 @@ def preview_diff(self, before, after, unified=True, inline=False): else: bn = before.n an = after.n + key = "%s-%s-pd-%s"%(bn,an,unified) needs_oneline = inline and key not in self.diff_has_oneline + if key in self.diffs and not needs_oneline: return self.diffs[key] diff --git a/autoload/mundo/util.py b/autoload/mundo/util.py index e121d5b..62cf274 100644 --- a/autoload/mundo/util.py +++ b/autoload/mundo/util.py @@ -12,7 +12,6 @@ def vim(): import vim return vim - def _goto_window_for_buffer(expr): """ Moves the cursor to the first window associated with buffer b in the current tab page (only). From 266d860e40ee7cecb161300140a6553455b829b7 Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Fri, 4 May 2018 12:17:17 +1000 Subject: [PATCH 10/16] Fixed issue with Nodes not detecting target file or buffer changes, minor cleanup of node.py --- autoload/mundo.py | 1 - autoload/mundo.vim | 19 +++++++------- autoload/mundo/node.py | 59 ++++++++++++++++++++++++++++-------------- autoload/mundo/util.py | 1 - 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index 1393e1a..d3af285 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -10,7 +10,6 @@ # ============================================================================ import re -import sys import tempfile import vim diff --git a/autoload/mundo.vim b/autoload/mundo.vim index f6ef814..dbb836e 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -60,12 +60,15 @@ endfunction"}}} " an integer buffer number or a string file-pattern; for a detailed description " see :h bufname. Returns 1 if successful, 0 otherwise. function! s:MundoGoToWindowForBuffer(expr)"{{{ - if bufwinnr(bufnr(a:expr)) != -1 - exe bufwinnr(bufnr(a:expr)) . "wincmd w" - return 1 + let l:winnr = bufwinnr(bufnr(a:expr)) + + if l:winnr == -1 + return 0 + elseif l:winnr != winnr() + exe l:winnr . "wincmd w" endif - return 0 + return 1 endfunction"}}} " Similar to MundoGoToWindowForBuffer, but considers windows in all tabs. @@ -319,7 +322,7 @@ function! s:MundoOpen() abort "{{{ " Validate and target buffer, store buffer number & file let is_valid_reason = s:MundoIsValidBuffer() - if ! is_valid_reason + if !is_valid_reason echom 'Current buffer ('.bufnr('').') is not a valid target for Mundo'. \ ' (Reason: '.is_valid_reason.')' return @@ -366,20 +369,18 @@ function! s:MundoOpen() abort "{{{ let &splitbelow = 0 call s:MundoOpenPreview() -" exe bufwinnr(g:mundo_target_n) . "wincmd w" call s:MundoGoToWindowForBuffer(g:mundo_target_n) call s:MundoOpenGraph() - call mundo#MundoRenderGraph() - " Move cursor to the graph if the window was created + " If necessary, move the graph window cursor to the first node if line('.') == 1 call s:MundoPython('MundoMove(1, 1)') endif call mundo#MundoRenderPreview() - " Restore `splitbelow` value. + " Restore `splitbelow` let &splitbelow = saved_splitbelow endfunction"}}} diff --git a/autoload/mundo/node.py b/autoload/mundo/node.py index 2e0388f..444f638 100644 --- a/autoload/mundo/node.py +++ b/autoload/mundo/node.py @@ -20,6 +20,7 @@ def __repr__(self): class Nodes(object): def __init__(self): + self.target_n_last = None self._clear_cache() def _clear_cache(self): @@ -33,25 +34,34 @@ def clear_oneline_diffs(self): self.diffs = {} self.diff_has_oneline = {} - def _check_version_location(self): - util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) + def _validate_cache(self): + """ Checks if the target file or buffer has changed, and if so + clears all cached data. + """ + target_n = int(util.vim().eval('g:mundo_target_n')) target_f = util.vim().eval('g:mundo_target_f') - if target_f != self.target_f: + + if self.target_n_last != target_n or target_f != self.target_f: self._clear_cache() + self.target_n_last = target_n def _make_nodes(self,alts, nodes, parent=None): p = parent for alt in alts: - if alt: - curhead = 'curhead' in alt - saved = 'save' in alt - node = Node(n=alt['seq'], parent=p, time=alt['time'], - curhead=curhead, saved=saved) - nodes.append(node) - if alt.get('alt'): - self._make_nodes(alt['alt'], nodes, p) - p = node + if not alt: + continue + + curhead = 'curhead' in alt + saved = 'save' in alt + node = Node(n=alt['seq'], parent=p, time=alt['time'], + curhead=curhead, saved=saved) + nodes.append(node) + + if alt.get('alt'): + self._make_nodes(alt['alt'], nodes, p) + + p = node def is_outdated(self): util._goto_window_for_buffer(int(util.vim().eval('g:mundo_target_n'))) @@ -59,12 +69,14 @@ def is_outdated(self): return self.changedtick != current_changedtick def make_nodes(self): + # Clear cache if it is invalid + self._validate_cache() + # If the current changedtick is unchanged, we don't need to do # anything: if not self.is_outdated(): return self.nodes_made - self._check_version_location() target_f = util.vim().eval('g:mundo_target_f') ut = util.vim().eval('undotree()') entries = ut['entries'] @@ -88,13 +100,15 @@ def make_nodes(self): def current(self): """ Return the number of the current change. """ - self._check_version_location() + self._validate_cache() nodes, nmap = self.make_nodes() _curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes)) + if _curhead_l: current = _curhead_l[0].parent.n else: current = int(util.vim().eval('changenr()')) + return current def _fmt_time(self,t): @@ -102,16 +116,19 @@ def _fmt_time(self,t): def _get_lines(self,node): n = 0 + if node: n = node.n if n not in self.lines: util._undo_to(n) self.lines[n] = util.vim().current.buffer[:] + return self.lines[n] - def change_preview_diff(self,before,after): - self._check_version_location() + def change_preview_diff(self, before, after): + self._validate_cache() key = "%s-%s-cpd"%(before.n,after.n) + if key in self.diffs: return self.diffs[key] @@ -127,8 +144,8 @@ def change_preview_diff(self,before,after): util._undo_to(self.current()) self.diffs[key] = list(difflib.unified_diff(before_lines, after_lines, - before_name, after_name, - before_time, after_time)) + before_name, after_name, + before_time, after_time)) return self.diffs[key] def preview_diff(self, before, after, unified=True, inline=False): @@ -143,9 +160,11 @@ def preview_diff(self, before, after, unified=True, inline=False): unified - If True, generate a unified diff inline - Generate a one line summary line. """ - self._check_version_location() + self._validate_cache() + bn = 0 an = 0 + if not after.n: # we're at the original file pass elif not before.n: # we're at a pseudo-root state @@ -153,8 +172,10 @@ def preview_diff(self, before, after, unified=True, inline=False): else: bn = before.n an = after.n + key = "%s-%s-pd-%s"%(bn,an,unified) needs_oneline = inline and key not in self.diff_has_oneline + if key in self.diffs and not needs_oneline: return self.diffs[key] diff --git a/autoload/mundo/util.py b/autoload/mundo/util.py index e121d5b..62cf274 100644 --- a/autoload/mundo/util.py +++ b/autoload/mundo/util.py @@ -12,7 +12,6 @@ def vim(): import vim return vim - def _goto_window_for_buffer(expr): """ Moves the cursor to the first window associated with buffer b in the current tab page (only). From 56e2889f16d369c20d63f146027c1ee21f54a7ca Mon Sep 17 00:00:00 2001 From: Michael De Pasquale Date: Sun, 6 May 2018 14:56:04 +1000 Subject: [PATCH 11/16] Fixed Mundo entering the preview window on explicit preview refresh, fixed default settings potentially overriding user settings, fixed the cpo setting not being restored on init failure, added check and error message for supported vim versions without the timers feature, misc. code cleanup and some refactoring --- autoload/mundo.py | 5 +- autoload/mundo.vim | 370 ++++++++++++++++++---------------------- autoload/mundo/util.vim | 177 +++++++++---------- plugin/mundo.vim | 87 +++++++++- 4 files changed, 335 insertions(+), 304 deletions(-) diff --git a/autoload/mundo.py b/autoload/mundo.py index d3af285..d984358 100644 --- a/autoload/mundo.py +++ b/autoload/mundo.py @@ -397,8 +397,9 @@ def MundoGetChangesForLine():# {{{ # }}} def MundoRenderChangePreview():# {{{ - """ Render the selected undo level with the current file. - Return True on success, False on failure. """ + """ Render a diff of the target buffer and the selected undo + tree node. Returns True on success, False otherwise. + """ if not _check_sanity(): return diff --git a/autoload/mundo.vim b/autoload/mundo.vim index dbb836e..19f6270 100644 --- a/autoload/mundo.vim +++ b/autoload/mundo.vim @@ -9,21 +9,51 @@ " ============================================================================ -"{{{ Init let s:save_cpo = &cpo set cpo&vim + +"{{{ Init + +" Initialise global vars +let s:auto_preview_timer = -1"{{{ +let s:auto_preview_line = -1 +let s:exec_python = 0 +let s:has_supported_python = 0 +let s:has_timers = 1 +let s:init_error = 'Initialisation failed due to an unknown error. ' + \ . 'Please submit a bug report :)' + +" This has to be outside of a function, otherwise it just picks up the CWD +let s:plugin_path = escape(expand(':p:h'), '\')"}}} + +" Default to placeholder functions for exposed methods +function! mundo#MundoToggle()"{{{ + call mundo#util#Message("WarningMsg", + \ 'Initialisation error: ' . s:init_error) +endfunction +function! mundo#MundoShow() + call mundo#util#Message("WarningMsg", + \ 'Initialisation error: ' . s:init_error) +endfunction +function! mundo#MundoHide() + call mundo#util#Message("WarningMsg" + \ 'Initialisation error: ' . s:init_error) +endfunction +function! mundo#MundoRenderGraph() + call mundo#util#Message("WarningMsg" + \ 'Initialisation error: ' . s:init_error) +endfunction"}}} + +" Check vim version if v:version < '703'"{{{ - function! s:MundoDidNotLoad() - echohl WarningMsg|echomsg "Mundo unavailable: requires Vim 7.3+"|echohl None - endfunction - command! -nargs=0 MundoToggle call s:MundoDidNotLoad() + let s:init_error = 'Vim version 7.03+ or later is required.' + let &cpo = s:save_cpo finish +elseif v:version < '800' || !has('timers') + let s:has_timers = 0 endif"}}} -call mundo#util#init() - - -let s:has_supported_python = 0 +" Check python version if g:mundo_prefer_python3 && has('python3')"{{{ let s:has_supported_python = 2 elseif has('python')" @@ -33,74 +63,27 @@ elseif has('python3')" endif if !s:has_supported_python - function! s:MundoDidNotLoad() - echohl WarningMsg|echomsg "Mundo requires Vim to be compiled with Python 2.4+"|echohl None - endfunction - command! -nargs=0 MundoToggle call s:MundoDidNotLoad() + let s:init_error = 'A supported python version was not found.' + let &cpo = s:save_cpo finish endif"}}} - -let s:plugin_path = escape(expand(':p:h'), '\') -let s:auto_preview_timer = -1 -let s:auto_preview_line = -1 -"}}} - -"{{{ Mundo utility functions +" Python init methods +function! s:InitPythonModule(python)"{{{ + exe a:python .' import sys' + exe a:python .' if sys.version_info[:2] < (2, 4): '. + \ 'vim.command("let s:has_supported_python = 0")' +endfunction"}}} function! s:MundoSetupPythonPath()"{{{ if g:mundo_python_path_setup == 0 let g:mundo_python_path_setup = 1 - call s:MundoPython('sys.path.insert(1, "'. s:mundo_path .'")') - call s:MundoPython('sys.path.insert(1, "'. s:mundo_path .'/mundo")') + call s:MundoPython('sys.path.insert(1, "'. s:plugin_path .'")') + call s:MundoPython('sys.path.insert(1, "'. s:plugin_path .'/mundo")') end endfunction"}}} -" Moves to the first window in the current tab corresponding to expr. Accepts -" an integer buffer number or a string file-pattern; for a detailed description -" see :h bufname. Returns 1 if successful, 0 otherwise. -function! s:MundoGoToWindowForBuffer(expr)"{{{ - let l:winnr = bufwinnr(bufnr(a:expr)) - - if l:winnr == -1 - return 0 - elseif l:winnr != winnr() - exe l:winnr . "wincmd w" - endif - - return 1 -endfunction"}}} - -" Similar to MundoGoToWindowForBuffer, but considers windows in all tabs. -" Prioritises matches in the current tab. -function! s:MundoGoToWindowForBufferGlobal(expr)"{{{ - if s:MundoGoToWindowForBuffer(a:expr) - return 1 - endif - - let l:bufWinIDs = win_findbuf(bufnr(a:expr)) - - if len(l:bufWinIDs) <= 0 - return 0 - endif - - call win_gotoid(l:bufWinIDs[0]) - return 1 -endfunction"}}} - -" Returns True if the graph or preview windows are open in the current tab. -function! s:MundoIsVisible()"{{{ - return bufwinnr(bufnr("__Mundo__")) != -1 || - \ bufwinnr(bufnr("__Mundo_Preview__")) != -1 -endfunction"}}} - -function! s:MundoInlineHelpLength()"{{{ - if g:mundo_help - return 10 - else - return 0 - endif -endfunction"}}}}} +"}}} "{{{ Mundo buffer settings @@ -115,13 +98,13 @@ function! s:MundoMapGraph()"{{{ nnoremap