emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

debounce (was: Some developement questions)


From: Juri Linkov
Subject: debounce (was: Some developement questions)
Date: Tue, 04 Sep 2018 01:15:10 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (x86_64-pc-linux-gnu)

>>> (setq Man-width 75)
>>
>> Emacs nowadays calculates the width dynamically, depending on the
>> dimensions of the window.
>
> Why not make Emacs dynamically size it's windows to the width of the
> display first? ;~O

Implementing this in bug#32536 revealed that mouse drag events become
too laggy when calling Man-update-manpage after every drag event on the
window separator.  JavaScript libraries provide a good solution that makes
web UI more responsible, see https://duckduckgo.com/?q=javascript+debounce

It could be good to have analogous in Emacs to e.g. make window resizing
more responsible.  So instead of

(add-hook 'window-size-change-functions 'Man-window-size-change)

in Man-mode this patch will allow

(add-hook 'window-size-change-functions (debounce 'Man-window-size-change 2))

where the last arg means 2 seconds sliding window to wait, and make the
final call once there are no more resizing events during that time period.

Since its args are similar to the args of run-with-timer, it makes sense
to add it to timer.el:

diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 795554fec5..26c8426d3e 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -545,6 +545,22 @@ internal-timer-start-idle
   (dolist (timer timer-idle-list)
     (if (timerp timer) ;; FIXME: Why test?
         (setf (timer--triggered timer) nil))))
+
+
+(defmacro debounce (function secs)
+  "Postpone FUNCTION call until after SECS seconds have elapsed.
+Return a debounced function that will postpone FUNCTION call
+until after SECS seconds have elapsed since the last time
+it was invoked."
+  (declare (indent 0) (debug t))
+  (let ((timer-sym (make-symbol "timer")))
+    `(let (,timer-sym)
+       (lambda (&rest args)
+         (when (timerp ,timer-sym)
+           (cancel-timer ,timer-sym))
+         (setq ,timer-sym
+           (run-with-timer ,secs nil (lambda () (apply ,function args))))))))
+
 
 (provide 'timer)
 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]