pax_global_header 0000666 0000000 0000000 00000000064 15202323131 0014502 g ustar 00root root 0000000 0000000 52 comment=b9df04cc518b9cca5f1b0d007d4359b1c93e2118 chawan-v0.4.0/ 0000775 0000000 0000000 00000000000 15202323131 0013132 5 ustar 00root root 0000000 0000000 chawan-v0.4.0/.build.yml 0000664 0000000 0000000 00000001247 15202323131 0015036 0 ustar 00root root 0000000 0000000 image: alpine/edge packages: - nim - brotli-dev - brotli-static - libssh2-dev - libssh2-static - openssl-dev - openssl-libs-static - zlib-dev - zlib-static - build-base - xz sources: - "https://git.sr.ht/~bptato/chawan" artifacts: - chawan/chawan-linux-amd64.tar.xz tasks: - linux-amd64: | cd chawan # Set flags sed -i '/^STATIC_LINK ?=/s/0/1/' Makefile export LDFLAGS="-lz" export CFLAGS="-ffile-prefix-map=$(pwd)/=" # Build make -j$(nproc) # Prepare archive dir=chawan-linux-amd64 mkdir "$dir" cp -rP target/ doc/ Makefile cha "$dir" # Create archive tar caf "$dir".tar "$dir" --owner=root --group=root xz "$dir".tar chawan-v0.4.0/.gitignore 0000664 0000000 0000000 00000000046 15202323131 0015122 0 ustar 00root root 0000000 0000000 /a /cha /target/ /.obj/ /test/net/run chawan-v0.4.0/Makefile 0000664 0000000 0000000 00000030353 15202323131 0014576 0 ustar 00root root 0000000 0000000 # Public variables. NIM ?= nim NIMC ?= $(NIM) c OBJDIR ?= .obj OUTDIR ?= target # These paths are quoted in recipes. PREFIX ?= /usr/local MANPREFIX ?= $(PREFIX)/share/man MANPREFIX1 ?= $(MANPREFIX)/man1 MANPREFIX5 ?= $(MANPREFIX)/man5 MANPREFIX7 ?= $(MANPREFIX)/man7 TARGET ?= release PANDOC ?= pandoc PKG_CONFIG ?= pkg-config # Note: this is not a real shell substitution. # The default setting is at {the binary's path}/../libexec/chawan. # You may override it with any path if your system does not have a libexec # directory. # (This way, `cha' can be directly executed without installation.) LIBEXECDIR ?= \$$CHA_BIN_DIR/../libexec/chawan # I won't take this from the environment for obvious reasons. Please override it # in the make command if you must, or (preferably) fix your environment so it's # not needed. DANGER_DISABLE_SANDBOX = 0 # Private variables. # If overridden, take libexecdir that was specified. # Otherwise, just install to libexec/chawan. ifeq ($(LIBEXECDIR),\$$CHA_BIN_DIR/../libexec/chawan) LIBEXECDIR_CHAWAN = "$(DESTDIR)$(PREFIX)/libexec/chawan" else LIBEXECDIR_CHAWAN = $(LIBEXECDIR) endif # Static linking. STATIC_LINK ?= 0 # These paths are quoted in recipes. OUTDIR_TARGET = $(OUTDIR)/$(TARGET) OUTDIR_BIN = $(OUTDIR_TARGET)/bin OUTDIR_LIBEXEC = $(OUTDIR_TARGET)/libexec/chawan OUTDIR_CGI_BIN = $(OUTDIR_LIBEXEC)/cgi-bin OUTDIR_MAN = $(OUTDIR_TARGET)/share/man # Force a poll implementation. 0 - do not force, 1 - poll, 2 - select. # This is an intentionally undocumented debugging flag; open a ticket if # you need it on a certain system, because it has subtle issues without # platform-specific adjustments. FORCE_POLL_MODE ?= 0 chac_flags = # Nim compiler flags ifeq ($(TARGET),debug) FLAGS += -d:debug --debugger:native CFLAGS += -DDUMP_LEAKS=1 else ifeq ($(TARGET),release) chac_flags = -s FLAGS += -d:release -d:strip -d:lto else ifeq ($(TARGET),release0) FLAGS += -d:release --stacktrace:on else ifeq ($(TARGET),release1) FLAGS += -d:release --debugger:native endif ssl_link = http gemini sftp tohtml_link = gopher2html md2html ansi2html gmi2html dirlist2html img2html protocols_bin = file ftp gopher finger man spartan chabookmark stbi jebp sixel \ canvas resize nanosvg ssl converters_bin = uri2html tohtml tools_bin = urlenc nc protocols = $(protocols_bin) $(ssl_link) converters = $(converters_bin) $(tohtml_link) tools = $(tools_bin) urldec scripts = init.jsb ifeq ($(STATIC_LINK),1) LDFLAGS += -static endif ifeq ($(FORCE_POLL_MODE),2) # for seccomp CFLAGS += -DCHA_FORCE_SELECT endif FLAGS += $(foreach flag,$(CFLAGS),-t:$(flag)) FLAGS += $(foreach flag,$(LDFLAGS),-l:$(flag)) FLAGS += -d:disableSandbox=$(DANGER_DISABLE_SANDBOX) FLAGS += -d:forcePollMode=$(FORCE_POLL_MODE) ssl_libs = libssl libcrypto libbrotlidec libbrotlicommon libssh2 ssl_flags = $(FLAGS) ssl_cflags := $(shell $(PKG_CONFIG) --cflags $(ssl_libs) || echo _cha_error) ifeq ($(ssl_cflags),_cha_error) $(error failed to find some dependencies) endif ssl_ldflags := $(shell $(PKG_CONFIG) --libs $(ssl_libs) || echo _cha_error) ifeq ($(ssl_ldflags),_cha_error) $(error failed to find some dependencies) endif ssl_flags += $(foreach flag,$(ssl_cflags),-t:$(flag)) ssl_flags += $(foreach flag,$(ssl_ldflags),-l:$(flag)) export CC CFLAGS LDFLAGS PANDOC binaries = $(OUTDIR_BIN)/cha $(OUTDIR_BIN)/mancha binaries += $(foreach bin,$(protocols),$(OUTDIR_CGI_BIN)/$(bin)) binaries += $(foreach bin,$(converters),$(OUTDIR_LIBEXEC)/$(bin)) binaries += $(foreach bin,$(tools),$(OUTDIR_LIBEXEC)/$(bin)) binaries += $(foreach bin,$(scripts),$(OUTDIR_LIBEXEC)/$(bin)) .PHONY: all all: $(binaries) ln -sf "$(OUTDIR)/$(TARGET)/bin/cha" cha ifeq ($(shell uname), Linux) chaseccomp = lib/chaseccomp/chaseccomp.o lib/chaseccomp/chaseccomp.o: .FORCE (cd lib/chaseccomp && $(MAKE)) .FORCE: endif twtstr = src/utils/twtstr.nim src/types/opt.nim dynstream = src/io/dynstream.nim chafile = src/io/chafile.nim $(dynstream) myposix = src/utils/myposix.nim connectionerror = src/server/connectionerror.nim lcgi = $(myposix) $(chafile) $(twtstr) $(sandbox) $(connectionerror) \ adapter/protocol/lcgi.nim lcgi_ssl = $(lcgi) adapter/protocol/lcgi_ssl.nim sandbox = src/utils/sandbox.nim $(chaseccomp) tinfl = adapter/protocol/tinfl.h # lib/*0 has a 0 so that it doesn't conflict with the old submodules. # git can't deal with this, it seems. $(OUTDIR_BIN)/cha: src/*.nim src/*/*.nim src/*/*.c res/* lib/chame0/chame/* \ lib/monoucha0/monoucha/* lib/monoucha0/monoucha/qjs/* $(chaseccomp) \ res/charwidth_gen.nim nim.cfg @mkdir -p "$(OUTDIR_BIN)" $(NIMC) --nimcache:"$(OBJDIR)/$(TARGET)/cha" -d:libexecPath=$(LIBEXECDIR) \ $(FLAGS) -o:"$(OUTDIR_BIN)/cha" src/main.nim $(OUTDIR_BIN)/mancha: adapter/tools/mancha @mkdir -p "$(OUTDIR_BIN)" install -m755 $< "$(OUTDIR_BIN)" unicode_version = 17.0.0 .PHONY: unicode_gen unicode_gen: @printf 'Download EastAsianWidth.txt from www.unicode.org? (y/n) ' @read res; if test "$$res" = "y"; then \ cha -d 'https://www.unicode.org/Public/$(unicode_version)/ucd/EastAsianWidth.txt' >res/EastAsianWidth.txt; \ fi $(NIMC) --nimcache:"$(OBJDIR)/charwidth_gen_cache" -d:danger -o:"$(OBJDIR)/gencharwidth" res/gencharwidth.nim $(OBJDIR)/gencharwidth > res/charwidth_gen.nim~ mv res/charwidth_gen.nim~ res/charwidth_gen.nim $(OUTDIR_CGI_BIN)/man: $(lcgi) src/utils/lrewrap.nim \ lib/monoucha0/monoucha/libregexp.nim \ lib/monoucha0/monoucha/qjs/libregexp.* \ lib/monoucha0/monoucha/qjs/libunicode.* \ lib/monoucha0/monoucha/qjs/cutils.* $(OUTDIR_CGI_BIN)/file: $(lcgi) $(OUTDIR_CGI_BIN)/ftp: $(lcgi) $(OUTDIR_CGI_BIN)/ssl: adapter/protocol/http.nim adapter/protocol/gemini.nim \ adapter/protocol/sftp.nim $(lcgi_ssl) $(sandbox) $(tinfl) $(OUTDIR_CGI_BIN)/stbi: adapter/img/stbi.nim adapter/img/stb_image.h \ adapter/img/stb_image_write.h $(lcgi) $(OUTDIR_CGI_BIN)/jebp: adapter/img/jebp.h $(lcgi) $(OUTDIR_CGI_BIN)/sixel: src/types/color.nim $(lcgi) $(OUTDIR_CGI_BIN)/canvas: src/types/canvastypes.nim src/types/path.nim \ src/io/packetreader.nim src/types/color.nim adapter/img/stb_image.h \ $(lcgi) $(OUTDIR_CGI_BIN)/resize: adapter/img/stb_image_resize.h $(lcgi) $(OUTDIR_CGI_BIN)/nanosvg: adapter/img/nanosvg.nim adapter/img/nanosvg.h \ adapter/img/nanosvgrast.h $(lcgi) $(OUTDIR_LIBEXEC)/urlenc: $(twtstr) $(chafile) $(OUTDIR_LIBEXEC)/nc: $(lcgi) $(OUTDIR_LIBEXEC)/tohtml: adapter/format/ansi2html.nim adapter/format/dirlist2html.nim \ adapter/format/gmi2html.nim adapter/format/gopher2html.nim \ adapter/format/md2html.nim adapter/format/img2html.nim \ $(twtstr) $(chafile) $(dynstream) src/types/color.nim $(foreach it,$(ssl_link),$(OUTDIR_CGI_BIN)/$(it)): $(OUTDIR_CGI_BIN)/ssl (cd "$(OUTDIR_CGI_BIN)" && ln -sf ssl $(notdir $@)) $(foreach it,$(tohtml_link),$(OUTDIR_LIBEXEC)/$(it)): $(OUTDIR_LIBEXEC)/tohtml (cd "$(OUTDIR_LIBEXEC)" && ln -sf tohtml $(notdir $@)) $(OUTDIR_CGI_BIN)/%: adapter/protocol/%.nim adapter/nim.cfg @mkdir -p "$(OUTDIR_CGI_BIN)" $(NIMC) $(FLAGS) --nimcache:"$(OBJDIR)/$(TARGET)/$(notdir $@)" -o:"$@" $< $(OUTDIR_CGI_BIN)/ssl: adapter/protocol/ssl.nim adapter/nim.cfg @mkdir -p "$(OUTDIR_CGI_BIN)" $(NIMC) $(ssl_flags) --nimcache:"$(OBJDIR)/$(TARGET)/$(notdir $@)" -o:"$@" $< $(OUTDIR_CGI_BIN)/%: adapter/protocol/% @mkdir -p "$(OUTDIR_CGI_BIN)" install -m755 $< "$(OUTDIR_CGI_BIN)" $(OUTDIR_LIBEXEC)/%: adapter/format/% @mkdir -p "$(OUTDIR_LIBEXEC)" install -m755 $< "$(OUTDIR_LIBEXEC)" $(OUTDIR_CGI_BIN)/%: adapter/img/%.nim adapter/nim.cfg @mkdir -p "$(OUTDIR_CGI_BIN)" rm -rf "$(OBJDIR)/$(TARGET)/$(notdir $@)" $(NIMC) $(FLAGS) --nimcache:"$(OBJDIR)/$(TARGET)/$(notdir $@)" -o:"$@" $< $(OUTDIR_LIBEXEC)/%: adapter/format/%.nim adapter/nim.cfg @mkdir -p "$(OUTDIR_LIBEXEC)" $(NIMC) $(FLAGS) --nimcache:"$(OBJDIR)/$(TARGET)/$(notdir $@)" -o:"$@" $< $(OUTDIR_LIBEXEC)/%: adapter/tools/%.nim adapter/nim.cfg @mkdir -p "$(OUTDIR_LIBEXEC)" $(NIMC) $(FLAGS) --nimcache:"$(OBJDIR)/$(TARGET)/$(notdir $@)" -o:"$@" $< $(OUTDIR_LIBEXEC)/urldec: $(OUTDIR_LIBEXEC)/urlenc (cd "$(OUTDIR_LIBEXEC)" && ln -sf urlenc urldec) # Do not add FLAGS here, because that breaks cross-compilation. $(OBJDIR)/chac: src/chac.nim lib/monoucha0/monoucha/* lib/monoucha0/monoucha/qjs/* $(NIMC) -o:$@ $< $(OUTDIR_LIBEXEC)/%.jsb: src/%.js $(OBJDIR)/chac $(OBJDIR)/chac $(chac_flags) $< $@ doc/%.1: doc/%.md md2man ./md2man $< > $@~ mv $@~ $@ doc/cha-%.5: doc/%.md md2man ./md2man $< > $@~ mv $@~ $@ doc/cha-%.7: doc/%.md md2man ./md2man $< > $@~ mv $@~ $@ .PHONY: clean clean: rm -rf "$(OBJDIR)/$(TARGET)" (cd lib/chaseccomp && $(MAKE) clean) .PHONY: distclean distclean: clean rm -rf "$(OUTDIR)" manpages1 = cha.1 mancha.1 manpages5 = cha-config.5 cha-mailcap.5 cha-mime.types.5 cha-cgi.5 \ cha-urimethodmap.5 manpages7 = cha-protocols.7 cha-api.7 cha-troubleshooting.7 cha-image.7 cha-css.7 cha-terminal.7 manpages = $(manpages1) $(manpages5) $(manpages7) .PHONY: manpage manpage: $(manpages:%=doc/%) .PHONY: install install: mkdir -p "$(DESTDIR)$(PREFIX)/bin" install -m755 "$(OUTDIR_BIN)/cha" "$(DESTDIR)$(PREFIX)/bin" install -m755 "$(OUTDIR_BIN)/mancha" "$(DESTDIR)$(PREFIX)/bin" # intentionally not quoted mkdir -p $(LIBEXECDIR_CHAWAN)/cgi-bin for f in $(protocols_bin); do \ install -m755 "$(OUTDIR_CGI_BIN)/$$f" $(LIBEXECDIR_CHAWAN)/cgi-bin; \ done for f in $(converters_bin) $(tools_bin) $(scripts); \ do install -m755 "$(OUTDIR_LIBEXEC)/$$f" $(LIBEXECDIR_CHAWAN); \ done (cd $(LIBEXECDIR_CHAWAN) && ln -sf urlenc urldec) for f in $(ssl_link); do (cd $(LIBEXECDIR_CHAWAN)/cgi-bin && ln -sf ssl "$$f"); done for f in $(tohtml_link); do (cd $(LIBEXECDIR_CHAWAN) && ln -sf tohtml "$$f"); done mkdir -p "$(DESTDIR)$(MANPREFIX1)" for f in $(manpages1); do install -m644 "doc/$$f" "$(DESTDIR)$(MANPREFIX1)"; done mkdir -p "$(DESTDIR)$(MANPREFIX5)" for f in $(manpages5); do install -m644 "doc/$$f" "$(DESTDIR)$(MANPREFIX5)"; done mkdir -p "$(DESTDIR)$(MANPREFIX7)" for f in $(manpages7); do install -m644 "doc/$$f" "$(DESTDIR)$(MANPREFIX7)"; done .PHONY: uninstall uninstall: rm -f "$(DESTDIR)$(PREFIX)/bin/cha" rm -f "$(DESTDIR)$(PREFIX)/bin/mancha" # intentionally not quoted for f in $(protocols); do rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/$$f; done for f in $(converters) $(tools) $(scripts); do rm -f $(LIBEXECDIR_CHAWAN)/$$f; done # We only want to uninstall binaries that the main distribution # includes or has ever included, but not those that the user might have # added. Some of these cannot be directly derived from our variables: # * png has been removed in favor of stbi # * data, about have been moved back into the main binary # * gmifetch has been replaced by gemini # * cha-finger has been renamed to finger rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/about rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/cha-finger rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/data rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/gmifetch rm -f $(LIBEXECDIR_CHAWAN)/cgi-bin/png rmdir $(LIBEXECDIR_CHAWAN)/cgi-bin || true rmdir $(LIBEXECDIR_CHAWAN) || true for f in $(manpages7); do rm -f "$(DESTDIR)$(MANPREFIX7)/$$f"; done for f in $(manpages5); do rm -f "$(DESTDIR)$(MANPREFIX5)/$$f"; done # moved to section 7 (and localcgi renamed to just cgi) for f in cha-protocols.5 cha-api.5 cha-troubleshooting.5 cha-image.5 cha-localcgi.5; do rm -f "$(DESTDIR)$(MANPREFIX5)/$$f"; done for f in $(manpages1); do rm -f "$(DESTDIR)$(MANPREFIX1)/$$f"; done test/net/run: test/net/run.nim $(NIMC) test/net/run.nim .PHONY: map map: $(NIM) $(FLAGS) r res/createmap.nim > src/encoding/charset_map.nim .PHONY: test_js test_js: (cd test/js && ./run.sh) .PHONY: test_layout test_layout: (cd test/layout && ./run.sh) .PHONY: test_md test_md: (cd test/md && ./run.sh) .PHONY: test_net test_net: test/net/run (cd test/net && ./run.sh) .PHONY: test_pager test_pager: test/pager/run.sh (cd test/pager && ./run.sh) $(OBJDIR)/chagashi_test: mkdir -p $(OBJDIR)/chagashi_test cp test/charset/data.tar.xz $(OBJDIR)/chagashi_test unxz $(OBJDIR)/chagashi_test/data.tar.xz tar xf $(OBJDIR)/chagashi_test/data.tar -C $(OBJDIR)/chagashi_test test_flags = --verbosity:0 .PHONY: test_charset test_charset: test/charset/run.sh $(OBJDIR)/chagashi_test (cd test/charset && ./run.sh) $(NIM) r $(test_flags) test/charset/basic.nim CGS_TESTDIR=$(OBJDIR)/chagashi_test $(NIM) r $(test_flags) test/charset/data.nim .PHONY: test_nim test_nim: test/nim/ttwtstr.nim (cd test/nim && $(NIM) r $(test_flags) ttwtstr.nim) .PHONY: test test: test_js test_layout test_net test_md test_pager test_charset test_nim chawan-v0.4.0/NEWS 0000664 0000000 0000000 00000015563 15202323131 0013643 0 ustar 00root root 0000000 0000000 0.4.0 (2026.05.17) * dupeBuffer/anchor navigation no longer forks buffer process * support VT420 * support DEC special graphics in ASCII mode * support all VP8L indexed color transforms * support pandoc-style definition list in markdown * support color, width, align, noshade properties on HR element * support Element#getAttributeNames * add status.format-mode (sets formatting of status bar) * add toggleLinkHintsAutoClick command (by Arthur Jacquin) * add saveScreen, editScreen commands; rename sourceEdit to editSource * add x-type, x-match, x-nc-match mailcap extensions (from w3mmee) * add mouse support to the line editor * improve keybinding format (mostly backwards-compatible; see cha-config(5)) * remove display.force-clear (shouldn't have ever been needed) * remove display.query-da1 (no longer needed) * remove deprecated special case in pager.load() with trailing newline * remove deprecated parentBuffer, prevSiblingBuffer, nextSiblingBuffer actions * remove MAILCAP_URL env var when executing mailcap entries (use %u instead) * make terminal querying asynchronous * work around FreeBSD vt(4) freezing on startup * work around a bug in URL standard that made us reject ed2k URLs * optimize out Sixel repaints when scrolling * drop excessive frames when the terminal/link cannot keep up * rework seccomp handling to support cross-compilation to incompatible archs * fix cached images not being cleared when a buffer is deleted * fix a NULL deref in jebp * fix y/n being truncated out of long ask() prompts * fix media queries not being re-evaluated on windowChange * fix load info not being set on cycling between buffers * fix color blending over body bgcolor * fix matching of nested subsequent sibling combinator * fix various CSS image sizing bugs * fix table row rendering order with multiple thead/tfoot children * fix absolutely positioned boxes not respecting min/max size constraints * fix percentage calc() output in color values * fix inline pre/nowrap not being flushed to the next line on overflow * fix bugs in our libregexp UTF-8 patch * fix various proxy authentication bugs * fix [attr|=value] and :lang() pseudo-class bugs * fix localStorage.key function * fix gotoLine malfunctioning in select menu * fix bug in negation of the minimum layout unit value * fix crash on Storage#key overflow on 32-bit targets * fix crash on calling status getter for unsent XHR * fix various charset decoder bugs * fix TypedArray handling * fix suspend() not suspending all processes * fix JS bindings having incorrect property descriptions * fix user/pass in Basic auth not being percent-decoded * fix decoding of data URLs that include a question mark 0.3.0 (2025.11.21) UI additions * wheel-scroll, side-wheel-scroll config options (by Tim Culverhouse) * new API functions Pager#traverse, Pager#navDirection, Pager#revDirection, Buffer#find * bracketed paste - pasting a URL now opens the URL bar automatically * "copy URL", "copy selection" now works over SSH when OSC 52 is supported * "hints mode" for jumping to specific links on the page (default keybinding is `f`, configurable using `input.link-hint-chars`) * added loaded stylesheet/image counters --- CSS additions * monochrome, color, color-index media queries * implement
\n")
let ps = newPosixStream(STDIN_FILENO)
var buffer {.noinit.}: array[4096, char]
while true:
state.flushOutbuf()
let n = ps.read(buffer)
if n <= 0:
break
state.processData(buffer.toOpenArray(0, n - 1))
if standalone:
state.puts("")
state.flushOutbuf()
{.pop.} # raises: []
chawan-v0.4.0/adapter/format/dirlist2html.nim 0000664 0000000 0000000 00000010464 15202323131 0021175 0 ustar 00root root 0000000 0000000 {.push raises: [].}
import std/algorithm
import std/os
import io/chafile
import types/opt
import utils/twtstr
type DirlistItemType = enum
ditFile, ditLink, ditDir
type DirlistItem = ref object
name: string # real name
dname: string # display name
modified: string # date last modified
case t: DirlistItemType
of ditLink:
linkto: string
of ditFile:
nsize: int64
of ditDir:
discard
proc printDirlist(f: ChaFile; items: openArray[DirlistItem]): Opt[void] =
?f.writeLine("[Upper Directory]" line &= "" & htmlEscape(item.dname) & "" line &= " | " line &= htmlEscape(item.modified) if item.t == ditFile: line &= ' ' & convertSize(uint64(max(item.nsize, 0))) elif item.t == ditLink: line &= " -> " & htmlEscape(item.linkto) line &= " |
\f[R] tags.)
.IP \(bu 2
\f[CR]text\-transform\f[R] accepts the keyword
\f[CR]\-cha\-half\-width\f[R], which has the opposite effect as
\f[CR]full\-width\f[R].
.RS 2
.PP
This can be used in user style sheets to compress distracting ruby text:
\f[CR]rt{text\-transform: \-cha\-half\-width}\f[R].
Characters without half\-width counterparts are left intact, except
hiragana is treated as katakana.
.RE
.IP \(bu 2
The \f[CR]\-cha\-colspan\f[R] and \f[CR]\-cha\-rowspan\f[R] properties
have the same effect as the \f[CR]colspan\f[R] and \f[CR]rowspan\f[R]
attributes on tables.
.IP \(bu 2
The \f[CR]:\-cha\-first\-node\f[R] and \f[CR]:\-cha\-last\-node\f[R]
pseudo\-classes apply to elements that have no preceding/subsequent
sibling node that is either an element node or a text node with
non\-whitespace contents.
(Modeled after \f[CR]:\-moz\-first\-node\f[R] and
\f[CR]:\-moz\-last\-node\f[R].)
.IP \(bu 2
If \f[CR]buffer.mark\-links\f[R] is set, the
\f[CR]::\-cha\-link\-marker\f[R] pseudo\-element will be generated on
all anchor elements.
.IP \(bu 2
In hints mode (by default, the \f[CR]f\f[R] key) the markers are
implemented by generating \f[CR]::\-cha\-link\-hint\f[R] on all
applicable elements.
So you can change the marker background in your \f[CR]user\-style\f[R]
(\f[CR][buffer]\f[R] section in \f[CR]config.toml\f[R]):
.RS 2
.IP
.EX
\f[BI]::\-cha\-link\-hint\f[R] { \f[B]background\f[R]: gainsboro }
.EE
.RE
.IP \(bu 2
The \f[CR]\-cha\-content\-type\f[R] media feature can be used to filter
documents for their content type.
For example, you can add
.RS 2
.IP
.EX
\f[B]\(atmedia\f[R] (\-cha\-content\-type: \(dqtext/markdown\(dq) { body { \f[B]width\f[R]: 80ch } }
.EE
.PP
to your \f[CR]user\-style\f[R] to set the body width of all markdown
documents to 80 characters.
(The string is matched case\-insensitively.)
.RE
.SS Rendering quirks
These are willful violations of the standard, usually made to better fit
the display model inherent to projecting the web to a cell\-based
screen.
.SS User agent style sheet
The user agent style sheet is a combination of the styles suggested by
the HTML standard and a CSS port of w3m\(cqs rendering.
In general, faithfulness to w3m is preferred over the standard\(cqs
suggestions, unless w3m\(cqs rendering breaks on existing websites.
.PP
Link colors differ depending on the terminal\(cqs color scheme.
.SS Sizing and positioning
Layout is performed on a finite canvas of coordinates represented by a
32\-bit fixed\-point number with 6 bits of precision.
After layout, these positions are divided by the cell width and/or
height, with the fractional part truncated.
(This is subject to change.)
.PP
In case of Kitty images, the fractional part is preserved, and is used
as an in\-cell offset.
.PP
The lengths \f[CR]1em\f[R] and \f[CR]1ch\f[R] compute to the cell height
and cell width respectively.
.PP
In outer inline boxes (\f[CR]inline\-block\f[R],
\f[CR]inline\-flex\f[R]) and \f[CR]list\-item\f[R] boxes, margins and
padding that are smaller than one cell (on the respective axis) are
ignored.
This does not apply to blockified inline boxes.
.PP
When calculating clip boxes (\f[CR]overflow: hidden\f[R] or
\f[CR]clip\f[R]), the clip box\(cqs offset is floored, and its size is
ceiled to the nearest cell\(cqs boundaries.
This means that \(lqwidth: 1px; overflow: hidden\(rq will still display
the first character of a text box.
.SS Scroll bars
Chawan does not have scroll bars, as they would complicate on\-page
navigation and would not work in dump mode.
Instead, the \(lqoverflow\-x/y\(rq properties are handled as follows.
.IP "1." 3
If \f[CR]overflow\f[R] is \f[CR]auto\f[R] or \f[CR]scroll\f[R], and the
intrinsic minimum size of the box is greater than its specified size,
then the former overrides the latter.
.IP "2." 3
Content that spills out of a scroll container on the X axis is
displayed, while content that spills out of a scroll container on the Y
axis is clipped.
.SS \f[CR]position: fixed\f[R], \f[CR]position: sticky\f[R]
To keep the document model static, these do not change their position
based on the viewport\(cqs scroll status.
Instead:
.IP \(bu 2
\f[CR]position: sticky\f[R] is treated as \f[CR]position: static\f[R],
except it also behaves as an absolute position container.
.IP \(bu 2
\f[CR]position: fixed\f[R] is placed at the bottom of the document.
.PP
Right now, \f[CR]position: fixed\f[R] is always positioned at the bottom
of the root element\(cqs margin box.
This breaks on pages that overflow it (e.g.
by setting \f[CR]height: 100%\f[R] on the root element), so it will be
moved to the bottom of its overflow box in the future.
.SS Color correction
Some authors only specify one of the foreground or the background color,
assuming a black\-on\-white canvas.
The \f[CR]display.minimum\-contrast\f[R] option adjusts the foreground
color so that text remains readable even if the terminal background does
not match this expectation.
(The exact algorithm is unspecified and subject to change.)
.PP
To avoid breaking spoiler mechanisms that rely on \(lqblack on black\(rq
text, color correction is not invoked on cells that have an RGB color
(typically specified by the author.)
.SS Borders
CSS borders are difficult to accurately display on a cell\-based
display.
So while the functionality exists, it has some limitations:
.IP \(bu 2
On tables, borders are always collapsed, even when
\f[CR]border\-collapse\f[R] is set to \f[CR]separate\f[R].
.IP \(bu 2
With \f[CR]border\-collapse: separate\f[R], the spacing between cells is
the largest of \f[CR]border\-spacing\f[R] times two and the cell width.
.IP \(bu 2
\f[CR]border\-*\-width\f[R] is interpreted as a binary value: a width of
0 results in no border, while any other width results in a border of a
single type.
If the width is smaller than one cell (in the respective direction), the
rest is subtracted from the margin (if there is any margin).
.IP \(bu 2
\f[CR]box\-sizing: border\-box\f[R] actually sets the padding box size,
so that borders rounded up to the cell size do not accidentally take all
space from the actual content.
(That in turn would cause problems if a child box set
\f[CR]overflow: hidden\f[R], etc.)
.SS See also
\f[B]cha\f[R](1)
chawan-v0.4.0/doc/cha-image.7 0000664 0000000 0000000 00000020627 15202323131 0015611 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-IMAGE" "7"
.SH Inline images
On terminals that support images, Chawan is capable of displaying
various image formats inline.
.SS Enabling images
There are actually two switches for images in the config:
.IP \(bu 2
buffer.images: this enables downloading images, \f[I]even if they cannot
be displayed\f[R].
This is the switch you typically need.
.IP \(bu 2
display.image\-mode: sets the inline image display method.
Defaults to \(lqauto\(rq, but may also be set to \(lqnone\(rq,
\(lqsixel\(rq, or \(lqkitty\(rq manually.
This switch is rarely useful.
.PP
In general, you only have to set \f[CR]buffer.images\f[R] to true:
.IP
.EX
\f[I]# in \(ti/.chawan/config.toml (or \(ti/.config/chawan/config.toml)\f[R]
\f[B][buffer]\f[R]
images = true
.EE
.PP
The \f[CR]image\-mode\f[R] switch is mainly useful if you want images to
be fetched, but not displayed (\(lqnone\(rq option).
It may also help if \(lqauto\(rq fails to detect the terminal\(cqs image
display capabilities; however, I am not aware of any terminal where this
can happen.
(If you find one, open a ticket.)
.SS Output formats
Supported output formats are:
.IP \(bu 2
The DEC Sixel format
.IP \(bu 2
The Kitty terminal graphics protocol
.PP
Support for other protocols (iTerm, MLTerm, etc.)
is not planned.
(To my knowledge, all image\-capable terminals support at least one of
the above two anyways.)
.PP
Support for environment\-specific hacks such as w3mimgdisplay, ueberzug,
etc.
is not planned.
.SS Sixel
Sixel is the most widely supported image format.
See \c
.UR https://arewesixelyet.com
.UE \c
\ to find a terminal that supports it.
.PP
Known quirks and implementation details:
.IP \(bu 2
XTerm needs extensive configuration for ideal sixel support.
In particular, you will want to set the decGraphicsID,
numColorRegisters, and maxGraphicSize attributes.
See \f[B]xterm\f[R](1) for details.
.IP \(bu 2
We assume private color registers are supported.
On terminals where they aren\(cqt (e.g.\ SyncTERM or hardware
terminals), colors will get messed up with multiple images on screen.
.IP \(bu 2
Zellij advertises Sixel support, but the feature is completely broken in
the current version, so Chawan specifically disables images in Zellij by
default.
In particular:
.RS 2
.IP \(bu 2
Zellij itself does no Sixel detection, emitting Sixel data even on
terminals that do not support it.
(A fairly puzzling bug, given the developers seem to be aware of the DA1
feature.)
.IP \(bu 2
On terminals that support Sixel, it fails to position images correctly,
with the misplaced images completely messing up layout.
.RE
.IP \(bu 2
We send XTSMGRAPHICS for retrieving the number of color registers; on
failure, we fall back to 256.
You can override color register count using the
\f[CR]display.sixel\-colors\f[R] configuration value.
.IP \(bu 2
Normally, Sixel encoding runs in two passes.
On slow computers, you can try setting
\f[CR]display.sixel\-colors = 2\f[R], which will skip the first pass
(but will also display everything in monochrome).
.IP \(bu 2
Transparency \f[I]is\f[R] supported, but looks weird because we
approximate an 8\-bit alpha channel with Sixel\(cqs 1\-bit alpha
channel.
Also, some terminals don\(cqt emulate it correctly \- when in doubt, try
XTerm (which does).
.IP \(bu 2
Terminal scroll (both with LF/RI and SU/SD) is used extensively to avoid
sending images several times.
Expect troubles on terminals that do not handle this correctly.
(For example, tmux is known to destroy images on scroll, so we avoid
using scroll there.)
.SS Kitty
On terminals that support it, Kitty\(cqs protocol is preferred over
Sixel.
Its main benefit is that images do not have to be sent again every time
a new slice of the image moves into the screen.
Support for full RGBA without quantization is another benefit.
.PP
Note: at the time of writing, tmux does not support the Kitty image
protocol.
While it is possible to hack Kitty images onto tmux nevertheless, this
requires significant concessions in display capabilities compared to the
regular Kitty protocol (or even Sixel).
Therefore, support for this hack is not planned.
.SS Input formats
Currently, the supported input formats are:
.IP \(bu 2
BMP, PNG, JPEG, GIF (through stb_image)
.IP \(bu 2
WebP (through JebP)
.IP \(bu 2
SVG (through NanoSVG)
.PP
More formats may be added in the future, provided there exists a
reasonably small implementation, preferably in the public domain.
(I do not want to depend on external image decoding libraries, but
something like stbi is OK to vendor.)
.SS Codec module system
All image codec implementations are specified by the URL scheme
\(lqimg\-codec+name:\(rq, where \(lqname\(rq is the MIME subtype.
e.g.\ for image/png, it is \(lqimg\-codec+png:\(rq.
(This indeed means that only \(lqimage\(rq MIME types can be used.)
.PP
Like all schemes, these are defined (and overridable) in the
urimethodmap file, and are implemented as local CGI programs.
These programs take an encoded image on stdin, and dump the decoded RGBA
data to stdout \- when encoding, vice versa.
.PP
This means that it is possible for users to define image decoders for
their preferred formats, or even override the built\-in ones.
(If you actually end up doing this for some reason, please send me a
mail so I can add it to the bonus directory.)
.PP
A codec can have one of, or both, \(lqdecode\(rq and \(lqencode\(rq
instructions; these are set in the path name.
So \(lqimg\-codec+png:decode\(rq is called for decoding PNGs, and
\(lqimg\-codec+png:encode\(rq for encoding them.
.PP
Headers are used for transferring metadata (like image dimensions), both
from the browser (input) and to the browser (output).
Detailed description of the decoder & encoder interfaces follows.
.SS decoding
When the path equals \(lqdecode\(rq, a codec CGI script must take a
binary stream of an encoded image on its standard input and print the
equivalent binary stream of big\-endian 8\-bit (per component) RGBA
values to stdout.
.PP
Input headers:
.IP \(bu 2
Cha\-Image\-Info\-Only: 1
.PP
This tells the image decoder to only send image metadata (i.e.\ size).
Technically, the decoder is free to fully decode the image, but this is
a waste of resources; the browser will ignore any output received after
headers.
.PP
Output headers:
.IP \(bu 2
Cha\-Image\-Dimensions: {width}x{height}
.PP
The size of the decoded image.
e.g.\ for 123x456, 123 is width and 456 is height.
.SS encoding
When the path equals \(lqencode\(rq, a codec CGI script must take a
binary stream of big\-endian 8\-bit (per component) RGBA values on its
standard input and print the equivalent encoded image to its standard
output.
.PP
Input headers:
.IP \(bu 2
Cha\-Image\-Dimensions: {width}x{height}
.PP
Specifies the dimensions of the input RGBA image.
This means that {width} * {height} * 4 == {size of data received on
stdin}.
.PP
The format is the same as above; in fact, the design is such that you
could directly pipe the output of decode to encode (and vice versa).
.IP \(bu 2
Cha\-Image\-Quality: {number}
.PP
The requested encoding quality, ranging from 1 to 100 inclusive
(i.e.\ 1..100).
It is up to the encoder to interpret this number.
.PP
(The stb_image JPEG encoder uses this.)
.PP
Output headers:
.PP
Currently, no output headers are defined for encoders.
.SS Skipping copies with mmap
The naive implementation of the above system would have to copy the
output at least twice when an image is resized.
To skip these copies, stdin and/or stdout is (currently) a file in the
tmp directory for:
.IP \(bu 2
decode stdin, when the image is already downloaded
.IP \(bu 2
decode stdout, always
.IP \(bu 2
encode stdin, always
.PP
This makes it possible to mmap stdin/stdout instead of streaming through
them with read and write.
When doing this, mind the following:
.IP \(bu 2
When reading, you must check your initial position in the file with
lseek.
.IP \(bu 2
When writing, your headers are part of the output.
At the very least, you must place a newline at the file\(cqs beginning.
.IP \(bu 2
mmapping for write is slower than streaming the data with
\f[CR]write\f[R].
The only reason to mmap for write is to save memory when you can\(cqt
stream the output.
.IP \(bu 2
This \f[I]is\f[R] an implementation detail, and might change at any time
in the future (e.g.\ if we add a \(lqno cache files\(rq mode).
Always check for S_ISREG to ensure that you are actually dealing with a
file.
(Use io/dynstream.nim\(cqs readLoopOrMmap and maybeMmapForSend to deal
with this automatically.)
.SS See also
\f[B]cha\f[R](1) \f[B]cha\-terminal\f[R](7)
chawan-v0.4.0/doc/cha-mailcap.5 0000664 0000000 0000000 00000021314 15202323131 0016125 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-MAILCAP" "5"
.SH Mailcap
By default, Chawan\(cqs buffers only handle HTML and plain text.
The \f[I]mailcap\f[R] file can be used to view other file formats using
external commands, or to convert them to HTML/plain text before
displaying them in Chawan.
.PP
Note that Chawan\(cqs default mime.types file only recognizes a few file
extensions, which may result in your entries not being executed if your
system lacks an /etc/mime.types file.
Please consult \f[B]cha\-mime.types\f[R](5) for details.
.PP
For an exact description of the mailcap format, see \c
.UR https://www.rfc-editor.org/rfc/rfc1524
RFC 1524
.UE \c
\&.
.SS Search path
The search path for mailcap files is set by the configuration variable
\f[CR]external.mailcap\f[R].
This matches the recommended path in the RFC:
.IP
.EX
$HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap
.EE
.PP
By default, mailcap entries are only executed if the user types
\f[CR]r\f[R] (run) after the prompt.
Other options are to view the file with \f[CR]t\f[R] (text), or to save
the file with \f[CR]s\f[R].
.PP
If a capital letter is typed (e.g.\ shift + \f[CR]R\f[R]), then a
corresponding entry is appended to \f[CR]external.auto\-mailcap\f[R]
(default: \f[CR]\(ti/.chawan/mailcap\f[R], or
\f[CR]\(ti/.config/chawan/mailcap\f[R] with XDG basedirs).
\f[CR](T)ext\f[R] and \f[CR](S)ave\f[R] may also be used to append
entries corresponding to the other display options.
.PP
Entries in auto\-mailcap are automatically executed, so it is
recommended to add your Chawan\-specific entries there (or just set it
to your personal mailcap file).
.SS Format
Chawan adheres to the format described in RFC 1524, with a few
extensions.
.PP
\f[CR]text/html\f[R] and \f[CR]text/plain\f[R] entries are ignored.
.SS Templating
The command part of entries may include template strings which are
substituted by the browser at execution.
.PP
Templates do not have to be quoted; Chawan quotes them automatically.
(This works with $(command substitutions) as well.)
However, other software may misbehave on such templates, so it may be
better to assign them to a variable first, e.g.
.IP
.EX
text/x\-example; s=%s cat \(dq$s\(dq; copiousoutput
.EE
.PP
Following templates are supported:
.IP \(bu 2
\f[CR]%s\f[R] expands to the path.
Specifying \f[CR]%s\f[R] forces download of the external resource
\f[I]before\f[R] the entry is executed.
If \f[CR]%s\f[R] is not specified, the resource is instead piped to
standard input.
(In this case, \f[CR]needsterminal\f[R] does not apply.)
.IP \(bu 2
\f[CR]%t\f[R] expands to the content type.
Named content type fields can also be specified with the syntax
\f[CR]%{charset}\f[R].
For example, in
.RS 2
.IP
.EX
text/html; charset=utf\-8
.EE
.PP
\f[CR]%t\f[R] would expand to the above string, while
\f[CR]%{charset}\f[R] would expand to \(lqutf\-8\(rq.
.RE
.IP \(bu 2
Non\-standard templates for the resource\(cqs original URL:
\f[CR]%u\f[R] (from Netscape) expands to the original URL of the
resource, \f[CR]%h\f[R] (from w3mmee) expands to the hostname without
the port, \f[CR]%H\f[R] expands to the hostname including the port, and
\f[CR]%?\f[R] (from w3mmee) expands to the query string including the
question mark.
.RS 2
.PP
(w3mmee did not actually include the question mark in \f[CR]%?\f[R].
However, that design could not express the difference between the empty
query string and the null query string, so it has been changed in
Chawan.)
.RE
.SS Fields
Following fields are recognized.
.IP \(bu 2
When the \f[CR]test\f[R] named field is specified, the mailcap entry is
only used if the test command returns 0.
For example, you can restrict entries that require X11 as follows:
.RS 2
.IP
.EX
image; feh \-; test=test \-n \(dq$DISPLAY\(dq
.EE
.PP
Warning: \f[CR]%s\f[R] does not work with \f[CR]test\f[R].
\f[CR]test\f[R] named fields with a \f[CR]%s\f[R] template are skipped,
and no data is piped into \f[CR]test\f[R] commands.
.RE
.IP \(bu 2
\f[CR]copiousoutput\f[R] makes Chawan redirect the output of the
external command\(cqs output into a new buffer.
If either \f[CR]x\-htmloutput\f[R] or \f[CR]x\-ansioutput\f[R] is
defined too, then \f[CR]copiousoutput\f[R] is ignored.
.IP \(bu 2
\f[CR]needsterminal\f[R] hands over control of the terminal to the
command while it is running.
It does nothing if one of \f[CR]copiousoutput\f[R],
\f[CR]x\-ansioutput\f[R], \f[CR]x\-saveoutput\f[R] or
\f[CR]x\-htmloutput\f[R] is specified.
.IP \(bu 2
\f[CR]nametemplate\f[R] provides a specific template for the temporary
file created when \f[CR]%s\f[R] is specified.
See the RFC for details.
.IP \(bu 2
\f[CR]x\-htmloutput\f[R] (from w3m) behaves the same as
\f[CR]copiousoutput\f[R], but makes Chawan interpret the command\(cqs
output as HTML.
.IP \(bu 2
\f[CR]x\-ansioutput\f[R] pipes the output through the
\(lqtext/x\-ansi\(rq content type handler, so that ANSI colors,
formatting, etc.
are displayed correctly.
.IP \(bu 2
\f[CR]x\-saveoutput\f[R] prompts the user to save the entry\(cqs output
in a file.
.IP \(bu 2
\f[CR]x\-needsstyle\f[R] forces CSS to be processed for the specific
type, even if styling is disabled in the config.
Only useful when combined with \f[CR]x\-htmloutput\f[R].
(Also see the \f[CR]\-cha\-content\-type\f[R] media query in
\f[B]cha\-css\f[R](7).)
.IP \(bu 2
\f[CR]x\-needsimage\f[R] forces images to be displayed in
\f[CR]x\-htmloutput\f[R], even if images are disabled.
.IP \(bu 2
\f[CR]x\-type\f[R] (from w3mmee) specifies a MIME type substitution.
The command part is interpreted as a MIME type (without template
expansion) which is used instead of the original type.
Such entries are only respected in \f[CR]external.auto\-mailcap\f[R].
.RS 2
.PP
Entries with \f[CR]x\-type\f[R] also match text/plain and text/html
documents (which are normally excluded from mailcap).
However, \f[CR]x\-type\f[R] does not apply if the content type was
forced (e.g.\ using the \f[CR]\-T\f[R] flag).
.PP
(Note: \f[CR]x\-type\f[R] is experimental.
Future changes to its semantics are to be expected.)
.RE
.IP \(bu 2
\f[CR]x\-match\f[R] (from w3mmee) restricts the entry\(cqs URL to the
specified regex.
\f[CR]x\-nc\-match\f[R] is the same, but it is case\-insensitive.
For example, \f[CR]x\-match=https?://example\(rs.org/.*\f[R] restricts
the entry to example.org (note the backslash.)
.RS 2
.PP
When one of these fields is present together with \f[CR]test\f[R], the
result is ANDed together.
.RE
.IP \(bu 2
\f[CR]x\-netpath\f[R] (from w3mmee) restricts the entry to URIs that
match the \f[CR]net_path\f[R] production of RFC 2396.
In other words, the URI must have an authority (hostname etc.), so
e.g.\ \f[CR]example://blah/path\f[R] is matched, while
\f[CR]example:/path\f[R] isn\(cqt.
.RS 2
.PP
For schemes other than \f[CR]file\f[R], two slashes after the colon
signify a \f[CR]net_path\f[R].
\f[CR]file:///path\f[R] is a special case: it looks like a
\f[CR]net_path\f[R], but it isn\(cqt one.
(This is inherited from the WHATWG URL standard.)
.RE
.SS Examples
To automatically execute these entries, place them in
\f[CR]\(ti/.chawan/mailcap\f[R] (or
\f[CR]\(ti/.config/chawan/mailcap\f[R] if you use XDG basedirs).
Alternatively, if you already have a mailcap file to share with other
programs, you can set \f[CR]external.auto\-mailcap\f[R] to
\f[CR]\(ti/.mailcap\f[R].
.IP
.EX
# Note: these examples require an entry in mime.types that sets e.g. md as
# the markdown content type.
# Handle markdown files using pandoc.
text/markdown; pandoc \- \-f markdown \-t html \-o \-; x\-htmloutput
# Show syntax highlighting for JavaScript source files using bat.
text/javascript; bat \-f \-l es6 \-\-file\-name %u \-; x\-ansioutput
# Play music using mpv, and hand over control of the terminal until mpv exits.
audio/*; mpv \-; needsterminal
# Play videos using mpv in the background, redirecting its standard output
# and standard error to /dev/null.
video/*; mpv \-
# Open docx files using LibreOffice Writer.
application/vnd.openxmlformats\-officedocument.wordprocessingml.document; lowriter %s
# Display manpages using pandoc. (Make sure the mime type matches the one
# set in your mime.types file for extensions .1, .2, .3, ...)
application/x\-troff\-man; pandoc \- \-f man \-t html \-o \-; x\-htmloutput
# epub \-> HTML using pandoc. (Again, don\(aqt forget to adjust mime.types.)
# We set http_proxy to keep it from downloading whatever through http/s.
application/epub+zip; http_proxy=localhost:0 pandoc \- \-f epub \(rs
\-\-embed\-resources \-\-standalone; x\-htmloutput
# Hex viewer. Usage: alias chadump=\(aqcha \-Ttext/x\-hexdump\(aq
# (Uses GNU\-specific flags, adjust as needed on other systems.)
text/x\-hexdump; od \-w12 \-A x \-t x1z \-v; copiousoutput
# Following entry will be ignored, as text/html is supported natively by Chawan.
text/html; cha \-dT text/html \-I %{charset}; copiousoutput
.EE
.SS See also
\f[B]cha\f[R](1)
chawan-v0.4.0/doc/cha-mime.types.5 0000664 0000000 0000000 00000003201 15202323131 0016604 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-MIME.TYPES" "5"
.SH mime.types
Chawan uses the mime.types file to map file extensions to MIME types
(also known as \f[CR]Content\-Type\f[R]).
.PP
MIME types in turn are used by mailcap to decide how to present a
certain file to the user (display as text, use external viewer, save,
etc.)
See \f[B]cha\-mailcap\f[R](5) for details of how that works.
.SS Search path
Chawan parses all mime.types files defined in
\f[CR]external.mime\-types\f[R].
When no mime.types file is found, the built\-in MIME type associations
are used.
.PP
The default search path for mime.types files is:
.IP
.EX
$HOME/.mime.types:/etc/mime.types:/usr/etc/mime.types:/usr/local/etc/mime.types
.EE
.SS Format
The mime.types file is a list of whitespace\-separated columns.
The first column represents the mime type, all following columns are
file extensions.
.PP
Lines starting with a hash character (#) are recognized as comments, and
are ignored.
.PP
Example:
.IP
.EX
# comment
application/x\-example exmpl ex
.EE
.PP
This mime.types file would register the file extensions \(lqexmpl\(rq
and \(lqex\(rq to be recognized as the mime type
\f[CR]application/x\-example\f[R].
.SS Note
Chawan only uses mime.types files for finding mailcap entries; buffers
use an internal mime.types file for content type detection instead.
.PP
The default mime.types file only includes file formats that buffers can
handle, which is rather limited (at the time of writing, 7 file
formats).
Therefore it is highly recommended to configure at least one external
mime.types file if you use mailcap.
.SS See also
\f[B]cha\f[R](1) \f[B]cha\-mailcap\f[R](5)
chawan-v0.4.0/doc/cha-protocols.7 0000664 0000000 0000000 00000026037 15202323131 0016554 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-PROTOCOLS" "7"
.SH Protocols
Chawan supports downloading resources from various protocols: HTTP, FTP,
SFTP, Gopher, Gemini, Spartan, and Finger.
Details on these protocols, and information on how users can add support
to their preferred protocols is outlined in this document.
.PP
You can find network adapters in the source distribution\(cqs
\f[CR]adapter/protocol\f[R] directory.
For protocol\-specific file formats (like gemtext or gopher directories)
you will also find an appropriate HTML converter in
\f[CR]adapter/format\f[R] \- note that these are ultimately compiled
into a single \f[CR]tohtml\f[R] program that dispatches based on its
\f[CR]argv[0]\f[R].
.SS OpenSSL\-based adapters
The HTTP(S), SFTP, and Gemini modules all depend on OpenSSL.
This is a huge library, and linking it separately with each adapter
would result in enormous code bloat in static builds.
.PP
Therefore, these modules are compiled into a single binary.
The entry point can be found at \f[CR]adapter/protocol/ssl.nim\f[R].
.SS HTTP
The HTTP(S) adapter supports HTTP/1.1 with arbitrary headers and POST
data, is able to use passed userinfo data (Basic authentication), and
returns all headers and response body it receives without exception.
.PP
Deflate decompression with gzip and zlib headers is supported.
(Accept\-Encoding: gzip, deflate.)
This is based on a modified version of the public domain tinfl.h
decompressor by Rich Geldreich.
.PP
Brotli decompression (Accept\-Encoding: br) is supported using the
decoder provided by the reference implementation.
.PP
The \f[CR]bonus\f[R] directory contains two alternative HTTP clients:
.IP \(bu 2
curlhttp; this is the old HTTP client based on libcurl.
It can be built using curl\-impersonate; see README.md in the bonus/
directory for details.
.IP \(bu 2
libfetch\-http: based on FreeBSD libfetch.
It is mostly a proof of concept, as FreeBSD libfetch HTTP support is
very limited; in particular, it does not support arbitrary HTTP headers,
so e.g.
cookies will not work.
.SS SFTP
The SFTP adapter wraps libssh2.
It works for me, but YMMV.
.PP
A slight usability issue is that if an IdentityFile declaration is found
in your ssh config, it will prompt for the identity file password, but
there is no way to tell whether it is really asking for that (or just
regular password auth).
Also, settings covered by the Match field are ignored.
.PP
The adapter does not have a way to register new known hosts, so you have
to first connect to new hosts with the regular \f[CR]sftp\f[R] command
before opening them in Chawan.
.SS Gemini
Currently, the Gemini adapter does not support sites that require
private key authentication.
Otherwise, it should work OK.
.PP
gmi2html is its companion program to convert the \f[CR]text/gemini\f[R]
file format to HTML.
.SS FTP
Chawan supports FTP passive mode browsing and downloads.
.PP
Directory listings return the \f[CR]text/x\-dirlist\f[R] content type,
which is parsed by \f[CR]dirlist2html\f[R] (and also used by the
\f[CR]file:\f[R] handler).
This assumes UNIX output style, and will probably break horribly on
receiving anything else.
.SS Shell\-based adapters
Following protocols are simple enough to have adapters implemented as
shell scripts.
As such, they are good starting points for understanding Chawan\(cqs
protocol adapter system.
.PP
To open TCP connections in a portable manner, these scripts use a very
limited \f[CR]nc\f[R] clone installed in \f[CR]$CHA_LIBEXEC_DIR\f[R].
.SS Gopher
Support for the Gopher protocol is implemented as a shell script, using
the \f[CR]nc\f[R] tool in the libexec directory (a very limited netcat
clone).
Gopher directories are returned with the \f[CR]text/gopher\f[R] type,
and gopher2html takes care of converting this to HTML.
.PP
Gopher selector types are converted to MIME types when possible;
however, this is very limited, as most of them (like \f[CR]s\f[R] sound,
or \f[CR]I\f[R] image) cannot be unambiguously converted without some
other sniffing method.
Chawan will fall back to extension\-based detection in these cases, and
in the worst case may end up with \f[CR]application/octet\-stream\f[R].
.SS Finger
Finger is supported through the \f[CR]finger\f[R] shell script, using
the same \f[CR]nc\f[R] clone as Gopher.
It is probably the simplest protocol of all.
.PP
The URL scheme is a simplified imitation of the one accepted by Lynx.
.SS Spartan
Spartan is a protocol similar to Gemini, but without TLS.
It is supported through the \f[CR]spartan\f[R] shell script, and like
Finger, it uses Chawan\(cqs \f[CR]nc\f[R] to make requests.
.PP
Spartan has the very strange property of extending gemtext with a
protocol\-specific line type.
This is implemented as a sed filter for gemtext outputs in the CGI
script (in other words, no modification to gmi2html was done to support
this).
.SS Local schemes: file:, man:
While these are not necessarily \f[I]protocols\f[R], they are
implemented similarly to the protocols listed above (and thus can also
be replaced, if the user wishes; see below).
.PP
\f[CR]file:\f[R] loads a file from the local filesystem.
In case of directories, it shows the directory listing using
\f[CR]dirlist2html\f[R] like FTP.
.PP
\f[CR]man:\f[R], \f[CR]man\-k:\f[R] and \f[CR]man\-l:\f[R] are wrappers
around the commands \f[CR]man\f[R], \f[CR]man \-k\f[R] and
\f[CR]man \-l\f[R].
These look up man pages using \f[CR]/usr/bin/man\f[R] and turn on\-page
references into links.
A wrapper command \f[CR]mancha\f[R] also exists; this has an interface
similar to \f[CR]man\f[R].
(This used to be based on w3mman2html.cgi, but it has been rewritten as
a standalone Nim program.)
.SS Internal schemes: cgi\-bin:, stream:, cache:, data:, about:
Five internal protocols exist: \f[CR]cgi\-bin:\f[R], \f[CR]stream:\f[R],
\f[CR]cache:\f[R], \f[CR]data:\f[R] and \f[CR]about:\f[R].
These are the basic building blocks for the implementation of every
protocol mentioned above; for this reason, these can \f[I]not\f[R] be
replaced, and are implemented in the main browser binary.
.PP
\f[CR]cgi\-bin:\f[R] executes a local CGI script.
This scheme is used for the actual implementation of the non\-internal
protocols mentioned above.
Local CGI scripts can also be used to implement wrappers of other
programs inside Chawan (e.g.\ dictionaries).
.PP
\f[CR]stream:\f[R] is used for streams returned by external programs.
It differs from \f[CR]cgi\-bin:\f[R] in that it does not cooperate with
the external process, and that the loader does not keep track of where
the stream originally comes from.
Therefore it is suitable for reading in the output of mailcap entries,
or for turning stdin into a URL.
.PP
It is not possible to reload \f[CR]stream:\f[R] URLs.
To support rewinding and \(lqview source\(rq, the output of
\f[CR]stream:\f[R]\(cqs is stored in a cache file until the buffer is
discarded.
.PP
\f[CR]cache:\f[R] is not something an end user would normally see;
it\(cqs used for rewinding or re\-interpreting streams already
downloaded.
.PP
Caching works differently than in most other browsers; files are
deterministically loaded from the cache upon certain actions, and from
the network upon others, but neither is used as a fallback to the other.
.PP
\f[CR]data:\f[R] decodes a data URL as defined in RFC 2397.
This used to be a CGI module, but has been moved back into the loader
process because these URLs can get so long that they no longer fit into
the environment.
.PP
\f[CR]about:\f[R] is inside the loader to allow for an implementation of
the download list panel.
It should be turned into a CGI module once the loader gets RPC
capabilities.
.PP
The following about pages are available: \f[CR]about:chawan\f[R],
\f[CR]about:blank\f[R], \f[CR]about:license\f[R],
\f[CR]about:downloads\f[R].
.SS Custom protocols
The \f[CR]cha\f[R] binary itself does not know much about the protocols
listed above; instead, it loads these through a combination of local
CGI, urimethodmap, and if conversion to HTML or plain text is necessary,
mailcap (using x\-htmloutput, x\-ansioutput and copiousoutput).
.PP
urimethodmap can also be used to override default handlers for the
protocols listed above.
This is similar to how w3m allows you to override the default directory
listing display, but much more powerful; this way, any library or
program that can retrieve and output text through a certain protocol can
be combined with Chawan.
.PP
For example, consider the urimethodmap definition of \f[CR]finger\f[R]:
.IP
.EX
finger: cgi\-bin:finger
.EE
.PP
This commands Chawan to load the \f[CR]finger\f[R] CGI script, setting
the \f[CR]$MAPPED_URI_*\f[R] variables to the target URL\(cqs parts in
the process.
.PP
Then, finger uses these passed parts to construct an appropriate curl
command that will retrieve the specified \f[CR]finger:\f[R] URL; it
prints the header `Content\-Type: text/plain' to the output, then an
empty line, then the body of the retrieved resource.
If an error is encountered, it prints a \f[CR]Cha\-Control\f[R] header
with an error code and a specific error message instead.
.SS Adding a new protocol
Here we will add a protocol called \(lqcowsay\(rq, so that the URL
cowsay:text prints the output of \f[CR]cowsay text\f[R] after a second
of waiting.
.PP
Note: following assumes you put your \f[CR]config.toml\f[R] in
\f[CR]\(ti/.chawan\f[R].
If you are using XDG base directories (i.e.\ your \f[CR]config.toml\f[R]
is in \f[CR]\(ti/.config/chawan\f[R]), substitute
\f[CR]\(ti/.chawan/cgi\-bin\f[R] with
\f[CR]\(ti/.config/chawan/cgi\-bin\f[R].
.PP
\f[CR]mkdir \-p \(ti/.chawan/cgi\-bin\f[R], and create a CGI script in
\f[CR]\(ti/.chawan/cgi\-bin/cowsay.cgi\f[R]:
.IP
.EX
\f[I]#!/bin/sh\f[R]
\f[I]# Signal to the browser that the connection has succeeded. After this,\f[R]
\f[I]# Chawan will now \(dqDownloading\(dq instead of \(dqConnecting\(dq.\f[R]
printf \(aqCha\-Control: Connected\(rsn\(aq
sleep 1 \f[I]# simulate a delay\f[R]
\f[I]# Status is a special header that signals the equivalent HTTP status code.\f[R]
printf \(aqStatus: 200\(rsn\(aq \f[I]# HTTP OK\f[R]
\f[I]# ControlDone is only useful if you want to send remotely received headers\f[R]
\f[I]# (i.e. in an HTTP adapter). With ControlDone sent, subsequent Cha\-Control\f[R]
\f[I]# headers are not interpreted specially.\f[R]
printf \(aqCha\-Control: ControlDone\(rsn\(aq
\f[I]# As in HTTP, send an empty line before the body.\f[R]
printf \(aq\(rsn\(aq
\f[I]# Print the body. We take the path passed to the URL, which urimethodmap\f[R]
\f[I]# sets as MAPPED_URI_PATH. This is URI\-encoded, so we also run the urldec\f[R]
\f[I]# utility on it.\f[R]
printf \(aq%s\(rsn\(aq \(dq$MAPPED_URI_PATH\(dq \f[B]|\f[R] \(dq$CHA_LIBEXEC_DIR\(dq/urldec \f[B]|\f[R] cowsay
.EE
.PP
Don\(cqt forget to set the executable bit, e.g.
.IP
.EX
chmod +x \(ti/.config/chawan/cgi\-bin/cowsay.cgi
.EE
.PP
Finally, create a \(lq.urimethodmap\(rq file in your \f[CR]$HOME\f[R]
directory, with the following content:
.IP
.EX
cowsay: /cgi\-bin/cowsay.cgi
.EE
.PP
Now try \f[CR]cha cowsay:Hello,%20world.\f[R].
If you did everything correctly, it should wait one second, then print a
cow saying \(lqHello, world.\(rq.
.SS See also
\f[B]cha\f[R](1), \f[B]cha\-cgi\f[R](5), \f[B]cha\-urimethodmap\f[R](5),
\f[B]cha\-mailcap\f[R](5)
chawan-v0.4.0/doc/cha-terminal.7 0000664 0000000 0000000 00000013223 15202323131 0016334 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-TERMINAL" "7"
.SH Chawan terminal compatibility
Chawan does not use termcap, terminfo, or ncurses; it relies solely on
built\-in terminal handling routines, mostly inspired by notcurses.
.SS XTerm compatibility
In general, Chawan assumes an XTerm\-compatible environment where XTerm
means the current XTerm version as developed and maintained by Thomas
E.\ Dickey.
This means that Chawan is compatible with any given terminal if:
.IP \(bu 2
the terminal is actually compatible with XTerm, OR
.IP \(bu 2
the terminal isn\(cqt compatible with XTerm, but reports its
capabilities via terminal queries correctly, OR
.IP \(bu 2
the terminal isn\(cqt compatible with XTerm, but its \f[CR]TERM\f[R]
value is hardcoded in Chawan.
.PP
Terminals pretending to be XTerm (\f[CR]TERM=xterm\f[R]) which are not
actually XTerm might malfunction.
.PP
(In practice, I have tested dozens of terminal emulators and haven\(cqt
encountered any major issues; in all likelihood, yours will work too.
If it doesn\(cqt, please \c
.UR https://todo.sr.ht/~bptato/chawan
open a ticket
.UE \c
\&.)
.SS Queries
Queries are preferred to hardcoded terminal descriptions because they
are forward\-compatible.
On startup, Chawan queries:
.IP \(bu 2
Whether the terminal has true color, with XTGETTCAP rgb.
.IP \(bu 2
The default background, foreground, and 16 ANSI(\-ish) colors with
\f[CR]OSC 10 ; ? ST\f[R], \f[CR]OSC 11 ; ? ST\f[R], and
\f[CR]OSC 4 ; {0..15} ; ? ST\f[R].
.IP \(bu 2
\f[CR]OSC 60 ST\f[R] and \f[CR]OSC 61 allowWindowOps ST\f[R] for
detecting OSC 52 support (see the \f[I]Clipboard\f[R] section).
.IP \(bu 2
Whether the terminal can use the Kitty image protocol, by sending a 1x1
Kitty image and listening for a response.
.IP \(bu 2
The number of Sixel color registers (\f[CR]CSI ? 1 ; 1 ; 0 $\f[R]).
.IP \(bu 2
Primary device attributes (DA1).
.IP \(bu 2
Text area and cell size using \f[CR]CSI 14 t\f[R] and
\f[CR]CSI 16 t\f[R].
(Cell size beats text area size as it is more reliable.)
.IP \(bu 2
Window size in cells by sending a CUP to 9999;9999 and then asking for
CPR (the same trick is used by \f[B]resize\f[R](1)).
.PP
Chawan processes responses to the above query in the same state machine
as user input, so it works reasonably well on all terminals that at
least emulate the most basic VT100 function (CPR).
This unified state machine also minimizes the chance of user input being
mistaken for a query response (or vice versa).
.PP
Terminals that do not respond to CPR will freeze on quit \- in this
case, you must type \f[CR]C\-c\f[R] to forcibly kill the state machine.
In practice, FreeBSD\(cqs \f[B]vt\f[R](4) is the only one I\(cqve found
that exhibits this behavior; to add insult to injury, it claims to be an
\(lqxterm\(rq in TERM.
Therefore we discriminate between \f[B]vt\f[R](4) and a real XTerm using
an ioctl.
(Idea shamelessly stolen from notcurses\(cq Linux console detection.)
.PP
Some terminals bleed the APC sequence used to recognize kitty image
support, and this may result in strange artifacts when no alt screen is
used.
On terminals that set TERM correctly, the APC sequence is not sent.
.SS Clipboard
Some terminals support sequences to override the clipboard.
Chawan differentiates between three tiers:
.IP "1." 3
Supports clipboard \f[I]and\f[R] primary selection.
The latter is what allows you on X11 to select some text with the mouse
and then middle\-click paste it elsewhere.
.RS 4
.PP
This applies to all terminals that respond to OSC 60/61 (XTerm) as well
as a hardcoded list of terminals that respond with 52 in DA1 and have
been confirmed to support the primary selection (Kitty).
.RE
.IP "2." 3
Supports clipboard, but may choke on trying to set primary selection.
.RS 4
.PP
This applies to terminals that include the number 52 in DA1.
This response guarantees nothing about support for the primary
selection, and indeed, some terminals that return it (e.g.\ Contour)
behave incorrectly when receiving primary.
.RE
.IP "3." 3
Does not support clipboard.
In this case we shell out to \f[CR]external.copy\-cmd\f[R] (defaults to
\f[B]xsel\f[R](1x)).
.RS 4
.PP
This applies to all other terminals.
Notably, this includes terminals that support OSC 52 but do not have a
reliable mechanism to detect whether it actually works, such as
Alacritty.
.RE
.PP
It is possible to manually adjust OSC 52 use with the
\f[CR]input.osc52\-copy\f[R] and \f[CR]input.osc52\-primary\f[R]
configuration options.
.SS Ancient terminals
Most pre\-ECMA\-48 (1979) terminals are not expected to work.
.PP
There is some degree of ADM\-3A support, tested in Kragen Javier
Sitaker\(cqs \c
.UR https://gitlab.com/kragen/bubbleos
admu
.UE \c
\ emulator.
.PP
Some DEC terminals have also been tested in simulators of the original
hardware running the actual ROM:
.IP \(bu 2
The VT100 has been tested in Lars Brinkhoff\(cqs \c
.UR https://github.com/larsbrinkhoff/terminal-simulator
terminal\-simulator
.UE \c
\&.
Note: use TERM=vt100\-nav if you don\(cqt have advanced video.
.IP \(bu 2
The VT420 has been tested in Matt Mastracci\(cqs \c
.UR https://github.com/mmastrac/blaze
Blaze
.UE \c
\&.
.PP
Patches for other terminals (hardware or software alike) are welcome.
.SS Ancient character encodings
For ASCII\-only terminals, don\(cqt forget to
\f[CR]export LC_ALL=C\f[R].
For terminals supporting other legacy encodings, you may also have some
luck with \f[CR]language.charset\f[R], such as
\f[CR]export LC_ALL=ja_JP.ISO\-2022\-JP\f[R].
.PP
Note that Chawan uses its own encoding library instead of the
notoriously broken C locale facility, and the two sets of supported
charsets may not fully overlap.
You can test whether a charset is supported using
\f[CR]cha \-O {charset name} \-V\f[R].
.SS See also
\f[B]cha\f[R](1)
chawan-v0.4.0/doc/cha-troubleshooting.7 0000664 0000000 0000000 00000015536 15202323131 0017761 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-TROUBLESHOOTING" "7"
.SH Troubleshooting Chawan
This document lists common problems you may run into when using Chawan.
.PP
If you encounter a problem not described in this document, please open a
ticket at \c
.UR https://todo.sr.ht/~bptato/chawan
.UE \c
\&.
.SS It doesn\(cqt compile?
Please open a ticket.
Don\(cqt forget to include the compilation error, and your operating
system (and its version).
.SS It crashes?
Please open a ticket that describes how to reproduce the crash.
Don\(cqt forget to include the error message you see after your buffer
disappeared.
.PP
If you don\(cqt see an error message, try:
\f[CR]cha example.org \-o start.console\-buffer=false 2>err.log\f[R].
Then check the contents of \f[CR]err.log\f[R] after the crash.
.PP
If you \f[I]still\f[R] don\(cqt see an error message, no problem, just
report that you couldn\(cqt get an error message.
.SS I can\(cqt select/copy text with my mouse?
Right click \-> select text, then right click \-> copy selection.
(You can also double click and drag the mouse to the left/right to
select.)
.PP
If Chawan complains about xsel, either install it or edit
\f[CR]external.copy\-cmd\f[R] and \f[CR]external.paste\-cmd\f[R] to your
liking.
.PP
You can also disable mouse tracking temporarily by holding down shift,
or permanently by setting in \f[CR]config.toml\f[R]:
.IP
.EX
\f[B][input]\f[R]
use\-mouse = false
.EE
.SS I was promised images but I see nothing?
The most common reason is that you didn\(cqt add following to
\f[CR]config.toml\f[R]:
.IP
.EX
\f[B][buffer]\f[R]
images = true
.EE
.PP
The second most common reason is that your terminal supports neither
Sixel nor Kitty images.
.PP
Other reasons are enumerated \f[B]cha\-image\f[R](7).
.SS Why do I get strange/incorrect/ugly colors?
By default, Chawan\(cqs display capabilities are limited to what your
terminal reports.
In particular:
.IP \(bu 2
If the \f[CR]$COLORTERM\f[R] environment variable is not set, it may
fall back to 8\-bit or ANSI colors.
Make sure you export it as \f[CR]COLORTERM=truecolor\f[R].
.IP \(bu 2
If it does not respond to querying the background color, then
Chawan\(cqs color contrast correction will likely malfunction.
You can correct this using the
\f[CR]display.default\-background\-color\f[R] and
\f[CR]display.default\-foreground\-color\f[R] options.
.PP
See the \f[I]Display\f[R] section in \f[B]cha\-config\f[R](5) for
details.
.SS I set my \f[CR]$PAGER\f[R] to \f[CR]cha\f[R] and now man pages are unreadable.
Most \f[CR]man\f[R] implementations print formatted manual pages by
default, which Chawan \f[I]can\f[R] parse if they are passed through
standard input.
.PP
Unfortunately, mandoc passes us the formatted document as a
\f[I]file\f[R], which Chawan reasonably interprets as plain text without
formatting.
.PP
At this point, you have two options:
.IP \(bu 2
\f[CR]export PAGER=\(aqcha \-T text/x\-ansi\(aq\f[R] and see that man
suddenly works as expected.
.IP \(bu 2
\f[CR]alias man=mancha\f[R] and see that man suddenly works better than
expected.
.PP
Ideally you should do both, to deal with cases like git help which
shells out to man directly.
.PP
There is still one problem with this solution: some programs will try to
call \f[CR]$PAGER\f[R] without shell expansion, breaking the
\f[CR]\-T text/x\-ansi\f[R] trick.
To fix this, put a script somewhere in your \f[CR]PATH\f[R]:
.IP
.EX
\f[I]#!/bin/sh\f[R]
exec cha \-T text/x\-ansi \(dq$\(at\(dq
.EE
.PP
and \f[CR]export PAGER=pcha\f[R] (or whatever you named the script).
.SS How do I view text files with wrapping?
By default, Chawan does not automatically wrap text files, which makes
viewing plain text files that were not wrapped by its authors
uncomfortable.
.PP
A workaround is to add this to your config\(cqs \f[CR][page]\f[R]
section:
.IP
.EX
\(aqSPC f\(aq = \(dqpager.externFilterSource(\(aqfmt\(aq)\(dq
.EE
.PP
and then type \f[CR] f\f[R] to view a wrapped version of the
current text file.
(This assumes your system has an \f[CR]fmt\f[R] program \- if not,
\f[CR]fold \-s\f[R] may be an alternative.)
.PP
To always automatically wrap, you can add this to your user style:
.IP
.EX
plaintext { \f[B]white\-space\f[R]: pre\-wrap }
.EE
.PP
To do the same for HTML and ANSI text, use \f[CR]plaintext, pre\f[R].
.SS Why does \f[CR]$WEBSITE\f[R] look awful?
Usually, this is because it uses some CSS features that are not yet
implemented in Chawan.
The most common offender is grid.
.PP
There are three ways of dealing with this:
.IP "1." 3
If the website\(cqs contents are mostly text, install \c
.UR https://github.com/eafer/rdrview
rdrview
.UE \c
\&.
Then bind the following command to a key of your choice in the config
(e.g.\ \f[CR] r\f[R]):
.RS 4
.PP
\f[CR]\(aq r\(aq = \(dqpager.externFilterSource(\(aqrdrview \-Hu \(rs\(dq$CHA_URL\(rs\(dq\(aq)\(dq\f[R]
.PP
This does not fix the core problem, but will significantly improve your
reading experience anyway.
.RE
.IP "2." 3
Complain \c
.UR https://todo.sr.ht/~bptato/chawan
here
.UE \c
, and wait until the problem goes away.
It helps if you can reduce the issue to a minimal reproducible example
(ideally a small HTML fragment.)
.IP "3." 3
Write a patch to fix the problem, and send it \c
.UR https://lists.sr.ht/~bptato/chawan-devel
here
.UE \c
\&.
.SS \f[CR]$WEBSITE\f[R]\(cqs interactive features don\(cqt work!
Some potential fixes:
.IP \(bu 2
Logging in to websites requires cookies.
Some websites also require cookie sharing across domains.
For security reasons, Chawan does not allow any of this by default, so
you will have to fiddle with siteconf to fix it.
See the \f[I]Siteconf\f[R] section in \f[B]cha\-config\f[R](5) for
details.
.IP \(bu 2
Set the \f[CR]referer\-from\f[R] siteconf value to true; this will cause
Chawan to send a \f[CR]Referer\f[R] header when navigating to other URLs
from the target URL.
.IP \(bu 2
Enable JavaScript.
If something broke, type M\-c M\-c to check the browser console, then
follow step 3.\ of the previous answer.
.SS Text areas discard my edits when I type C\-c in my editor!
This is a bug in your shell: \c
.UR https://people.freebsd.org/~cracauer/homepage-mirror/sigint.html
.UE \c
.PP
When Chawan runs an external text editor, it simply passes the
\f[CR]$EDITOR\f[R] command to the shell, and then examines its \f[I]wait
status\f[R] to determine if your editor exited gracefully.
This works if either the editor never receives a signal, or your shell
implements WCE.
.PP
However, if the editor (e.g.\ nvi) catches SIGINT on C\-c, and the shell
reports that the program was killed by a signal (WUE), then Chawan will
discard your changes (as it believes that the program has crashed).
.PP
The easiest workaround is to remove the shell from the equation using
\f[CR]exec\f[R]:
.IP
.EX
[external]
editor = \(aqexec vi +%d\(aq
.EE
.SS When I open Chawan from aerc, it prints garbage in the search field!
This should be fixed in the latest aerc version.
Please update aerc.
.SS See also
\f[B]cha\f[R](1)
chawan-v0.4.0/doc/cha-urimethodmap.5 0000664 0000000 0000000 00000007405 15202323131 0017222 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA-URIMETHODMAP" "5"
.SH URI method map support in Chawan
Chawan can be used to map unrecognized protocols to known protocols
using the \f[I]urimethodmap\f[R] format.
.PP
The main use case for this is implementing handlers to protocols unknown
to Chawan through a protocol that the browser does understand.
.SS Search path
The search path for urimethodmap files can be overridden using the
configuration variable \f[CR]external.urimethodmap\f[R].
.PP
The default search path for urimethodmap files is:
.IP
.EX
$CHA_DIR/urimethodmap:$HOME/.urimethodmap:/etc/urimethodmap
.EE
.SS Format
The urimethodmap format is taken 1:1 from w3m, with some modifications
to the interpretation of templates.
.PP
A rough attempt at the formal description of this:
.IP
.EX
URIMethodMap\-File = *URIMethodMap\-line
URIMethodMap\-Line = Comment / URIMethodMap\-Entry
URIMethodMap\-Entry = Protocol *WHITESPACE Template *WHITESPACE CR
Protocol = 1*CHAR COLON
Template = [see below]
Comment = *WHITESPACE CR / \(dq#\(dq *CHAR CR
.EE
.PP
Note that an ASCII colon sign (:) must be present after the protocol
name.
However, the whitespace may be omitted.
.PP
Examples:
.IP
.EX
# This is ok:
protocol: /cgi\-bin/interpret\-protocol?%s
# This is ok too:
protocol:/cgi\-bin/interpret\-protocol?%s
# Spaces and tabs are both allowed, so this is also ok:
protocol: /cgi\-bin/interpret\-protocol?%s
# However, this is incorrect, because the colon sign is missing:
protocol /cgi\-bin/interpret\-protocol?%s
.EE
.PP
The redirection template is the target URL.
If the string \f[CR]%s\f[R] is contained in the template, it will be
replaced by the target URL.
.PP
For compatibility with w3m, templates starting with
\f[CR]/cgi\-bin/\f[R] and \f[CR]file:/cgi\-bin/\f[R] are special\-cased
and the starting string is replaced with \f[CR]cgi\-bin:\f[R].
So for example, the template \f[CR]/cgi\-bin/w3mdict.cgi\f[R] is the
same as \f[CR]cgi\-bin:w3mdict.cgi\f[R] (and so is
\f[CR]file:/cgi\-bin/w3mdict.cgi\f[R]).
.PP
Example:
.IP
.EX
# The following are the same in Chawan
protocol: /cgi\-bin/interpret\-protocol?%s
protocol: file:/cgi\-bin/interpret\-protocol?%s
# Note: this last entry does not work in w3m.
protocol: cgi\-bin:interpret\-protocol?%s
.EE
.PP
Note however that absolute paths to cgi scripts are NOT special cased,
so e.g.\ \f[CR]file:///usr/local/libexec/w3m/cgi\-bin/w3mdict.cgi\f[R]
will simply open w3mdict.cgi in the file viewer.
(Unlike in w3m, where it could run \f[CR]w3mdict.cgi\f[R] depending on
the user\(cqs configuration.)
.SS Examples
Following lines should be specified in \f[CR]$CHA_DIR/urimethodmap\f[R]
(where \f[CR]$CHA_DIR\f[R] is either \(ti/.chawan or \(ti/.config/chawan
depending on where your config.toml is).
.SS magnet.cgi
.IP
.EX
# Use the \(gamagnet.cgi\(ga CGI shell script to pass magnet links to Transmission.
magnet: /cgi\-bin/magnet.cgi?%s
.EE
.PP
\f[CR]magnet.cgi\f[R] can be found in the \f[CR]bonus/\f[R] directory.
You can also write a local CGI wrapper to pass the links to your
BitTorrent client of choice.
.SS dict
In w3m, urimethodmap is commonly (ab)used to define shorthands for CGI
scripts.
.PP
This works in Chawan too; for an example, you could define a
\f[CR]tl:\f[R] shorthand like this:
.IP
.EX
# (trans.cgi is a script you can find and study in the bonus/ directory.)
tl: /cgi\-bin/trans.cgi?%s
.EE
.PP
Then, you could open the translation of any word using
\f[CR]tl:word\f[R].
.PP
Note however that Chawan has a more powerful facility for substitution
shorthands like this in the form of omni\-rules.
So if you want to redirect to an online dictionary site with tl:word
instead of providing a local CGI interface, it is easier to just use
omni\-rules instead of urimethodmap + local CGI redirection.
.SS See also
\f[B]cha\f[R](1) \f[B]cha\-cgi\f[R](5)
chawan-v0.4.0/doc/cha.1 0000664 0000000 0000000 00000013172 15202323131 0014520 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "CHA" "1"
.SH NAME
cha \- the Chawan text\-mode browser
.SH SYNOPSIS
\f[B]cha\f[R] [\f[B]options\f[R]] [\f[I]URL(s)\f[R] or
\f[I]file(s)\f[R]\&...]
.SH DESCRIPTION
Chawan is a text\-mode browser.
It can be used as a pager, or as a web/(S)FTP/gopher/gemini/file
browser.
It understands HTML and CSS, and when enabled by the user, can also
execute JavaScript and display images (on terminals supporting Sixel or
the Kitty image protocol.)
.PP
Chawan can also be used as a general text\-based document viewer as
described in \f[B]cha\-mailcap\f[R](5), or as a hyperlinked man page
viewer using \f[B]mancha\f[R](1).
.PP
This document describes the invocation of Chawan.
For a list of default keybindings, type \f[I]cha about:chawan\f[R].
For a detailed description of the configuration format, see
\f[B]cha\-config\f[R](5).
.SH ARGUMENTS
On invocation, Chawan attempts to open all URL/file arguments supplied.
If no URLs could successfully be opened, Chawan exits automatically.
.PP
Chawan may also be started without specifying a file, if a file is
provided through a pipe.
In this case, you can specify the content type using the \f[B]\-T\f[R]
switch.
.SH OPTIONS
All command line options have short forms (e.g.\ \f[B]\-d\f[R]) and long
forms (e.g.\ \f[B]\-\-dump\f[R]).
.PP
Long forms must be introduced with two dashes; when only a single dash
is provided, each letter is parsed as a separate short form.
.PP
In short form, it is also valid to provide values to arguments without a
subsequent space.
For example, \f[B]\-obuffer.images=true\f[R] is valid.
.TP
\f[B]\-c\f[R], \f[B]\-\-css\f[R] \f[I]stylesheet\f[R]
Temporarily modify the user stylesheet.
If a user stylesheet is already being used, the stylesheet given is
appended to that.
.TP
\f[B]\-d\f[R], \f[B]\-\-dump\f[R]
Start in headless mode, and sequentially print the opened files to
stdout.
This option is implicitly enabled if stdout is not a tty (e.g.\ when
piping \f[I]cha\f[R] output).
.TP
\f[B]\-h\f[R], \f[B]\-\-help\f[R]
Print a short version of this page, then exit.
.TP
\f[B]\-o\f[R], \f[B]\-\-opt\f[R] \f[I]config\f[R]
Pass temporary configuration options.
This accepts the configuration format described in
\f[B]cha\-config\f[R](5), so the passed string must be valid TOML.
.RS
.PP
To ease specifying string parameters, unrecognized bare keywords are
converted to strings.
So this works:
.PP
\f[B]\-\-opt\f[R] display.color\-mode=\f[I]eight\-bit\f[R].
.PP
However, symbols and words starting with a number must still be quoted,
i.e.\ you have to quote them twice to bypass shell quoting.
.RE
.TP
\f[B]\-r\f[R], \f[B]\-\-run\f[R] \f[I]script\f[R]/\f[I]file\f[R]
Execute the string provided as a JS script, or execute the supplied JS
file.
If the file ends in .mjs, it is executed as an ES module.
.TP
\f[B]\-v\f[R], \f[B]\-\-version\f[R]
Print information about the browser\(cqs version, then exit.
.TP
\f[B]\-C\f[R], \f[B]\-\-config\f[R] \f[I]file\f[R]
Override the default configuration search path.
Both absolute and relative paths are allowed.
.TP
\f[B]\-I\f[R], \f[B]\-\-input\-charset\f[R] \f[I]charset\f[R]
Override the character set of all input files.
Useful when Chawan is incorrectly recognizing the input character set.
.RS
.PP
(If this happens often, consider changing the default input charset
recognition list \f[I]encoding.document\-charset\f[R] in the
configuration.)
.RE
.TP
\f[B]\-M\f[R], \f[B]\-\-monochrome\f[R]
Force monochrome output.
Formatting (bold/italic/etc.)
is not affected.
This is a shortcut for \f[B]\-o\f[R]
display.color\-mode=\f[I]monochrome\f[R].
.TP
\f[B]\-O\f[R], \f[B]\-\-output\-charset\f[R] \f[I]charset\f[R]
Override the output character set.
This is a shortcut for \f[B]\-o\f[R]
encoding.display\-charset=\f[I]charset\f[R].
.TP
\f[B]\-T\f[R], \f[B]\-\-type\f[R] \f[I]content\-type\f[R]
Override the content type of all input files.
Useful when the content type cannot be guessed from the file extension,
or when reading a non\-plaintext file from stdin.
.TP
\f[B]\-V\f[R], \f[B]\-\-visual\f[R]
When no files/URLs are passed, open the page specified in
\f[I]start.visual\-home\f[R] instead of printing a help screen.
.TP
\f[B]\-\-\f[R]
Interpret all following arguments as files.
For example, you can open a file named \f[I]\-o\f[R], using
\f[I]cha\f[R] \f[B]\-\-\f[R] \f[I]\-o\f[R].
.SH ENVIRONMENT
Certain environment variables are read and used by Chawan.
.TP
\f[B]TMPDIR\f[R]
When set, the default configuration stores temporary files inside this
directory (and \f[I]/tmp/cha\-tmp\-user\f[R] otherwise.)
.TP
\f[B]HTTP_HOME\f[R], \f[B]WWW_HOME\f[R]
When set, Chawan starts in visual mode by default and opens the page
specified by one of these variables.
\f[B]HTTP_HOME\f[R] takes precedence over \f[B]WWW_HOME\f[R].
.TP
\f[B]CHA_DIR\f[R]
When set, it switches the configuration directory to the path specified.
.TP
\f[B]COLORTERM\f[R]
When set to \f[I]24bit\f[R] or \f[I]truecolor\f[R], and the
\f[I]display.color\-mode\f[R] configuration option is set to
\f[I]auto\f[R], Chawan sets the color mode to true color.
.TP
\f[B]TERM\f[R]
Used by Chawan to adjust to terminal\-specific quirks.
When not set, defaults to \f[I]xterm\f[R].
.TP
\f[B]VISUAL\f[R], \f[B]EDITOR\f[R]
Used to determine the editor to use when the \f[I]external.editor\f[R]
configuration option is not set.
.TP
\f[B]LINES\f[R], \f[B]COLUMNS\f[R]
Used as fallback values when window size detection fails.
.SH SEE ALSO
\f[B]mancha\f[R](1), \f[B]cha\-config\f[R](5),
\f[B]cha\-mailcap\f[R](5), \f[B]cha\-mime.types\f[R](5),
\f[B]cha\-cgi\f[R](5), \f[B]cha\-urimethodmap\f[R](5),
\f[B]cha\-protocols\f[R](7), \f[B]cha\-image\f[R](7),
\f[B]cha\-css\f[R](7), \f[B]cha\-troubleshooting\f[R](7),
\f[B]cha\-terminal\f[R](7)
chawan-v0.4.0/doc/cha.md 0000664 0000000 0000000 00000012263 15202323131 0014760 0 ustar 00root root 0000000 0000000
# NAME
cha - the Chawan text-mode browser
# SYNOPSIS
**cha** [**options**] [*URL(s)* or *file(s)*...]
# DESCRIPTION
Chawan is a text-mode browser. It can be used as a pager, or as a
web/(S)FTP/gopher/gemini/file browser. It understands HTML and CSS,
and when enabled by the user, can also execute JavaScript and display
images (on terminals supporting Sixel or the Kitty image protocol.)
Chawan can also be used as a general text-based document viewer as
described in **cha-mailcap**(5), or as a hyperlinked man page viewer
using **mancha**(1).
This document describes the invocation of Chawan. For a list of default
keybindings, type *cha about:chawan*. For a detailed description of
the configuration format, see **cha-config**(5).
# ARGUMENTS
On invocation, Chawan attempts to open all URL/file arguments supplied.
If no URLs could successfully be opened, Chawan exits automatically.
Chawan may also be started without specifying a file, if a file is
provided through a pipe. In this case, you can specify the content type
using the **\-T** switch.
# OPTIONS
All command line options have short forms (e.g. **\-d**) and long
forms (e.g. **\-\-dump**).
Long forms must be introduced with two dashes; when only a single
dash is provided, each letter is parsed as a separate short form.
In short form, it is also valid to provide values to arguments without a
subsequent space. For example, **\-obuffer.images=true** is valid.
**\-c**, **\-\-css** *stylesheet*
: Temporarily modify the user stylesheet. If a user stylesheet is
already being used, the stylesheet given is appended to that.
**\-d**, **\-\-dump**
: Start in headless mode, and sequentially print the opened files to
stdout. This option is implicitly enabled if stdout is not a tty
(e.g. when piping *cha* output).
**\-h**, **\-\-help**
: Print a short version of this page, then exit.
**\-o**, **\-\-opt** *config*
: Pass temporary configuration options. This accepts the configuration
format described in **cha-config**(5), so the passed string must
be valid TOML.
To ease specifying string parameters, unrecognized bare keywords
are converted to strings. So this works:
**\-\-opt** display.color-mode=*eight-bit*.
However, symbols and words starting with a number must still be
quoted, i.e. you have to quote them twice to bypass shell quoting.
**\-r**, **\-\-run** *script*/*file*
: Execute the string provided as a JS script, or execute the supplied JS
file. If the file ends in .mjs, it is executed as an ES module.
**\-v**, **\-\-version**
: Print information about the browser's version, then exit.
**\-C**, **\-\-config** *file*
: Override the default configuration search path. Both absolute and
relative paths are allowed.
**\-I**, **\-\-input-charset** *charset*
: Override the character set of all input files. Useful when Chawan is
incorrectly recognizing the input character set.
(If this happens often, consider changing the default input charset
recognition list *encoding.document-charset* in the configuration.)
**\-M**, **\-\-monochrome**
: Force monochrome output. Formatting (bold/italic/etc.) is not
affected. This is a shortcut for **\-o**
display.color\-mode=*monochrome*.
**\-O**, **\-\-output-charset** *charset*
: Override the output character set. This is a shortcut for **\-o**
encoding.display\-charset=*charset*.
**\-T**, **\-\-type** *content-type*
: Override the content type of all input files. Useful when the content
type cannot be guessed from the file extension, or when reading a
non-plaintext file from stdin.
**\-V**, **\-\-visual**
: When no files/URLs are passed, open the page specified in
*start.visual-home* instead of printing a help screen.
**\-\-**
: Interpret all following arguments as files. For example, you can
open a file named *\-o*, using *cha* **\-\-** *\-o*.
# ENVIRONMENT
Certain environment variables are read and used by Chawan.
**TMPDIR**
: When set, the default configuration stores temporary files inside this
directory (and */tmp/cha-tmp-user* otherwise.)
**HTTP_HOME**, **WWW_HOME**
: When set, Chawan starts in visual mode by default and opens the page
specified by one of these variables. **HTTP_HOME** takes precedence
over **WWW_HOME**.
**CHA_DIR**
: When set, it switches the configuration directory to the path specified.
**COLORTERM**
: When set to *24bit* or *truecolor*, and the *display.color-mode*
configuration option is set to *auto*, Chawan sets the color mode to
true color.
**TERM**
: Used by Chawan to adjust to terminal-specific quirks. When not
set, defaults to *xterm*.
**VISUAL**, **EDITOR**
: Used to determine the editor to use when the *external.editor*
configuration option is not set.
**LINES**, **COLUMNS**
: Used as fallback values when window size detection fails.
# SEE ALSO
[**mancha**](mancha.md)(1), [**cha\-config**](config.md)(5),
[**cha\-mailcap**](mailcap.md)(5), [**cha\-mime.types**](mime.types.md)(5),
[**cha\-cgi**](cgi.md)(5), [**cha\-urimethodmap**](urimethodmap.md)(5),
[**cha\-protocols**](protocols.md)(7), [**cha\-image**](image.md)(7),
[**cha\-css**](css.md)(7), [**cha\-troubleshooting**](troubleshooting.md)(7),
[**cha\-terminal**](terminal.md)(7)
chawan-v0.4.0/doc/config.md 0000664 0000000 0000000 00000124526 15202323131 0015500 0 ustar 00root root 0000000 0000000
# Configuration of Chawan
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]`, where `n` is 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:
1. config file specified through -C switch -> use that
2. `$CHA_DIR` is set -> use `$CHA_DIR/config.toml`
3. `${XDG_CONFIG_HOME:-~/.config}/chawan/config.toml` exists -> use that
4. `~/.chawan/config.toml` exists -> use that
See the [*Path handling*](#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.
**Table of contents**
* [Start](#start)
* [Search](#search)
* [Buffer](#buffer)
* [Encoding](#encoding)
* [External](#external)
* [Input](#input)
* [Network](#network)
* [Display](#display)
* [Status](#status)
* [Omnirule](#omnirule)
* [Siteconf](#siteconf)
* [Keybindings](#keybindings)
* [Pager actions](#pager-actions)
* [Buffer actions](#buffer-actions)
* [Line-editing actions](#line-editing-actions)
* [Appendix](#appendix)
* [Regex handling](#regex-handling)
* [Match mode](#match-mode)
* [Search mode](#search-mode)
* [Path handling](#path-handling)
* [Word types](#word-types)
* [w3m word](#w3m-word)
* [vi word](#vi-word)
* [Big word](#big-word)
## 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 -V option 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 like setTimeout
do 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 sets `setInterval`.)
Piping `cha` to an external program or passing the `-d` switch 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:
```toml
[buffer]
# show images on all websites
images = true
# disable website CSS
styling = false
# Specify user styles.
user-style = '''
/* you can import external UA styles like this: */
@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 }
@media (monochrome) { /* only in color-mode "monochrome" (or -M) */
/* 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 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 to
`external.cookie-file`. `true` still reads cookies.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 not `http-equiv=refresh` meta 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 `@import` is 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](#search-mode) 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.
Used in dump mode as well.
(This means that e.g. `cha -I EUC-JP -O UTF-8 a > b` is roughly
equivalent to `iconv -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. %s is substituted for the file name, %d for
the line number.
mailcap = ["~/.mailcap", "/etc/mailcap", "/usr/etc/mailcap", "/usr/local/etc/mailcap"]
: **array of paths**
: Search path for mailcap files. See [**cha-mailcap**](mailcap.md)(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 for mime.types files. See [**cha-mime.types**](mime.types.md)(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".
cgi-dir = ["\$CHA_DIR/cgi-bin", "\$CHA_LIBEXEC_DIR/cgi-bin"]
: **array of paths**
: Search path for local CGI scripts. See [**cha-cgi**](cgi.md)(5) for
details.
urimethodmap = ["\$CHA_DIR/urimethodmap", "~/.urimethodmap", "/etc/urimethodmap"]
: **array of paths**
: Search path for urimethodmap files. See
[**cha-urimethodmap**](urimethodmap.md)(5) for details.
w3m-cgi-compat = false
: **boolean**
: Enable local CGI compatibility with w3m. In short, it redirects
`file:///cgi-bin/*` and `file:///$LIB/cgi-bin/*` to `cgi-bin:*`.
See [**cha-cgi**](cgi.md)(5) for details.
download-dir = "\${TMPDIR:-/tmp}/"
: **path**
: Path to pre-fill for "Save to:" prompts.
show-download-panel = true
: **boolean**
: Whether `about:downloads` should be opened after starting a download.
copy-cmd = "xsel -bi"
: **shell command**
: Command to use for "copy to clipboard" operations. When
`input.osc52-copy` is set to "auto" (the default), `copy-cmd` is ignored
if support for OSC 52 is detected.
paste-cmd = "xsel -bo"
: **shell command**
: Command to use for "read from clipboard" operations.
bookmark = "\$CHA_DATA_DIR/bookmark.md"
: **path**
: Path to the bookmark.md file. (The file it points to should have a
.md extension, so that its type can be correctly deduced.)
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 equivalent to curl's "cookies.txt" format, except that a
"jar@" part is prepended for cookies that belong in a different jar than
the domain.
Cookies from this file are used if "buffer.cookie" (or its equivalent
siteconf override) is set to `true` or `"save"`. This means that `true`
sets the cookie-file to a "read-only" mode.
## Input
Input options are to be placed in the `[input]` section.
vi-numeric-prefix = true
: **boolean**
: Whether vi-style numeric prefixes to commands should be accepted.
Only applies for keybindings defined in `[page]`.
use-mouse = "auto"
: **boolean** / **"auto"**
: Whether Chawan is allowed to intercept mouse clicks.
The current implementation imitates w3m.
When set to "auto" (the default), Chawan tries to detect whether mouse
support is available.
osc52-copy = "auto"
: **boolean** / **"auto"**
: Whether Chawan should use the OSC 52 escape sequence for copying to
the clipboard directly through the terminal. When available, OSC 52
overrides `external.copy-cmd`.
When set to "auto" (the default), Chawan tries to detect whether OSC 52
is available on launch.
osc52-primary = "auto"
: **boolean** / **"auto"**
: Whether Chawan should try to set the primary selection through OSC 52.
This happens automatically on mouse selection, and also on all clipboard
copies.
When set to "auto" (the default), Chawan tries to detect whether the
terminal is capable of setting the primary selection. Note that very
few terminals actually implement OSC 52 correctly (to my knowledge, only
XTerm and Kitty), and on other terminals this might even break copying to
the clipboard selection.
bracketed-paste = "auto"
: **boolean** / **"auto"**
: Whether Chawan should ask for bracketed paste.
When true, the terminal will (hopefully) mark pasted text with escape
sequences, which a) ensures that pasting a newline character into the
line editor does not submit the editor, b) allows Chawan to intercept
text pasted into the pager, automatically loading it into the browser's
URL bar.
When set to "auto" (the default), Chawan tries to only enable bracketed
paste if the terminal is known not to misbehave when trying to do so.
wheel-scroll = 5
: **number**
: Number of lines to scroll for a mouse wheel event.
side-wheel-scroll = 5
: **number**
: Number of columns to scroll for a mouse side-wheel event.
link-hint-chars = "abcdefghijklmnoprstuvxyz"
: **string**
: A string of characters to use in `toggleLinkHints`. Any Unicode
codepoint is accepted, and they are ordered as specified 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 are to be placed in the `[network]` section.
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.
Further connections are held back until the number returns below the
threshold.
prepend-scheme = "https://"
: **string**
: Prepend this to URLs passed to Chawan (or typed into the URL bar) without
a scheme.
Note that local files (`file:` scheme) will always be checked first; only
if this fails, Chawan will retry the request with `prepend-scheme` set as
the scheme.
proxy = ""
: **URL**
: Specify a proxy for all network requests Chawan makes. Currently, the
formats `http://user:pass@domain` and `socks5://user:pass@domain` are
accepted. Unlike in curl, `socks5h` is an alias of `socks5`, and DNS
requests are always tunneled.
Can be overridden by siteconf.
default-headers = {see bonus/config.toml}
: **table**
: Specify a table of default headers for all HTTP(S) network requests.
Can be overridden by siteconf.
allow-http-from-file = false
: **boolean**
: **WARNING: think twice before enabling this.**
Allows HTTP and HTTPS requests from the `file:` and `stream:` schemes.
This is a bad idea in general, because it allows local files to ping
remote servers (a functionality commonly abused by HTML e-mails to track
your mailbox activity).
On the other hand, it allows loading images in HTML e-mails if you 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 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, "none" disables image display
completely.
"auto" (the default) detects sixel or kitty support automatically, and
falls back to "none" when neither are available. This is expected to
work on all known terminals with functional image support.
Note that `buffer.images` must be enabled for images to load at all.
sixel-colors = "auto"
: **"auto"** / **2..65535**
: Only applies when `display.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; instead, reverse video is
used.
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. Useful when e.g. ○ occupies two
cells.
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. 0 disables
this function (i.e. allows black letters on 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 to Chawan.
default-foreground-color = "auto"
: **"auto"** / **RGB color**
: Sets the assumed foreground color of the terminal. "auto" leaves
foreground color detection to Chawan.
columns = 80, lines = 24, pixels-per-column = 9, pixels-per-line = 18
: **number**
: Fallback values for the number of columns, lines, pixels per column,
and pixels per line for the cases where it cannot be determined
automatically. (For example, these values are used in dump mode.)
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 provided above.
## Status
Options concerning the status bar (last line on the screen) are to be
placed in the `[status]` section.
Following is a list of status options:
show-cursor-position = true
: **boolean**
: Whether or not the current line number should be displayed.
show-hover-link = true
: **boolean**
: Whether or not the link under the cursor should be displayed.
format-mode = "reverse"
: **{see \[display\] section}**
: Formatting of the status bar.
## Omnirule
The omni-bar (by default opened with C-l) can be used to perform
searches using omni-rules. These are to be specified as sub-keys
to table `[omnirule]`. (The sub-key itself is ignored; you can use
anything as long it doesn't conflict with other keys.)
Examples:
```
# 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.split(":").slice(1).join(":"))'
# 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,
selected 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 Wikitionary.
* `mo:` - Mojeek.
Omnirule options:
match
: **regex**
: Regular expression used to match the input string. Note that websites
passed as arguments are matched as well.
Note: regexes are handled according to the [match mode](#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 specified for individual sites. Entries
are to be specified as sub-keys to table `[siteconf]`. (The sub-key
itself is ignored; you can use anything as long 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 the `host`
option must be specified.
Note: regexes are handled according to the [match mode](#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 the `url` option (but not both) must be
specified.
Note: regexes are handled according to the [match mode](#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
on a.com that refers to b.com, and referer-from is true, b.com is sent
"a.com" as the Referer header.
scripting = buffer.scripting
: **boolean** / **"app"**
: Enable/disable JavaScript execution on this site. See `buffer.scripting`
for 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, like `curl --insecure` would.
Please do not use this unless you are absolutely sure you know what you
are doing.
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 not `http-equiv=refresh` meta 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 to `buffer.user-style` for details.
## Keybindings
Keybindings are to be placed in these sections:
* for pager interaction: `[page]`
* for line editing: `[line]`
Keybindings are configured using the syntax
```toml
'' = ''
```
Where `` is a combination of unicode characters using the syntax
described below.
`` 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**](api.md)(7).
Examples:
```toml
# 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`.
For backwards-compatibility, spaces can be omitted from key sequences that
do not start with an upper-case letter. For example, `'gg'` and `'g g'` are
equivalent. However, components that start with an upper-case letter
(e.g. `'Gg'`) are reserved for key names, so those must be space-separated
(e.g. `'G g'`) to avoid ambiguous parsing.
Also, for backwards-compatibility, spaces at the beginning/end of the
keybinding are translated to `SPC`.
### Pager actions
Default keybindings are highlighted in **bold**.
quit
: **q**
: Exit the browser.
suspend
: **C-z**
: Temporarily suspend the browser
Note: this also suspends e.g. buffer processes or CGI scripts. So if
you are downloading something, that will be delayed until you restart the
process.
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 no link/image is under the cursor, an empty URL bar is opened.
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.
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
: **\**
: If viewing an HTML buffer, open a new buffer with its source. Otherwise,
open the current buffer's contents as HTML.
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 .**
: Discard the current buffer, and move back to the previous/next buffer,
or open the link under the cursor.
discardTree
: **M-d**
: Discard all child buffers of the current buffer.
nextBuffer, prevBuffer
: **.**, **,**
: 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.
searchForward, searchBackward
: Search for a string in the current buffer, forwards or backwards.
isearchForward, searchBackward
: **/**, **?**
: Incremental-search for a string, highlighting the first result, forwards
or backwards.
searchNext, searchPrev
: **n**, **N**
: Jump to the nth (or if unspecified, first) next/previous search result.
peek
: Display a message of the current buffer's URL on the status line.
peekCursor
: **u**
: Display a message of the URL or title under the cursor on the status
line. Multiple calls allow cycling through the two. (i.e. by default,
press u once -> title, press again -> URL)
showFullAlert
: **s u**
: Show the last alert inside the line editor. You can also view previous
ones using C-p or C-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 with `input.link-hint-chars`.
toggleLinkHintsAutoClick
: Same as `toggleLinkHints`, but also click the selected link.
### 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.
Default keybindings are highlighted in **bold**.
cursorUp, cursorDown
: **j**/**C-p**/**Up**,
**k**/**C-n**/**Down**
: Move the cursor upwards/downwards by `n` lines, or if `n` is unspecified,
by 1.
cursorLeft, cursorRight
: **h**/**Left**, **l**/**Right**
: Move the cursor to the left/right by `n` cells, or if `n` is unspecified,
by 1.
cursorLineBegin
: **0**/**Home**
: Move the cursor to the first cell of the line.
cursorLineTextStart
: **^**
: Move the cursor to the first non-blank character of the line.
cursorLineEnd
: **$**/**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](#word-types).
cursorPrevWord, cursorPrevViWord, cursorPrevBigWord
: Move the cursor to the end of the nth previous [word](#word-types).
cursorWordEnd, cursorViWordEnd, cursorBigWordEnd
: **e**, **E**
: Move the cursor to the end of the current [word](#word-types), or if
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](#word-types),
or if 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).
cursorPrevParagraph, cursorNextParagraph
: **{**, **}**
: 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 by `n` pages, or if `n` is unspecified, by one
page.
halfPageUp, halfPageDown, halfPageLeft, halfPageUp
: **C-u**, **C-d**
: Scroll up/down/left/right by `n` half pages, or if `n` is unspecified, by
one page.
scrollUp, scrollDown, scrollLeft, scrollRight
: **K**/**C-y**, **J**/**C-e**, **z h**, **z l**
: Scroll up/down/left/right by `n` lines, or if `n` is unspecified, by one
line.
click
: **RET**/**LF**
: Click the HTML element currently under the cursor. `n` specifies 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.
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.
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 to `H`, `M`, `L` in vi.)
raisePage, raisePageBegin, centerLine, centerLineBegin, lowerPage, lowerPageBegin
: **z t**, **z RET**, **z z**, **z .**, **z b**, **z -**
: If `n` is specified, move cursor to line `n`. Then,
* `raisePage` scrolls down so that the cursor is on the top line of
the screen. (vi `z RET`, vim `z t`.)
* `centerLine` shifts the screen so that the cursor is in the middle
of the screen. (vi `z .`, vim `z z`.)
* `lowerPage` scrolls up so that the cursor is on the bottom line of
the screen. (vi `z -`, vim `z b`.)
The -Begin variants also move the cursor to the line's first
non-blank character, as the original keybindings in vi do.
nextPageBegin
: **z +**
: If `n` is 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 ^**
: If `n` is 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 $**
: Move to the first/middle/last column on the screen.
centerColumn
: Center screen around the current column. (w3m `Z`.)
gotoLineOrStart, gotoLineOrEnd
: **g g**, **G**
: If `n` is specified, jump to line `n`. Otherwise, jump to the first/last
line of the buffer.
gotoColumnOrBegin, gotoColumnOrEnd
: **|**
: If `n` is specified, jump to column `n` of 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
: **`**, **'**
: Wait for a character `x` and then jump to the mark with the ID `x` (if it
exists on the page).
`gotoMark` sets both the X and Y positions; gotoMarkY only sets the Y
position.
markURL
: **:**
: Convert URL-like strings to anchors on the current page.
saveLink
: **s RET**
: Save resource from the URL pointed to by the cursor to the disk.
saveSource
: **s S**
: Save the source of the current buffer to the disk.
saveImage
: **s I**
: 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**, **\***
: Search for the word currently under the cursor.
cursorSearchWordBackward
: **#**
: Search for the word currently under the cursor, backwards.
### Line-editing actions
line.submit
: **RET**, **LF**
: Submit the currently entered text.
line.cancel
: **C-g**
: Close the editor and cancel the operation it was opened for.
line.copyOrCancel
: **C-c**
: If there is an active selection, copy it. Otherwise, it's the same as
`line.cancel`.
line.backspace, line.delete
: **C-h**, **C-d**
: Delete character before (backspace)/after (delete) the cursor.
line.clear, line.kill
: **C-u**/**C-x C-?**, **C-k**
: Delete text before (clear)/after (kill) the cursor.
line.openEditor
: **C-x C-e**
: Open the line editor's contents in $EDITOR.
line.clearWord, line.killWord
: **C-w**, **M-d**
: Delete word before (clear)/after (kill) the cursor.
line.backward, line.forward
: **C-b**, **C-f**
: Move cursor backward/forward by one character.
line.prevWord, line.nextWord
: **M-b**, **M-f**
: Move cursor to the previous/next word by one character
line.begin, line.end
: **C-a**/**Home**, **C-e**/**End**
: Move cursor to the beginning/end of the line.
line.escape
: **C-v**
: Ignore keybindings for next character.
line.prevHist, line.nextHist
: **C-p**, **C-n**
: Jump to the previous/next history entry
Note: to facilitate URL editing, the line editor has a different definition
of what a word is than the pager. For the line editor, a word is either
a sequence of alphanumeric characters, or any single non-alphanumeric
character. (This means that e.g. `https://` consists of four words:
`https`, `:`, `/` and `/`.)
```Examples:
# 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
Regular expressions are currently handled using the libregexp library from
QuickJS. This means that all regular expressions work as in JavaScript.
There are two different modes of regex preprocessing in Chawan: "search"
mode and "match" mode. Match mode is used for configurations (meaning in
all values in this document described as "regex"). Search mode is used for
the on-page search function (using searchForward/isearchForward etc.)
#### Match mode
Regular expressions are assumed to be exact matches, except when they start
with a caret (^) sign or end with an unescaped dollar ($) sign.
In other words, the following transformations occur:
```
^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`.
#### Search mode
For on-page search, the above transformations do not apply; the search
`/abcd` searches for the string `abcd` inside all lines.
Search mode also has some other convenience transformations (these do
not work in match mode):
* The string `\c` (backslash + lower-case c) inside a search-mode regex
enables case-insensitive matching.
* Conversely, `\C` (backslash + capital C) disables case-insensitive
matching. (Useful if you have `ignore-case` set to true, which is
the default.)
* `\<` and `\>` is converted to `\b` (as in vi, grep, etc.)
Like match mode, search mode operates on individual lines. This means
that search patterns do not match text wrapped over multiple lines.
### Path handling
Rules for path handling are similar to how the shell handles strings.
* Tilde-expansion is used to determine the user's home directory. So
e.g. `~/whatever` 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 which the `cha` binary resides in.
Symbolic links are automatically resolved to determine this path.
* `$CHA_LIBEXEC_DIR`: the directory for all executables Chawan uses for
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 is the
same as `$CHA_DIR`.
- Exception: if `$CHA_DIR` is set before `cha` is invoked, then
`$CHA_DATA_DIR` is also read. This is to make nested invocations
work in configurations with XDG basedirs.
### Word types
Word-based pager commands can operate with different definitions of
words. Currently, these are:
* w3m words
* vi words
* Big words
#### w3m word
A w3m word is a sequence of alphanumeric characters. Symbols are
treated in the same way as whitespace.
#### vi word
A vi word is a sequence of characters in the same character category.
Currently, 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 do not 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 is essentially the same as a w3m word, but with symbols being defined
as non-whitespace.
## See also
[**cha**](cha.md)(1) [**cha-api**](api.md)(7)
chawan-v0.4.0/doc/css.md 0000664 0000000 0000000 00000023213 15202323131 0015012 0 ustar 00root root 0000000 0000000
# CSS in Chawan
This document describes CSS features supported by Chawan, as well as
its proprietary extensions and deviations from standards.
If you discover a deviation that is not covered by this document, please
open a ticket at .
## Standard properties
A list of supported standard properties, with notes on unimplemented values:
* background-color (see color)
* background-image (displays placeholders only)
* border-collapse
* border-\*-style, border-\*-color, border-\*-width (but see
[borders](#borders))
* border-spacing
* bottom
* box-sizing
* caption-side
* clear
* color (hex values and functions `rgb`, `rgba`, `hsl`, `hsla`)
* content (string, (no-)open/close-quote, counter())
* counter-increment
* counter-reset
* counter-set
* display (`block`, `inline-block`, `list-item`, `table`, `inline-table`,
`table-*`, `flex`, `inline-flex`, `flow-root`)
* flex-basis (but `content` not supported)
* flex-direction
* flex-grow
* flex-shrink
* flex-wrap
* float
* font-size (ignored; only for JS compatibility)
* font-style (`oblique` interpreted as `italic`)
* font-weight (numeric properties > 500 interpreted as bold, others
as regular)
* height
* left
* list-style-position
* list-style-type (but no custom list styles)
* margin-bottom
* margin-left
* margin-right
* margin-top
* max-height
* max-width
* min-height
* min-width
* opacity (hacky; only works with `opacity: 0`)
* overflow-x (see below on scrollbars)
* overflow-y (see below on scrollbars)
* padding-bottom
* padding-left
* padding-right
* padding-top
* position (see below for `sticky` and `fixed`)
* quotes
* right
* text-align
* text-decoration (`none`, `underline`, `overline`, `line-through`)
* text-transform
* top
* vertical-align
* visibility
* white-space
* width
* word-break
* z-index
Shorthands:
* all
* margin
* padding
* border, border-style, border-color, border-width (but see
[borders](#borders))
* background (only color and url; other components are skipped)
* list-style (list-style-image is skipped)
* flex
* flex-flow
* overflow
Variables (the `var()` function) are fully supported.
Values of `` or `` types fully support `calc()` expressions.
## Selectors
All selector types from CSS 2.1 are supported, except for namespaces.
Following standard pseudo-classes are supported: `:first-child`,
`:last-child`, `:only-child`, `:hover`, `:root`, `:nth-child()`,
`:nth-last-child()`, `:checked`, `:focus`, `:is()`, `:not()`,
`:where()`, `:lang()`, `:link`, `:target`, `:disabled`.
`:visited` is parsed, but for now it is not matched.
`:defined`, `:host`, and `:host()` are matched for compatibility; however,
custom elements and shadow DOM are not supported yet.
The standard pseudo-elements `::before`, `::after`, and `::marker` are
supported. `::backdrop` is parsed for compatibility, but is not supported
yet.
## At-rules
Following rules starting with an `@` sign are supported.
### `@media`
The `grid`, `hover`, `prefers-color-scheme`, `scripting`, `width`, and
`height` media features are fully supported.
The `color`, `color-index`, and `monochrome` features are supported, but
only consider the number of supported text colors (which can differ from
the number of colors in Sixel/Kitty images).
### `@import`
Importing to layers is supported.
`@import` combined with media queries is not yet supported.
### `@layer`
`@layer` is fully supported. (I think.)
## Proprietary extensions
* `text-align` accepts the values `-cha-center`, `-cha-left`, and
`-cha-right` to support the HTML ``, ``
and `` elements. (Analogous to `-moz-center` etc.)
* Properties with a `` value accept the function `-cha-ansi()`,
mapping to terminal-specific ("ANSI") colors. The function takes one of
- An 8-bit integer, indicating a color value as set by XTerm's
indexed color feature.
- One of the strings "black", "red", "green", "yellow", "blue",
"magenta", "cyan", "white" for an ANSI color, possibly
prefixed by the string "bright-" to indicate an aixterm
16-color value.
* `text-decoration` accepts the keyword `-cha-reverse`, which sets
the *reverse video* parameter on the text. (This is used by the UA
style sheet to highlight text in `` tags.)
* `text-transform` accepts the keyword `-cha-half-width`, which has the
opposite effect as `full-width`.
This can be used in user style sheets to compress distracting ruby
text: `rt{text-transform: -cha-half-width}`. Characters without
half-width counterparts are left intact, except hiragana is treated as
katakana.
* The `-cha-colspan` and `-cha-rowspan` properties have the same effect
as the `colspan` and `rowspan` attributes on tables.
* The `:-cha-first-node` and `:-cha-last-node` pseudo-classes apply to
elements that have no preceding/subsequent sibling node that is either
an element node or a text node with non-whitespace contents. (Modeled
after `:-moz-first-node` and `:-moz-last-node`.)
* If `buffer.mark-links` is set, the `::-cha-link-marker` pseudo-element
will be generated on all anchor elements.
* In hints mode (by default, the `f` key) the markers are implemented by
generating `::-cha-link-hint` on all applicable elements. So you can
change the marker background in your `user-style` (`[buffer]` section in
`config.toml`):
```css
::-cha-link-hint { background: gainsboro }
```
* The `-cha-content-type` media feature can be used to filter documents
for their content type. For example, you can add
```css
@media (-cha-content-type: "text/markdown") { body { width: 80ch } }
```
to your `user-style` to set the body width of all markdown documents to
80 characters. (The string is matched case-insensitively.)
## Rendering quirks
These are willful violations of the standard, usually made to better fit
the display model inherent to projecting the web to a cell-based screen.
### User agent style sheet
The user agent style sheet is a combination of the styles suggested by
the HTML standard and a CSS port of w3m's rendering. In general,
faithfulness to w3m is preferred over the standard's suggestions, unless
w3m's rendering breaks on existing websites.
Link colors differ depending on the terminal's color scheme.
### Sizing and positioning
Layout is performed on a finite canvas of coordinates represented by a
32-bit fixed-point number with 6 bits of precision. After layout, these
positions are divided by the cell width and/or height, with the
fractional part truncated. (This is subject to change.)
In case of Kitty images, the fractional part is preserved, and is used
as an in-cell offset.
The lengths `1em` and `1ch` compute to the cell height and cell width
respectively.
In outer inline boxes (`inline-block`, `inline-flex`) and `list-item`
boxes, margins and padding that are smaller than one cell (on the
respective axis) are ignored. This does not apply to blockified inline
boxes.
When calculating clip boxes (`overflow: hidden` or `clip`), the clip
box's offset is floored, and its size is ceiled to the nearest cell's
boundaries. This means that "width: 1px; overflow: hidden" will still
display the first character of a text box.
### Scroll bars
Chawan does not have scroll bars, as they would complicate on-page
navigation and would not work in dump mode. Instead, the "overflow-x/y"
properties are handled as follows.
1. If `overflow` is `auto` or `scroll`, and the intrinsic minimum size
of the box is greater than its specified size, then the former
overrides the latter.
2. Content that spills out of a scroll container on the X axis is
displayed, while content that spills out of a scroll container on the
Y axis is clipped.
### `position: fixed`, `position: sticky`
To keep the document model static, these do not change their position
based on the viewport's scroll status. Instead:
* `position: sticky` is treated as `position: static`, except it also
behaves as an absolute position container.
* `position: fixed` is placed at the bottom of the document.
Right now, `position: fixed` is always positioned at the bottom of the
root element's margin box. This breaks on pages that overflow it (e.g.
by setting `height: 100%` on the root element), so it will be moved to
the bottom of its overflow box in the future.
### Color correction
Some authors only specify one of the foreground or the background color,
assuming a black-on-white canvas. The `display.minimum-contrast` option
adjusts the foreground color so that text remains readable even if the
terminal background does not match this expectation. (The exact
algorithm is unspecified and subject to change.)
To avoid breaking spoiler mechanisms that rely on "black on black" text,
color correction is not invoked on cells that have an RGB color (typically
specified by the author.)
### Borders
CSS borders are difficult to accurately display on a cell-based display.
So while the functionality exists, it has some limitations:
* On tables, borders are always collapsed, even when `border-collapse` is
set to `separate`.
* With `border-collapse: separate`, the spacing between cells is the largest
of `border-spacing` times two and the cell width.
* `border-*-width` is interpreted as a binary value: a width of 0 results in
no border, while any other width results in a border of a single type.
If the width is smaller than one cell (in the respective direction), the
rest is subtracted from the margin (if there is any margin).
* `box-sizing: border-box` actually sets the padding box size, so that
borders rounded up to the cell size do not accidentally take all space
from the actual content. (That in turn would cause problems if a child
box set `overflow: hidden`, etc.)
## See also
[**cha**](cha.md)(1)
chawan-v0.4.0/doc/hacking.md 0000664 0000000 0000000 00000026021 15202323131 0015626 0 ustar 00root root 0000000 0000000 # Hacking
Some notes on modifying Chawan's code.
## Style
Refer to the [NEP1](https://nim-lang.org/docs/nep1.html) for the basics.
Also, try to keep the style of existing code.
In particular, style of vendored libraries should not be changed unless
upstream is dead.
### Casing
Everything is camelCase. Enums are camelCase too, but the first part is an
abbreviation of the type name. e.g. members of `SomeEnum` start with `se`.
Exceptions:
* Types/constants use PascalCase. enums in cssvalues use PascalCase too, to
avoid name collisions.
* We keep style of external C libraries, which is often snake_case.
* Chame is stuck with `SCREAMING_SNAKE_CASE` for its enums. This is
unfortunate, but does not warrant an API breakage.
Rationale: consistency.
### Wrapping
80 chars per line.
Exceptions: URL comments.
Rationale: makes it easier to edit in vi.
### Spacing
No blank lines inside procedures (and other code blocks). A single blank
line separates two procs, type defs, etc. If your proc doesn't fit on two
24-line screens, split it up into more procs instead of inserting blank
lines.
Exceptions: occasionally a proc will get larger than two screens, and that's
ok, but try to avoid it.
Rationale: makes it easier to edit in vi.
### Param separation
Semicolons, not commas. e.g.
```nim
# Good
proc foo(p1: int; p2, p3: string; p4 = true)
# Bad
proc bar(p1: int, p2, p3: string, p4 = true)
```
Rationale: makes it easier to edit in vi.
### Naming
Prefer short names. Don't copy verbose naming from the standard.
Rationale: we aren't a fruit company.
### Comments
Comment what is not obvious, don't comment what is obvious. Whether
something is obvious or not is left to your judgment.
Don't paste standard prose into the code unless you're making a point. If
you do, abridge the prose.
Rationale: common sense, copyright.
### C style
Note that most C code included in this repository is from vendored external
libraries like QuickJS; following points only apply to code we own, such
as chaseccomp.
* 80 spaces per line. Indent with 4 spaces (not mixed with tabs).
* Local variable declarations come before their use (a la C89). The two
sections have a blank line inbetween.
* Braces go on the same line as the statement, except for functions where
they go on the next line.
* `if`, `for`, etc. must have braces unless each part fits on a single line.
* Boolean operators (`||` etc.) belong on the same line as the left-hand
expression.
### JavaScript style
Similar to C style.
* 80 spaces per line. Indent with 4 spaces (not mixed with tabs).
* Prefer `const`/`let` to `var`.
* Braces go on the same line as the statement or function.
* `if`, `for`, etc. must have braces unless each part fits on a single line.
* Boolean operators (`||` etc.) belong on the same line as the left-hand
expression.
Note: although QJS has an optimizer, compared to that of a static language
it is very limited. Some ugliness is acceptable if it results in more
efficient code.
## Features to avoid
List of Nim features/patterns that sound like a good idea but aren't, for
non-obvious reasons.
### Exceptions
Avoid at all costs. If a standard library procedure throws, do not use it.
Also avoid `try...finally` (even without `catch`).
For own procs, use Result/Opt instead. For large objects this may result in
excessive copying; to avoid inefficient code, either make them `ref` or use
manual RVO:
```nim
proc blah(input: int; output: var BigObject): Opt[void] =
if input < 0:
return err()
output = BigObject(...)
ok()
```
In new modules, always specify:
```nim
# This is an example module.
# After any header comments, but before imports:
{.push raises: [].}
import ...
# At the end of the file:
{.pop.} # raises: []
```
### Implicit initialization
Avoid. The correct way to create an object:
```nim
let myObj = MyObject(
param1: x,
param2: y
# if there's e.g. a param3 too, it's OK to leave it out and let it be
# default initialized.
)
```
For primitive types, just set them to 0, "", etc.
As a special case, implicit initialization is allowed for arrays:
```nim
var buf1: array[1234, char] # when you need 0-initialization
var buf2 {.noinit.}: array[1234, char] # when you don't need 0-initialization
```
Note that the second example is unsafe and doesn't work with GC'ed types,
so don't use it unless you know what you're doing.
### `out` parameters
`out` parameters crash the 1.6.14 compiler. Use `var` instead.
### Copying operations
`substr` and `x[n..m]` copies. Try to use `toOpenArray` instead, which is a
non-copying slice. (Obviously, you should use `substr` if you *need* to
copy.)
Note that `=` usually copies. If you're copying a large object a lot, you
may want to set its type to `ref`. For `seq`/`string` you can also try
using `move`, but be sure to check the generated code because often times
it doesn't work in `refc`.
Beware of `pairs` on sequences of objects; it copies. Use `mypairs` if you
don't need mutation, `mpairs` if you do:
```nim
proc foo(objs: openArray[SomeObj]) =
for i, obj in objs: # Bad. this copies. obj's type is "SomeObj".
obj.bar(i)
# import utils/twtstr to use mypairs.
for i, obj in objs.mypairs: # OK, doesn't copy. obj's type is "lent "SomeObj".
obj.bar(i)
for i, obj in objs.mpairs: # OK, doesn't copy. obj's type is "var SomeObj".
obj.i = i
```
### `func`, `.noSideEffect`
These introduce function coloring for little to no benefit.
Just use `proc` without `.noSideEffect`.
### Closures
A closure is an anonymous `proc` that uses ("captures") variables in its
wrapper `proc`. These introduce implicit GC'ed environments which are
often wasteful, and combined with JS they are an easy way to produce memory
leaks.
To enforce this rule, `proc` variables or members always have a `nimcall`
(or `cdecl`) pragma. The environment can be passed explicitly, e.g.:
```nim
type
FooCallback = proc(foo: Foo; opaque: RootRef) {.nimcall, raises: [].}
Foo = ref object
callback: FooCallback
opaque: RootRef # add an explicit environment like this if needed
```
## Fixing cyclic imports
In Nim, you can't have circular dependencies between modules. This gets
unwieldy as the HTML/DOM/etc. specs are a huge cyclic OOP mess.
The preferred workaround is global function pointer variables:
```nim
# Forward declaration hack
var forwardDeclImpl*: proc(window: Window; x, y: int) {.nimcall, raises: [].}
# in the other module:
forwardDeclImpl = proc(window: Window; x, y: int) =
# [...]
```
Don't forget to make it `.nimcall`, and to comment "Forward declaration
hack" above. (Hopefully we can remove these once Nim supports cyclic module
dependencies.)
## Debugging
Note: following text assumes you are compiling in debug mode, i.e.
`make TARGET=debug`.
### The universal debugger
"eprint x, y" prints x, y to stderr, space separated.
Normally you can view what you printed through the M-c M-c (escape + c
twice) console. Except when you're printing from the pager, then do
`cha [...] 2>a` and check the "a" file.
Sometimes, printing to the console triggers a self-feeding loop of printing
to the console. To avoid this, disable the console buffer:
`cha [...] -o start.console-buffer=false 2>a`. Then check the "a" file.
You can also inspect open buffers from the console. Note that you must run
these *before* switching to the console buffer (i.e. before the second M-c),
or it will show info about the console buffer.
* `pager.process`: the current buffer's PID.
* `pager.cacheFile`: the current buffer's cache file.
* `pager.cacheId`: the cache ID of said file. Open the `cache:id` URL to
view the file.
### gdb
gdb should work fine too. You can attach it to buffers by putting a long
sleep call in runBuffer, then retrieving the PID as described above. Note
that this will upset seccomp, so you should compile with
`make TARGET=debug DANGER_DISABLE_SANDBOX=1`.
### Debugging layout bugs
One possible workflow:
* Save page from your favorite graphical browser.
* Binary search the HTML by deleting half of the file at each step. Be
careful to not remove any stylesheet LINK or STYLE tags.
* Binary search the CSS using the same method. You can format it using the
graphical browser's developer tools.
The `-o start.console-buffer=false` trick (see above) is especially useful
when debugging a flow layout path that the console buffer also needs.
Don't forget to add a test case after the fix:
```sh
$ ./test/layout/add test/layout/my-test-case.html
```
### Sandbox violations
You got a syscall number (assuming you're on Linux); look it up in the Linux
syscall table for your architecture.
To get more context on what happened, you can run
`strace -f ./cha -o start.console-buffer=false [...] 2>a`, trigger the
crash, then search for the last occurrence of "--- SIGSYS". Then search
backwards on the PID to see the last syscalls.
(*strace* also shows the syscall name, so it may be easier to check like
that than looking it up in the syscall table.)
## Resources
You may find these links useful.
### Chawan
Of particular interest in the documentation are:
* The [architecture](architecture.md) document.
* The Monoucha [manual](../lib/monoucha0/doc/manual.md), for JS-related
documentation.
### WHATWG
* HTML: . Includes everything and
then some more.
* DOM: . Includes events, basic node-related
stuff, etc.
* Encoding: . These algorithms are
implemented in encoding.
* URL: . For some incomprehensible reason,
it's defined as an equally incomprehensible state machine. types/url
implements this.
* Fetch: . Networking stuff. Also see
for XMLHttpRequest.
* Web IDL: . Relevant for Monoucha/JS
bindings.
Note that some of these are updated daily, such as the HTML standard.
### CSS standards
* CSS 2.1: . There's also an "Editor's
Draft" 2.2 version: , but so far I
haven't encountered significant differences.
Good news is that unlike WHATWG specs, this doesn't change daily. Bad news
is that CSS 2.1 was the last real CSS version, and newer features are spread
across a bunch of random documents with questionable status of stability:
.
### Other standards
It's unlikely that you will need these, but for completeness' sake:
* TOML: . config.toml's base language.
* Mailcap: .
* Cookies: .
* EcmaScript: is the latest draft.
### Nim docs
* Manual: . A detailed description
of all language features.
* Standard library docs: .
Everything found in the "std/" namespace.
### MDN
MDN is useful if you don't quite understand how a certain feature is
supposed to work. It also has links to relevant standards in page footers.
chawan-v0.4.0/doc/image.md 0000664 0000000 0000000 00000017760 15202323131 0015316 0 ustar 00root root 0000000 0000000
# Inline images
On terminals that support images, Chawan is capable of displaying various
image formats inline.
## Enabling images
There are actually two switches for images in the config:
* buffer.images: this enables downloading images, *even if they cannot be
displayed*. This is the switch you typically need.
* display.image-mode: sets the inline image display method. Defaults to
"auto", but may also be set to "none", "sixel", or "kitty" manually.
This switch is rarely useful.
In general, you only have to set `buffer.images` to true:
```toml
# in ~/.chawan/config.toml (or ~/.config/chawan/config.toml)
[buffer]
images = true
```
The `image-mode` switch is mainly useful if you want images to be fetched,
but not displayed ("none" option). It may also help if "auto" fails to
detect the terminal's image display capabilities; however, I am not aware of
any terminal where this can happen. (If you find one, open a ticket.)
## Output formats
Supported output formats are:
* The DEC Sixel format
* The Kitty terminal graphics protocol
Support for other protocols (iTerm, MLTerm, etc.) is not planned. (To my
knowledge, all image-capable terminals support at least one of the above
two anyways.)
Support for environment-specific hacks such as w3mimgdisplay, ueberzug,
etc. is not planned.
### Sixel
Sixel is the most widely supported image format.
See to find a terminal that supports it.
Known quirks and implementation details:
* XTerm needs extensive configuration for ideal sixel support. In
particular, you will want to set the decGraphicsID, numColorRegisters, and
maxGraphicSize attributes. See [**xterm**](man:xterm(1))(1) for details.
* We assume private color registers are supported. On terminals where they
aren't (e.g. SyncTERM or hardware terminals), colors will get messed up with
multiple images on screen.
* Zellij advertises Sixel support, but the feature is completely broken in
the current version, so Chawan specifically disables images in Zellij
by default. In particular:
- Zellij itself does no Sixel detection, emitting Sixel data even on
terminals that do not support it. (A fairly puzzling bug, given
the developers seem to be aware of the DA1 feature.)
- On terminals that support Sixel, it fails to position images
correctly, with the misplaced images completely messing up layout.
* We send XTSMGRAPHICS for retrieving the number of color registers; on
failure, we fall back to 256. You can override color register count using
the `display.sixel-colors` configuration value.
* Normally, Sixel encoding runs in two passes. On slow computers, you can
try setting `display.sixel-colors = 2`, which will skip the first pass
(but will also display everything in monochrome).
* Transparency *is* supported, but looks weird because we approximate
an 8-bit alpha channel with Sixel's 1-bit alpha channel. Also, some
terminals don't emulate it correctly - when in doubt, try XTerm (which
does).
* Terminal scroll (both with LF/RI and SU/SD) is used extensively to avoid
sending images several times. Expect troubles on terminals that do not
handle this correctly. (For example, tmux is known to destroy images on
scroll, so we avoid using scroll there.)
### Kitty
On terminals that support it, Kitty's protocol is preferred over Sixel. Its
main benefit is that images do not have to be sent again every time a new
slice of the image moves into the screen. Support for full RGBA without
quantization is another benefit.
Note: at the time of writing, tmux does not support the Kitty image
protocol. While it is possible to hack Kitty images onto tmux nevertheless,
this requires significant concessions in display capabilities compared to
the regular Kitty protocol (or even Sixel). Therefore, support for this
hack is not planned.
## Input formats
Currently, the supported input formats are:
* BMP, PNG, JPEG, GIF (through stb_image)
* WebP (through JebP)
* SVG (through NanoSVG)
More formats may be added in the future, provided there exists a reasonably
small implementation, preferably in the public domain. (I do not want to
depend on external image decoding libraries, but something like stbi is OK
to vendor.)
### Codec module system
All image codec implementations are specified by the URL scheme
"img-codec+name:", where "name" is the MIME subtype. e.g. for image/png,
it is "img-codec+png:". (This indeed means that only "image" MIME types can
be used.)
Like all schemes, these are defined (and overridable) in the urimethodmap
file, and are implemented as local CGI programs. These programs take an
encoded image on stdin, and dump the decoded RGBA data to stdout - when
encoding, vice versa.
This means that it is possible for users to define image decoders for their
preferred formats, or even override the built-in ones. (If you actually end
up doing this for some reason, please send me a mail so I can add it to the
bonus directory.)
A codec can have one of, or both, "decode" and "encode" instructions; these
are set in the path name. So "img-codec+png:decode" is called for decoding
PNGs, and "img-codec+png:encode" for encoding them.
Headers are used for transferring metadata (like image dimensions), both
from the browser (input) and to the browser (output). Detailed description
of the decoder & encoder interfaces follows.
#### decoding
When the path equals "decode", a codec CGI script must take a binary stream
of an encoded image on its standard input and print the equivalent binary
stream of big-endian 8-bit (per component) RGBA values to stdout.
Input headers:
* Cha-Image-Info-Only: 1
This tells the image decoder to only send image metadata (i.e. size).
Technically, the decoder is free to fully decode the image, but this is
a waste of resources; the browser will ignore any output received after
headers.
Output headers:
* Cha-Image-Dimensions: {width}x{height}
The size of the decoded image. e.g. for 123x456, 123 is width and 456 is
height.
#### encoding
When the path equals "encode", a codec CGI script must take a binary stream
of big-endian 8-bit (per component) RGBA values on its standard input and
print the equivalent encoded image to its standard output.
Input headers:
* Cha-Image-Dimensions: {width}x{height}
Specifies the dimensions of the input RGBA image. This means that
{width} * {height} * 4 == {size of data received on stdin}.
The format is the same as above; in fact, the design is such that you could
directly pipe the output of decode to encode (and vice versa).
* Cha-Image-Quality: {number}
The requested encoding quality, ranging from 1 to 100 inclusive
(i.e. 1..100). It is up to the encoder to interpret this number.
(The stb_image JPEG encoder uses this.)
Output headers:
Currently, no output headers are defined for encoders.
### Skipping copies with mmap
The naive implementation of the above system would have to copy the output
at least twice when an image is resized. To skip these copies, stdin and/or
stdout is (currently) a file in the tmp directory for:
* decode stdin, when the image is already downloaded
* decode stdout, always
* encode stdin, always
This makes it possible to [mmap](man:mmap(3)) stdin/stdout instead of
streaming through them with [read](man:read(3)) and [write](man:write(3)).
When doing this, mind the following:
* When reading, you must check your initial position in the file with
[lseek](man:lseek(3)).
* When writing, your headers are part of the output. At the very least,
you must place a newline at the file's beginning.
* mmapping for write is slower than streaming the data with `write`.
The only reason to mmap for write is to save memory when you can't stream
the output.
* This *is* an implementation detail, and might change at any time in
the future (e.g. if we add a "no cache files" mode). Always check
for S_ISREG to ensure that you are actually dealing with a file.
(Use io/dynstream.nim's readLoopOrMmap and maybeMmapForSend to deal with
this automatically.)
## See also
[**cha**](cha.md)(1) [**cha-terminal**](terminal.md)(7)
chawan-v0.4.0/doc/mailcap.md 0000664 0000000 0000000 00000017367 15202323131 0015645 0 ustar 00root root 0000000 0000000
# Mailcap
By default, Chawan's buffers only handle HTML and plain text.
The *mailcap* file can be used to view other file formats using external
commands, or to convert them to HTML/plain text before displaying them
in Chawan.
Note that Chawan's default mime.types file only recognizes a few file
extensions, which may result in your entries not being executed
if your system lacks an /etc/mime.types file. Please consult
[**cha-mime.types**](mime.types.md)(5) for details.
For an exact description of the mailcap format, see
[RFC 1524](https://www.rfc-editor.org/rfc/rfc1524).
## Search path
The search path for mailcap files is set by the configuration variable
`external.mailcap`. This matches the recommended path in the RFC:
```
$HOME/.mailcap:/etc/mailcap:/usr/etc/mailcap:/usr/local/etc/mailcap
```
By default, mailcap entries are only executed if the user types `r` (run)
after the prompt. Other options are to view the file with `t` (text), or
to save the file with `s`.
If a capital letter is typed (e.g. shift + `R`), then a corresponding entry
is appended to `external.auto-mailcap` (default: `~/.chawan/mailcap`, or
`~/.config/chawan/mailcap` with XDG basedirs). `(T)ext` and `(S)ave`
may also be used to append entries corresponding to the other display
options.
Entries in auto-mailcap are automatically executed, so it is recommended
to add your Chawan-specific entries there (or just set it to your
personal mailcap file).
## Format
Chawan adheres to the format described in RFC 1524, with a few extensions.
`text/html` and `text/plain` entries are ignored.
### Templating
The command part of entries may include template strings which are
substituted by the browser at execution.
Templates do not have to be quoted; Chawan quotes them automatically.
(This works with $(command substitutions) as well.) However, other
software may misbehave on such templates, so it may be better to assign
them to a variable first, e.g.
```
text/x-example; s=%s cat "$s"; copiousoutput
```
Following templates are supported:
* `%s` expands to the path. Specifying `%s` forces download of the
external resource *before* the entry is executed. If `%s` is not
specified, the resource is instead piped to standard input. (In this
case, `needsterminal` does not apply.)
* `%t` expands to the content type. Named content type fields can also
be specified with the syntax `%{charset}`. For example, in
```
text/html; charset=utf-8
```
`%t` would expand to the above string, while `%{charset}` would expand
to "utf-8".
* Non-standard templates for the resource's original URL: `%u` (from
Netscape) expands to the original URL of the resource, `%h` (from w3mmee)
expands to the hostname without the port, `%H` expands to the hostname
including the port, and `%?` (from w3mmee) expands to the query string
including the question mark.
(w3mmee did not actually include the question mark in `%?`. However,
that design could not express the difference between the empty query
string and the null query string, so it has been changed in Chawan.)
### Fields
Following fields are recognized.
* When the `test` named field is specified, the mailcap entry is only used
if the test command returns 0. For example, you can restrict entries
that require X11 as follows:
```
image; feh -; test=test -n "$DISPLAY"
```
Warning: `%s` does not work with `test`. `test` named fields with a `%s`
template are skipped, and no data is piped into `test` commands.
* `copiousoutput` makes Chawan redirect the output of the external
command's output into a new buffer. If either `x-htmloutput` or
`x-ansioutput` is defined too, then `copiousoutput` is ignored.
* `needsterminal` hands over control of the terminal to the command
while it is running. It does nothing if one of `copiousoutput`,
`x-ansioutput`, `x-saveoutput` or `x-htmloutput` is specified.
* `nametemplate` provides a specific template for the temporary file
created when `%s` is specified. See the RFC for details.
* `x-htmloutput` (from w3m) behaves the same as `copiousoutput`, but makes
Chawan interpret the command's output as HTML.
* `x-ansioutput` pipes the output through the "text/x-ansi" content type
handler, so that ANSI colors, formatting, etc. are displayed correctly.
* `x-saveoutput` prompts the user to save the entry's output in a file.
* `x-needsstyle` forces CSS to be processed for the specific type, even
if styling is disabled in the config. Only useful when combined with
`x-htmloutput`. (Also see the `-cha-content-type` media query in
[**cha-css**](css.md)(7).)
* `x-needsimage` forces images to be displayed in `x-htmloutput`, even if
images are disabled.
* `x-type` (from w3mmee) specifies a MIME type substitution. The command
part is interpreted as a MIME type (without template expansion) which is
used instead of the original type. Such entries are only respected in
`external.auto-mailcap`.
Entries with `x-type` also match text/plain and text/html documents
(which are normally excluded from mailcap). However, `x-type` does not
apply if the content type was forced (e.g. using the `-T` flag).
(Note: `x-type` is experimental. Future changes to its semantics are
to be expected.)
* `x-match` (from w3mmee) restricts the entry's URL to the specified regex.
`x-nc-match` is the same, but it is case-insensitive. For example,
`x-match=https?://example\.org/.*` restricts the entry to example.org
(note the backslash.)
When one of these fields is present together with `test`, the result is
ANDed together.
* `x-netpath` (from w3mmee) restricts the entry to URIs that match the
`net_path` production of RFC 2396. In other words, the URI must have an
authority (hostname etc.), so e.g. `example://blah/path` is matched,
while `example:/path` isn't.
For schemes other than `file`, two slashes after the colon signify
a `net_path`. `file:///path` is a special case: it looks like a
`net_path`, but it isn't one. (This is inherited from the WHATWG URL
standard.)
## Examples
To automatically execute these entries, place them in `~/.chawan/mailcap`
(or `~/.config/chawan/mailcap` if you use XDG basedirs). Alternatively,
if you already have a mailcap file to share with other programs, you can
set `external.auto-mailcap` to `~/.mailcap`.
```
# Note: these examples require an entry in mime.types that sets e.g. md as
# the markdown content type.
# Handle markdown files using pandoc.
text/markdown; pandoc - -f markdown -t html -o -; x-htmloutput
# Show syntax highlighting for JavaScript source files using bat.
text/javascript; bat -f -l es6 --file-name %u -; x-ansioutput
# Play music using mpv, and hand over control of the terminal until mpv exits.
audio/*; mpv -; needsterminal
# Play videos using mpv in the background, redirecting its standard output
# and standard error to /dev/null.
video/*; mpv -
# Open docx files using LibreOffice Writer.
application/vnd.openxmlformats-officedocument.wordprocessingml.document; lowriter %s
# Display manpages using pandoc. (Make sure the mime type matches the one
# set in your mime.types file for extensions .1, .2, .3, ...)
application/x-troff-man; pandoc - -f man -t html -o -; x-htmloutput
# epub -> HTML using pandoc. (Again, don't forget to adjust mime.types.)
# We set http_proxy to keep it from downloading whatever through http/s.
application/epub+zip; http_proxy=localhost:0 pandoc - -f epub \
--embed-resources --standalone; x-htmloutput
# Hex viewer. Usage: alias chadump='cha -Ttext/x-hexdump'
# (Uses GNU-specific flags, adjust as needed on other systems.)
text/x-hexdump; od -w12 -A x -t x1z -v; copiousoutput
# Following entry will be ignored, as text/html is supported natively by Chawan.
text/html; cha -dT text/html -I %{charset}; copiousoutput
```
## See also
[**cha**](cha.md)(1)
chawan-v0.4.0/doc/mancha.1 0000664 0000000 0000000 00000004117 15202323131 0015213 0 ustar 00root root 0000000 0000000 .\" Automatically generated by Pandoc 3.9.0.2
.\"
.TH "MANCHA" "1"
.SH NAME
mancha \- view manual pages via cha(1)
.SH SYNOPSIS
\f[B]mancha\f[R] [\f[B]\-M\f[R] \f[I]path\f[R]] [\f[I]section\f[R]]
\f[I]name\f[R]
.PD 0
.P
.PD
\f[B]mancha\f[R] [\f[B]\-M\f[R] \f[I]path\f[R]] [\f[I]section\f[R]]
\f[B]\-k\f[R] \f[I]keyword\f[R]
.PD 0
.P
.PD
\f[B]mancha\f[R] \f[B]\-l\f[R] \f[I]file\f[R]
.SH DESCRIPTION
\f[B]mancha\f[R] enables viewing man pages using the Chawan browser.
It is analogous to the \f[B]w3mman\f[R](1) utility.
.PP
\f[B]mancha\f[R] executes \f[B]cha\f[R](1) with the appropriate
\f[I]man:\f[R], \f[I]man\-k:\f[R] or \f[I]man\-l:\f[R] URLs.
The protocol adapter then opens the man page and injects markup into it,
e.g.\ man page references are converted into \f[I]man:\f[R] links.
.SH OPTIONS
Command line options are:
.TP
\f[B]\-M\f[R] \f[I]path\f[R]
Set \f[I]path\f[R] as the MANPATH environment variable.
See \f[B]man\f[R](1) for details of how this is interpreted.
.TP
\f[B]\-k\f[R] \f[I]keyword\f[R]
Use \f[I]keyword\f[R] for keyword\-based man page search.
.TP
\f[B]\-l\f[R] \f[I]file\f[R]
Open the specified local \f[I]file\f[R] as a man page.
.SH ENVIRONMENT
Following environment variables are used:
.TP
\f[B]MANCHA_CHA\f[R]
If set, the contents of the variable are used instead of \f[I]cha\f[R].
(Note that the \f[I]cha\f[R] command is called through
\f[B]system\f[R](3), so you do not have to override it so long as
\f[I]cha\f[R] is found in your \f[B]PATH\f[R].)
.TP
\f[B]MANCHA_MAN\f[R]
If set, the contents of the variable are used instead of
\f[I]/usr/bin/man\f[R].
.TP
\f[B]MANCHA_APROPOS\f[R]
If set, the contents of the variable are used instead of
\f[I]/usr/bin/man\f[R].
.RS
.PP
(This is not a typo; normally (except on FreeBSD), \f[B]mancha\f[R]
assumes that \f[B]man\f[R](1) is compatible with \f[B]apropos\f[R](1)
and accepts the \f[I]\-s\f[R] parameter.
Overriding \f[B]MANCHA_MAN\f[R] therefore also overrides the command
used for \f[B]man\-k\f[R], so long as \f[B]MANCHA_APROPOS\f[R] is not
set.)
.RE
.SH SEE ALSO
\f[B]man\f[R](1), \f[B]cha\f[R](1), \f[B]cha\-cgi\f[R](5),
\f[B]w3mman\f[R](1)
chawan-v0.4.0/doc/mancha.md 0000664 0000000 0000000 00000003230 15202323131 0015446 0 ustar 00root root 0000000 0000000
# NAME
mancha - view manual pages via cha(1)
# SYNOPSIS
**mancha** \[**-M** *path*\] \[*section*\] *name*\
**mancha** \[**-M** *path*\] \[*section*\] **-k** *keyword*\
**mancha** **-l** *file*
# DESCRIPTION
**mancha** enables viewing man pages using the Chawan browser. It is
analogous to the **w3mman**(1) utility.
**mancha** executes **cha**(1) with the appropriate *man:*, *man-k:* or
*man-l:* URLs. The protocol adapter then opens the man page and injects
markup into it, e.g. man page references are converted into *man:* links.
# OPTIONS
Command line options are:
**-M** *path*
: Set *path* as the MANPATH environment variable. See **man**(1) for
details of how this is interpreted.
**-k** *keyword*
: Use *keyword* for keyword-based man page search.
**-l** *file*
: Open the specified local *file* as a man page.
# ENVIRONMENT
Following environment variables are used:
**MANCHA_CHA**
: If set, the contents of the variable are used instead of *cha*. (Note
that the *cha* command is called through **system**(3), so you do not have
to override it so long as *cha* is found in your **PATH**.)
**MANCHA_MAN**
: If set, the contents of the variable are used instead of */usr/bin/man*.
**MANCHA_APROPOS**
: If set, the contents of the variable are used instead of */usr/bin/man*.
(This is not a typo; normally (except on FreeBSD), **mancha** assumes
that **man**(1) is compatible with **apropos**(1) and accepts the *-s*
parameter. Overriding **MANCHA_MAN** therefore also overrides the command
used for **man-k**, so long as **MANCHA_APROPOS** is not set.)
# SEE ALSO
**man**(1), **cha**(1), **cha-cgi**(5), **w3mman**(1)
chawan-v0.4.0/doc/mime.types.md 0000664 0000000 0000000 00000003042 15202323131 0016312 0 ustar 00root root 0000000 0000000
# mime.types
Chawan uses the mime.types file to map file extensions to MIME types (also
known as `Content-Type`).
MIME types in turn are used by mailcap to decide how to present a certain
file to the user (display as text, use external viewer, save, etc.)
See [**cha-mailcap**](mailcap.md)(5) for details of how that works.
## Search path
Chawan parses all mime.types files defined in `external.mime-types`. When
no mime.types file is found, the built-in MIME type associations are used.
The default search path for mime.types files is:
```
$HOME/.mime.types:/etc/mime.types:/usr/etc/mime.types:/usr/local/etc/mime.types
```
## Format
The mime.types file is a list of whitespace-separated columns. The first
column represents the mime type, all following columns are file extensions.
Lines starting with a hash character (#) are recognized as comments, and
are ignored.
Example:
```
# comment
application/x-example exmpl ex
```
This mime.types file would register the file extensions "exmpl" and "ex"
to be recognized as the mime type `application/x-example`.
## Note
Chawan only uses mime.types files for finding mailcap entries; buffers use an
internal mime.types file for content type detection instead.
The default mime.types file only includes file formats that buffers can handle,
which is rather limited (at the time of writing, 7 file formats). Therefore it
is highly recommended to configure at least one external mime.types file if you
use mailcap.
## See also
[**cha**](cha.md)(1) [**cha-mailcap**](mailcap.md)(5)
chawan-v0.4.0/doc/protocols.md 0000664 0000000 0000000 00000025120 15202323131 0016245 0 ustar 00root root 0000000 0000000
# Protocols
Chawan supports downloading resources from various protocols: HTTP, FTP,
SFTP, Gopher, Gemini, Spartan, and Finger. Details on these protocols,
and information on how users can add support to their preferred
protocols is outlined in this document.
You can find network adapters in the source distribution's
`adapter/protocol` directory. For protocol-specific file formats (like
gemtext or gopher directories) you will also find an appropriate HTML
converter in `adapter/format` - note that these are ultimately compiled
into a single `tohtml` program that dispatches based on its `argv[0]`.
**Table of contents**
* [OpenSSL-based adapters](#openssl-based-adapters)
- [HTTP](#http)
- [SFTP](#sftp)
- [Gemini](#gemini)
* [FTP](#ftp)
* [Shell-based adapters](#shell-based-adapters)
- [Gopher](#gopher)
- [Finger](#finger)
- [Spartan](#spartan)
* [Local schemes: file:, man:](#local-schemes-file-man)
* [Internal schemes: cgi-bin:, stream:, cache:, data:, about:](#internal-schemes-cgi-bin-stream-cache-data-about)
* [Custom protocols](#custom-protocols)
## OpenSSL-based adapters
The HTTP(S), SFTP, and Gemini modules all depend on OpenSSL. This
is a huge library, and linking it separately with each adapter would
result in enormous code bloat in static builds.
Therefore, these modules are compiled into a single binary. The entry
point can be found at `adapter/protocol/ssl.nim`.
### HTTP
The HTTP(S) adapter supports HTTP/1.1 with arbitrary headers and POST
data, is able to use passed userinfo data (Basic authentication), and
returns all headers and response body it receives without exception.
Deflate decompression with gzip and zlib headers is supported.
(Accept-Encoding: gzip, deflate.) This is based on a modified version
of the public domain tinfl.h decompressor by Rich Geldreich.
Brotli decompression (Accept-Encoding: br) is supported using the
decoder provided by the reference implementation.
The `bonus` directory contains two alternative HTTP clients:
* curlhttp; this is the old HTTP client based on libcurl. It can be
built using curl-impersonate; see [README.md](../bonus/README.md) in
the bonus/ directory for details.
* libfetch-http: based on FreeBSD libfetch. It is mostly a proof of
concept, as FreeBSD libfetch HTTP support is very limited; in
particular, it does not support arbitrary HTTP headers, so e.g.
cookies will not work.
### SFTP
The SFTP adapter wraps libssh2. It works for me, but YMMV.
A slight usability issue is that if an IdentityFile declaration is found
in your ssh config, it will prompt for the identity file password, but
there is no way to tell whether it is really asking for that (or just
regular password auth). Also, settings covered by the Match field are
ignored.
The adapter does not have a way to register new known hosts, so you have
to first connect to new hosts with the regular `sftp` command before
opening them in Chawan.
### Gemini
Currently, the Gemini adapter does not support sites that require
private key authentication. Otherwise, it should work OK.
gmi2html is its companion program to convert the `text/gemini` file
format to HTML.
## FTP
Chawan supports FTP passive mode browsing and downloads.
Directory listings return the `text/x-dirlist` content type, which is
parsed by `dirlist2html` (and also used by the `file:` handler).
This assumes UNIX output style, and will probably break horribly on
receiving anything else.
## Shell-based adapters
Following protocols are simple enough to have adapters implemented as
shell scripts. As such, they are good starting points for understanding
Chawan's protocol adapter system.
To open TCP connections in a portable manner, these scripts use a very
limited `nc` clone installed in `$CHA_LIBEXEC_DIR`.
### Gopher
Support for the Gopher protocol is implemented as a shell script, using
the `nc` tool in the libexec directory (a very limited netcat clone).
Gopher directories are returned with the `text/gopher` type, and
gopher2html takes care of converting this to HTML.
Gopher selector types are converted to MIME types when possible;
however, this is very limited, as most of them (like `s` sound, or `I`
image) cannot be unambiguously converted without some other sniffing
method. Chawan will fall back to extension-based detection in these
cases, and in the worst case may end up with `application/octet-stream`.
### Finger
Finger is supported through the `finger` shell script, using the same
`nc` clone as Gopher. It is probably the simplest protocol of all.
The URL scheme is a simplified imitation of the one accepted by Lynx.
### Spartan
Spartan is a protocol similar to Gemini, but without TLS. It is
supported through the `spartan` shell script, and like Finger, it uses
Chawan's `nc` to make requests.
Spartan has the very strange property of extending gemtext with a
protocol-specific line type. This is implemented as a sed filter for
gemtext outputs in the CGI script (in other words, no modification to
gmi2html was done to support this).
## Local schemes: file:, man:
While these are not necessarily *protocols*, they are implemented
similarly to the protocols listed above (and thus can also be replaced,
if the user wishes; see below).
`file:` loads a file from the local filesystem. In case of directories,
it shows the directory listing using `dirlist2html` like FTP.
`man:`, `man-k:` and `man-l:` are wrappers around the commands `man`,
`man -k` and `man -l`. These look up man pages using `/usr/bin/man`
and turn on-page references into links. A wrapper command `mancha`
also exists; this has an interface similar to `man`. (This used to be
based on w3mman2html.cgi, but it has been rewritten as a standalone Nim
program.)
## Internal schemes: cgi-bin:, stream:, cache:, data:, about:
Five internal protocols exist: `cgi-bin:`, `stream:`, `cache:`,
`data:` and `about:`. These are the basic building blocks for the
implementation of every protocol mentioned above; for this reason, these
can *not* be replaced, and are implemented in the main browser binary.
`cgi-bin:` executes a local CGI script. This scheme is used for the
actual implementation of the non-internal protocols mentioned above.
Local CGI scripts can also be used to implement wrappers of other
programs inside Chawan (e.g. dictionaries).
`stream:` is used for streams returned by external programs. It differs
from `cgi-bin:` in that it does not cooperate with the external process,
and that the loader does not keep track of where the stream originally
comes from. Therefore it is suitable for reading in the output of
mailcap entries, or for turning stdin into a URL.
It is not possible to reload `stream:` URLs. To support rewinding and
"view source", the output of `stream:`'s is stored in a cache file until
the buffer is discarded.
`cache:` is not something an end user would normally see; it's used for
rewinding or re-interpreting streams already downloaded.
Caching works differently than in most other browsers; files are
deterministically loaded from the cache upon certain actions, and from
the network upon others, but neither is used as a fallback to the other.
`data:` decodes a data URL as defined in RFC 2397. This used to be a
CGI module, but has been moved back into the loader process because
these URLs can get so long that they no longer fit into the environment.
`about:` is inside the loader to allow for an implementation of the
download list panel. It should be turned into a CGI module once the
loader gets RPC capabilities.
The following about pages are available: `about:chawan`, `about:blank`,
`about:license`, `about:downloads`.
## Custom protocols
The `cha` binary itself does not know much about the protocols listed
above; instead, it loads these through a combination of [local CGI](cgi.md),
[urimethodmap](urimethodmap.md), and if conversion to HTML or plain text is
necessary, [mailcap](mailcap.md) (using x-htmloutput, x-ansioutput and
copiousoutput).
urimethodmap can also be used to override default handlers for the
protocols listed above. This is similar to how w3m allows you to
override the default directory listing display, but much more powerful;
this way, any library or program that can retrieve and output text
through a certain protocol can be combined with Chawan.
For example, consider the urimethodmap definition of `finger`:
```
finger: cgi-bin:finger
```
This commands Chawan to load the `finger` CGI script, setting the
`$MAPPED_URI_*` variables to the target URL's parts in the process.
Then, finger uses these passed parts to construct an appropriate
curl command that will retrieve the specified `finger:` URL; it prints
the header 'Content-Type: text/plain' to the output, then an empty line,
then the body of the retrieved resource. If an error is encountered,
it prints a `Cha-Control` header with an error code and a specific error
message instead.
### Adding a new protocol
Here we will add a protocol called "cowsay", so that the URL cowsay:text
prints the output of `cowsay text` after a second of waiting.
Note: following assumes you put your `config.toml` in `~/.chawan`.
If you are using XDG base directories (i.e. your `config.toml` is
in `~/.config/chawan`), substitute `~/.chawan/cgi-bin` with
`~/.config/chawan/cgi-bin`.
`mkdir -p ~/.chawan/cgi-bin`, and create a CGI script in
`~/.chawan/cgi-bin/cowsay.cgi`:
```sh
#!/bin/sh
# Signal to the browser that the connection has succeeded. After this,
# Chawan will now "Downloading" instead of "Connecting".
printf 'Cha-Control: Connected\n'
sleep 1 # simulate a delay
# Status is a special header that signals the equivalent HTTP status code.
printf 'Status: 200\n' # HTTP OK
# ControlDone is only useful if you want to send remotely received headers
# (i.e. in an HTTP adapter). With ControlDone sent, subsequent Cha-Control
# headers are not interpreted specially.
printf 'Cha-Control: ControlDone\n'
# As in HTTP, send an empty line before the body.
printf '\n'
# Print the body. We take the path passed to the URL, which urimethodmap
# sets as MAPPED_URI_PATH. This is URI-encoded, so we also run the urldec
# utility on it.
printf '%s\n' "$MAPPED_URI_PATH" | "$CHA_LIBEXEC_DIR"/urldec | cowsay
```
Don't forget to set the executable bit, e.g.
```sh
chmod +x ~/.config/chawan/cgi-bin/cowsay.cgi
```
Finally, create a ".urimethodmap" file in your `$HOME` directory, with the
following content:
```
cowsay: /cgi-bin/cowsay.cgi
```
Now try `cha cowsay:Hello,%20world.`. If you did everything correctly,
it should wait one second, then print a cow saying "Hello, world.".
## See also
[**cha**](cha.md)(1), [**cha-cgi**](cgi.md)(5),
[**cha-urimethodmap**](urimethodmap.md)(5), [**cha-mailcap**](mailcap.md)(5)
chawan-v0.4.0/doc/showcase.png 0000664 0000000 0000000 00000060717 15202323131 0016234 0 ustar 00root root 0000000 0000000 PNG
IHDR { }iCCPicc (}=H@_SE*"VuP.*XP
VhIC(X:8* N.RB L5;bYF:1 Џ1JgS$<=||,sn%o2'ǘnXӛy8JB|N