Skip to content

Commit

Permalink
Merge pull request #3344 from atlas-engineer/fix-prompt-freezes
Browse files Browse the repository at this point in the history
  • Loading branch information
aadcg committed Feb 19, 2024
2 parents 1f046f3 + 55f2dbe commit 4c8d8fe
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 141 deletions.
6 changes: 3 additions & 3 deletions nyxt.asd
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
62 changes: 23 additions & 39 deletions source/buffer.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -1460,8 +1464,7 @@ Finally, if nothing else, set the `engine' to the `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
Expand Down Expand Up @@ -1516,32 +1519,13 @@ Finally, if nothing else, set the `engine' to the `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
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))
Expand Down
5 changes: 5 additions & 0 deletions source/changelog.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
98 changes: 98 additions & 0 deletions tests/offline/urls.lisp
Original file line number Diff line number Diff line change
@@ -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"))))
99 changes: 0 additions & 99 deletions tests/online/urls.lisp

This file was deleted.

0 comments on commit 4c8d8fe

Please sign in to comment.