vim-highlightedundo icon indicating copy to clipboard operation
vim-highlightedundo copied to clipboard

Error for too long change undo

Open KSR-Yasuda opened this issue 3 years ago • 5 comments

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.

KSR-Yasuda avatar Aug 10 '22 05:08 KSR-Yasuda

Fixed. It should shorten the original text rather than regexp pattern.

KSR-Yasuda avatar Aug 10 '22 06:08 KSR-Yasuda

Perhaps I misunderstand variable meanings... I'll rewrite later.

KSR-Yasuda avatar Aug 10 '22 08:08 KSR-Yasuda

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.

KSR-Yasuda avatar Aug 10 '22 09:08 KSR-Yasuda

But still TOOOOO slow...

It takes much time in setting / unsetting highlight style.

KSR-Yasuda avatar Aug 10 '22 09:08 KSR-Yasuda

The patch https://github.com/machakann/vim-highlightedundo/issues/4#issuecomment-1214546100 helps too much with highlight performance.

KSR-Yasuda avatar Aug 15 '22 02:08 KSR-Yasuda