GWEB is a literate programming
system for the Go programming language, modeled closely on Donald Knuth and Silvio Levy's
CWEB. You write a single .w source file that interleaves TeX
documentation with Go code, and two tools turn it into either a program or a
typeset document — exactly as CWEB does for C, with C replaced by Go:
| CWEB | GWEB | purpose |
|---|---|---|
ctangle |
gtangle |
extract compilable source (.go) for the machine |
cweave |
gweave |
produce a typeset document (.tex → PDF) for people |
gtanglestrips the documentation, reassembles the named code sections in the order the Go compiler needs, and writesgofmt-formatted.gofiles.gweaveproduces a TeX file in which reserved words are bold, identifiers are italic, strings are typewriter, named sections are linked by number, and a cross-referenced index and list of refinements are generated automatically. Declaredtypenames are set bold andconstnames typewriter; mark other names typewriter too (e.g. another package's@d http.StatusOK), and override any of it with@f/@s.
GWEB assumes you already know Go and are comfortable with TeX — in
particular plain TeX, since gwebmac.tex and this repository's macros are
plain TeX, not LaTeX. Beyond that:
- A TeX distribution (e.g. TeX Live or MacTeX)
must be installed, providing the
tex,pdftex, andluatexengines the woven output is typeset with. - For Korean output (
\input kotexgweb; see Usage), the Noto Serif/Sans CJK KR fonts must be installed locally —kotexgweb.texselects them by name.
make build # builds bin/gtangle and bin/gweave
make test # runs the test suiteAs in CWEB, only the Go needed to build gtangle is committed; gweave and the
weave engine are tangled from their .w sources on the fly. make build does
this for you: it builds gtangle from the committed sources, runs it to generate
the rest, then builds gweave. (make generate performs just the tangling step.)
So build through make, not a bare go build ./..., on a fresh checkout.
Producing a PDF additionally requires a TeX engine (e.g. pdftex, from TeX
Live or MacTeX).
gtangle installs the Go way (its sources are committed):
go install github.com/sjnam/gweb/cmd/gtangle@latestgweave is generated rather than committed, so install both from a checkout
with make install (or make install-tools to put just the binaries in your
GOBIN). Point TEXINPUTS at a copy of gwebmac.tex so
the TeX engine can find it.
For a full install — the commands plus gwebmac.tex (placed in your TeX tree
so pdftex foo.tex just works) plus the man page — use the install script:
./install.sh # into ~ (TEXMFHOME) and /usr/local (may need sudo)
./install.sh --prefix="$HOME/.local" # a writable prefix, no sudo
sudo ./install.sh # system-wide
./install.sh --uninstall # remove everything it installedmake install / make uninstall call the script (pass options with
ARGS=...); run ./install.sh --help for all options (--bindir, --mandir,
--texmf). Then man gtangle / man gweave describe the commands.
gtangle foo.w # -> foo.go (plus any @(file@>= outputs)
gweave foo.w # -> foo.tex
pdftex foo.tex # -> foo.pdf (gwebmac.tex must be on TEXINPUTS)The .w extension may be omitted, as in CWEB — gtangle foo reads foo.w (and
a bare change-file name gets .ch). Each command prints a brief cweb-style
progress line, one *N per starred (chapter) section.
For a hyperlinked PDF you can also go through DVI, exactly as CWEB does — request
the \special{pdf:…} back end with \let\pdf+, then convert with dvipdfmx:
tex "\let\pdf+ \input foo.tex" # -> foo.dvi (with pdf: specials)
dvipdfmx foo.dvi # -> foo.pdf (links + bookmarks)Both commands accept -o <dir> to choose an output directory, and an optional
change file as a second argument — gtangle foo.w foo.ch — which patches the
master source without editing it (CWEB's .ch mechanism; see
format.md). For example,
gtangle examples/wc.w examples/wc.ch builds a CSV variant of the word counter. gwebmac.tex
lives at the repository root; point TEXINPUTS there, or copy the file
next to your document.
The tangled Go always carries //line directives, so the Go compiler, go vet,
and panic traces report errors at .w positions instead of .go ones — the
Go counterpart of CWEB's #line, which ctangle likewise emits unconditionally:
gtangle foo.w && go build . # an error reads foo.w:42: ...GWEB tangles its own sources the same way, so editing a .w reshuffles the line
numbers in the bootstrap Go it commits — the price of keeping the generated code
honest about its literate origin.
For a tour of the bundled examples, the full .w file-format reference, and
non-English (e.g. Korean) documentation, see the manual — gwebman.tex
(make manual).
Each .w source sits next to the Go it generates. Only the Go that bootstraps
gtangle is committed (◇ below); the rest (✦) is tangled by make.
gweb.w the master web: @i-includes the three below (woven, not tangled)
cmd/
├── gtangle/ gtangle.w -> gtangle: front end + the tangle engine ◇
└── gweave/ gweave.w -> gweave: front end + the weave engine (lexer, ✦
pretty-printer, cross-references)
common/ common.w -> the shared parser (CWEB's common.w) ◇
gwebmac.tex TeX macros for woven output (CWEB's cwebmac.tex)
kotexgweb.tex Korean (luatexko) localization + fonts + LuaTeX PDF back end
gweb.1 the man page for both commands (CWEB's cweb.1)
format.md the .w file-format reference
gwebman.tex the GWEB manual
examples/ worked examples
editors/
└── vscode/ VS Code language support for .w files
install.sh installer for the commands, gwebmac.tex, and the man page
For editor support and how GWEB's self-hosting (make tangle, make bootstrap, make selfdoc) works, see the manual as well.
- Lexing for free. Tangle relies on
gofmt(go/format) to canonicalize the assembled program, so the emitted Go is always tidily formatted as long as the web assembles into valid Go. - Pretty-printing.
gweavehighlights tokens (bold keywords, italic identifiers, typewriter strings, real math symbols for≤ ≥ ≠ ←, …) and mirrors the source's own spacing rather than re-deriving layout from a full Go grammar the way CWEB does for C. Because gofmt-formatted Go already encodes the grammar in its spacing, mirroring it reproduces gofmt exactly — including the tricky cases (*Tvsa * b,[]Tvsa[i], precedence spacing likea*b + c) — without any parsing. Long code lines wrap at the inter-token spaces, with continuation lines indented one step deeper. Write the code in your sections in gofmt style for the best-looking output. - Definition detection in the index is heuristic (an identifier following
func/var/const/type, or just left of:=), not a full type check. - Diagnostics. Both tools report, with
file:linelocations, unterminated control codes, references to undefined sections, ambiguous...abbreviations, and named sections defined but never used. These are warnings;gtanglestill stops if it must actually expand an undefined reference. An origin map kept in step through@iincludes and change-file edits makes every location point back to the file (and line) you actually wrote. - Page layout follows cweave.
gwebmac.texgives the woven document the same furniture CWEB produces: run-in bold section headings (with a page break before each major starred section),§sec JOBNAME … GROUPTITLE pagerunning heads, a title-less index that sits under your own@* Index.section, a Names of the Sections list, and a contents page (centered title,Section/Pagecolumns, dotted leaders). The index is set in two columns. As in CWEB, the contents page is produced at the end in a single TeX pass; move it to the front when binding if you prefer. The font set mirrorscwebmac.tex(medium-caps\mc, thecmtex10string font, …), and a fewcwebmacprose helpers are available in commentary:\CEE/,\GO/,\UNIX/,\TEX/, and\\{id}for an italic identifier (though the GWEB idiom for inline code is|id|). - Hyperlinks and bookmarks. Every section number shown as a reference, in the
index, in a cross-reference note, or on the contents page is a blue link to that
section; clicking it jumps there (for the underlined index entries, to where the
identifier is defined). The starred sections also become a PDF outline (bookmark
tree), nested by their
@*,@*1,@*2depths. Two back ends produce these:pdftex/luatexin PDF mode use the engine's own primitives, while the DVI route emits\special{pdf:…}commands fordvipdfmxwhen you ask for them with\let\pdf+(the same convention as CWEB). With a plain DVI engine and no\let\pdf+, the links and bookmarks are simply omitted.
GWEB is released under the MIT License.