CHA-CONFIG(5)
π¦ Configuration of Chawan π¦
Okay bestie, this is CHA-CONFIG(5), from the File Formats Manual β the Chawan configuration glow-up guide. Chawan supports configuration of various options like keybindings, user stylesheets, site preferences, etc. The configuration format is similar to toml, with the following exceptions:
- Regular tables (
[table]) and inline tables (table = {}) have different semantics. The first is additive, meaning default values are not removed. The second is destructive, and clears all default definitions in the table specified. [[table-array]]is sugar for[table-array.n], wherenis the number of declared table arrays. For example, you can declare anonymous siteconfs using the syntax[[siteconf]].
The canonical configuration file path is ~/.chawan/config.toml, but the search path accommodates XDG basedirs as well:
- config file specified through
-Cswitch -> use that $CHA_DIRis set -> use$CHA_DIR/config.toml${XDG_CONFIG_HOME:-~/.config}/chawan/config.tomlexists -> use that~/.chawan/config.tomlexists -> use that
See the Path handling section for details on how the config directory can be accessed.
For a configuration template, see bonus/config.toml in the source distribution.
β¨ Start β¨
Start-up options are to be placed in the [start] section.
Following is a list of start-up options:
visual-home = βabout:chawanββ URL. Page opened when Chawan is called with the-Voption and no other pages are passed as arguments.startup-script = βββ JavaScript code. Script Chawan runs on start-up. Pages will not be loaded until this function exits. (Note however that asynchronous functions likesetTimeoutdo not block loading.)headless = falseβ boolean /βdumpβ. When set to true orβdumpβ, the browser does not take input; instead, it prints a rendered version of all buffers in order, then exits. The difference between true andβdumpβis that true first waits for all scripts and network requests to run to completion, whileβdumpβdoes not. This means that true may never exit when scripting is enabled (e.g. if a script setssetInterval.) Piping cha to an external program or passing the-dswitch has the same effect as setting this option toβdumpβ.console-buffer = trueβ boolean. Whether Chawan should open a console buffer in non-headless mode. Warning: this is only useful for debugging. Disabling this option without manually redirecting standard error will result in error messages randomly appearing on your screen.
πΈ Buffer πΈ
Buffer options are to be placed in the [buffer] section.
These options are global to all buffers. For more granular filtering, use [[siteconf]].
Example:
[buffer]
# show images on all websites
images = true
# disable website CSS
styling = false
# Specify user styles.
user-style = '''
/* you can import external user styles like this
* (rooted at your config directory): */
@import 'user.css';
/* or just insert the style inline as follows. */
/* enforce the default text-decoration for links (i.e. underline). */
a[href] { text-decoration: revert !important }
/* following rules are restricted to color-mode "monochrome" (or -M) */
@media (monochrome) {
/* disable UA style of bold font (no need for important here) */
a[href]:hover { font-weight: initial }
/* ...and italicize the font on hover instead.
* here we use important because we don't want websites to
* override the value. */
a[href]:hover { font-style: italic !important }
}
'''
# You *can* set scripting to true (or 'app') here, but I strongly recommend
# using [[siteconf]] to enable it on a per-site basis instead.
Following is a list of buffer options:
styling = trueβ boolean. Enable/disable author style sheets. Note that disabling this does not affect user styles.scripting = falseβ boolean /βappβ. Enable/disable JavaScript in all buffers."app"also enables JavaScript APIs that can be used to fingerprint users (e.g. querying the windowβs size). This may achieve better compatibility with websites that behave like applications, at the cost of reduced privacy. For security and performance reasons, users are encouraged to selectively enable JavaScript with[[siteconf]]instead of using this setting.images = falseβ boolean. Enable/disable inline image display.cookie = falseβ boolean /βsaveβ. Enable/disable cookies on sites. If the stringβsaveβis specified, then cookies are also saved toexternal.cookie-file. true still readscookies.txt, but does not modify it. In Chawan, each website gets a separate cookie jar, so websites relying on cross-site cookies may not work as expected. You may use the[[siteconf]]"share-cookie-jar"setting to adjust this behavior for specific sites.referer-from = falseβ boolean. Enable/disable theβRefererβheader. Defaults to false. For privacy reasons, users are encouraged to leave this option disabled, only enabling it for specific sites in[[siteconf]].autofocus = falseβ boolean. When set to true, elements with anβautofocusβattribute are focused on automatically after the buffer is loaded. If scripting is enabled, this also allows scripts to focus on elements.meta-refresh = βaskβββneverβ/βalwaysβ/βaskβ. Whether or nothttp-equiv=refreshmeta tags should be respected.βneverβcompletely disables them,βalwaysβautomatically accepts all of them,βaskβbrings up a pop-up menu.history = trueβ boolean. Whether or not browsing history should be saved to the disk.mark-links = falseβ boolean. Add numeric markers before links. In headless/dump mode, this also prints a list of URLs after the page.user-style = βββ CSS stylesheet. A user stylesheet applied to all buffers. External stylesheets can be imported using the@import 'file.css';syntax. Paths are relative to the configuration directory. Nested@importis not supported yet.
π Search π
Search options are to be placed in the [search] section.
Following is a list of search options:
wrap = trueβ boolean. Whether on-page searches should wrap around the document.ignore-case = βautoβββautoβ/ boolean. When set to true, document-wide searches are case-insensitive by default. When set toβautoβ, searches are only case-sensitive when the search term includes a capital letter. Note: this can also be overridden inline in the search bar (vim-style), with the escape sequences\c(ignore case) and\C(strict case). See search mode section for details.
π§ Encoding π§
Encoding options are to be placed in the [encoding] section.
Following is a list of encoding options:
document-charset = [βutf-8β, βsjisβ, βeuc-jpβ, βlatin2β]β array of charset label strings. List of character sets for loading documents. All listed character sets are enumerated until the document has been decoded without errors. In HTML, meta tags and the BOM may override this with a different charset, so long as the specified charset can decode the document correctly.display-charset = βautoββ charset label string /βautoβ. Character set for keyboard input and displaying documents both in interactive and headless/dump mode. (This means that e.g.cha -I EUC-JP -O UTF-8 a > bis roughly equivalent toiconv -f EUC-JP -t UTF-8.)
π External π
External options are to be placed in the [external] section.
Following is a list of external options:
tmpdir = {usually β/tmp/cha-tmp-userβ}β path. Directory used to save temporary files.editor = β${VISUAL:-${EDITOR:-vi}}ββ shell command. External editor command.%sis substituted for the file name,%dfor the line number.mailcap = [β~/.mailcapβ, β/etc/mailcapβ, β/usr/etc/mailcapβ, β/usr/local/etc/mailcapβ]β array of paths. Search path for mailcap files. Seecha-mailcap(5)for details. Directories specified first have higher precedence.mime-types = [β~/.mime.typesβ, β/etc/mime.typesβ, β/usr/etc/mime.typesβ, β/usr/local/etc/mime.typesβ]β array of paths. Search path formime.typesfiles. Seecha-mime.types(5)for details.auto-mailcap = β$CHA_DIR/mailcapββ path. Mailcap file for entries that are automatically executed. TheβOpen asβprompt also saves entries in this file. For backwards-compatibility, if this isβmailcapβand the file does not exist, Chawan will also checkβauto.mailcapβ.auto-browsecap = β$CHA_DIR/browsecapββ path. Browsecap file for entries that are automatically executed.cgi-dir = [β$CHA_DIR/cgi-binβ, β$CHA_LIBEXEC_DIR/cgi-binβ]β array of paths. Search path for local CGI scripts. Seecha-cgi(5)for details.urimethodmap = [β$CHA_DIR/urimethodmapβ, β~/.urimethodmapβ, β/etc/urimethodmapβ]β array of paths. Search path for urimethodmap files. This format is deprecated; instead,auto-browsecapshould be used. Seecha-urimethodmap(5)for details.menu-file = β$CHA_DIR/ββ path. Path for the menu file. See the Menu section ofcha-api(7)for how to use it.w3m-cgi-compat = falseβ boolean. Enable local CGI compatibility with w3m. In short, it redirectsfile:///cgi-bin/*andfile:///$LIB/cgi-bin/*tocgi-bin:*. Seecha-cgi(5)for details. Note: parts of Chawanβs security model depend on not confusing protocols with each other, so this option is deprecated. If you really need it for some reason, you can use an auto-browsecap entry like
file; %s%?; x-resource; x-cgioutput; \
x-match=^(file:///home/me/.chawan/cgi-bin/.*)|(file:///cgi-bin/.*)$
β¦and that gets you the same results (with the same caveat, bestie β nothing changed there).
download-dir="${TMPDIR:-/tmp}/"(path) β the path that gets pre-filled into the "Save to:" (so, download) prompt. πask-download-dir=true(boolean) β should Chawan actually ask you for a download directory? Yes by default. Siteconf can override it.show-download-panel=true(boolean) β whetherabout:downloadsshould open up after a download starts. πcopy-cmd="xsel -bi"(shell command) β the command used for "copy to clipboard" operations. Important tea β: wheninput.osc52-copyis set to"auto"(which is the default),copy-cmdis ignored if support for OSC 52 is detected.paste-cmd="xsel -bo"(shell command) β the command used for "read from clipboard" operations.bookmark="$CHA_DATA_DIR/bookmark.md"(path) β path to thebookmark.mdfile. (The file it points to should have a.mdextension so its type can be correctly deduced. iykyk.)history-file="$CHA_DATA_DIR/history.uri"(path) β path to the history file.history-size=100(number) β maximum length of the history file.cookie-file="$CHA_DATA_DIR/cookies.txt"(path) β path to the cookie file. The format is the same as curl's"cookies.txt"format, except that a"jar@"part gets prepended for cookies that belong in a different jar than the domain. Cookies from this file are used if"buffer.cookie"(or its siteconf equivalent) is set to true or"save"β which meanstrueputs the cookie-file into a "read-only" mode. πͺ
β¨οΈ INPUT β¨οΈ
Okay so all the input options live in the [input] section. π
vi-numeric-prefix=true(boolean) β should Chawan accept vi-style numeric prefixes to commands? Only applies to keybindings defined in[page].use-mouse="auto"(boolean / "auto") β is Chawan allowed to intercept mouse clicks? The current implementation imitates w3m. On"auto"(the default), Chawan tries to detect whether mouse support is even available. π±οΈosc52-copy="auto"(boolean / "auto") β should Chawan use the OSC 52 escape sequence to copy to the clipboard straight through the terminal? When it's available, OSC 52 overridesexternal.copy-cmd. On"auto"(the default), Chawan tries to detect whether OSC 52 is available at launch.osc52-primary="auto"(boolean / "auto") β should Chawan try to set the primary selection through OSC 52? This happens automatically on mouse selection, and also on all clipboard copies. On"auto"(the default), Chawan tries to detect whether the terminal is capable of setting the primary selection. Heads up though: very few terminals actually implement OSC 52 correctly (to my knowledge, only XTerm and Kitty), and on other terminals this might legitimately break copying to the clipboard selection. πbracketed-paste="auto"(boolean / "auto") β should Chawan ask for bracketed paste? When it's true, the terminal will (hopefully) mark pasted text with escape sequences, which a) makes sure that pasting a newline character into the line editor doesn't submit the editor, and b) lets Chawan intercept text pasted into the pager and automatically load it into the browser's URL bar. On"auto"(the default), Chawan tries to only turn on bracketed paste if the terminal is known not to misbehave when you try it.wheel-scroll=5(number) β how many lines to scroll per mouse wheel event.side-wheel-scroll=5(number) β how many columns to scroll per mouse side-wheel event.link-hint-chars="abcdefghijklmnoprstuvxyz"(string) β the string of characters to use intoggleLinkHints. Any Unicode codepoint is accepted, and they're ordered exactly as you specify in this option. β¨
Examples:
[input]
vi-numeric-prefix = true
[page]
# Here, the arrow function will be called with the vi numbered prefix if
# one was input, and with no argument otherwise.
# The numeric prefix can never be zero, so it is safe to test for undefined
# using the ternary operator.
G = 'n => n ? pager.gotoLine(n) : pager.cursorLastLine()'
π NETWORK π
Network options go in the [network] section, obvs.
max-redirect=10(number) β maximum number of redirections to follow.max-net-connections=12(number) β maximum number of simultaneous network connections allowed in one buffer. Any further connections are held back until that number drops back below the threshold. π¦prepend-scheme="https://"(string) β prepend this to URLs passed to Chawan (or typed into the URL bar) that don't have a scheme. Note that local files (thefile:scheme) are always checked first; only if that fails will Chawan retry the request withprepend-schemeset as the scheme.proxy=""(URL) β specify a proxy for all network requests Chawan makes. Right now, the formatshttp://user:pass@domainandsocks5://user:pass@domainare accepted. Unlike in curl,socks5his an alias ofsocks5, and DNS requests are always tunneled. Siteconf can override this.default-headers={see bonus/config.toml}(table) β specify a table of default headers for all HTTP(S) network requests. Siteconf can override this.allow-http-from-file=false(boolean) β > WARNING: think twice before enabling this, fr fr. It allows HTTP and HTTPS requests from thefile:andstream:schemes. That's a bad idea in general because it lets local files ping remote servers (a functionality commonly abused by HTML e-mails to track your mailbox activity π). On the other hand, it lets you load images in HTML e-mails if you genuinely don't care about the privacy implications.
π DISPLAY π
Display options are to be placed in the [display] section.
Following is a list of display options:
color-mode="auto"("monochrome" / "ansi" / "eight-bit" / "true-color" / "auto") β set the color mode."auto"for automatic detection,"monochrome"for black on white,"ansi"for eight ANSI plus eight aixterm colors,"eight-bit"for 256-color mode, and"true-color"for 24-bit colors. π¨format-mode="auto"("auto" / ["bold", "italic", "underline", "reverse", "strike", "overline", "blink"]) β specifies the allowed output formatting modes. Accepts the string"auto"or an array of specific attributes."auto"(the default) tries to detect supported formatting modes when launched visually, and omits all formatting modes in dump mode. An empty array ([]) disables formatting even in visual mode.no-format-mode=["overline"](["bold", "italic", "underline", "reverse", "strike", "overline", "blink"]) β disable specific formatting modes.image-mode="auto"("auto" / "none" / "sixel" / "kitty") β specifies the image output mode."sixel"uses sixels for output,"kitty"uses the Kitty image display protocol, and"none"disables image display completely."auto"(the default) detects sixel or kitty support automatically, and falls back to"none"when neither is available. This is expected to work on all known terminals with functional image support. Note thatbuffer.imagesmust be enabled for images to load at all. πΌοΈsixel-colors="auto"("auto" / 2..65535) β only applies whendisplay.image-mode="sixel". Setting this to a number overrides the number of sixel color registers reported by the terminal.alt-screen="auto"("auto" / boolean) β enable/disable the alternative screen."auto"(the default) tries to detect support for this feature. (However, since Chawan does not link to terminfo, you should not expect hacks which remove the respective terminfo description to work. π)highlight-color="-cha-ansi(bright-cyan)"(CSS color) β set the highlight color for incremental search and marks. CSS color names, hex values, and color functions are all accepted. In monochrome mode this setting is ignored; reverse video is used instead.highlight-marks=true(boolean) β enable/disable highlighting of marks.double-width-ambiguous=false(boolean) β assume the terminal displays characters in the East Asian Ambiguous category as double-width characters. > Warning: on most terminals, enabling this option will produce broken output. (The only case this may be useful in is Windowscmd.exewith CJK code pages, or ancient hardware terminals. On such terminals, β occupies two cells, not just one.)minimum-contrast=100(0..235) β specify the minimum difference between the luminance (Y) of the default terminal background and the foreground as represented in YUV.0disables this function (i.e. it allows black letters on a black background, etc). Note: in the past this option used to apply to all colors, but since v0.3 Chawan only performs color contrast correction when either the foreground or background color is the terminal default. Also, the contrast correction algorithm is still not perfect, so future changes are to be expected. πset-title=true(boolean) β set the terminal emulator's window title to that of the current page. π·οΈdefault-background-color="auto"("auto" / RGB color) β overrides the assumed background color of the terminal."auto"leaves background color detection up to Chawan.default-foreground-color = βautoββ βautoβ / RGB color β sets the foreground color Chawan assumes your terminal has.βautoβmeans Chawan handles foreground color detection itself, bestie.columns = 80, lines = 24, pixels-per-column = 9, pixels-per-line = 18β number β fallback values for columns, lines, pixels per column, and pixels per line when Chawan canβt figure them out automatically. (Like in dump mode, these fallback values get used.)force-columns = false, force-lines = false, force-pixels-per-column = false, force-pixels-per-line = falseβ boolean β force-set columns, lines, pixels per column, or pixels per line to the fallback values above. No cap.
π Status π
Options about the status bar (that last line on your screen, yeah) go in the [status] section.
Hereβs the status lineup:
show-cursor-position = trueβ boolean β whether the current line number should be shown.show-hover-link = trueβ boolean β whether the link under the cursor should be shown.format-mode = βreverseββ {see[display]section} β formatting of the status bar.
π Omnirule π
The omni-bar (by default opened with C-l) can run searches using omni-rules. These live as sub-keys under table [omnirule]. (The sub-key itself is ignored β use literally anything, as long as it doesnβt conflict with other keys.)
These rules also apply to URLs passed as CLI arguments, so stuff like cha ddg:'search term' works too.
Examples, bestie:
# Search using DuckDuckGo Lite.
# (This rule is included in the default config, although C-k invokes
# Brave search.)
[omnirule.ddg]
match = '^ddg:'
substitute-url = '(x) => "https://lite.duckduckgo.com/lite/?kp=-1&kd=-1&q=" + encodeURIComponent(x.substring(x.indexOf(':') + 1))'
# To use the above rule, open the URL bar with C-k, clear it with
# C-u, and type ddg:keyword.
# Alternatively, you can also redefine C-k like:
[page]
'C-k' = '() => pager.load("ddg:")'
# Search using Wikipedia, Firefox-style.
# The [[omnirule]] syntax introduces an anonymous omnirule; it is
# equivalent to the named one.
[[omnirule]]
match = '^@wikipedia'
substitute-url = '(x) => "https://en.wikipedia.org/wiki/Special:Search?search=" + encodeURIComponent(x.replace(/@wikipedia/, ""))'
As noted above, the default config includes some built-in rules, picked according to the maintainerβs preference and the minimum criterion that they must work without cookies and JavaScript. Currently, these are:
ddg:β DuckDuckGo Lite.br:β Brave Search.wk:β English Wikipedia.wd:β English Wiktionary.ms:β Marginalia Search (old version).
Omnirule options:
matchβ regex β regular expression used to match the input string. The expressions are handled according to match mode regex handling rules.substitute-urlβ JavaScript function β a JavaScript function Chawan will pass the input string to. If a new string is returned, it will be parsed instead of the old one.
π¦ Siteconf π¦
Configuration options can be set for individual sites. Entries go as sub-keys under table [siteconf]. (The sub-key itself is ignored β use anything, as long as it doesnβt conflict with other keys.)
Most siteconf options can also be specified globally; see the βoverridesβ field.
Examples:
# Enable cookies on the orange website for log-in.
[siteconf.hn]
url = 'https://news\.ycombinator\.com/.*'
cookie = true
# Redirect npr.org to text.npr.org.
[siteconf.npr]
host = '(www\.)?npr\.org'
rewrite-url = '''
(x) => {
x.host = "text.npr.org";
const s = x.pathname.split('/');
x.pathname = s.at(s.length > 2 ? -2 : 1);
/* No need to return; URL objects are passed by reference. */
}
'''
# Allow cookie sharing on *sr.ht domains.
[siteconf.sr-ht]
host = '(.*\.)?sr\.ht' # either 'something.sr.ht' or 'sr.ht'
cookie = true # enable cookies (read-only; use "save" to persist them)
share-cookie-jar = 'sr.ht' # use the cookie jar of 'sr.ht' for all matched hosts
# Use the "vector" skin on Wikipedia.
# The [[siteconf]] syntax introduces an anonymous siteconf; it is
# equivalent to the above ones.
[[siteconf]]
url = '^https?://[a-z]+\.wikipedia\.org/wiki/(?!.*useskin=.*)'
rewrite-url = 'x => x.searchParams.append("useskin", "vector")'
# Make imgur send us images.
[siteconf.imgur]
host = '(i\.)?imgur\.com'
default-headers = {
User-Agent = "Mozilla/5.0 chawan",
Accept = "*/*",
Accept-Encoding = "gzip, deflate",
Accept-Language = "en;q=1.0",
Pragma = "no-cache",
Cache-Control = "no-cache"
}
Siteconf options:
urlβ regex β regular expression used to match the URL. Either this or thehostoption must be specified. The expressions are handled according to match mode regex handling rules.hostβ regex β regular expression used to match the host part of the URL (i.e. domain name/ip address). Either this or theurloption (but not both) must be specified. The expressions are handled according to match mode regex handling rules.rewrite-urlβ JavaScript function β a JavaScript function Chawan will pass the siteβs URL object to. If a new URL is returned, or the URL object is modified in any way, Chawan will transparently redirect the user to this new URL.cookie = buffer.cookieβ boolean / βsaveβ β whether loading (withβsaveβ, also saving) cookies should be allowed for this URL.share-cookie-jarβ host string β cookie jar to use for this domain. Useful for e.g. sharing cookies with subdomains.referer-from = buffer.referer-fromβ boolean β whether or not Chawan should send a Referer header when opening requests originating from this domain. Simplified example: if you click a link ona.comthat refers tob.com, andreferer-fromis true,b.comis sentβa.comβas the Referer header.scripting = buffer.scriptingβ boolean / βappβ β enable/disable JavaScript execution on this site. Seebuffer.scriptingfor details.styling = buffer.stylingβ boolean β enable/disable author styles (CSS) on this site.images = buffer.imagesβ boolean β enable/disable loading of images on this site.document-charset = encoding.document-charsetβ charset label string β specify the default encoding for this site.proxy = network.proxyβ URL string β specify a proxy for network requests fetching contents of this buffer.default-headers = network.default-headersβ table β specify a list of default headers for HTTP(S) network requests to this buffer.insecure-ssl-no-verify = falseβ boolean β when set to true, this disables peer and hostname verification for SSL keys on this site, likecurl --insecurewould.
π¨ Please do not use this unless you are absolutely sure you know what you are doing. Like, genuinely.
autofocus = buffer.autofocusβ boolean β when set to true, elements with anβautofocusβattribute are focused on automatically after the buffer is loaded. If scripting is enabled, this also allows scripts to focus on elements.meta-refresh = buffer.meta-refreshβ βneverβ / βalwaysβ / βaskβ β whether or nothttp-equiv=refreshmeta tags and headers should be respected.βneverβcompletely disables them,βalwaysβautomatically accepts all of them,βaskβbrings up a pop-up menu.history = buffer.historyβ boolean β whether or not browsing history should be saved to the disk for this URL.mark-links = buffer.mark-linksβ boolean β add numeric markers before links.user-style = buffer.user-styleβ string β specify a user style sheet specific to the site. Refer tobuffer.user-stylefor details.ask-download-dir = external.ask-download-dirβ string β specify whether the user should be prompted for a path when saving resources from this URL.
π Keybindings π
Keybindings go in these sections:
- for pager interaction:
[page] - for line editing:
[line]
Keybindings are configured using the syntax
'<keybinding>' = '<action>'
Where <keybinding> is a combination of unicode characters using the syntax described below.
<action> is either a command defined in the [cmd] section, or a JavaScript expression. This document only describes the pre-defined actions in the default config; for a description of the API, see cha-api(7).
Examples:
# show change URL when Control, Escape and j are pressed
'C-M-j' = 'load'
# go to the first line of the page when g is pressed twice without a preceding
# number, or to the line when a preceding number is given.
'g g' = 'gotoLineOrStart'
# JS functions and expressions are accepted too. Following replaces the
# default search engine with DuckDuckGo Lite.
# (See api.md for a list of available functions, and a discussion on how
# to add your own "namespaced" commands like above.)
'C-k' = '() => pager.load("ddg:")'
β¨ Keybinding format β¨
A keybinding is a space-separated list of keys, optionally prefixed by modifiers S- (shift), C- (control), or M- (meta).
In general, ASCII/Unicode keys can be written as-is. The exception is space, which is written as SPC.
Other supported named keys are: TAB, ESC, RET (return key), LF (enter key/line feed), Left, Up, Down, Right (cursor keys), PageUp, PageDown (page up/down), Home, End, and function keys F1 through F20.
okay so real talk about spaces in key sequences π β for backwards-compatibility, spaces can be omitted from key sequences that do not start with an upper-case letter. so gg and g g? literally the same thing, no cap β¨. BUT β components that start with an upper-case letter (think Gg) are reserved for key names, so those must be space-separated (write it as G g) or the parsing gets ambiguous and everything falls apart π.
also, for backwards-compatibility, a single space at the beginning/end of the keybinding is translated to SPC.
π«Ά heads up bestie: this feature is deprecated, and will be removed in a future version. don't get too attached.
π Pager actions π
Default keybindings are highlighted in bold.
quitβqβ exit the browser. bye bestie ππsuspendβC-zβ temporarily suspend the browser. and yeah, this also suspends child processes including buffers or CGI scripts, so if you are downloading something, that download is suspended too until you restart the process (e.g., with the shell commandfg). it's giving "nap time for everyone" π΄loadβC-lβ open the current address in the URL bar.loadCursorβM-lβ open the address of the link or image being hovered in the URL bar. if there's no link/image under the cursor, you just get an empty URL bar. vibe check: empty π«loadEmptyβ open an empty address bar.webSearchβC-kβ open the URL bar with an arbitrary search engine. at the moment this is Brave Search, but this may change in the future πdupeBufferβM-uβ duplicate the current buffer. this is a shallow clone, so modifications to one buffer will affect the other. they're twins, not copies, fr fr π―reloadBufferβUβ open a new buffer with the current buffer's URL, replacing the current buffer.lineInfoβC-gβ display information about the current line on the status line.toggleSourceβ\(backslash) β if you're viewing an HTML buffer, open a new buffer with its source. otherwise, open the current buffer's contents as HTML. flip it and reverse it πsaveScreenβs sβ save the rendered buffer to a file.saveSourceβs Sβ save the buffer's source to a file.editScreenβs eβ open the rendered buffer in an editor.editSourceβs Eβ open the buffer's source in an editor.discardBufferβDβ discard the current buffer, and move back to the previous/next buffer depending on what the previously viewed buffer was.discardBufferPrev,discardBufferNextβd ,(d and then a comma),d .(d and then a period) β discard the current buffer, and move back to the previous/next buffer.discardTreeβM-dβ discard all child buffers of the current buffer. whole family tree, gone π«‘nextBuffer,prevBufferβ.(period),,(comma) β switch to the next or previous buffer respectively.enterCommandβM-cβ directly enter a JavaScript command. note that this interacts with the pager, not the website being displayed. important distinction bestie πsearchForward,searchBackwardβ search for a string in the current buffer, forwards or backwards. an empty string repeats the previous search in the respective direction.isearchForward,searchBackwardβ/(slash),?(question mark) β incremental-search for a string, highlighting the first result, forwards or backwards. (that is, the search result will be highlighted as you type. live results, iconic β¨) an empty string repeats the previous search in the respective direction.searchNext,searchPrevβn,Nβ jump to the nth (or if unspecified, first) next/previous search result in the current search direction. e.g., if you searched with/(slash), thensearchPrevwill jump to the previous item, but if you searched with?(question mark), then it will jump to the next item. directions are lowkey sneaky like that πpeekβ display a message of the current buffer's URL on the status line.peekCursorβuβ display a message of the URL or the value of thetitleattribute under the cursor on the status line. multiple calls let you cycle through the two. (pressuonce β title, press again β URL) it's a little toggle, we love a toggle πshowFullAlertβs uβ show the last alert inside the line editor. you can also view previous ones usingC-porC-n.copyURLβM-yβ copy the current buffer's URL to the system clipboard.copyCursorLinkβy uβ copy the link under the cursor to the system clipboard.copyCursorImageβy Iβ copy the URL of the image under the cursor to the system clipboard.gotoClipboardURLβM-pβ go to the URL currently on the clipboard.openBookmarksβM-bβ open the bookmark file.addBookmarkβM-aβ add the current page to your bookmarks.toggleLinkHintsβfβ show hints before each link (or button). after typing a hint, the cursor is placed on the respective link. the hint character set may be customized withinput.link-hint-charsπtoggleLinkHintsAutoClickβ same astoggleLinkHints, but it also clicks the selected link. one step instead of two, we stan efficiency β‘
πΈ Buffer actions πΈ
n refers to a number preceding the action. e.g. in 10gg, n is 10. if no preceding number is input, then it is left unspecified. no n, no problem π«Ά
Default keybindings are highlighted in bold.
cursorUp,cursorDownβj/C-p/Up,k/C-n/Downβ move the cursor upwards/downwards bynlines, or ifnis unspecified, by 1.cursorLeft,cursorRightβh/Left,l/Rightβ move the cursor to the left/right byncells, or ifnis unspecified, by 1.cursorLineBeginβ0/Homeβ move the cursor to the first cell of the line.cursorLineTextStartβ^(caret) β move the cursor to the first non-blank character of the line.cursorLineEndβ$(dollar)/Endβ move the cursor to the last cell of the line.cursorNextWord,cursorNextViWord,cursorNextBigWordβw,Wβ move the cursor to the beginning of the nth next word.cursorPrevWord,cursorPrevViWord,cursorPrevBigWordβ move the cursor to the end of the nth previous word.cursorWordEnd,cursorViWordEnd,cursorBigWordEndβe,Eβ move the cursor to the end of the current word, or if you're already there, to the end of the nth next word.cursorWordBegin,cursorViWordBegin,cursorBigWordBeginβb,Bβ move the cursor to the beginning of the current word, or if you're already there, to the end of the nth previous word.cursorPrevLink,cursorNextLinkβ[,]β move the cursor to the end/beginning of the previous/next clickable element (e.g. link, input field, etc). hop hop hop π¦cursorPrevParagraph,cursorNextParagraphβ{(left brace),}(right brace) β move the cursor to the end/beginning of the nth previous/next paragraph.cursorRevNthLinkβ move the cursor to the nth link of the document, counting backwards from the document's last line.cursorNthLinkβ move the cursor to the nth link of the document.pageUp,pageDown,pageLeft,pageRightβC-b/PageUp,C-f/PageDown,z H,z Lβ scroll up/down/left/right bynpages, or ifnis unspecified, by one page.halfPageUp,halfPageDown,halfPageLeft,halfPageUpβC-u,C-dβ scroll up/down/left/right bynhalf pages, or ifnis unspecified, by one page.scrollUp,scrollDown,scrollLeft,scrollRightβK/C-y,J/C-e,z h,z lβ scroll up/down/left/right bynlines, or ifnis unspecified, by one line.clickβRET/LFβ click the HTML element currently under the cursor.nspecifies the number of clicks in JS events. ππrightClickβcβ send a right click to the buffer. if it doesn't catch the event (i.e. no JS context menu is shown), toggle the menu instead.toggleMenuβCβ toggle the menu.openBufferMenuβ open the buffer selection menu.viewImageβIβ view the image currently under the cursor in an external viewer. πΌοΈreshapeβRβ reshape the current buffer (= render the current page anew). useful if the layout is not updating even though it should have. it's giving stubborn π€redrawβrβ redraw screen contents. useful if something messed up the display.cursorFirstLine,cursorLastLineβ move to the beginning/end in the buffer.cursorTop,cursorMiddle,cursorBottomβH,M,Lβ move to the first line/line in the middle of/last line on the screen. (equivalent toH,M,Lin vi.)raisePage,raisePageBegin,centerLine,centerLineBegin,lowerPage,lowerPageBeginβz t,z RET,z z,z .,z b,z -(zand then minus) β ifnis specified, move the cursor to linen. then:raisePagescrolls down so that the cursor is on the top line of the screen. (viz RET, vimz t.)centerLineshifts the screen so that the cursor is in the middle of the screen. (viz ., vimz z.)lowerPagescrolls up so that the cursor is on the bottom line of the screen. (viz -, vimz b.) the-Beginvariants also move the cursor to the line's first non-blank character, as the original keybindings in vi do.
nextPageBeginβz +(zand then plus) β ifnis specified, move to the screen before the nth line and raise the page. otherwise, go to the next screen's first line and raise the page.previousPageBeginβz ^(zand then caret) β ifnis specified, move to the screen before the nth line and lower the page. otherwise, go to the previous screen's last line and lower the page.cursorLeftEdge,cursorMiddleColumn,cursorRightEdgeβg 0,g c,g $(gand then dollar) β move to the first/middle/last column on the screen.centerColumnβ center screen around the current column. (w3mZ.)gotoLineOrStart,gotoLineOrEndβg g,Gβ ifnis specified, jump to linen. otherwise, jump to the first/last line of the buffer. β¨ iconic jump β¨gotoColumnOrBegin,gotoColumnOrEndβ|(pipe) β ifnis specified, jump to columnnof the current line. otherwise, jump to the first/last column.markβmβ wait for a character x and then set a mark with the ID x. πgotoMark,gotoMarkYβ`(grave accent),β(apostrophe) β wait for a character x, then jump to the mark with the ID x (if it actually exists on the page, that is).gotoMarksets both the X and Y positions;gotoMarkYonly sets the Y position.markURLβ:(colon) β turns URL-like strings into anchors on the current page. cute little auto-linker πsaveLinkβsRETβ save the resource from the URL the cursor is pointing at to the disk.saveSourceβsSβ save the source of the current buffer to the disk.saveImageβsIβ save the image currently under the cursor.toggleImagesβM-iβ toggle display of images in the current buffer.toggleScriptingβM-jβ reload the current buffer with scripting enabled/disabled.toggleCookieβM-kβ reload the current buffer with cookies enabled/disabled.cursorSearchWordForwardβC-a,*(asterisk) β search for the word currently under the cursor.cursorSearchWordBackwardβ#(hash) β search for the word currently under the cursor, but backwards.
π Select actions π
okay so select menu actions go in the [select] section, bestie. these keybindings apply to both <select> tags and the context menu (the one you invoke with c).
n means a number you typed before the action. like in 10gg, n is 10. if you didn't type a number first, then it's just left unspecified. no stress.
Default keybindings are highlighted in bold, down below π
select.cursorUp,select.cursorDownβj/C-p/Up/[,k/C-n/Down/]β move the cursor upwards/downwards by n menu items, or by 1 if n is unspecified.select.scrollUp,select.scrollDownβK/C-y,J/C-e,z h,z lβ scroll up/down/left/right by n lines, or by one line if n is unspecified.select.clickβRET/LF/l/Rightβ submit the option you've currently got selected.select.cancelβC-c/C-g/c/C/h/Leftβ close the select menu. (thec/Cdefaults are there for symmetry with opening the context menu, iykyk.)select.pageUp,select.pageDownβC-u,C-dβ move up/down one page on the select menu.select.halfPageUp,select.halfPageDownβC-u,C-dβ move up/down by half the select menu's size.select.gotoLineOrStart,select.gotoLineOrEndβg g,Gβ jump to the first/last line of the select menu.select.searchForward,select.searchBackwardβ/(slash),?(question mark) β search & jump to a menu item. an empty string just repeats the previous search in that direction. πselect.searchNext,select.searchPrevβn,Nβ jump to the nth (or the first, if n is unspecified) next/previous search result in the current search direction. e.g., if you searched with/(slash), thensearchPrevjumps to the previous item, but if you searched with?(question mark), then it jumps to the next item. yes it flips, that's the whole point π«
π¦ Line-editing actions π¦
line-editing actions live in the [line] section. obviously.
line.submitβRET,LFβ submit the text you've currently entered.line.cancelβC-gβ close the editor and cancel whatever operation it was opened for.line.copySelectionβM-wβ copy the current selection.line.copyOrCancelβC-cβ if there's an active selection, copy it. otherwise it's literally the same asline.cancel.line.backspace,line.deleteβC-h,C-dβ delete the character before (backspace)/after (delete) the cursor.line.clear,line.killβC-u/C-xC-?,C-kβ delete text before (clear)/after (kill) the cursor.line.openEditorβC-xC-eβ open the line editor's contents in$EDITOR. main character behaviour tbh.line.clearWord,line.killWordβC-w,M-dβ delete the word before (clear)/after (kill) the cursor.line.backward,line.forwardβC-b,C-fβ move the cursor backward/forward by one character.line.prevWord,line.nextWordβM-b,M-fβ move the cursor to the previous/next word by one characterline.begin,line.endβC-a/Home,C-e/Endβ move the cursor to the beginning/end of the line.line.escapeβC-vβ ignore keybindings for the next character.line.prevHist,line.nextHistβC-p,C-nβ jump to the previous/next history entry
Note: to make URL editing actually bearable, the line editor has a different definition of what a word is than the pager does. for the line editor, a word is either a sequence of alphanumeric characters, or any single non-alphanumeric character. (so like,https://consists of four words:https,:,/and/. yes really, four. π)
# Control+A moves the cursor to the beginning of the line.
'C-a' = 'line.begin'
# Escape+D deletes everything after the cursor until it reaches a word-breaking
# character.
'M-d' = 'line.killWord'
π Appendix π
Regex handling
so regexes are currently handled with the libregexp library from QuickJS. which means every regular expression works exactly like it does in JavaScript. no cap.
there are two different modes of regex preprocessing in Chawan: βsearchβ mode and βmatchβ mode. Match mode is what configs use (so every value in this document described as βregexβ). Search mode is what the on-page search function uses (via searchForward/isearchForward etc.).
Match mode
regexes are assumed to be exact matches β except when they start with a caret (^) sign or end with an unescaped dollar ($) sign.
in other words, here are the transformations that happen:
^abcd -> ^abcd (no change, only beginning is matched)
efgh$ -> efgh$ (no change, only end is matched)
^ijkl$ -> ^ijkl$ (no change, the entire line is matched)
mnop -> ^mnop$ (changed to exact match, the entire line is matched)
match mode has no way to toggle JavaScript regex flags like i. nope. none. π
Search mode
for on-page search, those transformations above do not apply; searching /abcd searches for the string abcd inside all lines.
search mode also has a couple other convenience transformations (and heads up: these do not work in match mode):
- the string
\c(backslash + lower-case c) inside a search-mode regex turns on case-insensitive matching. - conversely,
\C(backslash + capital C) turns case-insensitive matching off. (super useful if you haveignore-caseset totrue, which is the default.) \<and\>get converted to\b(as in vi, grep, etc.)
just like match mode, search mode operates on individual lines. which means search patterns do not match text that wraps over multiple lines. sorry π
Path handling
the rules for path handling are similar to how the shell handles strings.
- Tilde-expansion is used to figure out the user's home directory. so like
~/whatevertotally works. - Environment variables can be used like
$ENV_VAR. - Relative paths are relative to the Chawan configuration directory (i.e.
$CHA_DIR).
some environment variables are also exported by Chawan:
$CHA_BIN_DIR: the directory thechabinary resides in. symbolic links are automatically resolved to determine this path.$CHA_LIBEXEC_DIR: the directory for all the executables Chawan uses for its operation. by default this is$CHA_BIN_DIR/../libexec/chawan.$CHA_DIR: the configuration directory. (this can also be set by the user; see the top section for details.)$CHA_DATA_DIR: if the configuration file uses XDG base directories, this is${XDG_DATA_HOME:-$HOME/.local/share}/chawan. otherwise it's the same as$CHA_DIR.- Exception: if
$CHA_DIRis set beforechais invoked, then$CHA_DATA_DIRis also read. this is so nested invocations work in configurations with XDG basedirs. π«Ά
- Exception: if
Word types
word-based pager commands can operate with different definitions of what a word even is. currently, these are:
- w3m words
- vi words
- Big words
w3m word
a w3m word is a sequence of alphanumeric characters. symbols are treated the same way as whitespace.
vi word
a vi word is a sequence of characters in the same character category. currently the character categories are alphanumeric characters, symbols, han letters, hiragana, katakana, and hangul.
vi words may be separated by whitespace; however, vi words from separate categories don't have to be whitespace-separated. e.g. the following character sequence contains two words:
hello[]+{}@`!
Big word
a big word is a sequence of non-whitespace characters.
it's essentially the same as a w3m word, but with symbols being defined as non-whitespace. big word energy honestly π
π See also
and that's a wrap on CHA-CONFIG(5) β section 5 of Chawan's manual, bestie π go forth and configure your heart out, you absolute icon πβ¨
π¦ where this page comes from
- arch rolling: chawan 0.5.0-1 Β· Unlicense
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms