vim-highlightedundo
vim-highlightedundo copied to clipboard
Error for too long change undo
In too long change, it gets an error.
How to Repro
" Create 80 count of `.` x 1000 lines
:norm 80a.
yy
999p
" Join them into one line
:1
<Shift-v>G
gJ
" Redo to 1000 lines <= Error happens
u
Error
function highlightedundo#undo[3]..<SNR>147_common[7]..<SNR>147_parsediff[19]..<SNR>147_Diff[19]..<SNR>147_subdifflist_change[1]..<SNR>147_getchanged の処理中にエラーが検出されました:
行 8:
E339: パターンが長過ぎます (Too long pattern)
function highlightedundo#undo[3]..<SNR>147_common[7]..<SNR>147_parsediff[19]..<SNR>147_Diff[19]..<SNR>147_subdifflist_change の処理中にエラーが検出されました:
行 1:
E714: リスト型が必要です (Need a list type)
function highlightedundo#undo[3]..<SNR>147_common[7]..<SNR>147_parsediff[19]..<SNR>147_Diff の処理中にエラーが検出されました:
行 19:
E714: リスト型が必要です (Need a list type)
This happens in calling matchend() with too long pattern (see E339 error above).
So, shorten too long pattern.
Fixed. It should shorten the original text rather than regexp pattern.
Perhaps I misunderstand variable meanings... I'll rewrite later.
If it tries to use matchend() strictly, below would be correct variable use.
@@ -277,16 +277,16 @@ function! s:getchanged(before, after) abort "{{{
return [changedbefore, changedafter]
endif
- let headpat = printf('\m\C^\%%[%s]', substitute(escape(a:before[:99], '~"\.^$*'), '\([][]\)', '[\1]', 'g'))
- let start = matchend(a:after, headpat)
+ let headpat = printf('\m\C^%s\%%[%s]', len(a:before) > matchlen ? '.\{' . (len(a:before) - matchlen) . '}' : '', substitute(escape(a:before[-matchlen:], '~"\.^$*'), '\([][]\)', '[\1]', 'g'))
+ let start = matchend(a:after[:len(a:before) - 1], headpat)
if start == -1
let start = 0
endif
let revbefore = join(reverse(split(a:before, '\zs')), '')
let revafter = join(reverse(split(a:after, '\zs')), '')
- let tailpat = printf('\m\C^\%%[%s]', substitute(escape(revbefore[-100:], '~"\.^$*'), '\([][]\)', '[\1]', 'g'))
- let revend = matchend(revafter, tailpat)
+ let tailpat = printf('\m\C^%s\%%[%s]', len(revbefore) > matchlen ? '.\{' . (len(a:before) - matchlen). '}' : '', substitute(escape(revbefore[-matchlen:], '~"\.^$*'), '\([][]\)', '[\1]', 'g'))
+ let revend = matchend(revafter[:len(revbefore) - 1], tailpat)
if revend == -1
let revend = 0
endif
Although, for performance reason, if given before / after text are too long, it might better to skip strict checking.
I'll switch to the principle.
But still TOOOOO slow...
It takes much time in setting / unsetting highlight style.
The patch https://github.com/machakann/vim-highlightedundo/issues/4#issuecomment-1214546100 helps too much with highlight performance.