use(“atomy”)
require(“stringio”)
hl = require(“hl”) token = require(“hl/token”) ruby = hl load(“ruby”)
use(“anatomy/html”) base = require(“anatomy/base”) data = require(“anatomy/data”)
def = require(“define”)
fn(format-inline(tokens, link-only = nil)):
tokens collect [t]: data Element new( -- constants, identifiers, and operators if((link-only && link-only include?(t contents)) || (!link-only && ["no", "nf", "n", "o"] include?(t type tag))) then: data ResolveElement new( [part]: tag = part find-tag(t contents) if(tag) then: data Reference new(tag, t contents) else: t contents) else: t contents .class(t type tag))
fn(format-block(tokens, link-only = nil)):
data Block new( base verbatim(format-inline(tokens, link-only)) .class("highlight"))
fn(with-all-output-to(out, err) &action):
before-out = $stdout before-err = $stderr { $stdout = out $stderr = err action call } ensuring: $stdout = before-out $stderr = before-err
fn(interactive-line(bnd, input, line, context)):
out = StringIO new err = StringIO new output-tokens = with-restarts(use-tokens(ts): ts) { res = with-all-output-to(out, err): bnd eval(input) -- shorten the long-form inspections that show the ivars ruby lex(res inspect sub(r"#<([^\s]+)\s+@.*$", "#<\\1>")) } bind: (e & Error): restart( .use-tokens [ token Token new( token Tagged new(.gr) i"#{e name}: #{e message}") ]) [ format-inline( token Token new(token Tagged new(.caret), "> ") . ruby lex(input)) "\n" out string unless(err string empty?): data Element new(err string, .class("gr")) format-inline(output-tokens) "\n" ]
environments = #{} fn(new-interaction-env): binding fn(take-environment(name)):
if(name) then: environments[name] ||= new-interaction-env else: new-interaction-env
def(hl(x)): base code(format-inline(ruby new(x) run))
def(ruby(x)): format-block(ruby new(x) run)
def(evaluate(code, where = nil)):
with-restarts(err(msg): data Element new(msg, .class("gr"))) { take-environment(where) eval(code) nil } bind: (e & Error): /restart(.err, i"#{e name}: #{e message}")
def(interaction(x, where = nil)):
bnd = take-environment(where) data Block new( data Block new( x split("\n") collect with-index [input, line]: interactive-line(bnd, input, line + 1, where) .tt) .class("interaction"))
def(example(x, where = nil)):
data Block new( [ data Paragraph new([data Element new("Example:", .italic)]) interaction(x, where) ] .class("example"))
def(example-segment(x)):
data Block new( [ data Paragraph new([data Element new("Example:", .italic)]) format-block(ruby new(x) run) ] .class("example"))
def(define(what, *rules, returns, body)):
thumb = what to-ast message-name = thumb name to-s display = format-inline(ruby lex(what), [message-name]) data Block new( [ base target-element(message-name) data Block new( [ data Block new( [ display data Element new( " => " .class("definition_result_arrow")) format-inline(ruby lex(returns)) rules collect [rule]: ["\n | ", format-inline(ruby lex(rule))] ] .tt) ] .class("thumb")) body ] .class("definition"))
def(assign(name, to, body)):
display = format-inline(ruby lex(name), [name]) data Block new( [ base target-element(name) data Block new( [ data Block new( [ display data Element new( " = " .class("definition_result_arrow")) format-inline(ruby lex(to)) ] .tt) ] .class("thumb")) body ] .class("definition", "assign"))