From e20827304c15293f3051c541673124a937e96778 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Mon, 3 May 2021 08:45:17 +0200 Subject: [PATCH 01/13] Add *headless-p* control variable. --- source/global.lisp | 4 ++++ source/renderer/gtk.lisp | 9 ++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/source/global.lisp b/source/global.lisp index 3184f3e7201..50b8a8ce992 100644 --- a/source/global.lisp +++ b/source/global.lisp @@ -13,6 +13,10 @@ This is useful when the browser is run from a REPL so that quitting does not close the connection.") +(defvar *headless-p* nil + "If non-nil, don't display anything. +This is convenient for testing purposes or to drive Nyxt programmatically.") + (export-always '*browser*) (defvar *browser* nil "The entry-point object to a complete instance of Nyxt. diff --git a/source/renderer/gtk.lisp b/source/renderer/gtk.lisp index af308c63d5e..df35e07e5aa 100644 --- a/source/renderer/gtk.lisp +++ b/source/renderer/gtk.lisp @@ -368,7 +368,8 @@ response. The BODY is wrapped with `with-protect'." (gtk:gtk-container-add gtk-object root-box-layout) (setf (slot-value *browser* 'last-active-window) window) - (gtk:gtk-widget-show-all gtk-object) + (unless *headless-p* + (gtk:gtk-widget-show-all gtk-object)) (connect-signal window "key_press_event" nil (widget event) (declare (ignore widget)) #+darwin @@ -1058,7 +1059,8 @@ See `gtk-browser's `modifier-translator' slot." (let ((old-buffer (active-buffer window))) (gtk:gtk-container-remove (main-buffer-container window) (gtk-object old-buffer)) (gtk:gtk-box-pack-start (main-buffer-container window) (gtk-object buffer) :expand t :fill t) - (gtk:gtk-widget-show (gtk-object buffer)) + (unless *headless-p* + (gtk:gtk-widget-show (gtk-object buffer))) (when focus (gtk:gtk-widget-grab-focus (gtk-object buffer))) (nyxt/web-extensions::tabs-on-activated old-buffer buffer) @@ -1076,7 +1078,8 @@ See `gtk-browser's `modifier-translator' slot." (push buffer (panel-buffers-right window)))) (setf (gtk:gtk-widget-size-request (gtk-object buffer)) (list (width buffer) -1)) - (gtk:gtk-widget-show (gtk-object buffer))) + (unless *headless-p* + (gtk:gtk-widget-show (gtk-object buffer)))) (define-ffi-method ffi-window-set-panel-buffer-width ((window gtk-window) (buffer panel-buffer) width) "Set the width of a panel buffer." From 43ea7f03aabd735d64460df7e06881ce0044da49 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Mon, 3 May 2021 11:29:41 +0200 Subject: [PATCH 02/13] Add prompt-buffer-channel to allow waiting for prompt-buffer availability. --- source/prompt-buffer.lisp | 3 +++ source/window.lisp | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/source/prompt-buffer.lisp b/source/prompt-buffer.lisp index 65df4799910..43c8cd8b072 100644 --- a/source/prompt-buffer.lisp +++ b/source/prompt-buffer.lisp @@ -185,6 +185,7 @@ See also `hide-prompt-buffer'." ;; TODO: Add method that returns if there is only 1 source with no filter. (when prompt-buffer (push prompt-buffer (active-prompt-buffers (window prompt-buffer))) + (calispel:! (prompt-buffer-channel (window prompt-buffer)) prompt-buffer) (prompt-render prompt-buffer) (run-thread "Show prompt watcher" (let ((prompt-buffer prompt-buffer)) @@ -202,6 +203,8 @@ See also `show-prompt-buffer'." ;; Note that PROMPT-BUFFER is not necessarily first in the list, e.g. a new ;; prompt-buffer was invoked before the old one reaches here. (alex:deletef (active-prompt-buffers window) prompt-buffer) + ;; The channel values are irrelevant, so is the element order: + (calispel:? (prompt-buffer-channel (window prompt-buffer)) 0) (if (resumable-p prompt-buffer) (flet ((prompter= (prompter1 prompter2) (and (string= (prompter:prompt prompter1) diff --git a/source/window.lisp b/source/window.lisp index a9265cacf6a..ceeef78302e 100644 --- a/source/window.lisp +++ b/source/window.lisp @@ -21,6 +21,13 @@ It's a function of the window argument that returns the title as a string.") (list) :export nil :documentation "A list of panel buffers appearing on the window.") + (prompt-buffer-channel + (make-channel) ; TODO: Rename `prompt-buffer-ready-channel'? + :export nil + :documentation "A channel one may listen to if waiting +for the prompt buffer to be available. +You should not rely on the value of this channel. +The channel is popped when a prompt buffer is hidden.") (key-stack '() :documentation "A stack of the key chords a user has pressed.") @@ -34,6 +41,7 @@ It's a function of the window argument that returns the title as a string.") :export nil :type boolean :documentation "Whether the window is displayed in fullscreen.") + ;; TODO: each frame should have a status buffer, not each window (status-buffer :export nil) (message-buffer-height From fa9654603b9633e7ad5f98caffdccb78d87a9014 Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Mon, 3 May 2021 13:19:44 +0200 Subject: [PATCH 03/13] tests: Add first renderer test. --- nyxt.asd | 10 ++++++- tests/renderer-online/set-url.lisp | 46 ++++++++++++++++++++++++++++++ tests/renderer-package.lisp | 8 ++++++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 tests/renderer-online/set-url.lisp create mode 100644 tests/renderer-package.lisp diff --git a/nyxt.asd b/nyxt.asd index abe929211ef..621a203ca77 100644 --- a/nyxt.asd +++ b/nyxt.asd @@ -357,7 +357,15 @@ A naive benchmark on a 16 Mpbs bandwidth gives us cl-gobject-introspection bordeaux-threads) :pathname "source/" - :components ((:file "renderer/gi-gtk"))) + :components ((:file "renderer/gi-gtk")) + :in-order-to ((test-op (test-op "nyxt/gobject/gtk/tests")))) + +(defsystem "nyxt/gobject/gtk/tests" + :depends-on (nyxt/gobject/gtk prove) + :components ((:file "tests/renderer-package")) + :perform (test-op (op c) + (nyxt-run-test c "tests/renderer-offline/") + (nyxt-run-test c "tests/renderer-online/" :network-needed-p t))) (defsystem "nyxt/qt" :depends-on (nyxt diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp new file mode 100644 index 00000000000..f2d4413b32f --- /dev/null +++ b/tests/renderer-online/set-url.lisp @@ -0,0 +1,46 @@ +;;;; SPDX-FileCopyrightText: Atlas Engineer LLC +;;;; SPDX-License-Identifier: BSD-3-Clause + +(in-package :nyxt/tests/renderer) + +(plan nil) + +(class-star:define-class nyxt-user::test-data-profile (nyxt:data-profile) + ((nyxt:name :initform "test")) + (:documentation "Test profile.")) + +(defmethod nyxt:expand-data-path ((profile nyxt-user::test-data-profile) (path nyxt:data-path)) + "Don't persist data" + nil) + +(defmacro with-prompt-buffer-test (command &body body) + (alexandria:with-gensyms (thread) + `(let ((,thread (bt:make-thread (lambda () ,command)))) + (calispel:? (prompt-buffer-channel (current-window))) + ,@body + (return-selection) + (bt:join-thread ,thread)))) + +;; TODO: Use `with-prompt-buffer-test'. +;; (with-prompt-buffer-test (set-url) +;; (set-prompt-input (current-prompt-buffer) "foobar")) + +(subtest "set-url" + (setf nyxt::*headless-p* t) + (nyxt:start :no-init t :no-auto-config t + :socket "/tmp/nyxt-test.socket" + :data-profile "test") + (sleep 2) ; TODO: Wait properly. + (let ((url "http://example.org/")) + (let ((thread (bt:make-thread (lambda () (nyxt:set-url))))) + (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) + (nyxt::set-prompt-input (nyxt:current-prompt-buffer) url) + (prompter:all-ready-p (nyxt:current-prompt-buffer)) + (nyxt/prompt-buffer-mode:return-selection) + ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. + ) + (sleep 1) ; TODO: Wait properly. + (prove:is (nyxt:render-url (nyxt:url (nyxt:current-buffer))) + url))) + +(finalize) diff --git a/tests/renderer-package.lisp b/tests/renderer-package.lisp new file mode 100644 index 00000000000..d74f9e1de5c --- /dev/null +++ b/tests/renderer-package.lisp @@ -0,0 +1,8 @@ +;;;; SPDX-FileCopyrightText: Atlas Engineer LLC +;;;; SPDX-License-Identifier: BSD-3-Clause + +(uiop:define-package nyxt/tests/renderer + (:use #:common-lisp) + (:use #:nyxt) + (:use #:prove) + (:import-from #:class-star #:define-class)) From a19945b7fe6bf8112df8732b7ce128d67192d083 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Tue, 25 Jan 2022 12:22:17 +0500 Subject: [PATCH 04/13] browser: Add after-startup-hook. --- source/browser.lisp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/browser.lisp b/source/browser.lisp index ea80697fbe8..a97204bd03d 100644 --- a/source/browser.lisp +++ b/source/browser.lisp @@ -147,11 +147,16 @@ If nil, renderer-provided dialogs are used.") :documentation "Ask whether to restore the session. The possible values are `:always-ask', `:always-restore' and `:never-restore'.") ;; Hooks follow: + (after-startup-hook + (make-instance 'hooks:hook-void) + :type hooks:hook-void + :documentation "Hook run when the browser is started and ready for interaction. +The handlers take no argument.") (before-exit-hook (make-instance 'hooks:hook-void) :type hooks:hook-void - :documentation "Hook run before both `*browser*' and the -renderer get terminated. The handlers take no argument.") + :documentation "Hook run before both `*browser*' and the renderer get terminated. +The handlers take no argument.") (window-make-hook (make-instance 'hook-window) :type hook-window @@ -324,6 +329,7 @@ prevents otherwise.")) (startup browser urls))))))) ;; Set `init-time' at the end of finalize to take the complete startup time ;; into account. + (hooks:run-hook (after-startup-hook *browser*)) (setf (slot-value *browser* 'init-time) (local-time:timestamp-difference (local-time:now) startup-timestamp)) (setf (slot-value *browser* 'ready-p) t)) From 4468865d2bd24b955c2464628272a1c78630e1f6 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Tue, 25 Jan 2022 12:29:20 +0500 Subject: [PATCH 05/13] Make after-startup-hook a global variable. --- source/browser.lisp | 7 +------ source/global.lisp | 7 ++++++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/browser.lisp b/source/browser.lisp index a97204bd03d..cce28af4de4 100644 --- a/source/browser.lisp +++ b/source/browser.lisp @@ -147,11 +147,6 @@ If nil, renderer-provided dialogs are used.") :documentation "Ask whether to restore the session. The possible values are `:always-ask', `:always-restore' and `:never-restore'.") ;; Hooks follow: - (after-startup-hook - (make-instance 'hooks:hook-void) - :type hooks:hook-void - :documentation "Hook run when the browser is started and ready for interaction. -The handlers take no argument.") (before-exit-hook (make-instance 'hooks:hook-void) :type hooks:hook-void @@ -329,7 +324,7 @@ prevents otherwise.")) (startup browser urls))))))) ;; Set `init-time' at the end of finalize to take the complete startup time ;; into account. - (hooks:run-hook (after-startup-hook *browser*)) + (hooks:run-hook *after-startup-hook*) (setf (slot-value *browser* 'init-time) (local-time:timestamp-difference (local-time:now) startup-timestamp)) (setf (slot-value *browser* 'ready-p) t)) diff --git a/source/global.lisp b/source/global.lisp index 50b8a8ce992..9a3c7dbd58e 100644 --- a/source/global.lisp +++ b/source/global.lisp @@ -27,7 +27,7 @@ It can be initialized with It's possible to run multiple interfaces of Nyxt at the same time. You can let-bind *browser* to temporarily switch interface.") -(declaim (type hooks:hook-void *after-init-hook*)) +(declaim (type hooks:hook-void *after-init-hook* *after-startup-hook*)) (export-always '*after-init-hook*) (defvar *after-init-hook* (make-instance 'hooks:hook-void) "The entry-point object to configure everything in Nyxt. @@ -40,6 +40,11 @@ A handler can be added with: (hooks:add-hook *after-init-hook* 'my-foo-function)") +(export-always '*after-startup-hook*) +(defvar *after-startup-hook* (make-instance 'hooks:hook-void) + "Hook run when the browser is started and ready for interaction. +The handlers take no argument.") + (export-always '*swank-port*) (defvar *swank-port* 4006 "The port that Swank will open a new server on (default Emacs SLIME port From e73f1df361bb6c20bfae5f0e22ad38f995d78094 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Tue, 25 Jan 2022 12:38:47 +0500 Subject: [PATCH 06/13] tests/renderer-online/set-url: Update. --- nyxt.asd | 6 ++-- tests/renderer-online/set-url.lisp | 46 +++++++++++++++++++----------- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/nyxt.asd b/nyxt.asd index 621a203ca77..4a4ec77de6d 100644 --- a/nyxt.asd +++ b/nyxt.asd @@ -358,10 +358,10 @@ A naive benchmark on a 16 Mpbs bandwidth gives us bordeaux-threads) :pathname "source/" :components ((:file "renderer/gi-gtk")) - :in-order-to ((test-op (test-op "nyxt/gobject/gtk/tests")))) + :in-order-to ((test-op (test-op "nyxt/gi-gtk/tests")))) -(defsystem "nyxt/gobject/gtk/tests" - :depends-on (nyxt/gobject/gtk prove) +(defsystem "nyxt/gi-gtk/tests" + :depends-on (nyxt/gi-gtk prove) :components ((:file "tests/renderer-package")) :perform (test-op (op c) (nyxt-run-test c "tests/renderer-offline/") diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp index f2d4413b32f..3d99486b614 100644 --- a/tests/renderer-online/set-url.lisp +++ b/tests/renderer-online/set-url.lisp @@ -23,24 +23,36 @@ ;; TODO: Use `with-prompt-buffer-test'. ;; (with-prompt-buffer-test (set-url) -;; (set-prompt-input (current-prompt-buffer) "foobar")) +;; (update-prompt-input (current-prompt-buffer) "foobar")) (subtest "set-url" - (setf nyxt::*headless-p* t) - (nyxt:start :no-init t :no-auto-config t - :socket "/tmp/nyxt-test.socket" - :data-profile "test") - (sleep 2) ; TODO: Wait properly. - (let ((url "http://example.org/")) - (let ((thread (bt:make-thread (lambda () (nyxt:set-url))))) - (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) - (nyxt::set-prompt-input (nyxt:current-prompt-buffer) url) - (prompter:all-ready-p (nyxt:current-prompt-buffer)) - (nyxt/prompt-buffer-mode:return-selection) - ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. - ) - (sleep 1) ; TODO: Wait properly. - (prove:is (nyxt:render-url (nyxt:url (nyxt:current-buffer))) - url))) + (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 ((thread (bt:make-thread (lambda () (nyxt:set-url))))) + (declare (ignorable thread)) + (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) + (nyxt::update-prompt-input (nyxt:current-prompt-buffer) url) + (prompter:all-ready-p (nyxt:current-prompt-buffer)) + (nyxt/prompt-buffer-mode:return-selection) + ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. + ) + (nhooks:add-hook + (buffer-loaded-hook (current-buffer)) + (make-instance + 'nhooks:handler + :fn (lambda (buffer) + (calispel:! url-channel (nyxt:render-url (nyxt:url buffer)))) + :name 'check-buffer-url))) + :name 'browser-started)) + (nyxt:start :no-init t :no-auto-config t + :socket "/tmp/nyxt-test.socket" + :data-profile "test") + (prove:is (calispel:? url-channel 20) url))) (finalize) From ab5dde6d0f16661c016976d92c0dc1a9c984fd87 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Tue, 25 Jan 2022 13:15:45 +0500 Subject: [PATCH 07/13] browser: Move *after-startup-hook* later in the startup. --- source/browser.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/browser.lisp b/source/browser.lisp index cce28af4de4..07f2817ca3b 100644 --- a/source/browser.lisp +++ b/source/browser.lisp @@ -324,7 +324,6 @@ prevents otherwise.")) (startup browser urls))))))) ;; Set `init-time' at the end of finalize to take the complete startup time ;; into account. - (hooks:run-hook *after-startup-hook*) (setf (slot-value *browser* 'init-time) (local-time:timestamp-difference (local-time:now) startup-timestamp)) (setf (slot-value *browser* 'ready-p) t)) @@ -364,6 +363,7 @@ restored." (restore-session) (load-start-urls urls) (ffi-buffer-delete dummy)) + (hooks:run-hook *after-startup-hook*) (funcall* (startup-error-reporter-function *browser*)))) ;; Catch a common case for a better error message. From 66f450ac5e2f43a9dfad118117c4b0621ce168d8 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Tue, 25 Jan 2022 15:28:53 +0500 Subject: [PATCH 08/13] tests/renderer-online/set-url: Reorder events for predictability. --- tests/renderer-online/set-url.lisp | 44 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp index 3d99486b614..3a85fee0a91 100644 --- a/tests/renderer-online/set-url.lisp +++ b/tests/renderer-online/set-url.lisp @@ -34,25 +34,37 @@ (make-instance 'nhooks:handler :fn (lambda () - (let ((thread (bt:make-thread (lambda () (nyxt:set-url))))) - (declare (ignorable thread)) - (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) - (nyxt::update-prompt-input (nyxt:current-prompt-buffer) url) - (prompter:all-ready-p (nyxt:current-prompt-buffer)) - (nyxt/prompt-buffer-mode:return-selection) - ;; (bt:join-thread thread) ; TODO: Make sure thread always returns. - ) - (nhooks:add-hook - (buffer-loaded-hook (current-buffer)) - (make-instance - 'nhooks:handler - :fn (lambda (buffer) - (calispel:! url-channel (nyxt:render-url (nyxt:url buffer)))) - :name 'check-buffer-url))) + (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::update-prompt-input (nyxt:current-prompt-buffer) 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)) (nyxt:start :no-init t :no-auto-config t :socket "/tmp/nyxt-test.socket" :data-profile "test") - (prove:is (calispel:? url-channel 20) url))) + (prove:is (calispel:? url-channel 10) url))) (finalize) From ea9113c1b225a0bc8ca58f0aaa68e28e79be1a82 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Wed, 26 Jan 2022 11:07:36 +0500 Subject: [PATCH 09/13] tests/renderer-online/set-url: Use set-prompt-buffer-input. --- tests/renderer-online/set-url.lisp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp index 3a85fee0a91..ebb0d15a4df 100644 --- a/tests/renderer-online/set-url.lisp +++ b/tests/renderer-online/set-url.lisp @@ -48,7 +48,7 @@ (nyxt:set-url))))) (declare (ignorable thread)) (calispel:? (nyxt::prompt-buffer-channel (nyxt:current-window))) - (nyxt::update-prompt-input (nyxt:current-prompt-buffer) url) + (nyxt::set-prompt-buffer-input url) (prompter:all-ready-p (nyxt:current-prompt-buffer)) (nyxt/prompt-buffer-mode:return-selection) (nhooks:add-hook From 4628258729c91d1da383ab4380fe5228a1add731 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Thu, 27 Jan 2022 14:29:10 +0500 Subject: [PATCH 10/13] 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") From 4ecc71ae5ef580a2873351aabfe1f1f70989937e Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Thu, 27 Jan 2022 15:27:10 +0500 Subject: [PATCH 11/13] configuration: Fix on and once-on macro-writing. --- source/configuration.lisp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/source/configuration.lisp b/source/configuration.lisp index ee6a1b548f0..57ddebb4170 100644 --- a/source/configuration.lisp +++ b/source/configuration.lisp @@ -367,12 +367,13 @@ ARGS can be - 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))))) + (alex:once-only (args) + `(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) @@ -382,12 +383,12 @@ Remove the handler after it fires the first time. See `on'." (let ((handler-name (gensym "once-on-hook-handler"))) - (alex:once-only (hook) + (alex:once-only (hook args) `(hooks:add-hook ,hook (make-instance 'hooks:handler :fn (lambda ,(alex:ensure-list args) (declare (ignorable ,@(alex:ensure-list args))) (unwind-protect - ,@body + (progn ,@body) (hooks:remove-hook ,hook (quote ,handler-name)))) :name (quote ,handler-name)))))) From 1d279e8fee180df2ee6a0e3d5d50663645dfea0c Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Thu, 27 Jan 2022 15:49:19 +0500 Subject: [PATCH 12/13] configuration: Don't use once-only on args, ensure-list manually. --- source/configuration.lisp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/source/configuration.lisp b/source/configuration.lisp index 57ddebb4170..78e972220fa 100644 --- a/source/configuration.lisp +++ b/source/configuration.lisp @@ -366,14 +366,14 @@ 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"))) - (alex:once-only (args) - `(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)))))) + (let ((handler-name (gensym "on-hook-handler")) + (args (alex:ensure-list args))) + `(hooks:add-hook + ,hook (make-instance 'hooks:handler + :fn (lambda ,args + (declare (ignorable ,@args)) + ,@body) + :name (quote ,handler-name))))) (export-always 'once-on) (defmacro once-on (hook args &body body) @@ -382,12 +382,13 @@ ARGS can be Remove the handler after it fires the first time. See `on'." - (let ((handler-name (gensym "once-on-hook-handler"))) - (alex:once-only (hook args) + (let ((handler-name (gensym "once-on-hook-handler")) + (args (alex:ensure-list args))) + (alex:once-only (hook) `(hooks:add-hook ,hook (make-instance 'hooks:handler - :fn (lambda ,(alex:ensure-list args) - (declare (ignorable ,@(alex:ensure-list args))) + :fn (lambda ,args + (declare (ignorable ,@args)) (unwind-protect (progn ,@body) (hooks:remove-hook ,hook (quote ,handler-name)))) From b85e1b2504e68ce6bae1c6de7100abc63c015d13 Mon Sep 17 00:00:00 2001 From: Artyom Bologov Date: Thu, 27 Jan 2022 15:49:50 +0500 Subject: [PATCH 13/13] Replace prompt-buffer-channel with prompt-buffer-ready-hook. --- source/browser.lisp | 5 +++++ source/prompt-buffer.lisp | 4 +--- source/window.lisp | 7 ------- tests/renderer-online/set-url.lisp | 15 ++++++++------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/source/browser.lisp b/source/browser.lisp index 07f2817ca3b..3f19be3bb49 100644 --- a/source/browser.lisp +++ b/source/browser.lisp @@ -177,6 +177,11 @@ The handlers take the buffer as argument.") :type hook-prompt-buffer :documentation "Hook run after the `prompt-buffer' class is instantiated and before initializing the prompt-buffer modes. +The handlers take the prompt-buffer as argument.") + (prompt-buffer-ready-hook + (make-instance 'hook-prompt-buffer) + :type hook-prompt-buffer + :documentation "A hook one can attach to waiting for the prompt buffer to be available. The handlers take the prompt-buffer as argument.") (before-download-hook (make-instance 'hook-download) diff --git a/source/prompt-buffer.lisp b/source/prompt-buffer.lisp index 43c8cd8b072..7fa318bdbce 100644 --- a/source/prompt-buffer.lisp +++ b/source/prompt-buffer.lisp @@ -185,7 +185,7 @@ See also `hide-prompt-buffer'." ;; TODO: Add method that returns if there is only 1 source with no filter. (when prompt-buffer (push prompt-buffer (active-prompt-buffers (window prompt-buffer))) - (calispel:! (prompt-buffer-channel (window prompt-buffer)) prompt-buffer) + (hooks:run-hook (prompt-buffer-ready-hook *browser*) prompt-buffer) (prompt-render prompt-buffer) (run-thread "Show prompt watcher" (let ((prompt-buffer prompt-buffer)) @@ -203,8 +203,6 @@ See also `show-prompt-buffer'." ;; Note that PROMPT-BUFFER is not necessarily first in the list, e.g. a new ;; prompt-buffer was invoked before the old one reaches here. (alex:deletef (active-prompt-buffers window) prompt-buffer) - ;; The channel values are irrelevant, so is the element order: - (calispel:? (prompt-buffer-channel (window prompt-buffer)) 0) (if (resumable-p prompt-buffer) (flet ((prompter= (prompter1 prompter2) (and (string= (prompter:prompt prompter1) diff --git a/source/window.lisp b/source/window.lisp index ceeef78302e..a114f55858e 100644 --- a/source/window.lisp +++ b/source/window.lisp @@ -21,13 +21,6 @@ It's a function of the window argument that returns the title as a string.") (list) :export nil :documentation "A list of panel buffers appearing on the window.") - (prompt-buffer-channel - (make-channel) ; TODO: Rename `prompt-buffer-ready-channel'? - :export nil - :documentation "A channel one may listen to if waiting -for the prompt buffer to be available. -You should not rely on the value of this channel. -The channel is popped when a prompt buffer is hidden.") (key-stack '() :documentation "A stack of the key chords a user has pressed.") diff --git a/tests/renderer-online/set-url.lisp b/tests/renderer-online/set-url.lisp index 83620305f1c..8e3e8c37775 100644 --- a/tests/renderer-online/set-url.lisp +++ b/tests/renderer-online/set-url.lisp @@ -37,13 +37,14 @@ (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)))) + (on (prompt-buffer-ready-hook *browser*) + (prompt-buffer) + (sleep 1) + (nyxt::set-prompt-buffer-input url prompt-buffer) + (prompter:all-ready-p prompt-buffer) + (nyxt/prompt-buffer-mode:return-selection prompt-buffer) + (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