See e.g. call-with-{input,output}-pipe. Groups of functions; another example is scsh-process.
(define (foo bar)
@("For reals"
(bar (@inherit baz [qux]))))
(define (baz qux)
@("Sort of"
(qux "Yes, wirklich")))
This is usually bin-specific, though; we’d put directives in the
bin-file, then, wouldn’t we: and couldn’t we parse args
while
we’re at it?
Would define a form cock
on analogy with e.g. compile
;
basically, a wrapper around run
. Has options like: output:
; if
given no files, picks up all .scm
in the directory?
Would be nice if it could default to e.g. <egg-name>.wiki
.
An HTML driver is useful, unfortunately, for e.g. github-pages.
At the very least, let’s have a @(source ...)
directive; we could
have @(text ...)
, too, but we’re going to fill it with
wiki-specific crap.
I’m yearning for @(example ...)
.
There’s a lot of boilerplate work to be done there that we could specialize for e.g. wiki and latex.
A better mechanism would be to transform the code into some intermediate S-expression representation; that way, each driver is simply a ruleset.
Instead of using strings (which will be given verbatim), can’t we have some sort of ad-hoc s-expression-based markup? E.g.:
@(This is (em some) (_ markup).
(arg "Argument"))
Meh; we have no good way to differentiate argument lists. Fuck it: let’s go markdown.
(See the defunct multidoc, by the way.)
It’s going to be a pain-in-the-ass to distinguish between intra- and inter-document links, isn’t it? How I wish I could defer to the renderer.
(use debug lowdown posix srfi-69 test)
(test
"All the different items we'd have to deal with."
'(&
@
auto-link
blockquote
bullet-list
class
code
comment
div
emphasis
explicit-link
h2
h3
heading
hr
href
html-element
id
input
item
label
ordered-list
paragraph
ref
reference
reference-link
strong
title
ul
verbatim)
(let ((items (make-hash-table)))
(for-each
(lambda (file)
(call-with-input-file
file
(lambda (input)
(let ((document (markdown->sxml* input)))
(let iter ((document document))
(if (pair? document)
(for-each iter document)
(if (symbol? document)
(hash-table-set! items document #t))))))))
(glob "markdown-tests/*"))
(sort (hash-table-keys items)
(lambda (x y) (string< (symbol->string x)
(symbol->string y))))))
(use debug lowdown posix srfi-69 test)
(for-each
(lambda (file)
(call-with-input-file
file
(lambda (input)
(let ((document (markdown->sxml* input)))
(debug document)
(let iter ((document document))
(if (pair? document)
(for-each iter document)
(if (symbol? document)
'harro)))))))
(glob "markdown-tests/*"))
(reference (label "once") (href "/url") (title #f))
(explicit-link
(href "/url/")
(label "URL" (#\space) "and" (#\space) "title")
(title "title preceded by two spaces"))
(use debug lowdown sxpath sxml-transforms)
(define texify identity)
(define (node-children node)
((sxpath '((*not* @))) node))
(define (node-attributes node)
((sxpath '(@)) node))
(define (node-text node)
((sxpath '(*text*)) node))
(define (call-with-children-attributes tag f)
(f (node-children tag) (node-attributes tag)))
(define markdown->wiki
`(
;; Do we want text or children?
(code . ,(lambda tag `("{{" ,(node-children tag) "}}")))
(emphasis . ,(lambda tag `("''" ,(node-children tag) "''")))
(explicit-link
*preorder* . ,(lambda tag
(let ((href ((sxpath '(href)) tag))
(label ((sxpath '(label)) tag)))
`("[["
,(node-children href)
"|"
,(node-children label)
"]]"))))
(paragraph . ,(lambda tag `(,(node-children tag) "\n\n")))
(strong . ,(lambda tag `("'''" ,(node-children tag) "'''")))
(*TOP* . ,(lambda tag (node-children tag)))
(*PI* . ,(lambda tag '()))
(*text* . ,(lambda (tag text) text))
(*default* . ,(lambda tag (node-text tag)))))
(define markdown->latex
`(
;; Do we want text or children?
(code . ,(lambda tag `("\\texttt{" ,(node-children tag) "}")))
(emphasis . ,(lambda tag `("\\emph{" ,(node-children tag) "}")))
(explicit-link
*preorder* . ,(lambda tag
(let ((href ((sxpath '(href)) tag))
(label ((sxpath '(label)) tag)))
`("\\href{"
,(node-children href)
"}{"
,(node-children label)
"}"))))
(paragraph . ,(lambda tag `(,(node-children tag) "\n\n")))
(strong . ,(lambda tag `("\\textbf{" ,(node-children tag) "}")))
(*TOP* . ,(lambda tag (node-children tag)))
(*PI* . ,(lambda tag '()))
;; Hallelujah: this doesn't touch string-literals above; I'm free
;; to texify all text passing through here.
(*text* . ,(lambda (tag text) (texify text)))
(*default* . ,(lambda tag (node-text tag)))))
(for-each (lambda (markdown)
(SRV:send-reply
(pre-post-order (markdown->sxml* markdown)
markdown->latex
;; markdown->wiki
)))
'("[Intradocument link](#intra)"
"[Interdocument link](/inter)"
"[Blank link]"
"*harro*"
"_harro_"
"**harro**"
"__harro__"
"We're writing a paragraph of text here, aren't we?
I believe so."
"This `@`-read-syntax is for reals."))
In LaTeX, let’s look for a prepended-hash: if it’s there, it’s a ref to a label; if not, it’s a hyperlink.
See start-server.
Everything should be able to take examples, even modules; examples should be as fundamental as source-code.
Maybe this can be an extension.
If this, for instance, is our long-hand:
(define (procedure a)
@(description: "Do something."
parameters: ((a "Thing to do"))
to: "Thing done")
(void))
we can come up with any number of short-hands that reduce to it.
Let’s use @internal
. Or: instead of @<identifier>
, we should
reuse the keyword mechanism? Principle of least surprise? Would look
like: internal:
. All the asperands are alien, I think.
On the other hand, how would you document keywords? No, we have to resort to something noisy.
(define (procedure a)
@("Procedure does something."
(a "Parameter")
;; If we do this, we can't document keywords named `to:'.
(to: "Another thing")
;; That's why we settled on this:
(@to "Another thing")
@internal)
'b)
Or, fuck it: just use naked symbols:
(define (procedure a)
@("Procedure does something."
(a "Parameter")
;; Don't see how we can get around this one.
(@to "Another thing")
internal)
'b)
(define (procedure a)
@("Procedure does something."
(parameters
(a "Parameter"))
;; Don't see how we can get around this one.
(to "Another thing")
internal)
'b)
(define (procedure a)
@("Procedure does something."
(a "Parameter")
;; Don't see how we can get around this one.
to: "Another thing"
internal:)
'b)
;;; If we're going keyword-heavy:
(define (procedure a)
;; `description:' already fucks up the indentation.
@(description: "Procedure does something."
parameters:))
(define (procedure a)
@("Procedure does something."
parameters: '((a "Parameter"))
to: "Another thing"
internal: #t))
Authors, &c.
Using footnotes and using \texttt{\char`\ and}.
(define-syntax thunk
(lambda (expression rename compare)
(let ((body (cdr expression))
(%lambda (rename 'lambda)))
`(,%lambda () ,@body))))
(with-output-to-string (thunk (display 2)))
(use cock-parse debug stack)
(let ((docexprs (parse-files "test-parse.scm")))
(wiki-write-docexprs docexprs))
@to
to one word (the type?), something more descriptive
in the procedure description.
This happens when we simply rename functions. Have to catch this
case.
It’s a little more complicated: have to be able to specify optional
parameters, &c.
E.g.:
(arg "Some argument" default: 'china)
Useful for e.g. parameters and case lambda. (We already do this for parameters, thank the gods.)
The modules themselves have docs? Shit. That’s a lot of source-code.You know what, though? We can’t do this, I believe as long as we rely on the reader: the reader will have finished parsing the thing before we can backtrack and read the contained expressions.
We’d have to parse the file ourselves, looking for e.g. doc
-forms;
unless, of course, we did a dirty hack and read the embedded
expressions in through a string port.
At that point, though, why aren’t we just parsing the god-damn thing?
Interesting things to do with modules: list of exports; oh, shit: should the exports link to the docs? We have a table of contents; but, yeah: maybe. We’d have to check which objects we have documentation for.
Could we do a table and pluck a description from the docs?
Can’t do the string-port hack, by the way; since, by the time we see the expressions, the docs have been stripped. We do have parsed docexprs inside of the module; good luck, however, determining which expressions they’re associated with.
Yeah: to descend into modules, we’re going to have to parse the
source. @
has some preëxisting reader that maps it to #f
, but we
can disable that.
(use debug miscmacros ports test)
(test
'((test) @)
(with-input-from-string
"@(test)"
(lambda ()
(do ((expression (read) (read))
(expressions '() (cons expression expressions)))
((eof-object? expression) expressions)))))
Turns out we don’t need to disable it. Real modules have to wait for
a bona fide parser. How difficult would that be, btw? Scan for
@
, keeping track of parents; don’t descend into
lists-following-=@=; ignore symbols. @
tokenizes itself.
(use debug
define-record-and-printer
stack)
(define-record-and-printer docexpr doc expr)
(with-input-from-file "cock-parse.scm"
(lambda ()
(let read-next ((expression (read))
(parents '())
(docexprs '())
(docexpr? #f))
(debug (when (and (pair? expression)
(not (eof-object? expression)))
(car expression))
(if (pair? parents) (car parents))
docexprs
docexpr?)
(if (eof-object? expression)
docexprs
(if docexpr?
(if (pair? expression)
(read-next (cdr expression)
parents
(cons (make-docexpr (car parents)
expression))
#f)
(read-next (read)
parents
docexprs
#f))
(if (eq? expression '@)
(read-next (read)
parents
docexprs
#t)
(if (pair? expression)
(read-next (cdr expression)
(cons expression parents)
docexprs
#f)
(read-next (read)
parents
docexprs
#f))))))))
Use embedded expressions instead of string-templates.
- CLOSING NOTE [2012-08-17 Fri 14:08]
Messy
Holy shit: is it the case that we don’t have to escape backslashes?
(use debug)
(define (test-template test)
#<#EOF
#{test}
EOF
)
(debug (test-template "harro"))
Hmm: kind of ugly, though; that’s ok, isn’t it?
(use alist-lib args cock-parse debug usage)
(define options
(list (args:make-option (l latex) #:none "Output to LaTeX" (set! arg #t))
(args:make-option (h ? help) #:none "Help" (set! arg #t))))
(define usage
(make-usage
(lambda (program)
(format #t "Usage: ~a [OPTIONS]... FILE...~%" program)
(print (args:usage options)))))
(receive (options files)
(args:parse (command-line-arguments) options)
(cond ((alist-ref/default options 'help #f) (usage))
((null? files) (usage 1))
(else (tex-write-docexprs (apply parse-files files)))))
pp
.
Initially, let’s parse individual files; but let’s quickly follow up
with something for eggs that reads name, email, &c. from there:
possibly converts includes
into sections.
What should the actual name of the includes section be, though; fuck
it: maybe do the include and look for @(heading ...)
; yes.
Maybe all we have to do is parse the metadata and cat the .scm files
into cock; how do we control the order of the files, though, if not
for include
? But then we have to scour everything for include
.
If only we could depend upon Chicken to do the stitching.
It looks like read optionally takes parameters; it appears as though a@to
is necessary. Initial parameter should be something
describing the read-form; e.g. #~string
, #~(item ...)
.
(include "cock-parse")
(import cock-parse)
(use debug defstruct)
@(title "Test parse")
@(heading "Harro thar!")
@(text "We'd like to write a novel here, prease; none of this
Twitter-like hekato-sarantism.")
(module just-a-little-module
@("Little modules do work sometimes.")
(x y procedure tex-procedure-to))
(+ 2 2)
(define x
@("x is often the neighbor of y.")
2)
(define y
@("y is often the neighbor of x")
(make-parameter 3))
(define (procedure a b)
@("Do something."
(a "Thing to do")
(b "Some adjunct thing")
(@to "Thing done"))
(void))
(define (tex-procedure-to special-parameters)
@("Was, are we wirklich?"
(special-parameters "Very special")
(@to "There procedure thither"))
(alist-ref/default special-parameters '@to '("unspecified")))
(define-syntax harro
@("Tharths; tharths very thither."
(x "An opacity")
(... "Other opacities")
(@to "Clairvoyance"))
(lambda (e r c) 2))
(set-sharp-read-syntax!
@("Registers a shared library."
(library "The library to register"))
#\&
void)
(set-read-syntax!
@("Registers a shared library."
(library "The library to register"))
#\&
void)
(set-parameterized-read-syntax!
@("Registers a shared library."
(library "The library to register"))
#\&
void)
(defstruct a
@("This is for reals."
(b "Yes")
(c "No")
(d "Maybe"))
b c d)
(define-record a
@("This is for reals."
(b "Yes")
(c "No")
(d "Maybe"))
b c d)
(define-record-type a
@("This is for reals."
(b "Yes")
(c "No")
(d "Maybe"))
(make-a b c d)
a?
(b a-b set-a-b!)
(c a-c set-a-c!)
(d a-d set-a-d!))
(tex-write-docexprs (parse-file "test-parse.scm"))
all: test-parse.scm test-parse.mk
CHICKEN_SCHEME_OPTIONS='-X cock' ./test-parse.scm > test-parse.tex && \
xelatex -shell-escape test-parse && \
xelatex -shell-escape test-parse && \
xelatex -shell-escape test-parse && \
evince test-parse.pdf
test-parse.scm:
org-tangle TODO.org
test-parse.mk:
org-tangle TODO.org
(use cock)
@(test "This should be a noöp.")
CHICKEN_SCHEME_OPTIONS="-X cock" ./test-compiled.scm
- CLOSING NOTE [2012-10-04 Thu 09:37]
See internal-functions.
Yeah, let’s do markdown with multi-line docs.
Can we do it directly over svn; or do we need to use the web-interface to the wiki, somehow?- CLOSING NOTE [2012-10-04 Thu 09:40]
See setup-helper.
Should degrade gracefully if e.g. cock
is not installed.
- CLOSING NOTE [2012-08-17 Fri 14:07]
See Markup.
- CLOSING NOTE [2012-10-04 Thu 09:41]
See setup-helper.
See here:
- read
- parameter
- record
- string
- class
- method
- constant
- setter
- syntax
- type
Records are a really good idea; have to know: defstruct
,
define-record
, define-record-type
, &c.