diff --git a/README.md b/README.md index 21cab465..f05df10d 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,19 @@ telling other programmers how the program works (instead of just telling the compiler what it does). Telling this story can be done using non-linear, hyperlinked documents. -For now these utilities only help with manipulating LP chunks (e.g. repating +For now these utilities only help with manipulating LP chunks (e.g. repeating the same chunk in several places in the output document, but keep a single copy in the source code). Ultimately, the reading experience should be closer to viewing an interactive -presentation, focussing on the parts of the program that are of interest to +presentation, focusing on the parts of the program that are of interest to you: expand on-screen the chunks you are curious about, run some tests and see their result, etc. * Imagine something like [code bubbles](http://www.andrewbragdon.com/codebubbles_site.asp), but with - explanative text comming along with the source code. + explanatory text coming along with the source code. -* Imagine something like [Inform](http://inform7.com/), but focussed on +* Imagine something like [Inform](http://inform7.com/), but focused on exploring a program instead of exploring an imaginary world — after all, a program is some kind of imaginary world. \ No newline at end of file diff --git a/scribblings/hyper-literate.scrbl b/scribblings/hyper-literate.scrbl index c8aab4b8..6bb666d9 100644 --- a/scribblings/hyper-literate.scrbl +++ b/scribblings/hyper-literate.scrbl @@ -5,6 +5,140 @@ @title{hyper-literate} @author{Georges Dupéron} -@defmodule[hyper-literate] +@defmodulelang[hyper-literate] -Package Description Here +The @racketmodname[hyper-literate] metalanguage extends the +features of @racketmodname[scribble/lp2], with the goal of +providing a more modern view on literate programming. It can +be parameterized with the language used in the chunks (so +that it is possible to directly write +@racketmodname[typed/racket] programs with +@racketmodname[hyper-literate], for example). + +On the first line, which begins with @tt{#lang + hyper-literate}, the language recognises the following +options: + +@(require scribble/core + (only-in scribble/private/manual-vars boxed-style) + scribble/private/manual-utils) +@(make-table + boxed-style + (list + (list + @paragraph[(style #f '())]{ + @tt{@litchar{#lang} @racketmodname[hyper-literate] @racket[_lang] + @racket[maybe-no-req] @racket[maybe-no-auto]}}) + flow-empty-line + (list + @racketgrammar*[ + [maybe-no-req #:no-require-lang] + [maybe-no-auto #:no-auto-require]]))) + +where @racket[_lang] is a module name which can be used as +a @litchar{#lang}, for example @racketmodname[typed/racket] +or @racketmodname[racket/base]. + +@section{What is hyper-literate programming?} + +Hyper-literate programming is to literate programming +exactly what hypertext documents are to regular books and +texts. Literate programming is about telling other +programmers how the program works (instead of just telling +the compiler what it does). Telling this story can be done +using non-linear, hyperlinked documents. + +For now these utilities only help with manipulating literate +programming chunks (e.g. repeating the same chunk in several +places in the output document, but keep a single copy in the +source code). + +Ultimately, the reading experience should be closer to +viewing an interactive presentation, focusing on the parts +of the program that are of interest to you: expand on-screen +the chunks you are curious about, run some tests and see +their result, etc. + +@itemlist[ + @item{Imagine something like + @hyperlink["http://www.andrewbragdon.com/codebubbles_site.asp"]{ + code bubbles}, but with explanatory text coming along + with the source code.} + @item{Imagine something like + @hyperlink["http://inform7.com/"]{Inform}, but focused on + exploring a program instead of exploring an imaginary + world — after all, a program is some kind of imaginary + world.}] + +@section{Chunks of code} + +@(module scribble-doc-links racket/base + (require scribble/manual + (for-label scribble/lp2)) + (provide (all-defined-out)) + (define scribble-chunk @racket[chunk]) + (define scribble-CHUNK @racket[CHUNK])) +@(require 'scribble-doc-links) + +@defform[(chunk content ...)]{ + Same as @scribble-chunk from @racketmodname[scribble/lp2], + with a few tweaks and bug fixes.} + +@defform[(CHUNK content ...)]{ + Same as @scribble-CHUNK from @racketmodname[scribble/lp2], + with a few tweaks and bug fixes.} + +@section{Memorizing and repeating chunks} + +@defform[(defck content ...)]{ + Like @racket[chunk] from @racketmodname[scribble/lp2], but + remembers the chunk so that it can be re-displayed later + using @racket[repeat-chunk].} + +@defform[(repeat-chunk )]{ + Shows again a @racket[chunk] of code previously remembered + with @racket[defck]. If the @racket[] starts and + ends with angle brackets, they are replaced by parentheses + to hint that this is not the first occurrence of this + chunk, so that the name becomes @racket[|(name)|]} + +@section{Order of expansion of the program} + +The file is expanded a first time, in order to identify and +aggregate the chunks of code (declared with @racket[chunk]). +Then, the top-level module of the file is constructed using +these chunks, and a @racket[doc] submodule is added, which +contains all the surrounding text. The chunks are typeset +where they appear using @racket[racketblock]. + +The @racket[doc] submodule is declared using +@racket[module*], so that it can use +@racket[(require (submod ".."))] to use functions declared +in the the chunks. For example, it should be possible to +dynamically compute the result of a function, and insert it +into the document, so that the value displayed always +matches the implementation. + +When the file is expanded for the first time, however, the +@racket[(submod "..")] does not exist yet, and cannot be +required. This is the case because the first expansion is +performed precisely to extract the chunks and inject them in +that module. + +To solve this problem, the following macros behave +differently depending on whether the code is being expanded +for the first time or not (in which case the +@racket[(submod "..")] module can be used). + +@defform[(if-preexpanding a b)]{ + Expands to @racket[a] if the code is being pre-expanded, + and expands to @racket[b] if the @racket[(submod "..")] + module can be used.} + +@defform[(when-preexpanding . body)]{ + Expands to @racket[(begin . body)] if the code is being + pre-expanded, and expands to @racket[(begin)] otherwise.} + +@defform[(unless-preexpanding . body)]{ + Expands to @racket[(begin . body)] if the @racket[(submod "..")] + module can be used, and expands to @racket[(begin)] otherwise.}