From 4628258729c91d1da383ab4380fe5228a1add731 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Thu, 27 Jan 2022 14:29:10 +0500 Subject: [PATCH] configuration: Add on and once-on macros. Those are also used in tests/renderer-online/set-url.lisp now. --- source/configuration.lisp | 34 ++++++++++++++++++++ tests/renderer-online/set-url.lisp | 50 ++++++++++-------------------- 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/source/configuration.lisp b/source/configuration.lisp index 149ce54b1f7..ee6a1b548f0 100644 --- a/source/configuration.lisp +++ b/source/configuration.lisp @@ -357,3 +357,37 @@ exists." (defun ensure-file-exists (pathname) (open pathname :direction :probe :if-does-not-exist :create)) + +(export-always 'on) +(defmacro on (hook args &body body) + "Attach a handler with ARGS and BODY to the HOOK. + +ARGS can be +- A symbol if there's only one argument to the callback. +- A list of arguments. +- An empty list, if the hook is void." + (let ((handler-name (gensym "on-hook-handler"))) + `(hooks:add-hook + ,hook (make-instance 'hooks:handler + :fn (lambda ,(alex:ensure-list args) + (declare (ignorable ,@(alex:ensure-list args))) + ,@body) + :name (quote ,handler-name))))) + +(export-always 'once-on) +(defmacro once-on (hook args &body body) + "Attach a handler with ARGS and BODY to the HOOK. + +Remove the handler after it fires the first time. + +See `on'." + (let ((handler-name (gensym "once-on-hook-handler"))) + (alex:once-only (hook) + `(hooks:add-hook + ,hook (make-instance 'hooks:handler + :fn (lambda ,(alex:ensure-list args) + (declare (ignorable ,@(alex:ensure-list args))) + (unwind-protect + ,@body + (hooks:remove-hook ,hook (quote ,handler-name)))) + :name (quote ,handler-name)))))) diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp index ebb0d15a4df..83620305f1c 100644 --- a/tests/renderer-online/set-url.lisp +++ b/tests/renderer-online/set-url.lisp @@ -29,39 +29,23 @@ (let ((url-channel (nyxt::make-channel 1)) (url "http://example.org/")) (setf nyxt::*headless-p* t) - (nhooks:add-hook - nyxt:*after-startup-hook* - (make-instance - 'nhooks:handler - :fn (lambda () - (let ((buffer-loaded-channel (nyxt::make-channel 1))) - (nhooks:add-hook - (buffer-loaded-hook (current-buffer)) - (make-instance - 'nhooks:handler - :fn (lambda (buffer) - (calispel:! buffer-loaded-channel t) - (nhooks:remove-hook (buffer-loaded-hook buffer) 'first-buffer-loaded)) - :name 'first-buffer-loaded)) - (let ((thread (bt:make-thread (lambda () - (calispel:? buffer-loaded-channel 10) - (nyxt:set-url))))) - (declare (ignorable thread)) - (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) - (nyxt::set-prompt-buffer-input url) - (prompter:all-ready-p (nyxt:current-prompt-buffer)) - (nyxt/prompt-buffer-mode:return-selection) - (nhooks:add-hook - (buffer-loaded-hook (current-buffer)) - (make-instance - 'nhooks:handler - :fn (lambda (buffer) - (calispel:! url-channel (nyxt:render-url (nyxt:url buffer))) - (nhooks:remove-hook (buffer-loaded-hook buffer) 'example-org-loaded)) - :name 'example-org-loaded)) - ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. - ))) - :name 'browser-started)) + (on nyxt:*after-startup-hook* () + (let ((buffer-loaded-channel (nyxt::make-channel 1))) + (once-on (buffer-loaded-hook (current-buffer)) buffer + (calispel:! buffer-loaded-channel t)) + (let ((thread (run-thread "run set-url" + (calispel:? buffer-loaded-channel 10) + (nyxt:set-url)))) + (declare (ignorable thread)) + (sleep 1) ; waiting for set-url thread + (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) + (nyxt::set-prompt-buffer-input url) + (prompter:all-ready-p (nyxt:current-prompt-buffer)) + (nyxt/prompt-buffer-mode:return-selection) + (once-on (buffer-loaded-hook (current-buffer)) buffer + (calispel:! url-channel (nyxt:render-url (nyxt:url buffer)))) + ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. + ))) (nyxt:start :no-init t :no-auto-config t :socket "/tmp/nyxt-test.socket" :data-profile "test")