summaryrefslogtreecommitdiff
path: root/lisp/emacs-lisp/timer.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/emacs-lisp/timer.el')
-rw-r--r--lisp/emacs-lisp/timer.el44
1 files changed, 44 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 561cc70078f..5fdf9a426a7 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -488,6 +488,50 @@ The argument should be a value previously returned by `with-timeout-suspend'."
If the user does not answer after SECONDS seconds, return DEFAULT-VALUE."
(with-timeout (seconds default-value)
(y-or-n-p prompt)))
+
+(defmacro debounce (secs function)
+ "Call FUNCTION after SECS seconds have elapsed.
+Postpone FUNCTION call until after SECS seconds have elapsed since the
+last time it was invoked. On consecutive calls within the interval of
+SECS seconds, cancel all previous calls that occur rapidly in quick succession,
+and execute only the last call. This improves performance of event processing."
+ (declare (indent 1) (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))))))))
+
+(defmacro debounce-reduce (secs initial-state state-function function)
+ "Call FUNCTION after SECS seconds have elapsed.
+Postpone FUNCTION call until after SECS seconds have elapsed since the
+last time it was invoked. On consecutive calls within the interval of
+SECS seconds, cancel all previous calls that occur rapidly in quick succession,
+and execute only the last call. This improves performance of event processing.
+
+STATE-FUNCTION can be used to accumulate the state on consecutive calls
+starting with the value of INITIAL-STATE, and then execute the last call
+with the collected state value."
+ (declare (indent 1) (debug t))
+ (let ((timer-sym (make-symbol "timer"))
+ (state-sym (make-symbol "state")))
+ `(let (,timer-sym (,state-sym ,initial-state))
+ (lambda (&rest args)
+ (setq ,state-sym (apply ,state-function ,state-sym args))
+ (when (timerp ,timer-sym)
+ (cancel-timer ,timer-sym))
+ (setq ,timer-sym
+ (run-with-timer
+ ,secs nil (lambda ()
+ (apply ,function (if (listp ,state-sym)
+ ,state-sym
+ (list ,state-sym)))
+ (setq ,state-sym ,initial-state))))))))
+
(defconst timer-duration-words
(list (cons "microsec" 0.000001)