odd#
Keep an opam switch's HTML documentation continuously up to date.
odd wires opam's post-install-commands, pre-remove-commands,
post-remove-commands and post-session-commands hooks so that after every
successful opam install / opam upgrade / opam remove, the docs for
exactly the packages that changed are regenerated, in dependency order, by
odd-driver. The per-package hooks are plain coreutils (a touch to mark a
package stale, find -delete/rm -rf to drop a removed one's docs), so they
keep working even when odd itself isn't installed in the switch; only the
once-per-session worker needs the binary.
Documentation artifacts are installed under $OPAM_SWITCH_PREFIX/lib/: a
module's .odoc/.odocl files sit next to the .cmt/.cmti they were
compiled from, in the library's own directory, and a package's documentation
pages live under lib/<package>/, mirroring their ids — for most packages,
the same directory. HTML output and indexes are written to
$OPAM_SWITCH_PREFIX/odoc/<package>/, with a landing page at
$OPAM_SWITCH_PREFIX/odoc/index.html. (This is odd's own tree, kept separate
from opam's $OPAM_SWITCH_PREFIX/doc, where packages install their own
documentation.)
See doc/DESIGN.md for the full design, and
doc/DESIGN_DOC.md / doc/DESIGN_COMPLETE.md
for the doc and complete commands.
Setup#
$ odd setup # show the opam configuration to be added
$ odd setup --apply # add it to ~/.opam/config via `opam option`
$ odd rebuild --all # Initial (slow!) build of all the docs
The odoc driver (odd-driver) is bundled with odd (vendored under
driver/, built and installed alongside the odd binary), so there's nothing
else to install. It drives the odoc, odoc-md and sherlodoc binaries,
which must be present in the switch.
Commands#
odd sync— session worker (the post-session hook); rebuilds every package marked stale, in dependency order, and regenerates the landing page. Always exits 0; details go to$OPAM_SWITCH_PREFIX/var/cache/odd/log.odd rebuild [--all | PKG...]— mark packages stale and sync. Exits non-zero on failure (user-facing, unlike the hook commands).odd order [PKG...]— print the dependency order that sync would use (debugging aid).odd search [--package PKG]... [-n N] QUERY— search the generated documentation. Queries every package'ssherlodoc_db.marshaltogether (a single query covers the whole switch), printing each match with its owning library and package.--packagerestricts to named packages.odd doc REFERENCE— print an item's documentation as Markdown, under a header naming the item and the library/package it comes from, resolving an odoc reference against the whole switch.Stdlibis open, so bare names work (List,print_endline); references may also be qualified (Astring.String) or package-qualified (/stdlib/Stdlib.List.map). When a reference is ambiguous (e.g. a bareindex, a page in every package), it lists the package-qualified alternatives instead of picking one.odd complete PARTIAL— list the referencesPARTIALcould be completed to, one per line: members of what it names so far (List.m→List.map, …; kind tags filter, e.g.module-List.type-→module-List.type-t), package/library names for a leading/(/o→/odoc,/odoc.model, …), or the units under a/pkg/path. The engine for shell completion.
Shell completion (zsh)#
A zsh completion is shipped in completions/zsh/_odd. It completes the
subcommands and, for doc and complete, the reference argument — by calling
odd complete, so completion always matches the command's own resolver
(Stdlib open, package-qualified /pkg/... paths, kind tags like type-,
section labels, …). Type . or / and press TAB again to drill in.
opam install puts it under the package's share dir. That directory isn't on
zsh's $fpath by default, so add it (before compinit) in ~/.zshrc:
fpath=("$(opam var odd:share)/zsh" $fpath)
autoload -U compinit && compinit
(Or point $fpath at completions/zsh in a source checkout.)
Development#
$ opam install . --deps-only --with-test
$ dune build
$ dune runtest