Literate programming wiki (sh)

From LiteratePrograms

Jump to: navigation, search

Somewhat like an armillary sphere, this model attempts to capture the essence of the LiteratePrograms wiki, but on a much smaller scale.

Contents

theory

A few minor modifications suffice to mash up Literate Programming (Python) and Wiki (sh).

practice

The plan of attack is almost the same as the basic wiki, with 4 small additions.

<<serve WikiPage>>=
Wiki (sh)#9057#parse request
handle code downloads
Wiki (sh)#9057#synchronize with filesystem
reply to user

1. To handle the code downloads, we switch to an external program, wiklit.py which takes care of fulfilling the request to expand the requested node ($3) from the WikiPage.

<<handle code downloads>>=
if [ $request = code ]; then
    reply 'Content-Type: text/plain'
    exec python wiklit.py $3 < $wikipage
fi

2. When replying to the user, we make a single addition in the template for the read|write case:

$(findlinks < "$wikipage" | codelinks)

3. We add a few patterns to (very lightly) mark up codeblocks.

<<codeblock awk patterns>>=
    codeblock && $0 !~ /^>/ { print codeblock; codeblock = "" }
    $0 ~ /^@/    { print "<""pre>"$0; codeblock = "<""/pre>"; next }

4. and finish by defining the functions for generating the download links.

It might be nice to perform a Category:Topological sort to determine download targets, but here we take the simpler approach of looking for nodes that look like they might be source file names (lower case alphabetic with an extension).

<<download markup functions>>=
findlinks() { sed -n 's/^@\([a-z]*\.[a-z]*\)/\1/p'; }
codelinks() { sed -e "s|.*|(<a href=$me?code+$wikipage+&>download &</a>)|"; }

The remainder goes through unchanged:

<<define markup functions>>=
wikify() {
    PAGE="$allpages" awk '
    <<codeblock awk patterns>>
    <<Wiki (sh)#9057#awk patterns>>'
}
markup() { escapehtml | tr -d "\r" | wikify; }
download markup functions

wrapping up

Finally, we configure ourselves to be distinct from the original Wiki (sh) sample,

<<wiklit.sh>>=
#!/bin/sh
me="wiklit.sh"
homepage="WiklitWelcome"
Wiki (sh)#9057#define CGI functions
define markup functions
serve WikiPage

weave in the code weaver from Literate Programming (Python),

<<wiklit.py>>=
Literate Programming (Python)#8866#blit.py

and provide the intial Wiki content:

<<WiklitWelcome>>=
Welcome to a tiny working model of the LiteratePrograms wiki,
complete with a single SampleArticle.
----
see also
* http://en.wikipedia.org/wiki/Armillary_sphere for an ancient example of (very!) reduced scale modelling
* http://en.literateprograms.org/ for the full scale original
<<SampleArticle>>=
First, we try an old-timer program:
@knr.c
>main(@formal names@)
>@formal declarations@
>{
>	printf(@greetings@);
>}
>
Not that we use them in this program (it is,
after all, a constant function, cf. the 'K'
combinator) but for nostalgia value, we have
@formal names
>argc, argv
@formal declarations
>int argc;
>char *argv[];
and, of course, we should specify the value
which the function takes at all arguments:
@greetings
>"Hello, world\n"
----
Now, let's rewrite this in a more modern style:
@ansi.c
>@external declarations@
>
>int main(@inline formal declarations@)
>{
>	printf(@greetings@);
>	@more boilerplate...@
>}
>
You'll notice that we have an 'int' in there.
That's because once one has more than a few
K of memory to play with during a compile, it
turns out that silently assuming all params
are machine words isn't the best tradeoff.
Of course, now that we've declared that we're
returning an int, we'd probably better do so:
@more boilerplate...
>return 0;
We must declare the argument types as well
as the return types:
@inline formal declarations
>int argc, char **argv, char **envp
As in Pascal, the types are now specified in
with the argument names.  One might expect
that we'd need some additional bookkeeping
for printf() as well as main(), but luckily
(if one is not the preprocessor) this is a
matter of including the proper header file.
@external declarations
>#include <stdio.h>

appendix

The full reply to user code, incorporating the single addition of

$(findlinks < "$wikipage" | codelinks)

at line 7.

<<reply to user>>=
reply 'Content-Type: text/html'
case $request in
    read|write) cat <<-EOF
	<html><body><h1>$wikipage</h1>
	(<a href=$me?edit+$wikipage>edit</a>)
	(<a href=$me?link+$wikipage>links</a>)
	$(findlinks < $wikipage | codelinks)
	<hr>
	$(markup < "$wikipage")
	</body></html>
	EOF
	;;
    edit|create) cat <<-EOF
	<html><body><h1>editing: $wikipage</h1>
	(<a href=$me?read+$wikipage>page</a>)<hr>
	<form action=$me?write+$wikipage method=POST>
	<textarea name=wikitext rows=20 cols=60>
	$(escapehtml < "$wikipage")
	</textarea><br><input type=submit>
	</form></body></html>
	EOF
	;;
    link) cat <<-EOF
	<html><body><h1>pages linking to: $wikipage</h1>
	(<a href=$me?read+$wikipage>page</a>)<hr>
	$(grep -l "$wikipage" $allpages | sed -e 's/^/* /' | markup)
	</body></html>
	EOF
	;;
    *) cat <<-EOF
	<html><body><h1>unknown request</h1>
	(<a href=$me?read+$homepage>home</a>)<hr>
	didn't grok <code>$QUERY_STRING</code>
	</body></html>
	EOF
	;;
esac
Download code
Views