machakann / vim-highlightedyank

Make the yanked region apparent!
844 stars 22 forks source link

Disable highlight during macro execution #26

Closed MarioDotCom closed 6 years ago

MarioDotCom commented 6 years ago

I recently found this plugin and I've been using it for around a week. The only issue I have with it is this:

I find myself using macros quite often and they tend to involve yanking text. When I try to repeat a macro more than a few times the highlight function slows everything down A LOT, and it stops working all together if the number is high enough. You can get around this by deleting instead of yanking, or having a separate yank button map for recording macros... But I'd like to simply be able to change a variable and disable it.

It's not even useful, honestly. I don't think it should happen to begin with. I don't know if this is possible to implement, however.

machakann commented 6 years ago

I agree I do want this. However, the problem is a plugin cannot recognize a macro execution, and thus it cannot hook any processes at the beginning/end of a macro execution...

So, for example, it is not an elegant answer, but how about using a command to toggle the highlightedyank functionality?

Using the command or the keymapping both at the beginning and the end of macro, it works as we expected, although it is a little annoying workaround. This is a possible way, do you like it? If so, I will implement it.

MarioDotCom commented 6 years ago

I wonder if you could set a cooldown so that if I yank 3 times a second it pauses the plugin for the next 10 or whatever.

But yeah a toggle option is the simplest solution. The only other solution I came up with was to map Y to regular yank and use that for macros.

machakann commented 6 years ago

I see, it may be possible with timer feature.

machakann commented 6 years ago

Now, this plugin waits 10 milliseconds before highlighting, and if another yank operation comes in that period it does not highlight. This makes macro faster. In my environment, it seems to work very well!

If you have time, please test issue26 branch. Anyway, I will test it for a few days before merging.

MarioDotCom commented 6 years ago

Just for testing I used emmet to write a 100 word lorem ipsum and created a macro that would yank and paste the line. 100@@ takes half of the time with the plugin disabled. This is not the most realistic way of testing things but it was the first thing that came to my head.

Yesterday while trying things out I found the lazyredraw setting which I didn't know about. It stops updating the screen when a macro is running. 100@@ is basically instant with it enabled.

Maybe having some maps which use HighlightedYankToggle and lazyredraw and playing around with them is the best idea.

I'll keep using it for now.

machakann commented 6 years ago

I agree, using :HighlightedyankToggle would be the best idea at this moment, maybe.

I found that the hack using timer is not helpful at all when a macro is a little slow, whereas its implementation is complex. I tried the similar hacks but nothing is satisfactory. I will merge the patches excluding the timer hack.

somini commented 6 years ago

Can you use lazyredraw to avoid updating the screen during macros? Bonus point for making the macros faster.

markonm commented 6 years ago

Hi, this patch appears to solve the issue

diff --git a/autoload/highlightedyank.vim b/autoload/highlightedyank.vim
index 48bbf11..f35a66f 100644
--- a/autoload/highlightedyank.vim
+++ b/autoload/highlightedyank.vim
@@ -10,13 +10,31 @@ let s:ON = 1
 let s:OFF = 0

 let s:STATE = s:ON
-function! highlightedyank#autocmd_highlight() abort "{{{
-  if s:STATE is s:OFF
-    return
-  endif
+
+
+function! highlightedyank#debounce() abort
   let operator = v:event.operator
   let regtype = v:event.regtype
   let regcontents = v:event.regcontents
+
+  if exists('s:timer')
+    call timer_stop(s:timer)
+  endif
+  let marks = [line("'["), line("']"), col("'["), col("']")]
+  let s:timer = timer_start(1, {-> highlightedyank#autocmd_highlight(operator, regtype, regcontents, marks)})
+endfunction
+
+function! highlightedyank#autocmd_highlight(operator, regtype, regcontents, marks) abort "{{{
+  if a:marks !=#  [line("'["), line("']"), col("'["), col("']")]
+    return
+  endif
+
+  if s:STATE is s:OFF
+    return
+  endif
+  let operator = a:operator
+  let regtype = a:regtype
+  let regcontents = a:regcontents
   if operator !=# 'y' || regtype ==# ''
     return
   endif
diff --git a/plugin/highlightedyank.vim b/plugin/highlightedyank.vim
index 4853d08..b0eb7a6 100644
--- a/plugin/highlightedyank.vim
+++ b/plugin/highlightedyank.vim
@@ -23,7 +23,7 @@ augroup END
 if exists('##TextYankPost') && !hasmapto('<Plug>(highlightedyank)') && !exists('g:highlightedyank_disable_autocmd')
   augroup highlightedyank
     autocmd!
-    autocmd TextYankPost * call highlightedyank#autocmd_highlight()
+    autocmd TextYankPost * call highlightedyank#debounce()
   augroup END

   " commands

Could you test it @MarioDotCom @machakann

machakann commented 6 years ago

Looks great idea! It makes definitely better; I tested 10000 times one-line yank by a macro:

If no error reports, I will merge into master branch in a few days. @xtal8, could you make a pull-request for it? Or if you are busy, I will apply it by myself later, thanks!

markonm commented 6 years ago

I'd prefer you apply it yourself, that way you can change it to suit your code style better.

machakann commented 6 years ago

OK

machakann commented 6 years ago

I merged the patch from @xtal8 into the master branch!

I think the original issue has been largely reduced. Thank you all!