Prompt Buffer Issue on Arch Linux

Hello Nyxt engineers,

I previously used Nyxt on Gentoo Linux and had a good experience. However, after switching to Arch Linux, I noticed a significant decrease in performance, especially with the prompt buffer input for the set-url command. It hangs for around 45 seconds to a minute when I start typing quickly.

Interestingly, I am using the same configuration and building Nyxt from the same commit (0dce9fd75) on my ThinkPad x220, which also runs Arch Linux, but I cannot reproduce the issue. It seems to be specific to my desktop on Arch.

Could you please help me understand why this issue is occurring and how I can resolve it?

Note: I can also replicate this issue using the flatpak package.

Fixed by reinstalling cpu microcode & reboot. Ignore this.

@thanosapollo glad you've managed to find a solution.

It's good to know that Nyxt runs smoothly on a ThinkPad x220. Feel free to provide feedback or report issues, thanks!

It runs even smoother on my x220 than on my desktop with AMD Ryzen 7 5800X (16) @ 3.800GHz.

I'm not sure why, but the issue has reemerged. As a quick workaround, I've implemented this function using some hacky code:

(define-command-global thanos/set-url ()
  (let* ((prompt-result (first
                         (prompt
                          :prompt "Search"
                          :sources (list (make-instance 'prompter:raw-source))))))
    (cond 
      ((and (or (str:ends-with-p ".org" prompt-result)
                (str:ends-with-p ".com" prompt-result)
                (str:ends-with-p ".net" prompt-result)
                (str:ends-with-p ".engineer" prompt-result))
            (not (find #\Space prompt-result)))
       (buffer-load (str:concat "https://" prompt-result)))
      ((str:starts-with-p "localhost" prompt-result)
       (buffer-load (str:concat "http://" prompt-result)))
      ((let ((split-result (str:split #\Space prompt-result)))
         (find (first split-result) *thanos/search-engines* :key #'first :test #'string=))
       (let* ((engine-tag (subseq prompt-result 0 (position #\Space prompt-result)))
              (query (subseq prompt-result (+ 1 (position #\Space prompt-result))))
              (engine (find engine-tag *thanos/search-engines* :key #'first :test #'string=))
              (search-url (second engine)))
         (buffer-load (cl-ppcre:regex-replace "~a" search-url (quri:url-encode query)))))
     (t
      (let* ((engine (first (last *thanos/search-engines*)))
             (search-url (second engine)))
        (buffer-load (cl-ppcre:regex-replace "~a" search-url (quri:url-encode prompt-result))))))))

This performs surprisingly well!

I'm really enjoying using this browser. I haven't had much experience with Common Lisp before, but I find it interesting. Once I figure out the required gst plugins packages to play videos from Jellyfin on Arch, the only browsers I will have installed on my ThinkPad will be Nyxt and Emacs, if Emacs counts as a browser :slight_smile:

1 Like

If Nyxt is an editor, then Emacs is a browser :smiley:

glad you are enjoying it! I hope we have made it easy to hack!

1 Like

Yeah, ωραία δουλεία έχει γίνει!

@thanosapollo you're probably looking for gst-plugins-bad, gst-plugins-base, gst-plugins-good and gst-plugins-ugly.

1 Like

Indeed, thanks :slight_smile: we have worked quite a lot...!

1 Like

Just a follow up, I've made this "spartan" version of set-url for anyone that's interested.

(defvar *thanos/search-engines*
  (list
   '("google" "https://google.com/search?q=~a")
   '("aa" "https://annas-archive.org/search?q=~a")
   '("v" "https://yewtu.be/search?q=~a")
   '("aw" "https://wiki.archlinux.org/index.php?search=~a")
   '("duck" "https://duckduckgo.com/?q=~a"))
  "List of search engines.
Last entry is the default.")

(defun direct-url-p (url)
  "Checks if `url` is a direct URL with specific extensions, returning
t if so and nil otherwise. The URL must not contain spaces."
  (not (null (or (and (null (cl-ppcre:scan "\\s" url)) 
                      (or (cl-ppcre:scan "^(https?://)?.*\\.org(\\/.*)?$" url)
                          (cl-ppcre:scan "^(https?://)?.*\\.com(\\/.*)?$" url)
                          (cl-ppcre:scan "^(https?://)?.*\\.net(\\/.*)?$" url)
                          (cl-ppcre:scan "^(https?://)?.*\\.gr(\\/.*)?$" url)
			  (cl-ppcre:scan "^(https?://)?.*\\.co(\\/.*)?$" url)
                          (cl-ppcre:scan "^(https?://)?.*\\.engineer(\\/.*)?$" url)))))))

(defun handle-url (query func)
  "Process `prompt-result` as a URL or search query.

Applies `function-to-call` to the result, which may be an adjusted URL
or a search query URL. Requires the variable `*thanos/search-engines*`
for search queries."
  (cond
   ((str:starts-with-p "localhost" query)
    (funcall func (str:concat "http://" query)))
   ((direct-url-p query)
    (funcall func (str:concat "https://" query)))
   ((str:starts-with-p "http" query)
    (funcall func query))
   ((let ((split-result (str:split #\Space query)))
      (find (first split-result) *thanos/search-engines* :key #'first :test #'string=))
    (let* ((engine-tag (subseq query 0 (position #\Space query)))
           (query (subseq query (+ 1 (position #\Space query))))
           (engine (find engine-tag *thanos/search-engines* :key #'first :test #'string=))
           (search-url (second engine)))
      (funcall func (cl-ppcre:regex-replace "~a" search-url (quri:url-encode query)))))
   (t
    (let* ((engine (first (last *thanos/search-engines*)))
           (search-url (second engine)))
      (funcall func (cl-ppcre:regex-replace "~a" search-url (quri:url-encode query)))))))

(defun thanos/make-buffer-focus-url (url)
  (make-buffer-focus :url url))

(define-command-global thanos/set-url ()
  (let* ((prompt-result (first
                         (prompt
                          :prompt "Search"
                          :sources (list (make-instance 'prompter:raw-source))))))
    (handle-url prompt-result 'buffer-load)))

(define-command-global thanos/set-url-new-buffer ()
  (let* ((prompt-result (first
                         (prompt
                          :prompt "Search [New Buffer]"
                          :sources (list (make-instance 'prompter:raw-source))))))
    (handle-url prompt-result 'thanos/make-buffer-focus-url)))

I would also like to ask if there are any ongoing plans to introduce a package manager for Nyxt, given its highly customizable nature. Being able to conveniently install extensions, themes, and much more via a simple M-x package-install command would be extremely beneficial.

Moreover, I'm curious if there's a way to use Emacs keybindings when inputting text, similar to how anyone can set devtools.editor.keymap to emacs in Firefox. *For example to have C-b work as expected in emacs instead of history-backwards when inputting text.

@thanosapollo I like spartan and robust things.

Thanks for sharing the snippet. Note that URL matching could be done more elegantly by leveraging the quri library. There are some examples in Nyxt's codebase.


Sure, see:

But each step must be taken at the right moment. Note that Emacs curates and has a reviewing process to accept extensions (even the non-official MELPA). Nyxt extensions are few, and given that Nyxt is still going through fast development, they tend to require more maintenance.

Today it's easy enough to install an extension, given the users that we currently target - clone a repository into the right directory and add a declaration in the config file.


I wasn't aware of that Firefox setting. I usually write a file with the contents below at ~/.config/gtk-{3,4}.0/settings.ini.

[Settings]
gtk-key-theme-name=Emacs

I think you're looking for nyxt/mode/input-edit:input-edit-mode. Currently it only binds commands when using the Emacs keyscheme.

Thanks for the advice! I'm a med student, not a programmer, so any input is appreciated since maneuvering through programming concepts & the lisp ecosystem is a bit alien yet enjoyable to me

I don't think an Emacs package.el like implementation as a package manager is an ideal option. Considering Nyxt's fast-paced development and the maintenance requirements, an approach like straight.el might be more manageable. It wouldn't necessitate maintaining an "elpa", rather, possibly just a page with suggested extensions and the snippet to install them. This could enhance reproducibility of Nyxt configurations as well.

That's valid, but it seems unclear which directories are intended for extensions. Official extensions like the invader-theme suggest using ~/.local/share/nyxt/extensions, but ~/.config/nyxt/ seems fully functional too and some configurations suggest using this. Wouldn't it be more efficient to have all Nyxt-related files, including bookmarks and default-cookies, in a dedicated directory?

Thanks!

I heavily modify my about:config for firefox, and it does not play well with just use gtk-key-theme-name, I've written a blog post/guide about it, which was inspired by using nyxt for the first time a couple months ago.

I'm revisiting nyxt due to viewing the new video demos, especially for using visual-mode which I was aware of.

I agree with your point.


Ultimately, the key aspect is that ASDF needs to find the extension.

Nyxt-related files are located according to XDG. For instance, config files are under XDG_CONFIG_HOME (fallbacks to ~/.config/); while data files are under XDG_DATA_HOME (fallbacks to ~/.local/share/). Does that make sense?