Light-weight Markdown-based literate programming
Thus, programs must be written for people to read, and only incidentally for machines to execute.
-- Hal Abelson, SICP
Writ is an attempt to enable a light-weight literate programming workflow.
You write Markdown files with your code in normal Markdown code blocks (indented or fenced) and then run the writ command to compile to source files your language's compiler or interpreter will understand.
Writ expects a one-to-one mapping between Markdown source files and
source files in the target language, and uses a simple extension-based
convention for generating the target files: a Markdown file named
foo.js.markdown will generate a
Writ is available on npm.
npm install -g writ
To use it, just run
writ from the command line, specifying which
Markdown files you want to compile. By default, it compiles the output in
the same directory, you can pass the
--dir flag to specify a different
writ "src/*.md" --dir build
In the simplest case, if your code is completely straight-line, top-to-bottom, you don't need to know any syntax: writ will generate the target file by concatenating all the code blocks in the order they appear. This is exactly how literate CoffeeScript works.
For slightly more involved cases, writ supports 3 bits of syntax:
//!! .*[ !!//]for ignoring a code block
//== name[ ==//]for naming a code block
//:: name[ :://]for including a code block
// bits are configurable and are defaulted to the single-line comment
token for your language.
The 'closing tags' (
:://) are optional, but must match
the opening tag if present.
To keep a code block from being included in the generated output, start the code block with a line starting with:
//!! This is an ignored code block
A named code block is any code block in the document that starts with a line of the form:
//== name[ ==//]
You can later (or earlier) include that code in another block by dereferencing
So the following Markdown:
# Main code chunk ```js //:: requires ::// ``` ```js //== requires ==// var marked = require('marked'); var fs = require('fs'); ```
Would compile to:
var marked = require'marked';var fs = require'fs';
A name for sections can have internal whitespace, but it obviously should match up exactly when dereferencing names.
A few things to note about named sections:
Named sections that are never referenced by a 'top-level' code block won't show up in the compiled output.
If a name is referenced that doesn't exist, that comment line will remain as-is in the compiled output.
Named sections can refer to other named sections, and writ will whine if it has to recurse more than 50 times when compiling.
If you have multiple named sections with the same name, they'll get concatenated together in the order they appear in the source.
writ.js.mdfor the source.
If you build something using writ, send a pull request adding a link to your library.