Nyxt Configurations

Init

Buffer configurations

Default buffer modes

(define-configuration buffer
  ((default-modes (append '(nyxt::emacs-mode
                            noscript-mode
                            dark-mode
                            my-blocker-mode)
                          %slot-default%))))

A little of zoom ratio

(define-configuration buffer
  ((current-zoom-ratio 4)))

Browser configurations

External editor

(define-configuration browser
  ((external-editor-program '("/usr/bin/emacsclient"))))

Emacs connection

SBCL lisp interpreter and QuickLisp package manager are required.

(load "~/quicklisp/setup.lisp")
(ql:quickload :slynk)
(define-command-global start-slynk (&optional (slynk-port *swank-port*))
  "Start a Slynk server that can be connected to, for instance, in
Emacs via SLY.
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."
  (slynk:create-server :port slynk-port :dont-close t :interface "0.0.0.0")
  (echo "Slynk server started at port ~a" slynk-port))
; (start-slynk)

Blocker mode

(defvar *my-blocked-hosts*
  (nyxt/blocker-mode:make-hostlist
   :hosts '("platform.twitter.com"
            "syndication.twitter.com"
            "m.media-amazon.com"))
  "A list of blocked hosts")
(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*))))

Garbage collector and memory management

Call Garbage Collector now!

(define-command-global my-gc-now ()
  "Start the garbage collector right now!"
  (sb-ext:gc :full 1))

How much memory do I have?

(defun my-bytes-to-mb-str (bytes)
  "Convert bytes into MB as string."
  (format nil "(~dMB)" (float (/ bytes 1024 1024))))
(define-command my-memory-status ()
  "Show an HTML with the memory situation."
  (with-current-html-buffer (buffer "*Memory*" 'nyxt/help-mode:help-mode)
    (spinneret:with-html-string
      (:style (style buffer))
      (:style (cl-css:css '(("#documentation .button"
                             :min-width "100px"))))
      (let ((dynamic-size (sb-ext:dynamic-space-size))
            (dynamic-used (sb-kernel:dynamic-usage))              
            (consed-between-gcs (sb-ext:bytes-consed-between-gcs))
            (consed-bytes (sb-ext:get-bytes-consed))
            (ro-used (sb-kernel::read-only-space-usage))
            (static-used (sb-kernel::static-space-usage))
            (control-stack-used (sb-kernel::control-stack-usage))
            (binding-stack-used (sb-kernel::binding-stack-usage)))
        (:h1 "Memory status")
        (:p (:a :class "button" :href (lisp-url `(my-gc-now)) "Run GC Now!"))
        (:p "Dynamic space: " dynamic-size
            (my-bytes-to-mb-str dynamic-size))
        (:p "Dynamic usage: " dynamic-used
            (my-bytes-to-mb-str dynamic-used)
            (float (* (/ dynamic-used dynamic-size) 100)) "%")
        (:p "Dynamic free: " (- dynamic-size dynamic-used)
            (my-bytes-to-mb-str (- dynamic-size dynamic-used))
            (float (* (/ (- dynamic-size dynamic-used) dynamic-size) 100)) "%")
        (:p "Bytes consed between GCs calls: " consed-between-gcs)
        (:p "Bytes consed: " consed-bytes
            (my-bytes-to-mb-str consed-bytes))
        (:p "Read only space usage: " ro-used)
        (:p "Static space usage: " static-used)
        (:p "Control stack usage: " control-stack-used)
        (:p "Binding stack usage: " binding-stack-used)))))

Load my own Nyxt modifications

(load "~/.config/nyxt/my-nyxt.lisp")

My Nyxt Modifications

These are modifications inside the nyxt package.

Status bar

I don't like the tabs and those controls buttons... remove them!

(in-package :nyxt)
(defun format-status (window)
  (let* ((buffer (current-buffer window))
         (vi-class (cond ((find-submode buffer 'vi-normal-mode)
                          "vi-normal-mode")
                         ((find-submode buffer 'vi-insert-mode)
                          "vi-insert-mode"))))
    (spinneret:with-html-string
      (:div :id (if vi-class "container-vi" "container")
            ;; vi-status, url, modes
            :style "grid-template-columns: auto auto"
            ;; (:div :id "controls" :class "arrow-right")
            (when vi-class
              (:div :id "vi-mode" :class (str:concat vi-class " arrow-right")
                    (:raw (format-status-vi-mode buffer))))            
            (:div :id "url" :class "arrow-right"
                  (:raw
                   (format-status-load-status buffer)
                   (format-status-url buffer)))
            ;; (:div :id "tabs"
            ;;(:raw
            ;; (format-status-tabs)))
            (:div :id "modes" :class "arrow-left"
                  :title (list-modes buffer)
                  (:raw
                   (format-status-modes buffer window)))))))

My HTML Data

(define-command my-html-data ()
  "Just open an example buffer"
    (with-current-html-buffer (buffer "*My help*" 'nyxt/help-mode:help-mode)
      (spinneret:with-html-string
        (:style (style buffer))
        (:style (cl-css:css '(("#documentation .button"
                               :min-width "100px"))))
        (:h1 "Welcome to Nyxt :-)")
        (:p (:a :href "https://nyxt.atlas.engineer" "https://nyxt.atlas.engineer"))
        (:p (:a :class "button" :href (lisp-url `(help)) "Help"))
        (:p "This is a common example text."))))

Password Completion

(define-command password-complete (&optional (buffer (current-buffer)))
  "Complete login fields with the username and password from the pass program."
  (password-debug-info)
  (if (password-interface buffer)
      (with-password (password-interface buffer)
        (let ((password-name
                (first (prompt :prompt "pass-name"
                               :input (quri:uri-domain (url buffer))
                               :sources
                               (list (make-instance 'password-source
                                                    :buffer buffer
                                                    :password-instance (password-interface buffer)
                                                    :actions (sera:filter (sera:eqs 'clip-username)
                                                                          password-source-actions
                                                                          :key #'name)))))))
          ;; (copy-username)
          (password:clip-username (password-interface buffer)
                                  :password-name password-name)
          (nyxt/web-mode::focus-element () (ps:chain document (query-selector "input[autocomplete='username']")))
          (nyxt/web-mode:select-all)
          (nyxt/web-mode:paste)
          ;; (copy-password)
          (password:clip-password (password-interface buffer)
                                  :password-name password-name)
          (nyxt/web-mode::focus-element () (ps:chain document (query-selector "input[autocomplete='current-password']")))
          (nyxt/web-mode:select-all)
          (nyxt/web-mode:paste)))
      (echo-warning "No password manager found.")))

Remove the copy and get the data with less interactivity

Only ask once!

Change JS

Use this JS, maybe try with `ffi-buffer-evaluate-javascritp `:

,----

| document.querySelector("input[autocomplete='current-password']").setAttribute('value', 'test')

`----

Cannot be done: clip is only implemented in lisp library, and requires to much modifications.

The DDG is annoying! Remove multiple DDG entries

Making `:engine-completion-p into nil ` removes the search engine autocompletion search.

(define-configuration USER-NEW-URL-OR-SEARCH-SOURCE
  ((prompter::filter-postprocessor
    (lambda (nyxt::suggestions nyxt::source nyxt::input)
      (declare (ignore nyxt::suggestions nyxt::source))
      (nyxt::input->queries nyxt::input :check-dns-p t :engine-completion-p nil)))))

noscript disable when URL in whitelist

enabled-script-urls

This is the whitelist variable.

(defvar my/enabled-script-urls '("startpage.com")
  "A list of trusty hosts which pages can have Javascript enable." )

should-enable-scripts-p

Given a complete URL, should nyxt enable Javascript?

(defun my/should-enable-scripts-p (url)
  "Should nyxt enable Javascript for URL?"
  (member url
          nyxt::my/enabled-script-urls
          :test (lambda (lurl prefix)
                  "Check if LURL domain name starts with the PREFIX.
Remove protocol from LURL and check if it starts with PREFIX."
                  (metatilities:string-starts-with
                   (cl-ppcre:regex-replace "^(https://|http://)" lurl "")
                   prefix))))

enable-noscript

(defun my/enable-noscript (url)
  "Enable noscript-mode if URL is not in the white-list.
Check if URL prefixes are in the `my/enabed-script-urls'.
If it is not a prefix on any elements of the list, enable noscript-mode.
If it is a prefix on one of the elements on the list, do nothing."
  (let ((enable-scripts (not (my/should-enable-scripts-p url))))
    (echo "my/enable-noscript ~s -> ~s" url enable-scripts)
    (nyxt/noscript-mode:noscript-mode :activate enable-scripts)))

enable-noscript-current-buffer

(defun my/enable-noscript-current-buffer ()
  "Enable noscript depending on the URL of the current-buffer.
If the URL is in the `my/enabled-script-urls' variable, then disable noscript,
else enable it."
  (my/enable-noscript (render-url (url (current-buffer)))))

Add the hook

Another hook should be used because this requires to refresh the current buffer.

(hooks:add-hook set-url-after-hook
                (hooks:make-handler-void
                 #'nyxt::my/enable-noscript-current-buffer))

See variable `*after-init-hook* `:

(describe-variable '*after-init-hook*)

If the hook is not global, but a slot: see the manual, at the hook section, a code like this may help:

(define-configuration web-buffer
  ((request-resource-hook
    (hooks:add-hook %slot-default% (make-handler-resource #'old-reddit-handler)))))

The code above 👆 add a hook to the `request-resource-hook ` slot defined at the `web-buffer ` class.

Password Management

Install pass with all dependencies and initialite it.

read -P "Your GPG2 registered email?" mail
pacman -S pass dmenu xdotool
pass init "$yourid"

To import passwords from firefox

Clone firefox_decrypt repository and run it. Interactively, the python script will ask for the Mozilla profile. Select the profile with "default-release" suffix.

Wait, and wait... in any case, check the `~/.password-store ` folder with ls.

The parameters on the python script are:

Todoes

Disable noscript-mode on certains URLs

Already tried with blocker, but it blocks whole domains, not certains JS.

Maybe try the no-script extension... it is supposed to work

Maybe a little more work is required:

Problems with heap memory

,----

| (sb-ext:dynamic-space-size)

`----

To augment the amount of heap memory, compile nyxt with:

,----

| make all LISP_FLAGS=" --dynamic-space-size 2048 --no-userinit --non-interactive"

`----

Automatic Garbage collection

(defun gc-cron ()
 (loop
   (if (> (sb-kernel::dynamic-usage) 512000000)
      (gc :full t))
  (sleep 1200)))
(sb-thread:make-thread #'gc-cron)

In nyxt:

,----

| (sb-ext:gc)

`----