Next User Manual
Next is the next generation browsing experience designed for power users. 100% of the functions and classes are exposed to the end-user allowing for infinite customization.
- Advanced Topics
Within a tab, all navigation is possible using only the keyboard. To navigate up and down on a web page, the following keybindings are provided.
C-n: Move down
C-p: Move up
scroll-left: Move left (no keybindings for now)
scroll-right: Move right (no keybindings for now)
M->: Jump to bottom of page
M-<: Jump to top of page
Use the zoom keybindings to make everything on a web page larger or smaller. These keybindings mimic the Emacs counterpart:
C-x C-=: Increase size
C-x C--: Decrease size
C-x C-0: Restore defaults
Jumping to links (link-hints)
In order to visit a link, one never has to remove their fingers from the keyboard. It works like this:
- Enter in a special key combination
- Several strings will appear on screen “AZ” “CY”, these special strings represent links that you can visit
- Enter in one of these strings into the minibuffer
- Visit the page
The full key-bindings for link-hint based navigate are found below:
C-g: Go to link in current tab
M-g: Create new tab with link, focus on new tab
C-u M-g: Create new tab with link, keep focus on current tab
When ambiguous URLs are inputted, Next will attempt the best guess
about what the user wishes. If the user does not supply a protocol in
https will be assumed. To visit a site supporting only
http, the user must explicitly type the full URL with
C-l: Change URL of current document
M-l: New document-mode tab
Searching via search engine
From the new URL prompt, any input that is not recognized as a URL will be searched using the default search engine. Any query that starts with a known search engine prefix will use the corresponding search engine for the query.
For instance, to search “parrot” on Wikipedia:
M-lto open a new URL prompt.
From a Lisp REPL, you can query the list of search engines with
(get-default 'window 'search-engines)
It will return something like
'(("default" . "https://duckduckgo.com/?q=~a") ("wiki" . "https://en.wikipedia.org/w/index.php?search=~a"))
~a in the search engine URI is a place holder for the search pattern.
To set the list of search engines, do:
(setf (get-default 'window 'search-engines) '(("default" . "https://duckduckgo.com/?q=~a") ("yt" . "https://www.youtube.com/results?search_query=~a") ("wiki" . "https://en.wikipedia.org/w/index.php?search=~a")))
and to append a search engine do the list, you can do
(nconc (get-default 'window 'search-engines)) '(("q" . "http://quickdocs.org/search?q=~a") ("yt" . "https://www.youtube.com/results?search_query=~a")))
Jumping to Headings
Jumping to different headings based on fuzzy completion is available via the following keybindings:
C-.: Jump to heading
All input is handled within a special area called the minibuffer. The minibuffer will appear at the bottom of the screen when the user is responsible for inputting some value. The minibuffer may also suggest completions.
Any time a function activates the minibuffer there are two applicable returns:
C-RET: Return Immediate - Return EXACTLY what has been typed into the minibuffer, ignoring completions.
RET: Return Complete - If completion function provided, return the selected completion candidate. If completion not provided return the EXACT text inputted into the minibuffer. If completion function provided, no completion applicable (selected), and the :empty-complete is a truthy value, the function will accept the EXACT text inputted into the minibuffer.
Many browsers implement the concept of multiple views with “tabs”. Tabs are inherently flawed as they don’t scale: it’s hard to manage more than a few dozen of them.
In Next, multiple views are implemented as “buffers”. Each buffer can use its
own set of “modes”. A mode is a collection of settings, key bindings, commands,
etc. Regular web pages use the
document-mode by default.
The standard keybindings for buffer management are:
C-x b: Switch buffer
C-x Left: Switch to previous buffer
C-x Right: Switch to next buffer
C-x k: Kill buffer
M-l: Open URL in new buffer
C-l: Change URL of current buffer
C-t: Make new empty buffer
Switching Tabs by Order
In addition to switching tabs by selecting the current tab, you can cycle through them. This enables you to jump back and forth between two tabs that are next to each other.
C-[: Switch tab previous
C-]: Switch tab next
A mode is a collection of features, ranging from key bindings to network
options. It can be enabled or disabled on a per-buffer basis via the command of
the same name, e.g.
Each buffer has its own list of modes. The first mode in the list has highest priority: this is important, for instance, to determine which key binding takes precedence in case of conflict. See Keybinding for more details.
There are a number of keybindings provided to enable searching within a buffer.
C-s s: Search for a Given Term: This command will place a red box next to every match on a given web-page.
C-s n: Next match: This command will move the next match to the top of the browser screen.
C-s p: Previous match: This command will move the previous match to the top of the browser screen.
C-s k: Clear Search: Remove the read search boxes from the screen.
History is represented as a tree that you can traverse. More complex than the “forwards-backwards” abstraction found in other browsers, the tree makes sure you never lose track of where you’ve been.
In the example below, the user performs the following actions:
- Starts page
- Visits page
- Returns to page
- Visits page
- Returns to page
forwardskeybind in history
It is at this point that a normal browser would not be able to
navigate you forwards to your visit of
Ancient Greek. Instead of
erasing your history, Next offers smart navigation and prompts the
user. Do you wish to go forwards to
Ancient Greek or to
The standard keybindings for forward-backward navigation are:
C-f: Navigate Forward
C-b: Navigate Backward
M-f: Navigate Forward Tree
M-b: Navigate Backward
By using navigate forward tree you will be prompted for which branch you’d like to visit as in the example above. The simple navigate forward command will simply visit the first child of the current node in the tree.
Bookmarks are stored in a database located in
~/.local/share/next/bookmark.db by default. This (SQLite) database contains
one table with two columns: id, url. In order to navigate and manage your
bookmarks, a few functions are provided:
C-m k: Delete Bookmark
C-m o: Open Bookmark
C-m s: Bookmark Current Page
C-m u: Bookmark URL (input URL via minibuffer)
C-m g: Bookmark Anchor (input URL via link hints)
Clearing the Echo Area
In the area at the bottom of the screen where the minibuffer resides,
Next will occasionally display messages. These can be dismissed by
using the binding
To exit Next enter the key-combination
C-x C-c and the program will
quit. All of your open tabs and form data will not be persisted. The
only information saved will be your filled in passwords, cookies,
and other information within your cache.
Execute Extended Command
You can execute any command by name by typing
M-x. This will bring up a list
of candidates that you can fuzzily complete.
The help system allows you to look up variable and function docstrings directly within Next. Docstrings will appear in a new help buffer.
C-h v: Look up a variable docstring
C-h c: Look up a command docstring
SLIME with a compiled version of Next
SLIME provides a way of interacting with Next, and with Lisp code in
general (e.g. in a REPL).
From the SLIME manual:
SLIME extends Emacs with support for interactive programming in Common Lisp. The features are centered around slime-mode, an Emacs minor-mode that complements the standard lisp-mode. While lisp-mode supports editing Lisp source files, slime-mode adds support for interacting with a running Common Lisp process for compilation, debugging, documentation lookup, and so on.
To use SLIME with a compiled version of Next use the keybinding
S-h s to
launch a Swank server. SLIME will connect to the Swank server and give you
completion, debugging, documentation, etc. The port for Swank is define in
*swank-port* and its default value is different from that of Swank on Emacs to
avoid collisions with an Emacs
After launching the Swank server in Next, execute the following within Emacs:
127.0.0.1for the host
- Enter the port number set in the Next variable
To customize the port that Swank starts on, edit the global variable
*swank-port* in your init file.
All customization begins by creating a
file. Within your init file you can write your own keybindings and
customizations. If the directory
~/.config/next/ does not already
exist, you will have to make it.
The first line of an init file should contain the following package declaration in order to modify Next-specific variables and functions:
Following the package declaration, you can write or override any functions and variables.
Keys are defined with the
define-key command. The command takes multiple forms:
;; Bind multiple keys in root-mode using the default scheme. (define-key "C-x o" 'example "SPACE" 'scroll-page-down) ;; Bind in root-mode using the vi-normal scheme. (define-key :scheme :vi-normal "C-x o" 'example "SPACE" 'scroll-page-down) ;; Bind in document-mode using the vi-normal scheme. (define-key :mode document-mode :scheme :vi-normal "C-x C-c s" 'save-history) ;; Bind in current buffer's first mode. This won't affect other buffers. (define-key :keymap (getf (keymap-scheme (first (modes (active-buffer *interface*)))) :emacs) "C-x C-c h" 'hello-local-world)
Read on for an explanation of the meanings of
In the previous example, the key sequence
C-x o would invoke the
If later on another command is bound to
C-x, all other bindings starting with
C-x will be overridden.
The following keys exist as special keys:
S: Super (Windows key, Command Key)
M: Meta (Alt key, Option Key)
s: Shift key
Keymaps and key binding schemes
A keymap is a collection of key-to-command bindings.
Modes can define key binding schemes, which are sets of keymaps indexed by a
scheme name like
The currently active key binding scheme is selected by the
buffer slot. When a key is hit, Next looks up the keymaps of the corresponding
scheme for all active modes in the current buffer.
You can change the default binding scheme for any buffer by setting
current-key-scheme to the appropriate value. For instance to set VI bindings
(add-to-default-list 'vi-normal-mode 'buffer 'default-modes)
The override map is the first keymap that is looked up for a binding when a key is pressed. Override maps are stored in every buffer. They are exposed to the user as a mean to override any binding from any mode. They should not be modified by any library.
VI is a model text editor that is famous for its modal key bindings. In normal mode, all keys are commands, they won’t insert any text anywhere.
In insert mode, all textual keys insert the corresponding text.
Next offers two modes,
vi-insert-mode to simulate this
behaviour. For instance, in
j scrolls the page down and
To go from normal mode to insert mode, press
To go from insert mode to normal mode, press
To load a file again, or reload an init file use the function load-file. Within the minibuffer prompt enter the full path to the file you wish to load.
C-o: Load File
A convenience function for reloading the init file called
load-init-file can also be keybound.
Creating your own interactive commands
Creating your own invokable commands is the same as creating any other
defun except the form is
define-command. A docstring is highly
recommended and will produce a style warning when it is missing.
An example of a trivial command definition can be seen below.
(define-command bookmark-url () "Allow the user to bookmark a URL via minibuffer input." (with-result (url (read-from-minibuffer (minibuffer *interface*))) (%bookmark-url url)))
Getting input from the user
Getting input from the user via the minibuffer is an asynchronous
command. That is why the
read-from-minibuffer function is wrapped
within a continuation-passing-style macro
with-result. The form
therefore takes the following look:
(with-result (variable-name-to-bind-minibuffer-input (read-from-minibuffer (minibuffer *interface*))) (print variable-name-to-bind-minibuffer-input))
Network resource dispatch (including ad-blocking)
The dispatching of network queries can be fully customized in the
resource-query-function slot of the
resource-query-default function for an example which dispatches
downloads, new window requests,
This function can also serve as an entry point to URL-based resource blocking.
Resource blodking (Ad-blocking)
Next provides the
blocker-mode. It filters networks requests (including
ads)by the host name. A default filter list is automatically updated from
Multiple lists of hosts can be added and blocker mode will filter based on all the lists.
To add a list, add an instance of the
hostlist class to the
For instance, you can add this to your
(add-to-default-list (make-hostlist :hosts '("platform.twitter.com" "syndication.twitter.com" "m.media-amazon.com")) 'blocker-mode 'hostlists)
hostlist class also support fetching the list from a URL.
The list can be persisted to the file specified in the
Some actions will draw elements on the HTML page, for instance
draw link hints as boxes with indices.
The style of those boxes is defined in the
box-style slot of the
Like any other slot, you can set the default value from your
init.lisp. For instance,
to change the style to using upper case, no gradiant, and square boxes:
(setf (get-default 'buffer 'box-style) (cl-css:inline-css '(:background "#C38A22" :color "black" :border "1px #C38A22 solid" :font-weight "bold" :padding "1px 3px 0px 3px" :padding "1px 3px 0px 3px" :position "absolute" :text-align "center" :text-shadow "0 3px 7px 0px rgba(0,0,0,0.3)")))
To use a network proxy for the current buffer, you can enable
The mode has some configurable slots:
server-address: The address of the proxy server, e.g. ~”socks5://127.0.0.1:9050”~ for your local Tor daemon.
whitelist: A list of hosts for which proxy won’t be used.
If you want to change the default in your user initialization file, you can do something like:
(setf (get-default 'proxy-mode 'server-address) "http://10.0.1.254")
To enable the proxy for all buffers by default, add the mode to the list of default modes:
(add-to-default-list 'proxy-mode 'buffer 'default-modes)