Listed below are the current commands, their documentation, and their source. Non-command based features are currently unlisted.

Commands

nyxt-init-time

Return the duration of Nyxt initialization.

(define-command nil
    (echo "~,2f seconds" (slot-value *browser* 'init-time)))
load-init-file

Load or reload the init file.

(define-command (&key (init-file (expand-path *init-file-path*)))
    (load-lisp init-file :package (find-package :nyxt-user)))
load-file

Load the prompted Lisp file.

(define-command nil
    (let ((file-name-input
           (prompt-minibuffer :input-prompt "Load file"
                              :hide-suggestion-count-p t)))
      (load-lisp file-name-input)))
start-swank

Start a Swank server that can be connected to, for instance, in
Emacs via SLIME.

Warning: This allows Nyxt to be controlled remotely, that is, to
execute arbitrary code with the privileges of the user running Nyxt.
Make sure you understand the security risks associated with this
before running this command.

(define-command (&optional (swank-port *swank-port*))
    (swank:create-server :port swank-port :dont-close t)
  (echo "Swank server started at port ~a" swank-port))
quit-after-clearing-session

Clear session then quit Nyxt.

(define-command nil
    (uiop/filesystem:delete-file-if-exists
     (expand-path (session-path (current-buffer))))
  (quit))
quit

Quit Nyxt.

(define-command nil
    (sera:run-hook (before-exit-hook *browser*))
  (loop for window in (window-list)
        do (ffi-window-delete window))
  (ffi-kill-browser *browser*)
  (when (socket-thread *browser*)
    (ignore-errors (bordeaux-threads:destroy-thread (socket-thread *browser*)))
    (let ((socket-path (expand-path *socket-path*)))
      (when (uiop/filesystem:file-exists-p socket-path)
        (log:info "Deleting socket ~s." socket-path)
        (uiop/filesystem:delete-file-if-exists socket-path))))
  (unless *keep-alive* (uiop/image:quit 0 nil)))
replace-session-by-name

Delete all the buffers of the current session and restore the one chosen by user.

(define-command nil
    (let ((name
           (prompt-minibuffer :input-prompt
                              "The name of the session to replace the current one"
                              :history
                              (minibuffer-session-restore-history *browser*)
                              :suggestion-function
                              #'session-name-suggestion-filter)))
      (when name
        (dolist (buffer (buffer-list)) (buffer-delete buffer))
        (restore (data-profile (current-buffer))
                 (make-instance 'session-data-path :basename name :dirname
                                (dirname (session-path (current-buffer))))))))
restore-session-by-name

Restore the session data from the file named by user input.

(define-command nil
    (let ((name
           (prompt-minibuffer :input-prompt
                              "The name of the session to restore" :history
                              (minibuffer-session-restore-history *browser*)
                              :suggestion-function
                              #'session-name-suggestion-filter)))
      (when name
        (restore (data-profile (current-buffer))
                 (make-instance 'session-data-path :basename name :dirname
                                (dirname (session-path (current-buffer))))))))
store-session-by-name

Store the session data (i.e. all the opened buffers) in the file named by user input.

(define-command nil
    (let ((name
           (prompt-minibuffer :input-prompt "The name to store session with"
                              :history
                              (minibuffer-session-restore-history *browser*)
                              :suggestion-function
                              #'session-name-suggestion-filter)))
      (when name
        (store (data-profile (current-buffer))
               (make-instance 'session-data-path :dirname
                              (dirname (session-path (current-buffer)))
                              :basename name)))))
about

Show the list of contributors.

(define-command nil
    (with-current-html-buffer (buffer "*About*" 'base-mode)
      (cl-markup:markup (:style (style buffer)) (:h1 "Contributors")
                        (:p
                         "Let us know if you've contributed to the development of
                    Nyxt and would like to be included on this list.")
                        (:ul (:li "Adom Hartell (@4t0m)")
                         (:li "Artyom Bologov (@aartaka)")
                         (:li "John Mercouris (@jmercouris)")
                         (:li "Pierre Neidhardt (@ambrevar)")
                         (:li "Solomon Bloch (@noogie13)")
                         (:li "Vincent Dardel (@vindarel)"))
                        (:h1 "Supporters")
                        (:p "Thank you to NLnet for supporting Nyxt!")
                        (:h1 "Crowdfunding backers")
                        (:p
                         "Thank you to all who have supported and made Nyxt possible!")
                        (:h2 "2018-11 campaign: *NIX Support")
                        (:h3 "Digital Omnipresence")
                        (:ul (:li "Alexander.Shendi") (:li "Ashish SHUKLA")
                         (:li "Christopher Nascone") (:li "dan.girsh")
                         (:li "Eric Monson") (:li "Jack Randall")
                         (:li "James Anderson") (:li "liweitian")
                         (:li "Marco Heisig") (:li "Oluwafemi Agbabiaka")
                         (:li "pjb") (:li "Robert Krahn") (:li "Robert Uhl")
                         (:li "1 anonymous"))
                        (:h3 "Digital Magma")
                        (:ul (:li "Daniel V") (:li "Jason Hamilton")
                         (:li "Magnus Nyberg") (:li "Marek Kochanowicz")
                         (:li "Rich Smith") (:li "Robert Uhl") (:li "simon")
                         (:li "slade") (:li "Steve Last") (:li "ulf.makestad")
                         (:li "1 anonymous"))
                        (:h3 "Digital Immortality")
                        (:ul (:li "Alexey Abramov") (:li "Are Jensen")
                         (:li "Joseph Mingrone") (:li "Nikita Poliakov")
                         (:li "pjb") (:li "Sainath Adapa")
                         (:li "Spencer Heywood") (:li "Sungjin Chun")
                         (:li "Tom Delord") (:li "2 anonymous"))
                        (:h3 "Others")
                        (:ul (:li "Nicholas Zivkovic") (:li "Pierre Neidhardt")
                         (:li "Simon Zugmeyer") (:li "vindarel")
                         (:li "5 anonymous"))
                        (:h2 "2019-10 campaign: v1.4.0")
                        (:h3 "Digital Immortality")
                        (:ul (:li "Tim Johann") (:li "Julien Rousé")
                         (:li "ebababi") (:li "Emil Oppeln-Bronikowski")
                         (:li "Fox Kiester") (:li "Stefan Husmann")
                         (:li "Nils Grunwald") (:li "Florian Adamsky")
                         (:li "Valentin Atanasov") (:li "Pranav Vats")
                         (:li "Jörn Gersdorf") (:li "Matt Skinner")
                         (:li "Jelle Dirk Licht") (:li "Minori Yamashita")
                         (:li "Hugh Daschbach") (:li "Niklas Carlsson")
                         (:li "mestelan") (:li "Camille Troillard")
                         (:li "mace nicolas") (:li "dan.girsh")
                         (:li "Michael Bruderer") (:li "Patrice Rault")
                         (:li "Cees de Groot") (:li "Sam Hedin")
                         (:li "rbarzic") (:li "Jake Waksbaum")
                         (:li "Lukas Jenks") (:li "Rodrigo Lazo")
                         (:li "Lucas Sifoni") (:li "Calle Helmertz")
                         (:li "Kristian Nygaard Jensen") (:li "Robert Uhl")
                         (:li "Francis Burstall") (:li "Arnaud BEAUD'HUIN")
                         (:li "Daniel V") (:li "Albin Heimerson")
                         (:li "Alexander ter Weele") (:li "Jeremy Firth")
                         (:li "aim") (:li "liweitian") (:li "Philipe Dallaire")
                         (:li "Travis Brown") (:li "Divan Santana")
                         (:li "John C Haprian") (:li "Pierrick Maillard")
                         (:li "Dardel Renaud") (:li "Dardel Renaud")
                         (:li "Nils Grunwald") (:li "hector")
                         (:li "Jean Morel") (:li "Jos van Bakel") (:li "slade")
                         (:li "dietrich ayala") (:li "bacon totem")
                         (:li "Pierre Neidhardt") (:li "18 anonymous")))))
dashboard

Print a dashboard. Usable as a buffer-fn for make-startup-function.

(define-command nil
    (flet ((list-bookmarks (&key (separator " → "))
             (loop for bookmark in (get-data (bookmarks-path (current-buffer)))
                   collect (cl-markup:markup
                            (:li (title bookmark) separator
                             (:a :href (object-string (url bookmark))
                              (object-display (url bookmark)))))))
           (list-history (&key (separator " → ") (limit 20))
             (let* ((path (history-path (current-buffer)))
                    (history
                     (when (get-data path)
                       (sort (alex:hash-table-values (get-data path))
                             #'local-time:timestamp> :key #'last-access))))
               (loop for item in (sera:take limit history)
                     collect (cl-markup:markup
                              (:li (title item)
                               (unless (str:emptyp (title item)) separator)
                               (:a :href (object-string (url item))
                                (object-string (url item)))))))))
      (let ((dashboard-style
             (cl-css:css
              '((body :margin-top 0 :margin-bottom 0) ("a" :color "gray")
                ("#title" :font-size "400%")
                (.section :border-top "solid lightgray" :margin-top "10px"
                 :overflow "scroll" :min-height "150px")
                (".section h3" :color "dimgray")
                ("#container" :display "flex" :flex-flow "column" :height
                 "100vh")
                ("ul" :list-style-type "circle")))))
        (with-current-html-buffer (buffer "*Dashboard*" 'base-mode)
          (cl-markup:markup (:style (style buffer)) (:style dashboard-style)
                            (:div :id "container"
                             (:div :style "height: 210px"
                              (:h1 :id "title" "Nyxt "
                               (:span :style "color: lightgray" "browser ☺"))
                              (:h3
                               (local-time:format-timestring nil
                                                             (local-time:now)
                                                             :format
                                                             local-time:+rfc-1123-format+))
                              (:a :class "button" :href
                               (lisp-url `(restore-session-by-name))
                               "🗁 Restore Session")
                              (:a :class "button" :href
                               (lisp-url `(execute-command))
                               "⚙ Execute Command")
                              (:a :class "button" :href (lisp-url `(manual))
                               "🕮 Manual")
                              (:a :class "button" :href
                               "https://nyxt.atlas.engineer/download"
                               "⇡ Update"))
                             (:div :class "section" :style "flex: 3"
                              (:h3 "🏷 " (:b "Bookmarks"))
                              (:ul (list-bookmarks)))
                             (:div :class "section" :style "flex: 5"
                              (:h3 "🗐 " (:b "Recent URLs"))
                              (:ul (list-history)))))))))
copy-system-information

Save system information into the clipboard.

(define-command nil
    (let* ((*print-length* nil)
           (nyxt-information
            (format nil
                    (str:concat "Nyxt version: ~a ~%"
                                "Operating system kernel: ~a ~a~%"
                                "Lisp implementation: ~a ~a~%"
                                "Features: ~a~%")
                    +version+ (software-type) (software-version)
                    (lisp-implementation-type) (lisp-implementation-version)
                    *features*)))
      (copy-to-clipboard nyxt-information)
      (log:info nyxt-information)
      (echo "System information copied to clipboard.")))
tutorial

Show the tutorial.

(define-command nil
    (with-current-html-buffer (buffer "*Tutorial*" 'nyxt/help-mode:help-mode)
      (str:concat
       (cl-markup:markup (:style (style buffer)) (:h1 "Nyxt tutorial")
                         (:p
                          "The following tutorial introduces the core concepts and the
basic usage.  For more details, especially regarding the configuration, see
the "
                          (:code (command-markup 'manual)) "."))
       (tutorial-content))))
manual

Show the manual.

(define-command nil
    (with-current-html-buffer (buffer "*Manual*" 'nyxt/help-mode:help-mode)
      (str:concat (cl-markup:markup (:style (style buffer))) (manual-content))))
help

Print help information.

(define-command nil
    (with-current-html-buffer (buffer "*Help*" 'nyxt/help-mode:help-mode)
      (cl-markup:markup (:style (style buffer))
                        (:style
                         (cl-css:css
                          '((:h2 :font-weight 300 :padding-top "10px"))))
                        (:h1 "Welcome to Nyxt ☺")
                        (:p
                         "Attention: Nyxt is under active development. Feel free to "
                         (:a :href
                          "https://github.com/atlas-engineer/nyxt/issues"
                          "report")
                         " bugs, instabilities or feature wishes.")
                        (:p
                         "You can help with Nyxt development by supporting us in various ways:"
                         (:ul
                          (:li "Support continuous development on "
                           (:a :href "https://www.patreon.com/nyxt" "Patreon")
                           ".")
                          (:li "Spread the word on social media and "
                           (:a :href "https://github.com/atlas-engineer/nyxt"
                            "star the project on GitHub")
                           ".")))
                        (:hr) (:h2 "Quick configuration")
                        (:p
                         (:a :class "button" :href
                          (lisp-url `(common-settings)) "Common settings")
                         " Switch between Emacs/vi/CUA key bindings, set home page URL, and zoom level.")
                        (:h2 "Documentation")
                        (:p
                         (:a :class "button" :href
                          (lisp-url `(describe-bindings)) "List bindings")
                         " List all bindings for the current buffer.")
                        (:p
                         (:a :class "button" :href (lisp-url `(tutorial))
                          "Tutorial")
                         " An introduction to Nyxt core concepts.")
                        (:p
                         (:a :class "button" :href (lisp-url `(manual))
                          "Manual")
                         " Full documentation about Nyxt, how it works and how to configure it."))))
list-messages

Show the *Messages* buffer.

(define-command nil
    (with-current-html-buffer (buffer "*Messages*"
                                      'nyxt/message-mode:message-mode)
      (cl-markup:markup (:style (style buffer)) (:h1 "Messages")
                        (:a :class "button" :href (lisp-url '(list-messages))
                         "Update")
                        (:a :class "button" :href
                         (lisp-url '(nyxt/message-mode:clear-messages)
                                   '(list-messages))
                         "Clear")
                        (:ul
                         (loop for message in (reverse
                                               (messages-content *browser*))
                               collect (cl-markup:markup (:li message)))))))
nyxt-version

Version number of this version of Nyxt.
The version number is stored in the clipboard.

(define-command nil
    (trivial-clipboard:text +version+)
  (echo "Version ~a" +version+))
describe-key

Display binding of user-inputted keys.

(define-command nil
    (setf (input-dispatcher (current-window)) #'describe-key-dispatch-input)
  (echo "Press a key sequence to describe (cancel with 'escape escape'):"))
describe-bindings

Show a buffer with the list of all known bindings for the current buffer.

(define-command nil
    (with-current-html-buffer (buffer "*Help-bindings"
                                      'nyxt/help-mode:help-mode)
      (cl-markup:markup (:style (style buffer)) (:h1 "Bindings")
                        (:p
                         (loop for keymap in (current-keymaps (current-buffer))
                               collect (cl-markup:markup
                                        (:h3 (keymap:name keymap))
                                        (:table
                                         (loop for keyspec being the hash-keys in (keymap:keymap-with-parents->map
                                                                                   keymap) using (hash-value
                                                                                                  bound-value)
                                               collect (cl-markup:markup
                                                        (:tr (:td keyspec)
                                                         (:td
                                                          (string-downcase
                                                           bound-value))))))))))))
common-settings

Configure a set of frequently used settings.

(define-command nil
    (with-current-html-buffer (buffer "*Settings*" 'nyxt/help-mode:help-mode)
      (cl-markup:markup (:style (style buffer)) (:h1 "Common Settings")
                        (:p "Set the values for frequently configured
            settings. Changes made will apply to newly created
            buffers.")
                        (:h2 "Keybinding style")
                        (:p
                         (:a :class "button" :href
                          (lisp-url
                           `(configure-slot 'default-modes '(buffer web-buffer)
                                            :value '%slot-default)
                           `(nyxt/emacs-mode:emacs-mode :activate nil)
                           `(nyxt/vi-mode:vi-normal-mode :activate nil))
                          "Use default (CUA)"))
                        (:p
                         (:a :class "button" :href
                          (lisp-url
                           `(configure-slot 'default-modes '(buffer web-buffer)
                                            :value
                                            '(append '(emacs-mode)
                                                     %slot-default))
                           `(nyxt/emacs-mode:emacs-mode :activate t)
                           `(nyxt/vi-mode:vi-normal-mode :activate nil))
                          "Use Emacs"))
                        (:p
                         (:a :class "button" :href
                          (lisp-url
                           `(configure-slot 'default-modes '(buffer web-buffer)
                                            :value
                                            '(append '(vi-normal-mode)
                                                     %slot-default))
                           `(nyxt/vi-mode:vi-normal-mode :activate t)
                           `(nyxt/emacs-mode:emacs-mode :activate nil))
                          "Use vi"))
                        (:h2 "Default new buffer URL")
                        (:a :class "button" :href
                         (lisp-url
                          `(configure-slot 'default-new-buffer-url 'web-buffer
                                           :type 'string))
                         "Set default new buffer URL")
                        (:h2 "Default zoom ratio")
                        (:a :class "button" :href
                         (lisp-url
                          `(configure-slot 'current-zoom-ratio 'buffer))
                         "Set default zoom ratio"))))
describe-slot

Inspect a slot and show it in a help buffer.

(define-command nil
    (let* ((input
            (prompt-minibuffer :input-prompt "Describe slot"
                               :suggestion-function (slot-suggestion-filter))))
      (with-current-html-buffer (buffer
                                 (str:concat "*Help-"
                                             (symbol-name (name input)) "*")
                                 'nyxt/help-mode:help-mode)
        (str:concat (cl-markup:markup (:style (style buffer)))
                    (describe-slot* (name input) (class-sym input)
                                    :mention-class-p t)))))
describe-class

Inspect a class and show it in a help buffer.

(define-command nil
    (let* ((input
            (class-suggestion-name
             (prompt-minibuffer :input-prompt "Describe class"
                                :suggestion-function
                                (class-suggestion-filter)))))
      (with-current-html-buffer (buffer
                                 (str:concat "*Help-" (symbol-name input) "*")
                                 'nyxt/help-mode:help-mode)
        (let* ((slots (class-public-slots input))
               (slot-descs
                (apply #'str:concat
                       (mapcar (alex:rcurry #'describe-slot* input) slots))))
          (str:concat
           (cl-markup:markup (:style (style buffer)) (:h1 (symbol-name input))
                             (:p (:pre (documentation input 'type)))
                             (:h2 "Slots:"))
           slot-descs)))))
describe-command

Inspect a command and show it in a help buffer.
A command is a special kind of function that can be called with
`execute-command' and can be bound to a key.

(define-command nil
    (let ((input
           (prompt-minibuffer :input-prompt "Describe command"
                              :suggestion-function
                              (command-suggestion-filter))))
      (describe-command* input)))
describe-function

Inspect a function and show it in a help buffer.
For generic functions, describe all the methods.

(define-command nil
    (let ((input
           (prompt-minibuffer :input-prompt "Describe function"
                              :suggestion-function
                              (function-suggestion-filter))))
      (setf input (function-suggestion-name input))
      (flet ((method-desc (method)
               (cl-markup:markup
                (:h1 (symbol-name input) " "
                 (write-to-string (sb-mop:method-specializers method)))
                (:pre (documentation method 't)) (:h2 "Argument list")
                (:p (write-to-string (sb-mop:method-lambda-list method))))))
        (with-current-html-buffer (buffer
                                   (str:concat "*Help-" (symbol-name input)
                                               "*")
                                   'nyxt/help-mode:help-mode)
          (if (typep (symbol-function input) 'generic-function)
              (apply #'str:concat
                     (mapcar #'method-desc
                             (sb-mop:generic-function-methods
                              (symbol-function input))))
              (str:concat
               (cl-markup:markup (:style (style buffer))
                                 (:h1 (format nil "~s" input)
                                  (when (macro-function input) " (macro)"))
                                 (:pre (documentation input 'function))
                                 (:h2 "Argument list")
                                 (:p
                                  (write-to-string
                                   (metabang.moptilities:function-arglist
                                    input))))
               (unless (macro-function input)
                 (cl-markup:markup (:h2 "Type")
                                   (:p
                                    (format nil "~s"
                                            (sb-introspect:function-type
                                             input)))))))))))
describe-variable

Inspect a variable and show it in a help buffer.

(define-command nil
    (let* ((input
            (variable-suggestion-name
             (prompt-minibuffer :suggestion-function
                                (variable-suggestion-filter) :input-prompt
                                "Describe variable"))))
      (with-current-html-buffer (buffer
                                 (str:concat "*Help-" (symbol-name input) "*")
                                 'nyxt/help-mode:help-mode)
        (cl-markup:markup (:style (style buffer)) (:h1 (format nil "~s" input))
                          (:pre (documentation input 'variable))
                          (:h2 "Current Value:")
                          (:pre (object-display (symbol-value input)))))))
unzoom-page

Unzoom the page.

(define-command (&key (buffer (current-buffer))
                 (ratio (zoom-ratio-default (current-buffer))))
    (pflet ((nyxt/web-mode::unzoom nil
             (parenscript:lisp
              (setf (current-zoom-ratio (current-buffer)) ratio))
             (setf (parenscript:chain nyxt/web-mode::document
                                      nyxt/web-mode::body style
                                      nyxt/web-mode::zoom)
                     (parenscript:lisp ratio))))
      (with-current-buffer buffer
        (nyxt/web-mode::unzoom))))
zoom-out-page

Zoom out the current page.

(define-command (&key (buffer (current-buffer)))
    (pflet ((nyxt/web-mode::zoom-out nil
             (parenscript:lisp
              (nyxt/web-mode::ensure-zoom-ratio-range #'- (current-buffer)))
             (let ((style
                    (parenscript:chain nyxt/web-mode::document
                                       nyxt/web-mode::body style)))
               (setf (parenscript:@ style nyxt/web-mode::zoom)
                       (parenscript:lisp
                        (current-zoom-ratio (current-buffer)))))))
      (with-current-buffer buffer
        (nyxt/web-mode::zoom-out))))
zoom-in-page

Zoom in the current page.

(define-command (&key (buffer (current-buffer)))
    (pflet ((nyxt/web-mode::zoom nil
             (parenscript:lisp
              (nyxt/web-mode::ensure-zoom-ratio-range #'+ (current-buffer)))
             (let ((style
                    (parenscript:chain nyxt/web-mode::document
                                       nyxt/web-mode::body style)))
               (setf (parenscript:@ style nyxt/web-mode::zoom)
                       (parenscript:lisp
                        (current-zoom-ratio (current-buffer)))))))
      (with-current-buffer buffer
        (nyxt/web-mode::zoom))))
spell-check-suggest-word

Suggest a spelling for a given word.

(define-command (&key nyxt/web-mode::word)
    (let ((nyxt/web-mode::selected-word
           (prompt-minibuffer :input-buffer nyxt/web-mode::word :input-prompt
                              "Suggest spelling (3+ characters)"
                              :suggestion-function
                              'nyxt/web-mode::enchant-suggestion)))
      (trivial-clipboard:text nyxt/web-mode::selected-word)
      (echo "Word copied to clipboard.")))
spell-check-word-at-cursor

Spell check the word at cursor.

(define-command nil
    (let* ((nyxt/web-mode::contents
            (nyxt/input-edit-mode::active-input-area-content))
           (nyxt/web-mode::cursor-position
            (nyxt/input-edit-mode::active-input-area-cursor)))
      (let ((nyxt/web-mode::text-buffer
             (make-instance 'text-buffer:text-buffer))
            (nyxt/web-mode::cursor (make-instance 'text-buffer:cursor)))
        (cluffer:attach-cursor nyxt/web-mode::cursor
                               nyxt/web-mode::text-buffer)
        (text-buffer::insert-string nyxt/web-mode::cursor
                                    nyxt/web-mode::contents)
        (setf (cluffer:cursor-position nyxt/web-mode::cursor)
                (parse-integer nyxt/web-mode::cursor-position))
        (nyxt/web-mode::spell-check-prompt
         (text-buffer::word-at-cursor nyxt/web-mode::cursor)))))
spell-check-highlighted-word

Spell check a highlighted word. If a word is incorrectly spelled,
pull up a prompt of suggestions.

(define-command nil
    (let ((nyxt/web-mode::word (%copy)))
      (nyxt/web-mode::spell-check-prompt nyxt/web-mode::word)))
spell-check-word

Spell check a word.

(define-command (&key (nyxt/web-mode::word nil nyxt/web-mode::word-supplied-p))
    (if nyxt/web-mode::word-supplied-p
        (enchant:with-dict (nyxt/web-mode::lang
                            (spell-check-language *browser*))
          (enchant:dict-check nyxt/web-mode::lang nyxt/web-mode::word))
        (let ((nyxt/web-mode::word
               (prompt-minibuffer :input-prompt "Spell check word")))
          (if (enchant:with-dict (nyxt/web-mode::lang
                                  (spell-check-language *browser*))
                (enchant:dict-check nyxt/web-mode::lang nyxt/web-mode::word))
              (echo "~s spelled correctly." nyxt/web-mode::word)
              (echo "~s is incorrect." nyxt/web-mode::word)))))
remove-search-hints

Remove all search hints.

(define-command nil
    (nyxt/web-mode::%remove-search-hints))
search-buffers

Show a prompt in the minibuffer that allows to choose
one or more buffers, and then start a search prompt that
searches over the selected buffer(s).

(define-command (&key
                 (nyxt/web-mode::case-sensitive-p nil
                  nyxt/web-mode::explicit-case-p))
    (let ((buffers
           (prompt-minibuffer :input-prompt "Search buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (apply #'nyxt/web-mode::search-over-buffers buffers
             (if nyxt/web-mode::explicit-case-p
                 `(:case-sensitive-p ,nyxt/web-mode::case-sensitive-p)
                 'nil))))
search-buffer

Start a search on the current buffer.

(define-command (&key
                 (nyxt/web-mode::case-sensitive-p nil
                  nyxt/web-mode::explicit-case-p))
    (apply #'nyxt/web-mode::search-over-buffers (list (current-buffer))
           (if nyxt/web-mode::explicit-case-p
               `(:case-sensitive-p ,nyxt/web-mode::case-sensitive-p)
               'nil)))
scroll-page-up

Scroll up by one page height.

(define-command nil
    (pflet ((nyxt/web-mode:scroll-page-up nil
                                          (parenscript:chain window
                                                             (nyxt/web-mode::scroll-by
                                                              0
                                                              (*
                                                               (parenscript:lisp
                                                                (page-scroll-ratio
                                                                 (current-buffer)))
                                                               (-
                                                                (parenscript:@
                                                                 window
                                                                 nyxt/web-mode::inner-height)))))))
      (nyxt/web-mode:scroll-page-up)))
scroll-page-down

Scroll down by one page height.

(define-command nil
    (pflet ((nyxt/web-mode:scroll-page-down nil
                                            (parenscript:chain window
                                                               (nyxt/web-mode::scroll-by
                                                                0
                                                                (*
                                                                 (parenscript:lisp
                                                                  (page-scroll-ratio
                                                                   (current-buffer)))
                                                                 (parenscript:@
                                                                  window
                                                                  nyxt/web-mode::inner-height))))))
      (nyxt/web-mode:scroll-page-down)))
scroll-right

Scroll right the current page.
The amount scrolled is determined by the buffer's `horizontal-scroll-distance'.

(define-command (&key
                 (horizontal-scroll-distance
                  (horizontal-scroll-distance (current-buffer))))
    (pflet ((nyxt/web-mode:scroll-right nil
                                        (parenscript:chain window
                                                           (nyxt/web-mode::scroll-by
                                                            (parenscript:lisp
                                                             horizontal-scroll-distance)
                                                            0))))
      (nyxt/web-mode:scroll-right)))
scroll-left

Scroll left the current page.
The amount scrolled is determined by the buffer's `horizontal-scroll-distance'.

(define-command (&key
                 (horizontal-scroll-distance
                  (horizontal-scroll-distance (current-buffer))))
    (pflet ((nyxt/web-mode:scroll-left nil
                                       (parenscript:chain window
                                                          (nyxt/web-mode::scroll-by
                                                           (parenscript:lisp
                                                            (-
                                                             horizontal-scroll-distance))
                                                           0))))
      (nyxt/web-mode:scroll-left)))
scroll-up

Scroll up the current page.
The amount scrolled is determined by the buffer's `scroll-distance'.

(define-command (&key (scroll-distance (scroll-distance (current-buffer))))
    (pflet ((nyxt/web-mode:scroll-up nil
                                     (parenscript:chain window
                                                        (nyxt/web-mode::scroll-by
                                                         0
                                                         (parenscript:lisp
                                                          (-
                                                           scroll-distance))))))
      (nyxt/web-mode:scroll-up)))
scroll-down

Scroll down the current page.
The amount scrolled is determined by the buffer's `scroll-distance'.

(define-command (&key (scroll-distance (scroll-distance (current-buffer))))
    (pflet ((nyxt/web-mode:scroll-down nil
                                       (parenscript:chain window
                                                          (nyxt/web-mode::scroll-by
                                                           0
                                                           (parenscript:lisp
                                                            scroll-distance)))))
      (nyxt/web-mode:scroll-down)))
scroll-to-bottom

Scroll to the bottom of the current page.

(define-command nil
    (pflet ((nyxt/web-mode:scroll-to-bottom nil
                                            (parenscript:chain window
                                                               (nyxt/web-mode::scroll-by
                                                                0
                                                                (parenscript:chain
                                                                 nyxt/web-mode::document
                                                                 nyxt/web-mode::document-element
                                                                 nyxt/web-mode::scroll-height)))))
      (nyxt/web-mode:scroll-to-bottom)))
scroll-to-top

Scroll to the top of the current page.

(define-command nil
    (pflet ((nyxt/web-mode:scroll-to-top nil
                                         (parenscript:chain window
                                                            (nyxt/web-mode::scroll-by
                                                             0
                                                             (-
                                                              (parenscript:chain
                                                               nyxt/web-mode::document
                                                               nyxt/web-mode::document-element
                                                               nyxt/web-mode::scroll-height))))))
      (nyxt/web-mode:scroll-to-top)))
jump-to-heading

Jump to a particular heading, of type h1, h2, h3, h4, h5, or h6.

(define-command nil
    (let* ((nyxt/web-mode::headings (nyxt/web-mode::get-headings))
           (nyxt/web-mode::heading
            (prompt-minibuffer :input-prompt "Jump to heading"
                               :suggestion-function
                               (lambda (minibuffer)
                                 (fuzzy-match (input-buffer minibuffer)
                                              (nyxt/web-mode::make-headings
                                               (json:decode-json-from-string
                                                nyxt/web-mode::headings)))))))
      (nyxt/web-mode::paren-jump-to-heading :heading-inner-text
                                            (nyxt/web-mode::inner-text
                                             nyxt/web-mode::heading))))
select-previous-follow

Select previous entry in minibuffer and focus the referencing hint/match
if there is one such.

(define-command (&optional (minibuffer (current-minibuffer)))
    (nyxt/minibuffer-mode:select-previous minibuffer)
  (nyxt/web-mode::update-selection-highlight-hint :follow t :scroll t))
select-next-follow

Select next entry in minibuffer and focus the referencing hint/match
if there is one such.

(define-command (&optional (minibuffer (current-minibuffer)))
    (nyxt/minibuffer-mode:select-next minibuffer)
  (nyxt/web-mode::update-selection-highlight-hint :follow t :scroll t))
toggle-hints-transparency

Toggle the on-screen element hints transparency.

(define-command (&key (buffer (current-buffer)))
    (pflet ((nyxt/minibuffer-mode::toggle-transparent nil
             (defun nyxt/minibuffer-mode::qsa
                    (nyxt/minibuffer-mode::context
                     nyxt/minibuffer-mode::selector)
               "Alias of document.querySelectorAll"
               (parenscript:chain nyxt/minibuffer-mode::context
                                  (nyxt/minibuffer-mode::query-selector-all
                                   nyxt/minibuffer-mode::selector)))
             (dolist
                 (nyxt/minibuffer-mode::element
                  (nyxt/minibuffer-mode::qsa nyxt/minibuffer-mode::document
                   ".nyxt-hint"))
               (if (or
                    (=
                     (parenscript:chain nyxt/minibuffer-mode::element style
                                        nyxt/minibuffer-mode::opacity)
                     "1")
                    (=
                     (parenscript:chain nyxt/minibuffer-mode::element style
                                        nyxt/minibuffer-mode::opacity)
                     ""))
                   (setf (parenscript:chain nyxt/minibuffer-mode::element style
                                            nyxt/minibuffer-mode::opacity)
                           "0.2")
                   (setf (parenscript:chain nyxt/minibuffer-mode::element style
                                            nyxt/minibuffer-mode::opacity)
                           "1.0")))))
      (with-current-buffer buffer
        (nyxt/minibuffer-mode::toggle-transparent))))
element-hint-mode

Minibuffer mode for setting the tag of a bookmark.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command ELEMENT-HINT-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/minibuffer-mode:element-hint-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/minibuffer-mode:user-element-hint-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/minibuffer-mode:element-hint-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/minibuffer-mode:element-hint-mode))))
  buffer)
download-hint-url

Download the file under the URL(s) hinted by the user.

(define-command (&key nyxt/web-mode::annotate-visible-only-p)
    (nyxt/web-mode::query-hints "Download link URL"
                                (lambda (nyxt/web-mode::selected-links)
                                  (loop nyxt/web-mode::for nyxt/web-mode::link nyxt/web-mode::in nyxt/web-mode::selected-links
                                        do (download
                                            (quri.uri:uri
                                             (url nyxt/web-mode::link))) (sleep
                                                                          0.25))
                                  (list-downloads))
                                :multi-selection-p t :annotate-visible-only-p
                                nyxt/web-mode::annotate-visible-only-p))
bookmark-hint

Show link hints on screen, and allow the user to bookmark one

(define-command nil
    (let* ((nyxt/web-mode::elements-json (nyxt/web-mode::add-element-hints))
           (nyxt/web-mode::result
            (prompt-minibuffer :input-prompt "Bookmark hint" :default-modes
                               '(nyxt/web-mode::element-hint-mode
                                 nyxt/web-mode::minibuffer-mode)
                               :history nil :suggestion-function
                               (nyxt/web-mode::hint-suggestion-filter
                                (nyxt/web-mode::elements-from-json
                                 nyxt/web-mode::elements-json))
                               :cleanup-function
                               (lambda ()
                                 (nyxt/web-mode::remove-element-hints))))
           (tags
            (prompt-minibuffer :input-prompt "Space-separated tag(s)"
                               :default-modes
                               '(set-tag-mode nyxt/web-mode::minibuffer-mode)
                               :input-buffer
                               (url-bookmark-tags
                                (quri.uri:uri (url nyxt/web-mode::result)))
                               :suggestion-function (tag-suggestion-filter))))
      (when nyxt/web-mode::result
        (bookmark-add (quri.uri:uri (url nyxt/web-mode::result)) :tags tags))))
copy-hint-url

Show a set of element hints, and copy the URL of the user inputted one.

(define-command (&key nyxt/web-mode::annotate-visible-only-p)
    (nyxt/web-mode::query-hints "Copy element URL"
                                'nyxt/web-mode::%copy-hint-url
                                :annotate-visible-only-p
                                nyxt/web-mode::annotate-visible-only-p))
follow-hint-new-buffer-focus

Show a set of element hints, and open the user inputted one in a new
visible active buffer.

(define-command (&key nyxt/web-mode::annotate-visible-only-p)
    (nyxt/web-mode::query-hints "Go to element in new buffer"
                                (lambda (nyxt/web-mode::result)
                                  (nyxt/web-mode::%follow-hint-new-buffer-focus
                                   (first nyxt/web-mode::result))
                                  (mapcar
                                   #'nyxt/web-mode::%follow-hint-new-buffer
                                   (rest nyxt/web-mode::result)))
                                :multi-selection-p t :annotate-visible-only-p
                                nyxt/web-mode::annotate-visible-only-p))
follow-hint-new-buffer

Show a set of element hints, and open the user inputted one in a new
buffer (not set to visible active buffer).

(define-command (&key nyxt/web-mode::annotate-visible-only-p)
    (nyxt/web-mode::query-hints "Open element in new buffer"
                                (lambda (nyxt/web-mode::result)
                                  (mapcar
                                   #'nyxt/web-mode::%follow-hint-new-buffer
                                   nyxt/web-mode::result))
                                :multi-selection-p t :annotate-visible-only-p
                                nyxt/web-mode::annotate-visible-only-p))
follow-hint

Show a set of element hints, and go to the user inputted one in the
currently active buffer.

(define-command (&key nyxt/web-mode::annotate-visible-only-p)
    (nyxt/web-mode::query-hints "Go to element" 'nyxt/web-mode::%follow-hint
                                :annotate-visible-only-p
                                nyxt/web-mode::annotate-visible-only-p))
input-edit-mode

Mode for editing input areas in HTML. Overrides many of the
bindings in other modes, so you will have to disable/enable it as
necessary.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command INPUT-EDIT-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/input-edit-mode:input-edit-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/input-edit-mode:user-input-edit-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/input-edit-mode:input-edit-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/input-edit-mode:input-edit-mode))))
  buffer)
delete-forwards-word

Delete forwards a word.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::delete-forward-word nyxt/input-edit-mode::cursor)
        (nyxt/input-edit-mode::set-active-input-area-content
         (text-buffer::string-representation nyxt/input-edit-mode::text-buffer))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
delete-backwards-word

Delete backwards a word.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::delete-backward-word nyxt/input-edit-mode::cursor)
        (nyxt/input-edit-mode::set-active-input-area-content
         (text-buffer::string-representation nyxt/input-edit-mode::text-buffer))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
delete-backwards

Delete character before cursor.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::delete-item-backward nyxt/input-edit-mode::cursor)
        (nyxt/input-edit-mode::set-active-input-area-content
         (text-buffer::string-representation nyxt/input-edit-mode::text-buffer))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
delete-forwards

Delete character after cursor.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::delete-item-forward nyxt/input-edit-mode::cursor)
        (nyxt/input-edit-mode::set-active-input-area-content
         (text-buffer::string-representation nyxt/input-edit-mode::text-buffer))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
cursor-backwards-word

Move cursor backwards a word.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::move-backward-word nyxt/input-edit-mode::cursor
                                         :conservative-word-move
                                         (conservative-word-move
                                          (current-buffer)))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
cursor-forwards-word

Move cursor forwards a word.

(define-command nil
    (nyxt/input-edit-mode::with-input-area (nyxt/input-edit-mode::contents
                                            nyxt/input-edit-mode::cursor-position)
      (nyxt/input-edit-mode::with-text-buffer (nyxt/input-edit-mode::text-buffer
                                               nyxt/input-edit-mode::cursor
                                               nyxt/input-edit-mode::contents
                                               nyxt/input-edit-mode::cursor-position)
        (text-buffer::move-forward-word nyxt/input-edit-mode::cursor
                                        :conservative-word-move
                                        (conservative-word-move
                                         (current-buffer)))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)
         (cluffer:cursor-position nyxt/input-edit-mode::cursor)))))
cursor-backwards

Move cursor backwards by one element.

(define-command nil
    (let* ((nyxt/input-edit-mode::cursor-position
            (nyxt/input-edit-mode::active-input-area-cursor)))
      (let ((nyxt/input-edit-mode::new-position
             (- (parse-integer nyxt/input-edit-mode::cursor-position) 1)))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         nyxt/input-edit-mode::new-position
         nyxt/input-edit-mode::new-position))))
cursor-forwards

Move cursor forward by one element.

(define-command nil
    (let* ((nyxt/input-edit-mode::cursor-position
            (nyxt/input-edit-mode::active-input-area-cursor)))
      (let ((nyxt/input-edit-mode::new-position
             (+ (parse-integer nyxt/input-edit-mode::cursor-position) 1)))
        (nyxt/input-edit-mode::set-active-input-area-cursor
         nyxt/input-edit-mode::new-position
         nyxt/input-edit-mode::new-position))))
darken

Darken the page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "javascript:document.querySelectorAll('*').forEach(e=>e.setAttribute('style','background-color:#222 !important;background-image:none !important;color:#'+(/^A|BU/.test(e.tagName)?'36c;text-decoration:underline;':'eee;')+e.getAttribute('style')))"))
invert-color

Invert the color of the web page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(d=>{var css=`:root{background-color:#fefefe;filter:invert(100%)}*{background-color:inherit}img:not([src*=\".svg\"]),video{filter: invert(100%)}`,style,id=\"dark-theme-snippet\",ee=d.getElementById(id);if(null!=ee)ee.parentNode.removeChild(ee);else {style = d.createElement('style');style.type=\"text/css\";style.id=id;if(style.styleSheet)style.styleSheet.cssText=css;else style.appendChild(d.createTextNode(css));(d.head||d.querySelector('head')).appendChild(style)}})(document)"))
decrease-brightness

Decrease the brightness of the web page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function RGBtoHSL(RGBColor){with(Math){var R,G,B;var cMax,cMin;var sum,diff;var Rdelta,Gdelta,Bdelta;var H,L,S;R=RGBColor[0];G=RGBColor[1];B=RGBColor[2];cMax=max(max(R,G),B);cMin=min(min(R,G),B);sum=cMax+cMin;diff=cMax-cMin;L=sum/2;if(cMax==cMin){S=0;H=0;}else{if(L<=(1/2))S=diff/sum;else S=diff/(2-sum);Rdelta=R/6/diff;Gdelta=G/6/diff;Bdelta=B/6/diff;if(R==cMax)H=Gdelta-Bdelta;else if(G==cMax)H=(1/3)+Bdelta-Rdelta;else H=(2/3)+Rdelta-Gdelta;if(H<0)H+=1;if(H>1)H-=1;}return[H,S,L];}}function getRGBColor(node,prop){var rgb=getComputedStyle(node,null).getPropertyValue(prop);var r,g,b;if(/rgb((d+),s(d+),s(d+))/.exec(rgb)){r=parseInt(RegExp.$1,10);g=parseInt(RegExp.$2,10);b=parseInt(RegExp.$3,10);return[r/255,g/255,b/255];}return rgb;}function hslToCSS(hsl){return \"hsl(\"+Math.round(hsl[0]*360)+\", \"+Math.round(hsl[1]*100)+\"%, \"+Math.round(hsl[2]*100)+\"%)\";}var props=[\"color\",\"background-color\",\"border-left-color\",\"border-right-color\",\"border-top-color\",\"border-bottom-color\"];var props2=[\"color\",\"backgroundColor\",\"borderLeftColor\",\"borderRightColor\",\"borderTopColor\",\"borderBottomColor\"];if(typeof getRGBColor(document.documentElement,\"background-color\")==\"string\")document.documentElement.style.backgroundColor=\"white\";revl(document.documentElement);function revl(n){var i,x,color,hsl;if(n.nodeType==Node.ELEMENT_NODE){for(i=0;x=n.childNodes[i];++i)revl(x);for(i=0;x=props[i];++i){color=getRGBColor(n,x);if(typeof(color)!=\"string\"){hsl=RGBtoHSL(color);hsl[2] = Math.pow(hsl[2], 6/5);n.style[props2[i]]=hslToCSS(hsl);}}}}})()"))
increase-brightness

Increase the brightness of the web page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function RGBtoHSL(RGBColor){with(Math){var R,G,B;var cMax,cMin;var sum,diff;var Rdelta,Gdelta,Bdelta;var H,L,S;R=RGBColor[0];G=RGBColor[1];B=RGBColor[2];cMax=max(max(R,G),B);cMin=min(min(R,G),B);sum=cMax+cMin;diff=cMax-cMin;L=sum/2;if(cMax==cMin){S=0;H=0;}else{if(L<=(1/2))S=diff/sum;else S=diff/(2-sum);Rdelta=R/6/diff;Gdelta=G/6/diff;Bdelta=B/6/diff;if(R==cMax)H=Gdelta-Bdelta;else if(G==cMax)H=(1/3)+Bdelta-Rdelta;else H=(2/3)+Rdelta-Gdelta;if(H<0)H+=1;if(H>1)H-=1;}return[H,S,L];}}function getRGBColor(node,prop){var rgb=getComputedStyle(node,null).getPropertyValue(prop);var r,g,b;if(/rgb((d+),s(d+),s(d+))/.exec(rgb)){r=parseInt(RegExp.$1,10);g=parseInt(RegExp.$2,10);b=parseInt(RegExp.$3,10);return[r/255,g/255,b/255];}return rgb;}function hslToCSS(hsl){return \"hsl(\"+Math.round(hsl[0]*360)+\", \"+Math.round(hsl[1]*100)+\"%, \"+Math.round(hsl[2]*100)+\"%)\";}var props=[\"color\",\"background-color\",\"border-left-color\",\"border-right-color\",\"border-top-color\",\"border-bottom-color\"];var props2=[\"color\",\"backgroundColor\",\"borderLeftColor\",\"borderRightColor\",\"borderTopColor\",\"borderBottomColor\"];if(typeof getRGBColor(document.documentElement,\"background-color\")==\"string\")document.documentElement.style.backgroundColor=\"white\";revl(document.documentElement);function revl(n){var i,x,color,hsl;if(n.nodeType==Node.ELEMENT_NODE){for(i=0;x=n.childNodes[i];++i)revl(x);for(i=0;x=props[i];++i){color=getRGBColor(n,x);if(typeof(color)!=\"string\"){hsl=RGBtoHSL(color);hsl[2] = Math.pow(hsl[2], 5/6);n.style[props2[i]]=hslToCSS(hsl);}}}}})()"))
hue-shift-negative

Shift the colors of the web page with a negative hue.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function RGBtoHSL(RGBColor){with(Math){var R,G,B;var cMax,cMin;var sum,diff;var Rdelta,Gdelta,Bdelta;var H,L,S;R=RGBColor[0];G=RGBColor[1];B=RGBColor[2];cMax=max(max(R,G),B);cMin=min(min(R,G),B);sum=cMax+cMin;diff=cMax-cMin;L=sum/2;if(cMax==cMin){S=0;H=0;}else{if(L<=(1/2))S=diff/sum;else S=diff/(2-sum);Rdelta=R/6/diff;Gdelta=G/6/diff;Bdelta=B/6/diff;if(R==cMax)H=Gdelta-Bdelta;else if(G==cMax)H=(1/3)+Bdelta-Rdelta;else H=(2/3)+Rdelta-Gdelta;if(H<0)H+=1;if(H>1)H-=1;}return[H,S,L];}}function getRGBColor(node,prop){var rgb=getComputedStyle(node,null).getPropertyValue(prop);var r,g,b;if(/rgb((d+),s(d+),s(d+))/.exec(rgb)){r=parseInt(RegExp.$1,10);g=parseInt(RegExp.$2,10);b=parseInt(RegExp.$3,10);return[r/255,g/255,b/255];}return rgb;}function hslToCSS(hsl){return \"hsl(\"+Math.round(hsl[0]*360)+\", \"+Math.round(hsl[1]*100)+\"%, \"+Math.round(hsl[2]*100)+\"%)\";}var props=[\"color\",\"background-color\",\"border-left-color\",\"border-right-color\",\"border-top-color\",\"border-bottom-color\"];var props2=[\"color\",\"backgroundColor\",\"borderLeftColor\",\"borderRightColor\",\"borderTopColor\",\"borderBottomColor\"];if(typeof getRGBColor(document.documentElement,\"background-color\")==\"string\")document.documentElement.style.backgroundColor=\"white\";revl(document.documentElement);function revl(n){var i,x,color,hsl;if(n.nodeType==Node.ELEMENT_NODE){for(i=0;x=n.childNodes[i];++i)revl(x);for(i=0;x=props[i];++i){color=getRGBColor(n,x);if(typeof(color)!=\"string\"){hsl=RGBtoHSL(color);hsl[0] = (hsl[0] + 23/24) % 1;n.style[props2[i]]=hslToCSS(hsl);}}}}})()"))
hue-shift-positive

Shift the colors of the web page with a positive hue.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function RGBtoHSL(RGBColor){with(Math){var R,G,B;var cMax,cMin;var sum,diff;var Rdelta,Gdelta,Bdelta;var H,L,S;R=RGBColor[0];G=RGBColor[1];B=RGBColor[2];cMax=max(max(R,G),B);cMin=min(min(R,G),B);sum=cMax+cMin;diff=cMax-cMin;L=sum/2;if(cMax==cMin){S=0;H=0;}else{if(L<=(1/2))S=diff/sum;else S=diff/(2-sum);Rdelta=R/6/diff;Gdelta=G/6/diff;Bdelta=B/6/diff;if(R==cMax)H=Gdelta-Bdelta;else if(G==cMax)H=(1/3)+Bdelta-Rdelta;else H=(2/3)+Rdelta-Gdelta;if(H<0)H+=1;if(H>1)H-=1;}return[H,S,L];}}function getRGBColor(node,prop){var rgb=getComputedStyle(node,null).getPropertyValue(prop);var r,g,b;if(/rgb((d+),s(d+),s(d+))/.exec(rgb)){r=parseInt(RegExp.$1,10);g=parseInt(RegExp.$2,10);b=parseInt(RegExp.$3,10);return[r/255,g/255,b/255];}return rgb;}function hslToCSS(hsl){return \"hsl(\"+Math.round(hsl[0]*360)+\", \"+Math.round(hsl[1]*100)+\"%, \"+Math.round(hsl[2]*100)+\"%)\";}var props=[\"color\",\"background-color\",\"border-left-color\",\"border-right-color\",\"border-top-color\",\"border-bottom-color\"];var props2=[\"color\",\"backgroundColor\",\"borderLeftColor\",\"borderRightColor\",\"borderTopColor\",\"borderBottomColor\"];if(typeof getRGBColor(document.documentElement,\"background-color\")==\"string\")document.documentElement.style.backgroundColor=\"white\";revl(document.documentElement);function revl(n){var i,x,color,hsl;if(n.nodeType==Node.ELEMENT_NODE){for(i=0;x=n.childNodes[i];++i)revl(x);for(i=0;x=props[i];++i){color=getRGBColor(n,x);if(typeof(color)!=\"string\"){hsl=RGBtoHSL(color);hsl[0]=(hsl[0]+1/24)%1;n.style[props2[i]]=hslToCSS(hsl);}}}}})()"))
remove-images

Remove images from web pages.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function toArray (c){var a, k;a=new Array;for (k=0; k < c.length; ++k)a[k]=c[k];return a;}var images, img, altText;images=toArray(document.images);for (var i=0; i < images.length; ++i){img=images[i];altText=document.createTextNode(img.alt);img.parentNode.replaceChild(altText, img)}})();"))
remove-color

Remove color from web pages.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var newSS, styles='* { background: white ! important; color: black !important } :link, :link * { color: #0000EE !important } :visited, :visited * { color: #551A8B !important }'; if(document.createStyleSheet) { document.createStyleSheet(\"javascript:'\"+styles+\"'\"); } else { newSS=document.createElement('link'); newSS.rel='stylesheet'; newSS.href='data:text/css,'+escape(styles); document.getElementsByTagName(\"head\")[0].appendChild(newSS); } })();"))
transpose-tables

Transpose all table row and columns.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var d=document,q=\"table\",i,j,k,y,r,c,t;for(i=0;t=d.getElementsByTagName(q)[i];++i){var w=0,N=t.cloneNode(0);N.width=\"\";N.height=\"\";N.border=1;for(j=0;r=t.rows[j];++j)for(y=k=0;c=r.cells[k];++k){var z,a=c.rowSpan,b=c.colSpan,v=c.cloneNode(1);v.rowSpan=b;v.colSpan=a;v.width=\"\";v.height=\"\";if(!v.bgColor)v.bgColor=r.bgColor;while(w<y+b)N.insertRow(w++).p=0;while(N.rows[y].p>j)++y;N.rows[y].appendChild(v);for(z=0;z<b;++z)N.rows[y+z].p+=a;y+=b;}t.parentNode.replaceChild(N,t);}})()"))
number-lines

Numberlines in plaintext documents and PRE tags.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var i,p,L,d,j,n; for(i=0; p=document.getElementsByTagName(\"pre\")[i]; ++i) { L=p.innerHTML.split(\"rn\"); d=\"\"+L.length; for(j=0;j<L.length;++j) { n = \"\"+(j+1)+\". \"; while(n.length<d.length+2) n=\"0\"+n; L[j] = n + L[j]; } p.innerHTML=L.join(\"<br>\");/*join with br for ie*/ } })()"))
number-table-rows

Add numbers to table rows.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){function has(par,ctag){for(var k=0;k<par.childNodes.length;++k)if(par.childNodes[k].tagName==ctag)return true;} function add(par,ctag,text){var c=document.createElement(ctag); c.appendChild(document.createTextNode(text)); par.insertBefore(c,par.childNodes[0]);} var i,ts=document.getElementsByTagName(\"TABLE\"); for(i=0;i<ts.length;++i) { var n=0,trs=ts[i].rows,j,tr; for(j=0;j<trs.length;++j) {tr=trs[j]; if(has(tr,\"TD\"))add(tr,\"TD\",++n); else if(has(tr,\"TH\"))add(tr,\"TH\",\"Row\");}}})()"))
sort-table

Sort a table alphabetically.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "function toArray (c){var a, k;a=new Array;for (k=0; k<c.length; ++k)a[k]=c[k];return a;}function insAtTop(par,child){if(par.childNodes.length) par.insertBefore(child, par.childNodes[0]);else par.appendChild(child);}function countCols(tab){var nCols, i;nCols=0;for(i=0;i<tab.rows.length;++i)if(tab.rows[i].cells.length>nCols)nCols=tab.rows[i].cells.length;return nCols;}function makeHeaderLink(tableNo, colNo, ord){var link;link=document.createElement('a');link.href='javascript:sortTable('+tableNo+','+colNo+','+ord+');';link.appendChild(document.createTextNode((ord>0)?'a':'d'));return link;}function makeHeader(tableNo,nCols){var header, headerCell, i;header=document.createElement('tr');for(i=0;i<nCols;++i){headerCell=document.createElement('td');headerCell.appendChild(makeHeaderLink(tableNo,i,1));headerCell.appendChild(document.createTextNode('/'));headerCell.appendChild(makeHeaderLink(tableNo,i,-1));header.appendChild(headerCell);}return header;}g_tables=toArray(document.getElementsByTagName('table'));if(!g_tables.length) alert(\"This page doesn't contain any tables.\");(function(){var j, thead;for(j=0;j<g_tables.length;++j){thead=g_tables[j].createTHead();insAtTop(thead, makeHeader(j,countCols(g_tables[j])))}}) ();function compareRows(a,b){if(a.sortKey==b.sortKey)return 0;return (a.sortKey < b.sortKey) ? g_order : -g_order;}function sortTable(tableNo, colNo, ord){var table, rows, nR, bs, i, j, temp;g_order=ord;g_colNo=colNo;table=g_tables[tableNo];rows=new Array();nR=0;bs=table.tBodies;for(i=0; i<bs.length; ++i)for(j=0; j<bs[i].rows.length; ++j){rows[nR]=bs[i].rows[j];temp=rows[nR].cells[g_colNo];if(temp) rows[nR].sortKey=temp.innerHTML;else rows[nR].sortKey=\"\";++nR;}rows.sort(compareRows);for (i=0; i < rows.length; ++i)insAtTop(table.tBodies[0], rows[i]);}"))
zoom-images-out

Zoom images out.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){ function zoomImage(image, amt) { if(image.initialHeight == null) { /* avoid accumulating integer-rounding error */ image.initialHeight=image.height; image.initialWidth=image.width; image.scalingFactor=1; } image.scalingFactor*=amt; image.width=image.scalingFactor*image.initialWidth; image.height=image.scalingFactor*image.initialHeight; } var i,L=document.images.length; for (i=0;i<L;++i) zoomImage(document.images[i],.5); if (!L) alert(\"This page contains no images.\"); })();"))
zoom-images-in

Zoom images in.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){ function zoomImage(image, amt) { if(image.initialHeight == null) { /* avoid accumulating integer-rounding error */ image.initialHeight=image.height; image.initialWidth=image.width; image.scalingFactor=1; } image.scalingFactor*=amt; image.width=image.scalingFactor*image.initialWidth; image.height=image.scalingFactor*image.initialHeight; } var i,L=document.images.length; for (i=0;i<L;++i) zoomImage(document.images[i], 2); if (!L) alert(\"This page contains no images.\"); })();"))
highlight-regexp

Highlights each match for a regular expression.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var count=0, text, regexp;text=prompt(\"Search regexp:\", \"\");if(text==null || text.length==0)return;try{regexp=new RegExp(\"(\" + text +\")\", \"i\");}catch(er){alert(\"Unable to create regular expression using text '\"+text+\"'.nn\"+er);return;}function searchWithinNode(node, re){var pos, skip, spannode, middlebit, endbit, middleclone;skip=0;if( node.nodeType==3 ){pos=node.data.search(re);if(pos>=0){spannode=document.createElement(\"SPAN\");spannode.style.backgroundColor=\"yellow\";middlebit=node.splitText(pos);endbit=middlebit.splitText(RegExp.$1.length);middleclone=middlebit.cloneNode(true);spannode.appendChild(middleclone);middlebit.parentNode.replaceChild(spannode,middlebit);++count;skip=1;}}else if( node.nodeType==1 && node.childNodes && node.tagName.toUpperCase()!=\"SCRIPT\" && node.tagName.toUpperCase!=\"STYLE\"){for (var child=0; child < node.childNodes.length; ++child){child=child+searchWithinNode(node.childNodes[child], re);}}return skip;}window.status=\"Searching for \"+regexp+\"...\";searchWithinNode(document.body, regexp);window.status=\"Found \"+count+\" match\"+(count==1?\"\":\"es\")+\" for \"+regexp+\".\";})();"))
show-textbox-character-count

Displays a running count of the characters in each textbox.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var D=document,i,f,j,e;for(i=0;f=D.forms[i];++i)for(j=0;e=f[j];++j)if(e.type==\"text\"||e.type==\"password\"||e.tagName.toLowerCase()==\"textarea\")S(e);function S(e){if(!e.N){var x=D.createElement(\"span\"),s=x.style;s.color=\"green\";s.background=\"white\";s.font=\"bold 10pt sans-serif\";s.verticalAlign=\"top\";e.parentNode.insertBefore(x,e.nextSibling);function u(){x.innerHTML=e.value.length;}u();e.onchange=u;e.onkeyup=u;e.oninput=u;e.N=x;}else{e.parentNode.removeChild(e.N);e.N=0;}}})()"))
enlarge-textareas

Increase height of all text areas by 5 vertical lines.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var i,x; for(i=0;x=document.getElementsByTagName(\"textarea\")[i];++i) x.rows += 5; })()"))
show-hidden-form-elements

Show hidden form elements.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var i,f,j,e,div,label,ne; for(i=0;f=document.forms[i];++i)for(j=0;e=f[j];++j)if(e.type==\"hidden\"){ D=document; function C(t){return D.createElement(t);} function A(a,b){a.appendChild(b);} div=C(\"div\"); label=C(\"label\"); A(div, label); A(label, D.createTextNode(e.name + \": \")); e.parentNode.insertBefore(div, e); e.parentNode.removeChild(e); ne=C(\"input\");/*for ie*/ ne.type=\"text\"; ne.value=e.value; A(label, ne); label.style.MozOpacity=\".6\"; --j;/*for moz*/}})()"))
view-password-field-contents

View passwords on page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var s,F,j,f,i; s = \"\"; F = document.forms; for(j=0; j<F.length; ++j) { f = F[j]; for (i=0; i<f.length; ++i) { if (f[i].type.toLowerCase() == \"password\") s += f[i].value + \"n\"; } } if (s) alert(\"Passwords in forms on this page:nn\" + s); else alert(\"There are no passwords in forms on this page.\");})();"))
toggle-checkboxes

Toggle all checkboxes.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){ function toggle(box){ temp=box.onchange; box.onchange=null; box.checked=!box.checked; box.onchange=temp; } var x,k,f,j; x=document.forms; for (k=0; k<x.length; ++k) { f=x[k]; for (j=0;j<f.length;++j) if (f[j].type.toLowerCase() == \"checkbox\") toggle(f[j]); } })();"))
hide-visited-urls

Hide visited URLs.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var newSS, styles=':visited {display: none}'; if(document.createStyleSheet) { document.createStyleSheet(\"javascript:'\"+styles+\"'\"); } else { newSS=document.createElement('link'); newSS.rel='stylesheet'; newSS.href='data:text/css,'+escape(styles); document.getElementsByTagName(\"head\")[0].appendChild(newSS); } })();"))
urls-as-link-text

Changes the text of links to match their absolute URLs.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var i,c,x,h; for(i=0;x=document.links[i];++i) { h=x.href; x.title+=\" \" + x.innerHTML; while(c=x.firstChild)x.removeChild(c); x.appendChild(document.createTextNode(h)); } })()"))
color-internal-external-links

Color internal links red, external links blue, and in-page links orange.

(define-command (&optional (buffer (current-buffer)))
    (ffi-buffer-evaluate-javascript-async buffer
                                          "(function(){var i,x; for (i=0;x=document.links[i];++i)x.style.color=['blue','red','orange'][sim(x,location)]; function sim(a,b) { if (a.hostname!=b.hostname) return 0; if (fixPath(a.pathname)!=fixPath(b.pathname) || a.search!=b.search) return 1; return 2; } function fixPath(p){ p = (p.charAt(0)=='/' ? '' : '/') + p;/*many browsers*/ p=p.split('?')[0];/*opera*/ return p; } })()"))
delete-os-generations

Delete generations of selected profile.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter :include-manager-p
                                                           t)
                             :input-prompt "Target profile"))
         (generations
          (prompt-minibuffer :suggestion-function
                             (os-generation-suggestion-filter profile)
                             :input-prompt "Delete generations"
                             :multi-selection-p t)))
    (operate-os-package "Deleting generations..." #'ospama:delete-generations
                        profile generations)))
switch-os-generation

Switch generation of selected profile.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter :include-manager-p
                                                           t)
                             :input-prompt "Target profile"))
         (generation
          (prompt-minibuffer :suggestion-function
                             (os-generation-suggestion-filter profile)
                             :input-prompt "Switch to generation")))
    (operate-os-package "Switching to generation..." #'ospama:switch-generation
                        profile generation)))
describe-os-generation

Show the packages of a given profile generation.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter :include-manager-p
                                                           t)
                             :input-prompt "Profile"))
         (generation
          (prompt-minibuffer :suggestion-function
                             (os-generation-suggestion-filter profile)
                             :input-prompt "Generation"))
         (buffer
          (or (find-buffer 'os-package-manager-mode)
              (nyxt/os-package-manager-mode:os-package-manager-mode :activate t
                                                                    :buffer
                                                                    (make-internal-buffer
                                                                     :title
                                                                     "*OS packages*")))))
    (echo "Loading package database...")
    (html-set
     (cl-markup:markup (:style (style buffer))
                       (:h2
                        (format nil "Packages for generation ~a"
                                (ospama:id generation)))
                       (:p "Profile " profile)
                       (:ul
                        (loop for package-output in (ospama:list-packages
                                                     (ospama:path generation))
                              for package = (ospama:parent-package
                                             package-output)
                              collect (cl-markup:markup*
                                       `(:li
                                         (:a :class "button" :href
                                          ,(lisp-url
                                            `(%describe-os-package
                                              (or
                                               (ospama:find-os-packages
                                                ,(ospama:name package) :version
                                                ,(ospama:version package))
                                               (ospama:find-os-packages
                                                ,(ospama:name package)))))
                                          ,(object-string package-output))
                                         " " ,(ospama:version package))))))
     buffer)
    (echo "")
    (set-current-buffer buffer)
    buffer))
edit-package-manifest

Edit select manifest.

(define-command nil
    (assert-package-manager)
  (let ((manifest
         (prompt-minibuffer :suggestion-function
                            (os-manifest-suggestion-filter) :input-prompt
                            "Manifest")))
    (echo "Opening ~s with ~a" manifest (external-editor-program *browser*))
    (uiop/launch-program:launch-program
     (list (external-editor-program *browser*) manifest))))
install-package-manifest

Install select manifest to a profile.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter) :input-prompt
                             "Target profile"))
         (manifest
          (prompt-minibuffer :suggestion-function
                             (os-manifest-suggestion-filter) :input-prompt
                             "Manifest")))
    (operate-os-package "Installing package manifest..."
                        #'ospama:install-manifest profile manifest)))
uninstall-os-package

Uninstall select packages.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter) :input-prompt
                             "Target profile"))
         (packages
          (prompt-minibuffer :suggestion-function
                             (os-installed-package-suggestion-filter profile)
                             :input-prompt "Uninstall OS package(s)"
                             :multi-selection-p t)))
    (operate-os-package "Uninstalling packages..." #'ospama:uninstall profile
                        packages)))
install-os-package

Install select packages.

(define-command nil
    (assert-package-manager)
  (let* ((profile
          (prompt-minibuffer :suggestion-function
                             (os-profile-suggestion-filter) :input-prompt
                             "Target profile"))
         (packages
          (prompt-minibuffer :suggestion-function
                             (os-package-output-suggestion-filter)
                             :input-prompt "Install OS package(s)"
                             :multi-selection-p t)))
    (operate-os-package "Installing packages..." #'ospama:install profile
                        packages)))
list-os-package-files

List files of select packages.

(define-command nil
    (assert-package-manager)
  (let* ((packages-or-outputs
          (if (typep (ospama:manager) 'ospama:guix-manager)
              (prompt-minibuffer :suggestion-function
                                 (os-package-output-suggestion-filter)
                                 :input-prompt
                                 "List files of OS package outputs(s)"
                                 :multi-selection-p t)
              (prompt-minibuffer :suggestion-function
                                 (os-package-suggestion-filter) :input-prompt
                                 "List files of OS package(s)"
                                 :multi-selection-p t)))
         (buffer
          (or (find-buffer 'os-package-manager-mode)
              (nyxt/os-package-manager-mode:os-package-manager-mode :activate t
                                                                    :buffer
                                                                    (make-internal-buffer
                                                                     :title
                                                                     "*OS packages*")))))
    (echo "Computing file list...")
    (html-set
     (cl-markup:markup (:style (style buffer)) (:h1 "Package files")
                       (:ul
                        (loop for package-or-output in packages-or-outputs
                              collect (cl-markup:markup*
                                       `(:li ,(object-string package-or-output)
                                         (:ul
                                          ,@(mapcar
                                             (lambda (file)
                                               `(:li
                                                 ,(if (viewable-file-type-p
                                                       file)
                                                      `(:a :href ,file ,file)
                                                      file)))
                                             (ospama:list-files
                                              (list package-or-output)))))))))
     buffer)
    (echo "")
    (set-current-buffer buffer)
    buffer))
describe-os-package

Show description of select packages.

(define-command nil
    (assert-package-manager)
  (let* ((packages
          (prompt-minibuffer :suggestion-function
                             (os-package-suggestion-filter) :input-prompt
                             "Describe OS package(s)" :multi-selection-p t)))
    (%describe-os-package packages)))
cancel-package-operation

Terminate the package manager process in the current buffer.

(define-command nil
    (sera:and-let* ((nyxt/os-package-manager-mode::process-info
                     (nyxt/os-package-manager-mode:current-process-info
                      (find-submode (current-buffer)
                                    'nyxt/os-package-manager-mode:os-package-manager-mode))))
      (uiop/launch-program:terminate-process
       nyxt/os-package-manager-mode::process-info)
      (ffi-buffer-evaluate-javascript-async (current-buffer)
                                            (parenscript:ps
                                              (parenscript:chain
                                               nyxt/os-package-manager-mode::document
                                               (write
                                                (parenscript:lisp
                                                 (cl-markup:markup
                                                  (:p
                                                   "Operation cancelled.")))))))))
os-package-manager-mode

Mode for package management.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command OS-PACKAGE-MANAGER-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer
                    'nyxt/os-package-manager-mode:os-package-manager-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/os-package-manager-mode:user-os-package-manager-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled."
                     'nyxt/os-package-manager-mode:os-package-manager-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/os-package-manager-mode:os-package-manager-mode))))
  buffer)
reduce-tracking-mode

Set specific settings in the web view in order to mitigate fingerprinting,
(how third-party trackers attempt to indentify you.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command REDUCE-TRACKING-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/reduce-tracking-mode:reduce-tracking-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/reduce-tracking-mode:user-reduce-tracking-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled."
                     'nyxt/reduce-tracking-mode:reduce-tracking-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/reduce-tracking-mode:reduce-tracking-mode))))
  buffer)
force-https-mode

Impose HTTPS on every queried URI.
Use at your own risk -- it can break websites whose certificates are not known
and websites that still don't have HTTPS version (shame on them!).

To permanently bypass the "Unacceptable TLS Certificate" error:
(setf nyxt/certificate-exception-mode:*default-certificate-exceptions*
       '("your.unacceptable.cert.website"))

Example:

(define-configuration buffer
  ((default-modes (append '(force-https-mode) %slot-default))))

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command FORCE-HTTPS-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/force-https-mode:force-https-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/force-https-mode:user-force-https-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/force-https-mode:force-https-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/force-https-mode:force-https-mode))))
  buffer)
vcs-update-local-projects

Scan the project roots and update the list of existing repositories.

(define-command nil
    (setf nyxt/vcs::*git-projects* (nyxt/vcs::parse-projects))
  (echo "VCS projects updated."))
git-clone

Alias of `vcs-clone'.

(define-command nil
    (vcs-clone))
vcs-clone

Clone the repository of the current URL to disk.  Only Git is supported at
the moment.  Set the list of preferred destinations in the `*vcs-projects-roots*' variable.
The default username can be set in `*vcs-username*' or `*vcs-username-alist*'.

(define-command nil
    (let* ((uri (url (current-buffer)))
           (root-name
            (first (str:split "/" (quri.uri:uri-path uri) :omit-nulls t)))
           (project-name
            (second (str:split "/" (quri.uri:uri-path uri) :omit-nulls t)))
           (clone-uri (quri:copy-uri uri))
           (existing-repo (nyxt/vcs::find-project-directory project-name))
           target-dir)
      (cond ((not project-name) (echo "Could not find the project name."))
            (existing-repo (echo "This repository exists in ~a" existing-repo))
            ((= 1 (length nyxt/vcs:*vcs-projects-roots*))
             (setf target-dir (first nyxt/vcs:*vcs-projects-roots*))
             (nyxt/vcs::clone project-name root-name target-dir clone-uri))
            (t
             (let ((target-dir
                    (prompt-minibuffer :input-prompt "Target directory"
                                       :suggestion-function
                                       #'nyxt/vcs::projects-roots-suggestion-filter)))
               (nyxt/vcs::clone project-name root-name target-dir
                                clone-uri))))))
download-open-file

Open a downloaded file.
See also `open-file'.

(define-command nil
    (let ((filename
           (prompt-minibuffer :input-prompt "Open file" :suggestion-function
                              (downloaded-files-suggestion-filter))))
      (nyxt/file-manager-mode:open-file-function filename)))
download-url

Download the page or file of the current buffer.

(define-command nil
    (download (url (current-buffer)))
  (unless (find-buffer 'download-mode) (list-downloads)))
list-downloads

Display a buffer listing all downloads.

(define-command nil
    (unless (download-watcher *browser*)
      (setf (download-watcher *browser*)
              (bordeaux-threads:make-thread #'download-watch)))
  (set-current-buffer (download-refresh)))
download-mode

Display list of downloads.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command DOWNLOAD-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'download-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'user-download-mode :buffer buffer
                        args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'download-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'download-mode))))
  buffer)
open-file

Open a file from the filesystem.

The user is prompted with the minibuffer, files are browsable with
fuzzy suggestion.

The default directory is the one computed by
`download-manager:default-download-directory' (usually `~/Downloads').

Press `Enter' to visit a file, `M-Left' or `C-l' to go one directory
up, `M-Right' or `C-j' to browse the directory at point.

By default, it uses the `xdg-open' command. The user can override the
`nyxt:open-file-function' function, which takes the filename (or directory
name) as parameter.

The default keybinding is `C-x C-f'.

Note: this feature is alpha, get in touch for more!

(define-command nil
    (uiop/filesystem:with-current-directory ((uiop/os:getcwd))
      (let ((nyxt/file-manager-mode::filename
             (prompt-minibuffer :default-modes
                                '(nyxt/file-manager-mode:file-manager-mode
                                  nyxt/minibuffer-mode:minibuffer-mode)
                                :input-prompt (namestring (uiop/os:getcwd))
                                :suggestion-function
                                #'nyxt/file-manager-mode:open-file-from-directory-suggestion-filter)))
        (funcall nyxt/file-manager-mode:*open-file-function*
                 (namestring nyxt/file-manager-mode::filename)))))
enter-directory

If the suggestion at point is a directory, refresh the minibuffer suggestions with its list of files.

Default keybindings: `M-Right' and `C-j'. 

(define-command (&optional (minibuffer (current-minibuffer)))
    (let ((nyxt/file-manager-mode::filename (get-suggestion minibuffer)))
      (when
          (and
           (uiop/pathname:directory-pathname-p
            nyxt/file-manager-mode::filename)
           (uiop/filesystem:directory-exists-p
            nyxt/file-manager-mode::filename))
        (uiop/os:chdir nyxt/file-manager-mode::filename)
        (erase-input minibuffer)
        (update-display minibuffer))))
display-parent-directory

Get the parent directory and update the minibuffer.

Default keybindings: `M-Left' and `C-l'.

(define-command (&optional (minibuffer (current-minibuffer)))
    (uiop/os:chdir "..")
  (erase-input minibuffer)
  (update-display minibuffer))
file-manager-mode

Mode to open any file from the filesystem with fuzzy suggestion
on the minibuffer. Specialize keybindings on this mode. See the
command `open-file'.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command FILE-MANAGER-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/file-manager-mode:file-manager-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/file-manager-mode:user-file-manager-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/file-manager-mode:file-manager-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/file-manager-mode:file-manager-mode))))
  buffer)
nowebgl-mode

Disable WebGL in current buffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command NOWEBGL-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/nowebgl-mode:nowebgl-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/nowebgl-mode:user-nowebgl-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/nowebgl-mode:nowebgl-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/nowebgl-mode:nowebgl-mode))))
  buffer)
noscript-mode

Disable Javascript in current buffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command NOSCRIPT-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/noscript-mode:noscript-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/noscript-mode:user-noscript-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/noscript-mode:noscript-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/noscript-mode:noscript-mode))))
  buffer)
nosound-mode

Disable sound in current buffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command NOSOUND-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/nosound-mode:nosound-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/nosound-mode:user-nosound-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/nosound-mode:nosound-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/nosound-mode:nosound-mode))))
  buffer)
noimage-mode

Disable images in current buffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command NOIMAGE-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/noimage-mode:noimage-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/noimage-mode:user-noimage-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/noimage-mode:noimage-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/noimage-mode:noimage-mode))))
  buffer)
proxy-mode

Enable forwarding of all network requests to a specific host.
As for every mode, it only applies to the current buffer.  If you want to enable
a proxy for all buffers, add it to the list of default modes.

Example to use Tor as a proxy both for browsing and downloading:

(define-configuration nyxt/proxy-mode:proxy-mode
  ((nyxt/proxy-mode:proxy (make-instance 'proxy
                                         :server-address (quri:uri "socks5://localhost:9050")
                                         :allowlist '("localhost" "localhost:8080")
                                         :proxied-downloads-p t))))

(define-configuration buffer
  ((default-modes (append '(proxy-mode) %slot-default))))

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command PROXY-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/proxy-mode:proxy-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/proxy-mode:user-proxy-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/proxy-mode:proxy-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/proxy-mode:proxy-mode))))
  buffer)
blocker-mode

Enable blocking of listed hosts.
To customize the list of blocked hosts, set the `hostlists' slot.
See the `hostlist' class documentation.

Example:

(defvar *my-blocked-hosts*
  (nyxt/blocker-mode:make-hostlist
   :hosts '("platform.twitter.com"
            "syndication.twitter.com"
            "m.media-amazon.com")))

(define-mode my-blocker-mode (nyxt/blocker-mode:blocker-mode)
  "Blocker mode with custom hosts from `*my-blocked-hosts*'."
  ((nyxt/blocker-mode:hostlists (list *my-blocked-hosts* nyxt/blocker-mode:*default-hostlist*))))

(define-configuration buffer
  ((default-modes (append '(my-blocker-mode) %slot-default))))

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command BLOCKER-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/blocker-mode:blocker-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/blocker-mode:user-blocker-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/blocker-mode:blocker-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/blocker-mode:blocker-mode))))
  buffer)
vi-button1

Enable VI insert mode when focus is on an input element on the web page.

(define-command (&optional (buffer (current-buffer)))
    (ffi-generate-input-event (current-window) (last-event buffer))
  (let ((nyxt/vi-mode::response (nyxt/web-mode:%clicked-in-input?)))
    (cond
     ((and (nyxt/web-mode:input-tag-p nyxt/vi-mode::response)
           (find-submode buffer 'nyxt/vi-mode:vi-normal-mode))
      (nyxt/vi-mode:vi-insert-mode))
     ((and (not (nyxt/web-mode:input-tag-p nyxt/vi-mode::response))
           (find-submode buffer 'nyxt/vi-mode:vi-insert-mode))
      (nyxt/vi-mode:vi-normal-mode)))))
vi-insert-mode

Enable VI-style modal bindings (insert mode).
See `vi-normal-mode'.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command VI-INSERT-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/vi-mode:vi-insert-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/vi-mode:user-vi-insert-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/vi-mode:vi-insert-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/vi-mode:vi-insert-mode))))
  buffer)
vi-normal-mode

Enable VI-style modal bindings (normal mode).
To enable these bindings by default, add the mode to the list of default modes
in your configuration file.

Example:

(define-configuration buffer
  ((default-modes (append '(vi-normal-mode) %slot-default))))

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command VI-NORMAL-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/vi-mode:vi-normal-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/vi-mode:user-vi-normal-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/vi-mode:vi-normal-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/vi-mode:vi-normal-mode))))
  buffer)
emacs-mode

Enable Emacs-style bindings.
To enable these bindings by default, add the mode to the list of default modes
in your configuration file.

Example:

(define-configuration buffer
  ((default-modes (append '(emacs-mode) %slot-default))))

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command EMACS-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/emacs-mode:emacs-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/emacs-mode:user-emacs-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/emacs-mode:emacs-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/emacs-mode:emacs-mode))))
  buffer)
add-domain-to-certificate-exceptions

Add the current hostname to the buffer's certificate exception list.
This is only effective if `certificate-exception-mode' is enabled.

To make this change permanent, you can customize
`*default-certificate-exceptions*' in your init file:

(setf nyxt/certificate-exception-mode:*default-certificate-exceptions*
      '("nyxt.atlas.engineer" "example.org"))

(define-command (&optional (buffer (current-buffer)))
    (if (find-submode buffer
                      'nyxt/certificate-exception-mode:certificate-exception-mode)
        (let ((nyxt/certificate-exception-mode::input
               (prompt-minibuffer :input-prompt "URL host to exception list:"
                                  :suggestion-function
                                  (nyxt/certificate-exception-mode::previous-history-urls-suggestion-filter))))
          (unless
              (url-empty-p
               (url
                (history-tree:data nyxt/certificate-exception-mode::input)))
            (let ((nyxt/certificate-exception-mode::host
                   (quri.uri:uri-host
                    (url
                     (history-tree:data
                      nyxt/certificate-exception-mode::input)))))
              (echo "Added exception for ~s."
                    nyxt/certificate-exception-mode::host)
              (pushnew nyxt/certificate-exception-mode::host
                       (certificate-exceptions buffer) :test #'string=))))
        (echo "Enable certificate-exception-mode first.")))
certificate-exception-mode

Enable ignoring of certificate errors.
This can apply to specific buffers.
See the `add-domain-to-certificate-exceptions' command.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command CERTIFICATE-EXCEPTION-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer
                    'nyxt/certificate-exception-mode:certificate-exception-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/certificate-exception-mode:user-certificate-exception-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled."
                     'nyxt/certificate-exception-mode:certificate-exception-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/certificate-exception-mode:certificate-exception-mode))))
  buffer)
dark-mode

Mode for styling documents.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command DARK-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/style-mode:dark-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/style-mode:user-dark-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/style-mode:dark-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/style-mode:dark-mode))))
  buffer)
style-mode

Mode for styling documents.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command STYLE-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/style-mode:style-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/style-mode:user-style-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/style-mode:style-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/style-mode:style-mode))))
  buffer)
reading-line-cursor-down

Move the reading line cursor down. If scrolling off screen, move
the screen as well.

(define-command (&key (nyxt/reading-line-mode::step-size 20)
                 (buffer (current-buffer)))
    (pflet ((nyxt/reading-line-mode::cursor-down nil
             (let ((nyxt/reading-line-mode::original-position
                    (parenscript:chain
                     (nyxt/reading-line-mode::parse-int
                      (parenscript:@
                       (parenscript:chain nyxt/reading-line-mode::document
                                          (nyxt/reading-line-mode::query-selector
                                           "#reading-line-cursor"))
                       style nyxt/reading-line-mode::top)
                      10))))
               (setf (parenscript:@
                      (parenscript:chain nyxt/reading-line-mode::document
                                         (nyxt/reading-line-mode::query-selector
                                          "#reading-line-cursor"))
                      style nyxt/reading-line-mode::top)
                       (+
                        (+ nyxt/reading-line-mode::original-position
                           (parenscript:lisp
                            nyxt/reading-line-mode::step-size))
                        "px")))))
      (with-current-buffer buffer
        (nyxt/reading-line-mode::cursor-down)))
  (nyxt/reading-line-mode:jump-to-reading-line-cursor :buffer buffer))
reading-line-cursor-up

Move the reading line cursor up. If scrolling off screen, move the
screen as well.

(define-command (&key (nyxt/reading-line-mode::step-size 20)
                 (buffer (current-buffer)))
    (pflet ((nyxt/reading-line-mode::cursor-up nil
             (let ((nyxt/reading-line-mode::original-position
                    (parenscript:chain
                     (nyxt/reading-line-mode::parse-int
                      (parenscript:@
                       (parenscript:chain nyxt/reading-line-mode::document
                                          (nyxt/reading-line-mode::query-selector
                                           "#reading-line-cursor"))
                       style nyxt/reading-line-mode::top)
                      10))))
               (setf (parenscript:@
                      (parenscript:chain nyxt/reading-line-mode::document
                                         (nyxt/reading-line-mode::query-selector
                                          "#reading-line-cursor"))
                      style nyxt/reading-line-mode::top)
                       (+
                        (- nyxt/reading-line-mode::original-position
                           (parenscript:lisp
                            nyxt/reading-line-mode::step-size))
                        "px")))))
      (with-current-buffer buffer
        (nyxt/reading-line-mode::cursor-up)))
  (nyxt/reading-line-mode:jump-to-reading-line-cursor :buffer buffer))
jump-to-reading-line-cursor

Move the view port to show the reading line cursor.

(define-command (&key (buffer (current-buffer)))
    (pflet ((nyxt/reading-line-mode::jump-to-cursor nil
             (parenscript:chain
              (parenscript:chain nyxt/reading-line-mode::document
                                 (nyxt/reading-line-mode::query-selector
                                  "#reading-line-cursor"))
              (nyxt/reading-line-mode::scroll-into-view-if-needed))))
      (with-current-buffer buffer
        (nyxt/reading-line-mode::jump-to-cursor))))
reading-line-mode

Mode for drawing a line on screen that you can use to keep track of
your reading position. To use this mode, first enable this mode and
then use the bindings for `reading-line-cursor-up' and
`reading-line-cursor-down' to move the reading line cursor. If you
navigate away from the reading line, you can always invoke the command
`jump-to-reading-line-cursor' to jump back to your reading
position. To remove the reading line from the screen, disable this
mode.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command READING-LINE-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/reading-line-mode:reading-line-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/reading-line-mode:user-reading-line-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/reading-line-mode:reading-line-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/reading-line-mode:reading-line-mode))))
  buffer)
autofill

Fill in a field with a value from a saved list.

(define-command nil
    (let ((nyxt/web-mode::selected-fill
           (prompt-minibuffer :input-prompt "Autofill" :suggestion-function
                              (lambda (minibuffer)
                                (fuzzy-match (input-buffer minibuffer)
                                             (autofills *browser*))))))
      (cond
       ((stringp (autofill-fill nyxt/web-mode::selected-fill))
        (%paste :input-text (autofill-fill nyxt/web-mode::selected-fill)))
       ((functionp (autofill-fill nyxt/web-mode::selected-fill))
        (%paste :input-text
                (funcall (autofill-fill nyxt/web-mode::selected-fill)))))))
copy

Copy selected text to clipboard.

(define-command nil
    (let ((nyxt/web-mode::input (%copy)))
      (copy-to-clipboard nyxt/web-mode::input)
      (echo "Text copied.")))
paste-from-ring

Show `*browser*' clipboard ring and paste selected entry.

(define-command nil
    (let ((nyxt/web-mode::ring-item
           (prompt-minibuffer :suggestion-function
                              (nyxt/web-mode::ring-suggestion-filter
                               (clipboard-ring *browser*)))))
      (%paste :input-text nyxt/web-mode::ring-item)))
paste

Paste from clipboard into active-element.

(define-command nil
    (%paste))
buffer-history-tree

Open a new buffer displaying the whole history tree.

(define-command (&optional (buffer (current-buffer)))
    (labels ((nyxt/web-mode::traverse
                 (nyxt/web-mode::node nyxt/web-mode::current)
               (when nyxt/web-mode::node
                 `(:li
                   (:a :href
                    ,(object-string
                      (url (history-tree:data nyxt/web-mode::node)))
                    ,(let ((title
                            (or
                             (match (title
                                     (history-tree:data nyxt/web-mode::node))
                               ((guard nyxt/web-mode::e
                                 (not (str:emptyp nyxt/web-mode::e)))
                                nyxt/web-mode::e))
                             (object-display
                              (url (history-tree:data nyxt/web-mode::node))))))
                       (if (eq nyxt/web-mode::node nyxt/web-mode::current)
                           `(:b ,title)
                           title)))
                   ,(match (mapcar
                            (lambda (nyxt/web-mode::n)
                              (nyxt/web-mode::traverse nyxt/web-mode::n
                               nyxt/web-mode::current))
                            (history-tree:children nyxt/web-mode::node))
                      ((guard nyxt/web-mode::l nyxt/web-mode::l)
                       `(:ul ,@nyxt/web-mode::l)))))))
      (let* ((nyxt/web-mode::buffer-name
              (format nil "*History-~a*" (id buffer)))
             (nyxt/web-mode::output-buffer
              (or
               (find-if
                (lambda (nyxt/web-mode::b)
                  (string= nyxt/web-mode::buffer-name
                           (title nyxt/web-mode::b)))
                (buffer-list))
               (nyxt/help-mode:help-mode :activate t :buffer
                                         (make-internal-buffer :title
                                                               nyxt/web-mode::buffer-name))))
             (history (history (find-submode buffer 'nyxt/web-mode:web-mode)))
             (nyxt/web-mode::tree
              `(:ul
                ,(nyxt/web-mode::traverse (history-tree:root history)
                  (history-tree:current history))))
             (nyxt/web-mode::tree-style
              (cl-css:css
               '((nyxt/web-mode::body :line-height "initial")
                 (* :margin 0 :padding 0 :list-style "none")
                 ("ul li" :margin-left "15px" :position "relative"
                  :padding-left "5px")
                 ("ul li::before" :content "' '" :position "absolute" :width
                  "1px" :background-color "#000" :top "5px" :bottom "-12px"
                  :left "-10px")
                 ("body > ul > li:first-child::before" :top "12px")
                 ("ul li:not(:first-child):last-child::before" :display "none")
                 ("ul li:only-child::before" :display "list-item" :content
                  "' '" :position "absolute" :width "1px" :background-color
                  "#000" :top "5px" :bottom "7px" :height "7px" :left "-10px")
                 ("ul li::after" :content "' '" :position "absolute" :left
                  "-10px" :width "10px" :height "1px" :background-color "#000"
                  :top "12px"))))
             (nyxt/web-mode::content
              (cl-markup:markup
               (:body (:h1 "History")
                (:style (style nyxt/web-mode::output-buffer))
                (:style (cl-markup:raw nyxt/web-mode::tree-style))
                (:div
                 (cl-markup:raw (cl-markup:markup* nyxt/web-mode::tree))))))
             (nyxt/web-mode::insert-content
              (parenscript:ps
                (setf (parenscript:@ nyxt/web-mode::document
                       nyxt/web-mode::body nyxt/web-mode::|innerHTML|)
                        (parenscript:lisp nyxt/web-mode::content)))))
        (ffi-buffer-evaluate-javascript-async nyxt/web-mode::output-buffer
                                              nyxt/web-mode::insert-content)
        (set-current-buffer nyxt/web-mode::output-buffer))))
history-all-query

Query URL to go to, from the whole history.

(define-command nil
    (let ((nyxt/web-mode::input
           (prompt-minibuffer :input-prompt "Navigate to" :suggestion-function
                              (nyxt/web-mode::history-all-suggestion-filter))))
      (when nyxt/web-mode::input
        (nyxt/web-mode::set-url-from-history nyxt/web-mode::input))))
history-forwards-all-query

Query URL to forward to, from all child branches.

(define-command nil
    (let ((nyxt/web-mode::input
           (prompt-minibuffer :input-prompt
                              "Navigate forwards to (all branches)"
                              :suggestion-function
                              (nyxt/web-mode::history-forwards-all-suggestion-filter))))
      (when nyxt/web-mode::input
        (nyxt/web-mode::set-url-from-history nyxt/web-mode::input))))
history-forwards-maybe-query

If current node has multiple chidren, query forward-URL to navigate to.
Otherwise go forward to the only child.

(define-command (&optional
                 (nyxt/web-mode::mode
                  (find-submode (current-buffer) 'nyxt/web-mode:web-mode)))
    (if (<= 2
            (length
             (history-tree:children-nodes (history nyxt/web-mode::mode))))
        (nyxt/web-mode:history-forwards-all-query)
        (nyxt/web-mode:history-forwards)))
history-forwards-query

Query forward-URL to navigate to.

(define-command nil
    (let ((nyxt/web-mode::input
           (prompt-minibuffer :input-prompt "Navigate forwards to"
                              :suggestion-function
                              (nyxt/web-mode::history-forwards-suggestion-filter))))
      (when nyxt/web-mode::input
        (nyxt/web-mode::set-url-from-history nyxt/web-mode::input))))
history-backwards-query

Query parent URL to navigate back to.

(define-command nil
    (let ((nyxt/web-mode::input
           (prompt-minibuffer :input-prompt "Navigate backwards to"
                              :suggestion-function
                              (nyxt/web-mode::history-backwards-suggestion-filter))))
      (when nyxt/web-mode::input
        (nyxt/web-mode::set-url-from-history nyxt/web-mode::input))))
history-forwards

Go to forward URL in history.

(define-command (&optional (buffer (current-buffer)))
    (let* ((nyxt/web-mode::mode (find-submode buffer 'nyxt/web-mode:web-mode)))
      (if (history-tree:children-nodes (history nyxt/web-mode::mode))
          (progn
           (history-tree:forward (history nyxt/web-mode::mode))
           (match (history-tree:current (history nyxt/web-mode::mode))
             ((guard nyxt/web-mode::n nyxt/web-mode::n)
              (buffer-load (url (history-tree:data nyxt/web-mode::n))))))
          (echo "No forward history."))))
history-backwards

Go to parent URL in history.

(define-command (&optional (buffer (current-buffer)))
    (let* ((nyxt/web-mode::mode (find-submode buffer 'nyxt/web-mode:web-mode)))
      (if (eq (history-tree:root (history nyxt/web-mode::mode))
              (history-tree:current (history nyxt/web-mode::mode)))
          (echo "No backward history.")
          (progn
           (history-tree:back (history nyxt/web-mode::mode))
           (match (history-tree:current (history nyxt/web-mode::mode))
             ((guard nyxt/web-mode::n nyxt/web-mode::n)
              (buffer-load (url (history-tree:data nyxt/web-mode::n)))))))))
maybe-scroll-to-top

Scroll to top if no input element is active, forward event otherwise.

(define-command (&optional (buffer (current-buffer)))
    (nyxt/web-mode::call-non-input-command-or-forward
     #'nyxt/web-mode:scroll-to-top :buffer buffer))
maybe-scroll-to-bottom

Scroll to bottom if no input element is active, forward event otherwise.

(define-command (&optional (buffer (current-buffer)))
    (nyxt/web-mode::call-non-input-command-or-forward
     #'nyxt/web-mode:scroll-to-bottom :buffer buffer))
paste-or-set-url

Paste text if active element is an input tag, forward event otherwise.

(define-command (&optional (buffer (current-buffer)))
    (let ((nyxt/web-mode::response (nyxt/web-mode:%clicked-in-input?)))
      (let ((nyxt/web-mode::url-empty (url-empty-p (url-at-point buffer))))
        (if (and (nyxt/web-mode:input-tag-p nyxt/web-mode::response)
                 nyxt/web-mode::url-empty)
            (funcall-safely #'nyxt/web-mode:paste)
            (unless nyxt/web-mode::url-empty
              (make-buffer-focus :url (url-at-point buffer)))))))
web-mode

Base mode for interacting with documents.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command WEB-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/web-mode:web-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/web-mode:user-web-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/web-mode:web-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/web-mode:web-mode))))
  buffer)
application-mode

Mode that forwards all keys to the renderer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command APPLICATION-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/application-mode:application-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/application-mode:user-application-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/application-mode:application-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/application-mode:application-mode))))
  buffer)
clear-messages

Clear the *Messages* buffer.

(define-command nil
    (setf (messages-content *browser*) 'nil)
  (echo "Messages cleared."))
message-mode

Mode for log and message listing.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command MESSAGE-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/message-mode:message-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/message-mode:user-message-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/message-mode:message-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/message-mode:message-mode))))
  buffer)
help-mode

Mode for displaying documentation.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command HELP-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/help-mode:help-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/help-mode:user-help-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/help-mode:help-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/help-mode:help-mode))))
  buffer)
lisp-repl

Show Lisp REPL.

(define-command nil
    (let* ((repl-buffer
            (make-buffer :title "*Lisp REPL*" :modes
                         '(nyxt/repl-mode:repl-mode base-mode))))
      (set-current-buffer repl-buffer)
      repl-buffer))
self-insert-repl

Insert pressed key in the current REPL.

(define-command nil
    (nyxt/minibuffer-mode:self-insert (nyxt/repl-mode::current-repl)))
return-input

Return inputted text.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (let ((nyxt/repl-mode::input
           (str:replace-all " " " "
                            (text-buffer::string-representation
                             (input-buffer nyxt/repl-mode::repl)))))
      (nyxt/repl-mode::add-object-to-evaluation-history nyxt/repl-mode::repl
                                                        (format nil "> ~a"
                                                                nyxt/repl-mode::input))
      (dolist (nyxt/repl-mode::result (evaluate nyxt/repl-mode::input))
        (nyxt/repl-mode::add-object-to-evaluation-history nyxt/repl-mode::repl
                                                          nyxt/repl-mode::result))
      (text-buffer::kill-line (input-cursor nyxt/repl-mode::repl))
      (update-display nyxt/repl-mode::repl)))
kill-line

Delete forwards a word.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::kill-forward-line (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
delete-forwards-word

Delete forwards a word.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::delete-forward-word (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
delete-backwards-word

Delete backwards a word.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::delete-backward-word (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-backwards-word

Move cursor backwards a word.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::move-backward-word (input-cursor nyxt/repl-mode::repl)
                                     :conservative-word-move
                                     (conservative-word-move (current-buffer)))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-forwards-word

Move cursor forwards a word.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::move-forward-word (input-cursor nyxt/repl-mode::repl)
                                    :conservative-word-move
                                    (conservative-word-move (current-buffer)))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-end

Move cursor to the end of the buffer.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (cluffer:end-of-line (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-beginning

Move cursor to the beginning of the buffer.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (cluffer:beginning-of-line (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
delete-backwards

Delete character before cursor.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::delete-item-backward (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
delete-forwards

Delete character after cursor.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (cluffer:delete-item (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-backwards

Move cursor backwards by one element.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::safe-backward (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
cursor-forwards

Move cursor forward by one element.

(define-command (&optional
                 (nyxt/repl-mode::repl (nyxt/repl-mode::current-repl)))
    (text-buffer::safe-forward (input-cursor nyxt/repl-mode::repl))
  (update-input-buffer-display nyxt/repl-mode::repl))
repl-mode

Mode for interacting with the REPL.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command REPL-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/repl-mode:repl-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/repl-mode:user-repl-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/repl-mode:repl-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/repl-mode:repl-mode))))
  buffer)
list-buffers

Show the *Buffers* buffer.

(define-command (&key (cluster nil))
    (labels ((cluster-buffers ()
               "Return buffers as hash table, where each value is a cluster (list of documents)."
               (let ((collection
                      (make-instance 'analysis::document-collection)))
                 (loop for buffer in (buffer-list)
                       unless (internal-buffer-p buffer)
                       do (with-current-buffer buffer
                            (analysis::add-document collection
                                                    (make-instance
                                                     'analysis::document-cluster
                                                     :source buffer
                                                     :string-contents
                                                     (document-get-paragraph-contents)))))
                 (analysis::tf-vectorize-documents collection)
                 (analysis::generate-document-distance-vectors collection)
                 (analysis::dbscan collection :minimum-points 3 :epsilon 0.065)
                 (analysis::clusters collection)))
             (buffer-markup (buffer)
               "Create the presentation for a buffer."
               (cl-markup:markup
                (:p
                 (:a :class "button" :href
                  (lisp-url `(delete-buffer :id ,(id buffer))) "✕")
                 (:a :class "button" :href
                  (lisp-url `(switch-buffer :id ,(id buffer))) "→")
                 (:span (title buffer) " - " (quri:render-uri (url buffer))))))
             (cluster-markup (cluster-id cluster)
               "Create the presentation for a cluster."
               (cl-markup:markup
                (:div (:h2 (format nil "Cluster ~a" cluster-id))
                 (loop for document in cluster
                       collect (buffer-markup (analysis::source document))))))
             (internal-buffers-markup ()
               "Create the presentation for the internal buffers."
               (cl-markup:markup
                (:div (:h2 "Internal Buffers")
                 (loop for buffer in (buffer-list)
                       when (internal-buffer-p buffer)
                       collect (buffer-markup buffer))))))
      (with-current-html-buffer (buffer "*Buffers*"
                                        'nyxt/buffer-listing-mode:buffer-listing-mode)
        (cl-markup:markup (:style (style buffer)) (:h1 "Buffers")
                          (:a :class "button" :href (lisp-url '(list-buffers))
                           "Update")
                          (:br "")
                          (:div
                           (if cluster
                               (append (list (internal-buffers-markup))
                                       (loop for cluster-key being the hash-key using (hash-value
                                                                                       cluster) of (cluster-buffers)
                                             collect (cluster-markup
                                                      cluster-key cluster)))
                               (loop for buffer in (buffer-list)
                                     collect (buffer-markup buffer))))))))
base-mode

Mode that does nothing but bind the general-purpose key bindings.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command BASE-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'base-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'user-base-mode :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'base-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'base-mode))))
  buffer)
buffer-listing-mode

Mode for buffer-listing.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command BUFFER-LISTING-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/buffer-listing-mode:buffer-listing-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/buffer-listing-mode:user-buffer-listing-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled."
                     'nyxt/buffer-listing-mode:buffer-listing-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled."
                     'nyxt/buffer-listing-mode:buffer-listing-mode))))
  buffer)
add-distribution

Add a new Quicklisp distribution.

(define-command nil
    (let ((url
           (prompt-minibuffer :input-prompt "New distribution URL"
                              :must-match-p nil)))
      (ql-dist:install-dist url :prompt nil)))
load-system

Load a system from Quicklisp.

(define-command nil
    (let ((system
           (prompt-minibuffer :input-prompt "Load system" :suggestion-function
                              (lambda (minibuffer)
                                (fuzzy-match (input-buffer minibuffer)
                                             (mapcar
                                              #'ql-dist:short-description
                                              (quicklisp-client:system-list))))
                              :must-match-p t)))
      (quicklisp-client:quickload system)))
list-systems

List systems available via Quicklisp.

(define-command nil
    (with-current-html-buffer (buffer "*Systems*" 'base-mode)
      (cl-markup:markup (:style (style buffer)) (:h1 "Systems")
                        (:p "Listing of all available Quicklisp systems.")
                        (:body
                         (loop for system in (quicklisp-client:system-list)
                               collect (let ((name
                                              (ql-dist:short-description
                                               system))
                                             (size
                                              (format nil "~a"
                                                      (ql-dist:archive-size
                                                       (ql-dist:preference-parent
                                                        system))))
                                             (dependencies
                                              (format nil "~a"
                                                      (ql-dist:required-systems
                                                       system))))
                                         (cl-markup:markup
                                          (:div (:h2 name) (:p "Size: " size)
                                           (:p "Requires: " dependencies)
                                           (:p
                                            (:a :class "button" :href
                                             (lisp-url
                                              `(quicklisp-client:quickload
                                                ,name))
                                             "Load"))
                                           (:hr)))))))))
fill-input-from-external-editor

This command will open your editor specified by your VISUAL-EDITOR
  of the BROWSER class, if unset, it will default to your VISUAL
  environment variable. It will then capture whatever text you enter
  and save in your editor.

(define-command nil
    (bordeaux-threads:make-thread
     (lambda ()
       (let ((text (get-text-from-external-editor)))
         (ffi-within-renderer-thread *browser*
                                     (lambda () (%paste :input-text text)))))))
save-exact-modes-for-future-visits

Store the exact list of enabled modes to auto-mode rules for all the future visits of this
domain/host/URL/group of websites inferring the suitable matching condition by user input.
Uses `url-infer-match', see its documentation for matching rules.

For the storage format see the comment in the head of your `auto-mode-rules-data-path' file.

(define-command nil
    (let ((url
           (prompt-minibuffer :input-prompt "URL:" :input-buffer
                              (object-string (url (current-buffer)))
                              :suggestion-function
                              (history-suggestion-filter :prefix-urls
                                                         (list
                                                          (object-string
                                                           (url
                                                            (current-buffer)))))
                              :history (minibuffer-set-url-history *browser*)
                              :must-match-p nil)))
      (when (typep url 'history-entry) (setf url (url url)))
      (nyxt/auto-mode:add-modes-to-auto-mode-rules
       (nyxt/auto-mode::url-infer-match url) :include (modes (current-buffer))
       :exact-p t)))
save-non-default-modes-for-future-visits

Save the modes present in `default-modes' and not present in current modes as :excluded,
and modes that are present in mode list but not in `default-modes' as :included,
to one of auto-mode rules. Apply the resulting rule for all the future visits to this URL,
inferring the matching condition with `url-infer-match'.

For the storage format see the comment in the head of your `auto-mode-rules-data-path' file.

(define-command nil
    (let ((url
           (prompt-minibuffer :input-prompt "URL:" :input-buffer
                              (object-string (url (current-buffer)))
                              :suggestion-function
                              (history-suggestion-filter :prefix-urls
                                                         (list
                                                          (object-string
                                                           (url
                                                            (current-buffer)))))
                              :history (minibuffer-set-url-history *browser*)
                              :must-match-p nil)))
      (when (typep url 'history-entry) (setf url (url url)))
      (nyxt/auto-mode:add-modes-to-auto-mode-rules
       (nyxt/auto-mode::url-infer-match url) :include
       (set-difference (modes (current-buffer))
                       (default-modes (current-buffer)) :test
                       #'nyxt/auto-mode::mode-equal)
       :exclude
       (set-difference (default-modes (current-buffer))
                       (modes (current-buffer)) :test
                       #'nyxt/auto-mode::mode-equal))))
auto-mode

Remember the modes setup for given domain/host/URL and store it in an editable form.
These modes will then be activated on every visit to this domain/host/URL.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command AUTO-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'nyxt/auto-mode:auto-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/auto-mode:user-auto-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/auto-mode:auto-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/auto-mode:auto-mode))))
  buffer)
delete-history-entry

Delete queried history entries.

(define-command nil
    (with-data-access (history (history-path (current-buffer)))
      (let ((entries
             (prompt-minibuffer :input-prompt "Delete entries"
                                :suggestion-function
                                (history-suggestion-filter) :history
                                (minibuffer-set-url-history *browser*)
                                :multi-selection-p t)))
        (dolist (entry entries)
          (remhash (object-string (url entry)) history)))))
import-bookmarks-from-html

Import bookmarks from an HTML file.

(define-command nil
    (let ((html-file
           (prompt-minibuffer :default-modes
                              '(nyxt/file-manager-mode:file-manager-mode
                                minibuffer-mode)
                              :input-prompt "Path to the HTML file"
                              :suggestion-function
                              #'nyxt/file-manager-mode:open-file-from-directory-suggestion-filter
                              :must-match-p nil)))
      (if (and (uiop/filesystem:file-exists-p html-file)
               (equal (pathname-type html-file) "html"))
          (with-open-file (in-html html-file :external-format :utf-8)
            (let ((a-tags
                   (plump-dom:get-elements-by-tag-name
                    (plump-parser:parse in-html) "a")))
              (dolist (a-tag a-tags)
                (let* ((url (plump-dom:attribute a-tag "href"))
                       (title (plump-dom:render-text a-tag))
                       (date (plump-dom:attribute a-tag "add_date"))
                       (tags (plump-dom:attribute a-tag "tags"))
                       (url-uri (quri.uri:uri url)))
                  (when (str:starts-with? "http" (quri.uri:uri-scheme url-uri))
                    (bookmark-add url-uri :title title :date
                                  (ignore-errors
                                   (local-time:unix-to-timestamp
                                    (parse-integer date)))
                                  :tags (when tags (str:split "," tags))))))))
          (echo "The file doesn't exist or is not an HTML file."))))
set-url-from-bookmark-new-buffer

Open selected bookmarks in new buffers.

(define-command nil
    (let ((entries
           (prompt-minibuffer :input-prompt "Open bookmarks in new buffers"
                              :default-modes
                              '(minibuffer-tag-mode minibuffer-mode)
                              :suggestion-function (bookmark-suggestion-filter)
                              :multi-selection-p t)))
      (dolist (entry (rest entries))
        (make-buffer :url (object-string (url entry))))
      (make-buffer-focus :url (url (first entries)))))
set-url-from-bookmark

Set the URL for the current buffer from a bookmark.
With multiple selections, open the first bookmark in the current buffer, the
rest in background buffers.

(define-command nil
    (let ((entries
           (prompt-minibuffer :input-prompt "Open bookmark(s)" :default-modes
                              '(minibuffer-tag-mode minibuffer-mode)
                              :suggestion-function (bookmark-suggestion-filter)
                              :multi-selection-p t)))
      (dolist (entry (rest entries))
        (make-buffer :url (object-string (url entry))))
      (buffer-load (url (first entries)))))
minibuffer-tag-mode

Minibuffer mode for setting the bookmark and their tags.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command MINIBUFFER-TAG-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'minibuffer-tag-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'user-minibuffer-tag-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'minibuffer-tag-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'minibuffer-tag-mode))))
  buffer)
insert-suggestion-or-tag

Paste selected suggestion or tag in input.
If character before cursor is '+' or '-' complete against tag.

(define-command (&optional (minibuffer (current-minibuffer)))
    (let* ((current-word
            (text-buffer::word-at-cursor (input-cursor minibuffer)))
           (operand?
            (unless (str:emptyp current-word) (subseq current-word 0 1))))
      (if (or (equal "-" operand?) (equal "+" operand?))
          (let ((tag
                 (prompt-minibuffer :input-prompt "Tag" :input-buffer
                                    (subseq current-word 1)
                                    :suggestion-function
                                    (tag-suggestion-filter))))
            (when tag
              (text-buffer::replace-word-at-cursor (input-cursor minibuffer)
                                                   (str:concat operand?
                                                               (tag-name
                                                                tag)))))
          (nyxt/minibuffer-mode:insert-suggestion minibuffer))))
bookmark-delete

Delete bookmark(s).

(define-command nil
    (with-data-access (bookmarks (bookmarks-path (current-buffer)))
      (let ((entries
             (prompt-minibuffer :input-prompt "Delete bookmark(s)"
                                :multi-selection-p t :default-modes
                                '(minibuffer-tag-mode minibuffer-mode)
                                :suggestion-function
                                (bookmark-suggestion-filter))))
        (setf bookmarks (set-difference bookmarks entries :test #'equals)))))
bookmark-url

Allow the user to bookmark a URL via minibuffer input.

(define-command nil
    (let ((url (prompt-minibuffer :input-prompt "Bookmark URL")))
      (if (not (valid-url-p url))
          (echo "Invalid URL")
          (let* ((url (quri.uri:uri url))
                 (tags
                  (prompt-minibuffer :input-prompt "Space-separated tag(s)"
                                     :default-modes
                                     '(set-tag-mode minibuffer-mode)
                                     :input-buffer (url-bookmark-tags url)
                                     :suggestion-function
                                     (tag-suggestion-filter))))
            (bookmark-add url :tags tags)))))
bookmark-page

Bookmark the currently opened page(s) in the active buffer.

(define-command nil
    (let ((buffers
           (prompt-minibuffer :input-prompt "Bookmark URL from buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (mapc #'bookmark-current-page buffers)))
bookmark-current-page

Bookmark the URL of BUFFER.

(define-command (&optional (buffer (current-buffer)))
    (flet ((extract-keywords (html limit)
             (sera:take limit
                        (delete ""
                                (mapcar #'first
                                        (analysis:keywords
                                         (make-instance 'analysis:document
                                                        :string-contents
                                                        (plump-dom:text
                                                         (plump-parser:parse
                                                          html)))))
                                :test #'string=)))
           (make-tags (name-list)
             (mapcar
              (lambda (name) (make-tag :name name :description "suggestion"))
              name-list)))
      (if (url-empty-p (url buffer))
          (echo "Buffer has no URL.")
          (let* ((body
                  (with-current-buffer buffer
                    (document-get-body)))
                 (tags
                  (prompt-minibuffer :input-prompt "Space-separated tag(s)"
                                     :default-modes
                                     '(set-tag-mode minibuffer-mode)
                                     :input-buffer
                                     (url-bookmark-tags (url buffer))
                                     :suggestion-function
                                     (tag-suggestion-filter :extra-tags
                                                            (make-tags
                                                             (extract-keywords
                                                              body 5))))))
            (bookmark-add (url buffer) :title (title buffer) :tags tags)
            (echo "Bookmarked ~a." (object-display (url buffer)))))))
list-bookmarks

List all bookmarks in a new buffer.

(define-command nil
    (with-current-html-buffer (bookmarks-buffer "*Bookmarks*" 'base-mode)
      (cl-markup:markup (:style (style bookmarks-buffer)) (:h1 "Bookmarks")
                        (:body
                         (loop for bookmark in (get-data
                                                (bookmarks-path
                                                 (current-buffer)))
                               collect (let ((url-display
                                              (object-display (url bookmark)))
                                             (url-href
                                              (object-string (url bookmark))))
                                         (cl-markup:markup
                                          (:div
                                           (:p (:b "Title: ") (title bookmark))
                                           (:p (:b "URL: ")
                                            (:a :href url-href url-display))
                                           (:p (:b "Tags: ")
                                            (when (tags bookmark)
                                              (format nil " (~{~a~^, ~})"
                                                      (tags bookmark))))
                                           (:p
                                            (:a :class "button" :href
                                             (lisp-url
                                              `(delete-bookmark ,url-href))
                                             "Delete"))
                                           (:hr "")))))))))
set-tag-mode

Minibuffer mode for setting the tag of a bookmark.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command SET-TAG-MODE called on non-buffer"))
  (let ((#:existing-instance0 (find-mode buffer 'set-tag-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'user-set-tag-mode :buffer buffer
                        args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'set-tag-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'set-tag-mode))))
  buffer)
insert-tag

Replace current word with selected tag.

(define-command (&optional (minibuffer (current-minibuffer)))
    (let ((selection (get-suggestion minibuffer)))
      (unless (uiop/utility:emptyp selection)
        (text-buffer::replace-word-at-cursor (input-cursor minibuffer)
                                             (str:concat selection " "))
        (update-display minibuffer))))
copy-password

Copy chosen password from minibuffer.

(define-command nil
    (password-debug-info)
  (if (password-interface *browser*)
      (with-password (password-interface *browser*)
        (let ((password-name
               (prompt-minibuffer :suggestion-function
                                  (password-suggestion-filter
                                   (password-interface *browser*)))))
          (password:clip-password (password-interface *browser*) :password-name
                                  password-name)
          (echo "Password saved to clipboard for ~a seconds."
                password:*sleep-timer*)))
      (echo-warning "No password manager found.")))
copy-password-prompt-details

Copy password prompting for all the details without suggestion.

(define-command nil
    (password-debug-info)
  (if (password-interface *browser*)
      (let* ((password-name
              (prompt-minibuffer :input-prompt "Name of password"))
             (service (prompt-minibuffer :input-prompt "Service")))
        (handler-case
         (password:clip-password (password-interface *browser*) :password-name
                                 password-name :service service)
         (error (c) (echo-warning "Error retrieving password: ~a" c))))
      (echo-warning "No password manager found.")))
save-new-password

Save password to password interface.

(define-command nil
    (password-debug-info)
  (cond
   ((and (password-interface *browser*)
         (has-method-p (password-interface *browser*)
                       #'password:save-password))
    (let* ((password-name
            (prompt-minibuffer :input-prompt "Name for new password"
                               :input-buffer
                               (or
                                (quri.domain:uri-domain (url (current-buffer)))
                                "")))
           (new-password
            (prompt-minibuffer :invisible-input-p t :input-prompt
                               "New password (leave empty to generate)")))
      (password:save-password (password-interface *browser*) :password-name
                              password-name :password new-password)))
   ((null (password-interface *browser*))
    (echo-warning "No password manager found."))
   (t
    (echo-warning "Password manager ~s does not support saving passwords."
                  (string-downcase
                   (class-name (class-of (password-interface *browser*))))))))
reopen-last-buffer

Open a new buffer with the URL of the most recently deleted buffer.

(define-command nil
    (if (plusp (metabang.utilities:size (recent-buffers *browser*)))
        (let ((buffer
               (buffer-make *browser* :dead-buffer
                            (metabang.cl-containers:delete-first
                             (recent-buffers *browser*)))))
          (reload-current-buffer buffer)
          (when (focus-on-reopened-buffer-p *browser*)
            (set-current-buffer buffer)))
        (echo "There are no recently-deleted buffers.")))
reopen-buffer

Reopen queried deleted buffer(s).

(define-command nil
    (let ((buffers
           (prompt-minibuffer :input-prompt "Reopen buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (recent-buffer-suggestion-filter))))
      (dolist (buffer buffers)
        (metabang.cl-containers:delete-item-if (recent-buffers *browser*)
                                               (buffer-match-predicate buffer))
        (reload-current-buffer (buffer-make *browser* :dead-buffer buffer))
        (when
            (and (eq buffer (first buffers))
                 (focus-on-reopened-buffer-p *browser*))
          (set-current-buffer buffer)))))
enable-hook-handler

Remove handler(s) from a hook.

(define-command nil
    (let* ((hook-desc
            (prompt-minibuffer :input-prompt "Hook where to enable handler"
                               :suggestion-function (hook-suggestion-filter)))
           (handler
            (prompt-minibuffer :input-prompt
                               (format nil "Enable handler from ~a"
                                       (name hook-desc))
                               :suggestion-function
                               (disabled-handler-suggestion-filter
                                (value hook-desc)))))
      (hooks:enable-hook (value hook-desc) handler)))
disable-hook-handler

Remove handler(s) from a hook.

(define-command nil
    (let* ((hook-desc
            (prompt-minibuffer :input-prompt "Hook where to disable handler"
                               :suggestion-function (hook-suggestion-filter)))
           (handler
            (prompt-minibuffer :input-prompt
                               (format nil "Disable handler from ~a"
                                       (name hook-desc))
                               :suggestion-function
                               (handler-suggestion-filter (value hook-desc)))))
      (hooks:disable-hook (value hook-desc) handler)))
execute-extended-command

Execute a command by name, also supply required, optional, and
keyword parameters.

(define-command nil
    (let* ((command
            (prompt-minibuffer :input-prompt "Execute extended command"
                               :suggestion-function
                               (command-suggestion-filter
                                (mapcar #'mode-name (modes (current-buffer))))
                               :hide-suggestion-count-p t))
           (command-symbol (sym command))
           (argument-list (swank/backend:arglist command-symbol))
           (required-arguments
            (nth-value 0 (alex:parse-ordinary-lambda-list argument-list)))
           (optional-arguments
            (nth-value 1 (alex:parse-ordinary-lambda-list argument-list)))
           (key-arguments
            (nth-value 3 (alex:parse-ordinary-lambda-list argument-list))))
      (apply command-symbol
             (append
              (when required-arguments
                (loop for argument in required-arguments
                      collect (read-from-string
                               (prompt-minibuffer :input-prompt argument))))
              (when optional-arguments
                (loop for argument in optional-arguments
                      collect (read-from-string
                               (prompt-minibuffer :input-prompt
                                                  (first argument)))))
              (when key-arguments
                (loop for argument in key-arguments
                      collect (first (car argument))
                      collect (read-from-string
                               (prompt-minibuffer :input-prompt
                                                  (second (car argument))))))))
      (setf (access-time command) (get-internal-real-time))))
execute-command

Execute a command by name.

(define-command nil
    (unless (active-minibuffers (current-window))
      (let ((command
             (prompt-minibuffer :input-prompt "Execute command"
                                :suggestion-function
                                (command-suggestion-filter
                                 (mapcar #'mode-name (modes (current-buffer))))
                                :hide-suggestion-count-p t)))
        (setf (access-time command) (get-internal-real-time))
        (run-async command))))
minibuffer-toggle-mark-all

Toggle the mark over all visible suggestions.
Only available if minibuffer `multi-selection-p' is non-nil.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when (multi-selection-p minibuffer)
      (with-slots ((nyxt/minibuffer-mode::suggestions suggestions)
                   (nyxt/minibuffer-mode::marked-suggestions
                    marked-suggestions))
          minibuffer
        (cond
         ((subsetp nyxt/minibuffer-mode::marked-suggestions
                   nyxt/minibuffer-mode::suggestions)
          (setf nyxt/minibuffer-mode::marked-suggestions
                  (set-difference nyxt/minibuffer-mode::suggestions
                                  nyxt/minibuffer-mode::marked-suggestions)))
         ((subsetp nyxt/minibuffer-mode::suggestions
                   nyxt/minibuffer-mode::marked-suggestions)
          (setf nyxt/minibuffer-mode::marked-suggestions
                  (set-difference nyxt/minibuffer-mode::marked-suggestions
                                  nyxt/minibuffer-mode::suggestions)))
         (t
          (setf nyxt/minibuffer-mode::marked-suggestions
                  (union nyxt/minibuffer-mode::suggestions
                         nyxt/minibuffer-mode::marked-suggestions))))))
  (state-changed minibuffer)
  (update-display minibuffer))
minibuffer-unmark-all

Unmark all visible suggestions.
Only available if minibuffer `multi-selection-p' is non-nil.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when (multi-selection-p minibuffer)
      (with-slots (suggestions marked-suggestions)
          minibuffer
        (setf marked-suggestions
                (set-difference marked-suggestions suggestions)))
      (state-changed minibuffer)
      (update-display minibuffer)))
minibuffer-mark-all

Mark all visible suggestions.
Only available if minibuffer `multi-selection-p' is non-nil.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when (multi-selection-p minibuffer)
      (with-slots (suggestions marked-suggestions)
          minibuffer
        (setf marked-suggestions (union suggestions marked-suggestions)))
      (state-changed minibuffer)
      (update-display minibuffer)))
minibuffer-toggle-mark-backwards

Toggle suggestion and select previous suggestion.
See `minibuffer-toggle-mark'. 

(define-command (&key (minibuffer (current-minibuffer)))
    (nyxt/minibuffer-mode:minibuffer-toggle-mark :minibuffer minibuffer
                                                 :direction :previous))
minibuffer-toggle-mark

Toggle suggestion.
Only available if minibuffer `multi-selection-p' is non-nil.  DIRECTION can be
:next or :previous and specifies which suggestion to select once done.

(define-command (&key (minibuffer (current-minibuffer))
                 (nyxt/minibuffer-mode::direction :next))
    (when (multi-selection-p minibuffer)
      (with-slots (suggestions suggestion-cursor marked-suggestions)
          minibuffer
        (let ((nyxt/minibuffer-mode::suggestion
               (nth suggestion-cursor suggestions)))
          (match (member nyxt/minibuffer-mode::suggestion marked-suggestions)
            ((guard nyxt/minibuffer-mode::n nyxt/minibuffer-mode::n)
             (setf marked-suggestions
                     (delete nyxt/minibuffer-mode::suggestion
                             marked-suggestions)))
            (nyxt/minibuffer-mode::_
             (push nyxt/minibuffer-mode::suggestion marked-suggestions)))))
      (state-changed minibuffer)
      (update-display minibuffer)
      (match nyxt/minibuffer-mode::direction
        (:next (nyxt/minibuffer-mode:select-next minibuffer))
        (:previous (nyxt/minibuffer-mode:select-previous minibuffer)))))
minibuffer-history

Choose a minibuffer input history entry to insert as input.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when (history minibuffer)
      (let ((nyxt/minibuffer-mode::input
             (object-string
              (prompt-minibuffer :input-prompt "Input history" :history nil
                                 :suggestion-function
                                 (nyxt/minibuffer-mode::minibuffer-history-suggestion-filter
                                  (history minibuffer))))))
        (unless (str:empty? nyxt/minibuffer-mode::input)
          (log:debug nyxt/minibuffer-mode::input minibuffer)
          (text-buffer::kill-line (input-cursor minibuffer))
          (insert minibuffer nyxt/minibuffer-mode::input)))))
insert-suggestion

Paste selected suggestion to input.
As a special case, if the inserted suggestion is a URI, we decode it to make it
readable.

(define-command (&optional (minibuffer (current-minibuffer)))
    (let ((nyxt/minibuffer-mode::suggestion (get-suggestion minibuffer)))
      (when nyxt/minibuffer-mode::suggestion
        (nyxt/minibuffer-mode:kill-whole-line minibuffer)
        (insert minibuffer
                (if (valid-url-p nyxt/minibuffer-mode::suggestion)
                    (quri.decode:url-decode nyxt/minibuffer-mode::suggestion
                                            :lenient t)
                    nyxt/minibuffer-mode::suggestion)))))
copy-suggestion

Copy suggestion to clipboard.

(define-command (&optional (minibuffer (current-minibuffer)))
    (let ((nyxt/minibuffer-mode::suggestion
           (if (and (multi-selection-p minibuffer)
                    (not (null (marked-suggestions minibuffer))))
               (str:join (string #\Newline)
                         (get-marked-suggestions minibuffer))
               (get-suggestion minibuffer))))
      (unless (str:emptyp nyxt/minibuffer-mode::suggestion)
        (trivial-clipboard:text nyxt/minibuffer-mode::suggestion))))
minibuffer-paste

Paste clipboard text to input.

(define-command (&optional (minibuffer (current-minibuffer)))
    (bordeaux-threads:make-thread
     (lambda ()
       (trivial-clipboard:text
        (or (ignore-errors (trivial-clipboard:text)) ""))
       (ffi-within-renderer-thread *browser*
                                   (lambda ()
                                     (insert minibuffer
                                             (ring-insert-clipboard
                                              (clipboard-ring *browser*))))))))
select-previous

Select previous entry in minibuffer.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when (> (suggestion-cursor minibuffer) 0)
      (decf (suggestion-cursor minibuffer))
      (state-changed minibuffer)
      (update-suggestions-display minibuffer)
      (evaluate-script minibuffer
                       (parenscript:ps
                         (parenscript:chain
                          (parenscript:chain nyxt/minibuffer-mode::document
                                             (nyxt/minibuffer-mode::get-element-by-id
                                              "head"))
                          (nyxt/minibuffer-mode::scroll-into-view
                           nyxt/minibuffer-mode::false))))))
select-next

Select next entry in minibuffer.

(define-command (&optional (minibuffer (current-minibuffer)))
    (when
        (< (suggestion-cursor minibuffer)
           (- (length (suggestions minibuffer)) 1))
      (incf (suggestion-cursor minibuffer))
      (state-changed minibuffer)
      (update-suggestions-display minibuffer)
      (evaluate-script minibuffer
                       (parenscript:ps
                         (parenscript:chain
                          (parenscript:chain nyxt/minibuffer-mode::document
                                             (nyxt/minibuffer-mode::get-element-by-id
                                              "selected"))
                          (nyxt/minibuffer-mode::scroll-into-view
                           nyxt/minibuffer-mode::false))))))
kill-whole-line

Delete all characters in the input.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::kill-line (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
kill-line

Delete all characters from cursor position until the end of the line.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::kill-forward-line (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
delete-backwards-word

Delete characters from cursor position until the beginning of the word at point.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::delete-backward-word (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
delete-forwards-word

Delete characters from cursor position until the end of the word at point.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::delete-forward-word (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
cursor-backwards-word

Move cursor to the beginning of the word at point.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::move-backward-word (input-cursor minibuffer)
                                     :conservative-word-move
                                     (conservative-word-move (current-buffer)))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer)
  (cluffer:cursor-position (input-cursor minibuffer)))
cursor-forwards-word

Move cursor to the end of the word at point.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::move-forward-word (input-cursor minibuffer)
                                    :conservative-word-move
                                    (conservative-word-move (current-buffer)))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer)
  (cluffer:cursor-position (input-cursor minibuffer)))
cursor-end

Move cursor to the end of the input area.

(define-command (&optional (minibuffer (current-minibuffer)))
    (cluffer:end-of-line (input-cursor minibuffer))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer))
cursor-beginning

Move cursor to the beginning of the input area.

(define-command (&optional (minibuffer (current-minibuffer)))
    (cluffer:beginning-of-line (input-cursor minibuffer))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer))
cursor-backwards

Move cursor backwards by one.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::safe-backward (input-cursor minibuffer))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer))
cursor-forwards

Move cursor forward by one.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::safe-forward (input-cursor minibuffer))
  (state-changed minibuffer)
  (update-input-buffer-display minibuffer))
delete-backwards

Delete character before cursor.

(define-command (&optional (minibuffer (current-minibuffer)))
    (text-buffer::delete-item-backward (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
delete-forwards

Delete character after cursor.

(define-command (&optional (minibuffer (current-minibuffer)))
    (cluffer:delete-item (input-cursor minibuffer))
  (reset-suggestion-state minibuffer)
  (state-changed minibuffer)
  (update-display minibuffer))
self-insert

Insert last key from current window to the receiver.

(define-command (nyxt/minibuffer-mode::receiver)
    (let ((nyxt/minibuffer-mode::key-string
           (keymap:key-value (last-key (current-window))))
          (nyxt/minibuffer-mode::translation-table
           '(("hyphen" "-") ("space" " "))))
      (setf nyxt/minibuffer-mode::key-string
              (or
               (cadr
                (assoc nyxt/minibuffer-mode::key-string
                       nyxt/minibuffer-mode::translation-table :test
                       #'string=))
               nyxt/minibuffer-mode::key-string))
      (insert nyxt/minibuffer-mode::receiver nyxt/minibuffer-mode::key-string)))
self-insert-minibuffer

Self insert with the current minibuffer.

(define-command nil
    (nyxt/minibuffer-mode:self-insert (current-minibuffer)))
cancel-input

Close the minibuffer query without further action.

(define-command (&optional (minibuffer (current-minibuffer)))
    (calispel:! (interrupt-channel minibuffer) t)
  (hide minibuffer))
return-input

Return with minibuffer input, ignoring the selection.

(define-command (&optional (minibuffer (current-minibuffer)))
    (calispel:! (channel minibuffer) (input-buffer minibuffer))
  (nyxt/minibuffer-mode::quit-minibuffer minibuffer))
return-selection

Return with minibuffer selection.

(define-command (&optional (minibuffer (current-minibuffer)))
    (let ((nyxt/minibuffer-mode::result))
      (with-slots (must-match-p suggestions suggestion-cursor invisible-input-p
                                multi-selection-p marked-suggestions)
          minibuffer
        (match (or marked-suggestions
                   (and suggestions (list (nth suggestion-cursor suggestions)))
                   (and (not must-match-p) (list (input-buffer minibuffer))))
          ((guard suggestions suggestions)
           (setf suggestions
                   (mapcar
                    (lambda (nyxt/minibuffer-mode::suggestion)
                      (if (stringp nyxt/minibuffer-mode::suggestion)
                          (str:replace-all " " " "
                                           nyxt/minibuffer-mode::suggestion)
                          nyxt/minibuffer-mode::suggestion))
                    suggestions))
           (setf nyxt/minibuffer-mode::result
                   (if multi-selection-p
                       suggestions
                       (first suggestions))))
          (nil
           (when invisible-input-p
             (setf nyxt/minibuffer-mode::result (input-buffer minibuffer))))))
      (nyxt/minibuffer-mode::quit-minibuffer minibuffer)
      (calispel:! (channel minibuffer) nyxt/minibuffer-mode::result)))
insert-suggestion-or-search-engine

Paste selected suggestion or search engine to input.
If minibuffer input is not empty and the selection is on first position,
complete against a search engine.

(define-command (&optional (minibuffer (current-minibuffer)))
    (cond
     ((and (not (str:emptyp (input-buffer minibuffer)))
           (zerop (suggestion-cursor minibuffer)))
      (let* ((nyxt/minibuffer-mode::engines (search-engines (current-buffer)))
             (nyxt/minibuffer-mode::matching-engines
              (remove-if
               (complement
                (alex:curry #'str:starts-with-p (input-buffer minibuffer)))
               nyxt/minibuffer-mode::engines :key #'shortcut)))
        (match (length nyxt/minibuffer-mode::matching-engines)
          (1 (nyxt/minibuffer-mode:kill-whole-line minibuffer)
           (insert minibuffer
                   (str:concat
                    (shortcut (first nyxt/minibuffer-mode::matching-engines))
                    " ")))
          (nyxt/minibuffer-mode::match-count
           (let ((nyxt/minibuffer-mode::engine
                  (prompt-minibuffer :input-prompt "Search engine"
                                     :input-buffer
                                     (if (zerop
                                          nyxt/minibuffer-mode::match-count)
                                         ""
                                         (input-buffer minibuffer))
                                     :suggestion-function
                                     #'search-engine-suggestion-filter)))
             (when nyxt/minibuffer-mode::engine
               (nyxt/minibuffer-mode:kill-whole-line minibuffer)
               (insert minibuffer
                       (str:concat (shortcut nyxt/minibuffer-mode::engine)
                                   " "))))))))
     (t (nyxt/minibuffer-mode:insert-suggestion minibuffer))))
set-url-mode

Minibuffer mode for setting the URL of a buffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command SET-URL-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/minibuffer-mode:set-url-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance 'nyxt/minibuffer-mode:user-set-url-mode
                        :buffer buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/minibuffer-mode:set-url-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/minibuffer-mode:set-url-mode))))
  buffer)
minibuffer-mode

Mode for the minibuffer.

(define-command (&rest args &key (buffer (current-buffer))
                 (activate t explicit?) &allow-other-keys)
    (unless
        (find 'buffer (metabang.moptilities:superclasses buffer) :key
              #'class-name)
      (error "Mode command MINIBUFFER-MODE called on non-buffer"))
  (let ((#:existing-instance0
         (find-mode buffer 'nyxt/minibuffer-mode:minibuffer-mode)))
    (unless explicit? (setf activate (not #:existing-instance0)))
    (if activate
        (unless #:existing-instance0
          (let ((#:new-mode1
                 (apply #'make-instance
                        'nyxt/minibuffer-mode:user-minibuffer-mode :buffer
                        buffer args)))
            (when (constructor #:new-mode1)
              (funcall-safely (constructor #:new-mode1) #:new-mode1))
            (push #:new-mode1 (modes buffer))
            (sera:run-hook (enable-hook #:new-mode1) #:new-mode1)
            (sera:run-hook (enable-mode-hook buffer) #:new-mode1))
          (print-status)
          (log:debug "~a enabled." 'nyxt/minibuffer-mode:minibuffer-mode))
        (when #:existing-instance0
          (sera:run-hook (disable-hook #:existing-instance0)
                         #:existing-instance0)
          (sera:run-hook (disable-mode-hook buffer) #:existing-instance0)
          (when (destructor #:existing-instance0)
            (funcall-safely (destructor #:existing-instance0)
                            #:existing-instance0))
          (setf (modes buffer) (delete #:existing-instance0 (modes buffer)))
          (print-status)
          (log:debug "~a disabled." 'nyxt/minibuffer-mode:minibuffer-mode))))
  buffer)
search-selection

Search selected text using the queried search engine.

(define-command nil
    (let* ((selection (%copy))
           (engine
            (prompt-minibuffer :input-prompt "Search engine"
                               :suggestion-function
                               #'search-engine-suggestion-filter)))
      (when engine
        (buffer-load (generate-search-query selection (search-url engine))))))
toggle-toolbars

Toggle the visibility of the message and status buffer areas.

(define-command (&optional (window (current-window)))
    (if (= 0 (ffi-window-get-status-buffer-height window)
           (ffi-window-get-message-buffer-height window))
        (unpresent-current-window window)
        (present-current-window window)))
toggle-fullscreen

Fullscreen WINDOW, or the currently active window if unspecified.

(define-command (&optional (window (current-window)))
    (if (fullscreen-p window)
        (ffi-window-unfullscreen window)
        (ffi-window-fullscreen window)))
make-window

Create a new window.

(define-command (&optional buffer)
    (let ((window (window-make *browser*))
          (buffer (or buffer (make-buffer :url :default))))
      (window-set-active-buffer window buffer)
      (values window buffer)))
delete-current-window

Delete WINDOW, or the currently active window if unspecified.

(define-command (&optional (window (current-window)))
    (let ((window-count (hash-table-count (windows *browser*))))
      (cond ((and window (> window-count 1)) (ffi-window-delete window))
            (window (echo "Can't delete sole window.")))))
delete-window

Delete the queried window(s).

(define-command nil
    (let ((windows
           (prompt-minibuffer :input-prompt "Delete window(s)"
                              :multi-selection-p t :suggestion-function
                              (window-suggestion-filter))))
      (mapcar #'delete-current-window windows)))
print-buffer

Print the current buffer.

(define-command nil
    (%print-buffer))
open-inspector

Open the inspector, a graphical tool to inspect and change the content of the buffer.

(define-command nil
    (ffi-inspector-show (current-buffer)))
enable-mode-for-buffer

Enable queried mode(s) for select buffer(s).

(define-command nil
    (let ((buffers
           (prompt-minibuffer :input-prompt "Enable mode(s) for buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (enable-mode-for-current-buffer :buffers buffers)))
enable-mode-for-current-buffer

Enable queried mode(s).

(define-command (&key (buffers (list (current-buffer))))
    (let ((modes
           (prompt-minibuffer :input-prompt "Enable mode(s)" :multi-selection-p
                              t :suggestion-function
                              (inactive-mode-suggestion-filter buffers))))
      (dolist (buffer buffers) (enable-modes modes buffer))))
disable-mode-for-buffer

Disable queried mode(s) for select buffer(s).

(define-command nil
    (let ((buffers
           (prompt-minibuffer :input-prompt "Disable mode(s) for buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (disable-mode-for-current-buffer :buffers buffers)))
disable-mode-for-current-buffer

Disable queried mode(s).

(define-command (&key (buffers (list (current-buffer))))
    (let ((modes
           (prompt-minibuffer :input-prompt "Disable mode(s)"
                              :multi-selection-p t :suggestion-function
                              (active-mode-suggestion-filter buffers))))
      (dolist (buffer buffers) (disable-modes modes buffer))))
switch-buffer-next

Switch to the oldest buffer in the list of buffers.

(define-command nil
    (let* ((buffers (buffer-list :sort-by-time t))
           (oldest-buffer (alex:last-elt buffers)))
      (when (eq oldest-buffer (current-buffer))
        (setf oldest-buffer (or (second (nreverse buffers)) oldest-buffer)))
      (set-current-buffer oldest-buffer)))
switch-buffer-previous

Switch to the previous buffer in the list of buffers.
That is to say, the one with the most recent access time after the current buffer.
The current buffer access time is set to be the last so that if we keep calling
this command it cycles through all buffers.

(define-command nil
    (let* ((buffers (buffer-list :sort-by-time t))
           (last-buffer (alex:last-elt buffers))
           (current-buffer (current-buffer)))
      (when (second buffers)
        (set-current-buffer (second buffers))
        (setf (last-access current-buffer)
                (local-time:timestamp- (last-access last-buffer) 1 :sec)))))
reload-buffer

Reload queried buffer(s).

(define-command nil
    (let ((buffers
           (prompt-minibuffer :input-prompt "Reload buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (mapcar #'reload-current-buffer buffers)))
reload-current-buffer

Reload of BUFFER or current buffer if unspecified.

(define-command (&optional (buffer (current-buffer)))
    (buffer-load (url buffer) :buffer buffer))
set-url-new-buffer

Prompt for a URL and set it in a new focused buffer.

(define-command nil
    (set-url :new-buffer-p t))
set-url-from-current-url

Set the URL for the current buffer, pre-filling in the current URL.

(define-command nil
    (set-url :prefill-current-url-p t))
set-url

Set the URL for the current buffer, completing with history.

(define-command (&key new-buffer-p prefill-current-url-p)
    (let ((history (minibuffer-set-url-history *browser*)))
      (when history
        (metabang.cl-containers:insert-item history (url (current-buffer))))
      (let ((url
             (prompt-minibuffer :input-prompt
                                (format nil "Open URL in ~A buffer"
                                        (if new-buffer-p
                                            "new"
                                            "current"))
                                :input-buffer
                                (if prefill-current-url-p
                                    (object-string (url (current-buffer)))
                                    "")
                                :default-modes '(set-url-mode minibuffer-mode)
                                :suggestion-function
                                (history-suggestion-filter :prefix-urls
                                                           (list
                                                            (object-string
                                                             (url
                                                              (current-buffer)))))
                                :history history :must-match-p nil)))
        (when (typep url 'history-entry) (setf url (url url)))
        (buffer-load url :buffer
                     (if new-buffer-p
                         (make-buffer-focus :url "")
                         (current-buffer))))))
delete-other-buffers

Delete all other buffers but `buffer` which if not explicitly set defaults
to the currently active buffer.

(define-command (&optional (buffer (current-buffer)))
    (let* ((all-buffers (buffer-list))
           (buffers-to-delete (remove buffer all-buffers))
           (count (list-length buffers-to-delete)))
      (if-confirm ("Are you sure to delete ~a buffer~p?" count count)
                  (mapcar #'buffer-delete buffers-to-delete))))
delete-current-buffer

Delete the currently active buffer, and make the next buffer the
visible buffer. If no other buffers exist, set the url of the current
buffer to the start page.

(define-command (&optional (buffer (current-buffer)))
    (buffer-delete buffer))
delete-all-buffers

Delete all buffers, with confirmation.

(define-command nil
    (let ((count (length (buffer-list))))
      (if-confirm ("Are you sure to delete ~a buffer~p?" count count)
                  (delete-buffers))))
reduce-to-buffer

Reduce the buffer(s) via minibuffer input and copy their titles/URLs to a
single buffer, optionally delete them. This function is useful for archiving a
set of useful URLs or preparing a list to send to a someone else.

(define-command (&key (delete t))
    (let ((buffers
           (prompt-minibuffer :input-prompt "Reduce buffer(s)"
                              :multi-selection-p t :suggestion-function
                              (buffer-suggestion-filter))))
      (with-current-html-buffer (reduced-buffer "*Reduced Buffers*" 'base-mode)
        (cl-markup:markup (:style (style reduced-buffer))
                          (:h1 "Reduced Buffers:")
                          (:div
                           (loop for buffer in buffers
                                 collect (with-current-buffer buffer
                                           (cl-markup:markup
                                            (:div
                                             (:p (:b "Title: ") (title buffer))
                                             (:p (:b "URL: ")
                                              (:a :href
                                               (object-string (url buffer))
                                               (object-string (url buffer))))
                                             (:p
                                              (:b
                                               "Automatically generated summary: ")
                                              (:ul
                                               (loop for summary-bullet in (analysis:summarize-text
                                                                            (document-get-paragraph-contents
                                                                             :limit
                                                                             10000))
                                                     collect (cl-markup:markup
                                                              (:li
                                                               (str:collapse-whitespaces
                                                                summary-bullet))))))
                                             (:hr ""))))))))
      (when delete (mapcar #'buffer-delete buffers))))
delete-buffer

Delete the buffer(s) via minibuffer input.

(define-command (&key id)
    (if id
        (buffer-delete (gethash id (slot-value *browser* 'buffers)))
        (let ((buffers
               (prompt-minibuffer :input-prompt "Delete buffer(s)"
                                  :multi-selection-p t :suggestion-function
                                  (buffer-suggestion-filter))))
          (mapcar #'buffer-delete buffers))))
make-buffer-focus

Switch to a new buffer.
See `make-buffer'.

(define-command (&key (url :default))
    (let ((buffer (make-buffer :url url)))
      (set-current-buffer buffer)
      buffer))
switch-buffer-domain

Switch the active buffer in the current window from the current domain.

(define-command (&key domain (buffer (current-buffer)))
    (let ((domain (or domain (quri.domain:uri-domain (url buffer)))))
      (let ((buffer
             (prompt-minibuffer :input-prompt
                                "Switch to buffer in current domain:"
                                :suggestion-function
                                (buffer-suggestion-filter :domain domain
                                                          :current-is-last-p
                                                          t))))
        (set-current-buffer buffer))))
switch-buffer

Switch the active buffer in the current window.

(define-command (&key id)
    (if id
        (set-current-buffer (gethash id (slot-value *browser* 'buffers)))
        (let ((buffer
               (prompt-minibuffer :input-prompt "Switch to buffer"
                                  :suggestion-function
                                  (buffer-suggestion-filter :current-is-last-p
                                                            t))))
          (set-current-buffer buffer))))
copy-title

Save current page title to clipboard.

(define-command nil
    (copy-to-clipboard (title (current-buffer)))
  (echo "~a copied to clipboard." (title (current-buffer))))
copy-url

Save current URL to clipboard.

(define-command nil
    (copy-to-clipboard (object-string (url (current-buffer))))
  (echo "~a copied to clipboard." (object-string (url (current-buffer)))))
make-internal-buffer

Create a new buffer.
MODES is a list of mode symbols.
If URL is `:default', use `default-new-buffer-url'.

(define-command (&key (title "") modes)
    (buffer-make *browser* :title title :default-modes modes :internal-buffer-p
                 t))
make-buffer

Create a new buffer.
MODES is a list of mode symbols.
If URL is `:default', use `default-new-buffer-url'.

(define-command (&key (title "") modes (url ""))
    (let* ((buffer (buffer-make *browser* :title title :default-modes modes))
           (url
            (if (eq url :default)
                (default-new-buffer-url buffer)
                url)))
      (unless (url-empty-p url) (buffer-load url :buffer buffer))
      buffer))
noop

A command that does nothing.
This is useful to override bindings to do nothing.

(define-command nil
    (values))