From adbb9a787c7fead411362366ad9d94d3f7074c13 Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 11:54:27 +0200 Subject: [PATCH 1/6] Refactor parse-url and url-processing tests. They don't require the network or *browser*. --- nyxt.asd | 6 +-- tests/offline/urls.lisp | 98 ++++++++++++++++++++++++++++++++++++++++ tests/online/urls.lisp | 99 ----------------------------------------- 3 files changed, 101 insertions(+), 102 deletions(-) create mode 100644 tests/offline/urls.lisp delete mode 100644 tests/online/urls.lisp diff --git a/nyxt.asd b/nyxt.asd index 3bb3d2b4713..b8e59bf6919 100644 --- a/nyxt.asd +++ b/nyxt.asd @@ -239,6 +239,8 @@ :components ((:file "package") (:file "offline/define-configuration") (:file "offline/global-history") + (:file "offline/prompt-buffer") + (:file "offline/urls") (:file "offline/user-script-parsing") (:file "offline/mode") (:module "Modes" @@ -297,9 +299,7 @@ ;; more information. ;; (:file "tests/offline/mode/visual") (:file "user-script") - (:file "watch"))) - (:file "offline/prompt-buffer") - (:file "online/urls")) + (:file "watch")))) :test-suite-args (:package :nyxt/tests)) (defsystem "nyxt/benchmarks" diff --git a/tests/offline/urls.lisp b/tests/offline/urls.lisp new file mode 100644 index 00000000000..b18bdca5450 --- /dev/null +++ b/tests/offline/urls.lisp @@ -0,0 +1,98 @@ +;;;; SPDX-FileCopyrightText: Atlas Engineer LLC +;;;; SPDX-License-Identifier: BSD-3-Clause + +(in-package :nyxt/tests) + +(define-test parse-url (:tags :online) + ;; "full URL" + (assert-equality #'quri:uri= + (quri:uri "https://nyxt-browser.com") + (url (make-instance 'nyxt:new-url-query :query "https://nyxt-browser.com"))) + ;; "URL without protocol" + (assert-equality #'quri:uri= + (quri:uri "https://nyxt-browser.com") + (url (first (nyxt::input->queries "nyxt-browser.com")))) + ;; "search engine" + (assert-equality #'quri:uri= + (quri:uri "https://en.wikipedia.org/w/index.php?search=wikipedia") + (url (first (nyxt::input->queries "wiki wikipedia")))) + ;; "search engine with special characters" + (assert-equality #'quri:uri= + (quri:uri "https://en.wikipedia.org/w/index.php?search=wiki%2Bpédia") + (url (first (nyxt::input->queries "wiki wiki+pédia")))) + ;; "default search engine" + (assert-equality #'quri:uri= + (quri:uri "https://search.atlas.engineer/searxng/search?q=nyxt browser") + (url (first (nyxt::input->queries "nyxt browser")))) + ;; "wiki search engine" + (assert-equality #'quri:uri= + (quri:uri "https://en.wikipedia.org/w/index.php?search=wikipedia") + (url (first (nyxt::input->queries "wiki wikipedia")))) + ;; "local file" + (assert-equality #'quri:uri= + (quri:uri "file:///readme.org") + (url (first (nyxt::input->queries "file:///readme.org")))) + ;; "empty domain" + (assert-equality #'quri:uri= + (quri:uri "https://search.atlas.engineer/searxng/search?q=foo") + (url (first (nyxt::input->queries "foo")))) + ;; "same domain and TLD" + (assert-equality #'quri:uri= + (quri:uri "https://search.atlas.engineer/searxng/search?q=algo") + (url (first (nyxt::input->queries "algo")))) + ;; "localhost" + (assert-equality #'quri:uri= + (quri:uri "http://localhost:8080") + (url (first (nyxt::input->queries "http://localhost:8080")))) + ;; "ignore wildcards" + (assert-equality #'quri:uri= + (quri:uri "https://search.atlas.engineer/searxng/search?q=*spurious*") + (url (first (nyxt::input->queries "*spurious*")))) + ;; "about:blank" + (assert-equality #'quri:uri= + (quri:uri "about:blank") + (url (first (nyxt::input->queries "about:blank")))) + ;; "valid syntax but unknown scheme" + (assert-equality #'quri:uri= + (quri:uri "https://search.atlas.engineer/searxng/search?q=foo:blank") + (url (first (nyxt::input->queries "foo:blank"))))) + +(define-test url-processing (:tags :online) + ;; "Invalid URL (empty host)" + (assert-false (valid-url-p "http://foo")) + ;; "Invalid URL (TLD == host)" + (assert-false (valid-url-p "http://algo")) + ;; "Valid URL" + (assert-no-error t (valid-url-p "http://example.org/foo/bar?query=baz#qux")) + ;; "Valid IP URL" + (assert-no-error t (valid-url-p "http://192.168.1.1")) + ;;"Valid IP URL with path" + (assert-no-error t (valid-url-p "http://192.168.1.1/foo")) + ;; "same schemeless URLs" + (assert-true (nyxt::url-equal (quri:uri "http://example.org") + (quri:uri "https://example.org/"))) + ;; "different schemeless URLs" + (assert-false (nyxt::url-equal (quri:uri "https://example.org") + (quri:uri "https://example.org/foo"))) + ;; "schemeless URL" + (assert-string= (nyxt::schemeless-url + (quri:uri "http://example.org/foo/bar?query=baz#qux")) + "example.org/foo/bar?query=baz#qux") + ;; "comparing same URL" + (assert-false (nyxt::url< (quri:uri "http://example.org") + (quri:uri "http://example.org"))) + ;; "comparing same URL but for trailing slash" + (assert-false (nyxt::url< (quri:uri "http://example.org") + (quri:uri "http://example.org/"))) + ;; "comparing same URL but for scheme" + (assert-false (nyxt::url< (quri:uri "https://example.org") + (quri:uri "http://example.org"))) + ;; "comparing same URL but for scheme and trailing slash" + (assert-false (nyxt::url< (quri:uri "https://example.org") + (quri:uri "http://example.org/"))) + ;; "comparing different URLs (HTTPS first)" + (assert-true (nyxt::url< (quri:uri "https://example.org/a") + (quri:uri "http://example.org/b"))) + ;; "comparing different URLs (HTTP first)" + (assert-true (nyxt::url< (quri:uri "http://example.org/a") + (quri:uri "https://example.org/b")))) diff --git a/tests/online/urls.lisp b/tests/online/urls.lisp deleted file mode 100644 index 73e03e943ef..00000000000 --- a/tests/online/urls.lisp +++ /dev/null @@ -1,99 +0,0 @@ -;;;; SPDX-FileCopyrightText: Atlas Engineer LLC -;;;; SPDX-License-Identifier: BSD-3-Clause - -(in-package :nyxt/tests) - -(define-test parse-url (:tags :online) - (let ((*browser* (make-instance 'browser))) - ;; "full URL" - (assert-equality #'quri:uri= - (quri:uri "https://nyxt-browser.com") - (url (make-instance 'nyxt:new-url-query :query "https://nyxt-browser.com"))) - ;; "URL without protocol" - (assert-equality #'quri:uri= - (quri:uri "https://nyxt-browser.com") - (url (first (nyxt::input->queries "nyxt-browser.com")))) - ;; "search engine" - (assert-equality #'quri:uri= - (quri:uri "https://en.wikipedia.org/w/index.php?search=wikipedia") - (url (first (nyxt::input->queries "wiki wikipedia")))) - ;; "search engine with special characters" - (assert-equality #'quri:uri= - (quri:uri "https://en.wikipedia.org/w/index.php?search=wiki%2Bpédia") - (url (first (nyxt::input->queries "wiki wiki+pédia")))) - ;; "default search engine" - (assert-equality #'quri:uri= - (quri:uri "https://search.atlas.engineer/searxng/search?q=nyxt browser") - (url (first (nyxt::input->queries "nyxt browser")))) - ;; "wiki search engine" - (assert-equality #'quri:uri= - (quri:uri "https://en.wikipedia.org/w/index.php?search=wikipedia") - (url (first (nyxt::input->queries "wiki wikipedia")))) - ;; "local file" - (assert-equality #'quri:uri= - (quri:uri "file:///readme.org") - (url (first (nyxt::input->queries "file:///readme.org")))) - ;; "empty domain" - (assert-equality #'quri:uri= - (quri:uri "https://search.atlas.engineer/searxng/search?q=foo") - (url (first (nyxt::input->queries "foo")))) - ;; "same domain and TLD" - (assert-equality #'quri:uri= - (quri:uri "https://search.atlas.engineer/searxng/search?q=algo") - (url (first (nyxt::input->queries "algo")))) - ;; "localhost" - (assert-equality #'quri:uri= - (quri:uri "http://localhost:8080") - (url (first (nyxt::input->queries "http://localhost:8080")))) - ;; "ignore wildcards" - (assert-equality #'quri:uri= - (quri:uri "https://search.atlas.engineer/searxng/search?q=*spurious*") - (url (first (nyxt::input->queries "*spurious*")))) - ;; "about:blank" - (assert-equality #'quri:uri= - (quri:uri "about:blank") - (url (first (nyxt::input->queries "about:blank")))) - ;; "valid syntax but unknown scheme" - (assert-equality #'quri:uri= - (quri:uri "https://search.atlas.engineer/searxng/search?q=foo:blank") - (url (first (nyxt::input->queries "foo:blank")))))) - -(define-test url-processing (:tags :online) - ;; "Invalid URL (empty host)" - (assert-false (valid-url-p "http://foo")) - ;; "Invalid URL (TLD == host)" - (assert-false (valid-url-p "http://algo")) - ;; "Valid URL" - (assert-no-error t (valid-url-p "http://example.org/foo/bar?query=baz#qux")) - ;; "Valid IP URL" - (assert-no-error t (valid-url-p "http://192.168.1.1")) - ;;"Valid IP URL with path" - (assert-no-error t (valid-url-p "http://192.168.1.1/foo")) - ;; "same schemeless URLs" - (assert-true (nyxt::url-equal (quri:uri "http://example.org") - (quri:uri "https://example.org/"))) - ;; "different schemeless URLs" - (assert-false (nyxt::url-equal (quri:uri "https://example.org") - (quri:uri "https://example.org/foo"))) - ;; "schemeless URL" - (assert-string= (nyxt::schemeless-url - (quri:uri "http://example.org/foo/bar?query=baz#qux")) - "example.org/foo/bar?query=baz#qux") - ;; "comparing same URL" - (assert-false (nyxt::url< (quri:uri "http://example.org") - (quri:uri "http://example.org"))) - ;; "comparing same URL but for trailing slash" - (assert-false (nyxt::url< (quri:uri "http://example.org") - (quri:uri "http://example.org/"))) - ;; "comparing same URL but for scheme" - (assert-false (nyxt::url< (quri:uri "https://example.org") - (quri:uri "http://example.org"))) - ;; "comparing same URL but for scheme and trailing slash" - (assert-false (nyxt::url< (quri:uri "https://example.org") - (quri:uri "http://example.org/"))) - ;; "comparing different URLs (HTTPS first)" - (assert-true (nyxt::url< (quri:uri "https://example.org/a") - (quri:uri "http://example.org/b"))) - ;; "comparing different URLs (HTTP first)" - (assert-true (nyxt::url< (quri:uri "http://example.org/a") - (quri:uri "https://example.org/b")))) From 4a15ab31ba273972fb19195dd2eea25c20ae0b22 Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 18:12:46 +0200 Subject: [PATCH 2/6] buffer(new-url-query): Minor refactor. --- source/buffer.lisp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/source/buffer.lisp b/source/buffer.lisp index 70633c04966..cc3ecf32a7d 100644 --- a/source/buffer.lisp +++ b/source/buffer.lisp @@ -1376,24 +1376,28 @@ URL-DESIGNATOR is then transformed by BUFFER's `buffer-load-hook'." Loads the entry with default `prompter:actions-on-return'.")) (define-class new-url-query () - ((query "" - :documentation "Either a URL or a string query passed to `engine'.") - (label nil - :type (or null string) - :documentation "The meaningful text for the query, if query is a URL.") - (engine nil - :type (or null search-engine))) + ((query + "" + :type (maybe string) + :documentation "Either a URL or a string query passed to `engine'.") + (label + nil + :type (maybe string) + :documentation "The meaningful text for the query, if query is a URL.") + (engine + nil + :type (maybe search-engine) + :documentation "See `search-engine'.")) (:export-class-name-p t) (:export-accessor-names-p t) (:documentation "Structure holding the new URL query generated from a user - string input. -If `engine' is set, `query' is passed to it. See the `url' method. +string input. + +If `engine' is set, `query' is passed to it (see the `url' method). If `query' is a valid URL, use it as is. -If it points to an existing file, 'file://' is automatically prepended to it on -instantiation. -If prefixing with 'https://' results in a valid URL, set `query' to this result -on instantiation. -Finally, if nothing else, set the `engine' to the `default-search-engine'.")) +If it points to an existing file, 'file://' is prepended to it. +If prefixing with 'https://' results in a valid URL, set `query' to it. +Otherwise, set `engine' to `default-search-engine'.")) (defmethod initialize-instance :after ((query new-url-query) &key check-dns-p &allow-other-keys) From acbee11fe1f5874fa6691a006d2eacb1500c455f Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 18:13:16 +0200 Subject: [PATCH 3/6] buffer(input->queries): Fix indentation. --- source/buffer.lisp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/buffer.lisp b/source/buffer.lisp index cc3ecf32a7d..c7b6b32e761 100644 --- a/source/buffer.lisp +++ b/source/buffer.lisp @@ -1464,8 +1464,7 @@ Otherwise, set `engine' to `default-search-engine'.")) :query (second completion) :label (first completion))))) -(defun input->queries (input &key (check-dns-p t) - (engine-completion-p)) +(defun input->queries (input &key (check-dns-p t) (engine-completion-p)) (let* ((terms (sera:tokens input)) (engines (let ((all-prefixed-engines (remove-if From 36589e3d622c510df40baf6e4fd8b0bffa644a71 Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 18:14:49 +0200 Subject: [PATCH 4/6] buffer(new-url-or-search-source): Fix bug. Fixes #2134. --- source/buffer.lisp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/source/buffer.lisp b/source/buffer.lisp index c7b6b32e761..5ab1cbf0047 100644 --- a/source/buffer.lisp +++ b/source/buffer.lisp @@ -1519,16 +1519,8 @@ Otherwise, set `engine' to `default-search-engine'.")) (prompter:filter-preprocessor (lambda (suggestions source input) (declare (ignore suggestions source)) - (input->queries input - :check-dns-p nil - :engine-completion-p nil))) + (input->queries input :check-dns-p nil :engine-completion-p t))) (prompter:filter nil) - (prompter:filter-postprocessor - (lambda (suggestions source input) - (declare (ignore suggestions source)) - (input->queries input - :check-dns-p t - :engine-completion-p t))) (prompter:actions-on-return #'buffer-load*)) (:export-class-name-p t) (:documentation "This prompter source tries to \"do the right thing\" to From 2d7191a396cb3426facd6324cc0f2b3ee94e1d80 Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 18:13:42 +0200 Subject: [PATCH 5/6] buffer(new-url-or-search-source): Review documentation. --- source/buffer.lisp | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/source/buffer.lisp b/source/buffer.lisp index 5ab1cbf0047..7ecfcd422a5 100644 --- a/source/buffer.lisp +++ b/source/buffer.lisp @@ -1523,20 +1523,9 @@ Otherwise, set `engine' to `default-search-engine'.")) (prompter:filter nil) (prompter:actions-on-return #'buffer-load*)) (:export-class-name-p t) - (:documentation "This prompter source tries to \"do the right thing\" to -generate a new URL query from user input. -- If the query is a URL, open it directly. -- If it's a file, prefix the query with 'file://'. -- If it's a search engine shortcut, include it in the suggestions. -- If it's none of the above, use the `default-search-engine'. - -It runs in two passes. The first pass does not check the DNS for domain -validity, nor does it return any search engine suggestions. This guarantees -that a good-enough default suggestion is showed instantaneously. -(We really want this prompter source to be fast!) The second pass checks the -DNS to precisely validate domains and returns the search engines suggestions, if -any.") - (:metaclass user-class)) + (:metaclass user-class) + (:documentation "Source listing URL queries from user input in a DWIM fashion. See +`new-url-query'.")) (defmethod prompter:object-attributes ((query new-url-query) (source new-url-or-search-source)) (declare (ignore source)) From 55f2dbee81a1cfd91a8182c894ac04fb2e6d3088 Mon Sep 17 00:00:00 2001 From: "Andre A. Gomes" Date: Mon, 19 Feb 2024 18:18:45 +0200 Subject: [PATCH 6/6] changelog: Mention bug fix. --- source/changelog.lisp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/changelog.lisp b/source/changelog.lisp index 6e89e8bd4e4..7aa170399f1 100644 --- a/source/changelog.lisp +++ b/source/changelog.lisp @@ -77,6 +77,11 @@ elements are scaled accordingly.") (:li "When on pre-release, push " (:code "X-pre-release") " feature in addition to " (:code "X-pre-release-N") "one.")) +(define-version "3.11.3" + (:nsection :title "Bug fixes" + (:ul + (:li "Fix prompt buffer freezes when invoking command " (:nxref :command 'set-url) ".")))) + (define-version "3.11.2" (:nsection :title "Bug fixes" (:ul