Download code

Jump to: navigation, search

Back to Literate_programming_wiki_(sh)

Download for Windows: zip

Download for UNIX: zip, tar.gz, tar.bz2

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


wiklit.sh

 1 #!/bin/sh
 2 # The authors of this work have released all rights to it and placed it
 3 # in the public domain under the Creative Commons CC0 1.0 waiver
 4 # (http://creativecommons.org/publicdomain/zero/1.0/).
 5 # 
 6 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 7 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 8 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 9 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
10 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
11 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 # 
14 # Retrieved from: http://en.literateprograms.org/Literate_programming_wiki_(sh)?oldid=16381
15 
16 me="wiklit.sh"
17 homepage="WiklitWelcome"
18 reply()      { printf '%s\r\n\r\n' "$1"; }
19 urldecode()  { echo "16i[$(sed -e 's/+/ /g;s/\%\(..\)/]P\1P[/g')]P" | dc; }
20 escapehtml() { sed -e 's/&/\&amp;/g;s/</\&lt;/g;s/>/\&gt;/g'; }
21 wikify() {
22     PAGE="$allpages" awk '
23         codeblock && $0 !~ /^&gt;/ { print codeblock; codeblock = "" }
24         $0 ~ /^@/    { print "<""pre>"$0; codeblock = "<""/pre>"; next }
25         BEGIN { split(ENVIRON["PAGE"],rev)
26                 for(r in rev) { page[rev[r]] = r } }
27         listing && $0 !~ /^[#\*]/  { print listing; listing = "" }
28         $0 ~ /^# /   { if(!listing) { print "<ol>"; listing = "</ol>" } }
29         $0 ~ /^\* /  { if(!listing) { print "<ul>"; listing = "</ul>" } }
30         listing      { sub(/./, "<li>") }
31         $0 == ""     { $0 = "<p>" }
32         $0 == "----" { $0 = "<hr>" }
33         { for(i=1; i<=NF; ++i) {
34             if(match($i, /^[A-Z][a-z]+[A-Z][a-z]+/))	{
35               wikiname = substr($i, RSTART, RLENGTH)
36               if(page[wikiname]) l = "<a href='$me'?read+"wikiname">"wikiname"</a>"
37               else               l = wikiname"<a href='$me'?create+"wikiname">?</a>"
38               $i = l substr($i, RSTART+RLENGTH)
39             } else if(match($i, /http:\/\//)) {
40               $i = "<a href=\""$i"\">"$i"</a>"
41             }
42           }
43           print }'
44 }
45 markup() { escapehtml | tr -d "\r" | wikify; }
46 findlinks() { sed -n 's/^@\([a-z]*\.[a-z]*\)/\1/p'; }
47 codelinks() { sed -e "s|.*|(<a href=$me?code+$wikipage+&>download &</a>)|"; }
48 
49 set -- $(echo $QUERY_STRING | urldecode)
50 request=$1
51 wikipage=$2
52 [ $request ] || { reply "Location: $me?read+$homepage"; exit; }
53 if [ $request = code ]; then
54     reply 'Content-Type: text/plain'
55     exec python wiklit.py $3 < $wikipage
56 fi
57 [ $request = write ] && sed 's/wikitext=//' | urldecode > $wikipage
58 allpages=$(ls [A-Z][a-z]*[A-Z][a-z]*)
59 reply 'Content-Type: text/html'
60 case $request in
61     read|write) cat <<-EOF
62 	<html><body><h1>$wikipage</h1>
63 	(<a href=$me?edit+$wikipage>edit</a>)
64 	(<a href=$me?link+$wikipage>links</a>)
65 	$(findlinks < $wikipage | codelinks)
66 	<hr>
67 	$(markup < "$wikipage")
68 	</body></html>
69 	EOF
70 	;;
71     edit|create) cat <<-EOF
72 	<html><body><h1>editing: $wikipage</h1>
73 	(<a href=$me?read+$wikipage>page</a>)<hr>
74 	<form action=$me?write+$wikipage method=POST>
75 	<textarea name=wikitext rows=20 cols=60>
76 	$(escapehtml < "$wikipage")
77 	</textarea><br><input type=submit>
78 	</form></body></html>
79 	EOF
80 	;;
81     link) cat <<-EOF
82 	<html><body><h1>pages linking to: $wikipage</h1>
83 	(<a href=$me?read+$wikipage>page</a>)<hr>
84 	$(grep -l "$wikipage" $allpages | sed -e 's/^/* /' | markup)
85 	</body></html>
86 	EOF
87 	;;
88     *) cat <<-EOF
89 	<html><body><h1>unknown request</h1>
90 	(<a href=$me?read+$homepage>home</a>)<hr>
91 	didn't grok <code>$QUERY_STRING</code>
92 	</body></html>
93 	EOF
94 	;;
95 esac
96 


hijacker
hijacker
hijacker
hijacker

wiklit.py

 1 # The authors of this work have released all rights to it and placed it
 2 # in the public domain under the Creative Commons CC0 1.0 waiver
 3 # (http://creativecommons.org/publicdomain/zero/1.0/).
 4 # 
 5 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 6 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 7 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 8 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 9 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
10 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
11 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 # 
13 # Retrieved from: http://en.literateprograms.org/Literate_programming_wiki_(sh)?oldid=16381
14 
15 import sys
16 
17 if len(sys.argv) < 2:
18     print "Usage: %s node" % sys.argv[0]
19     sys.exit(1)
20 
21 def findcode(file):
22     cs, cur = ({}, None)
23     for line in file.readlines():
24         if line[0] is '@':    cur = line[1:-1]
25         if line[0] is '>':    cs[cur] = cs.get(cur,"") + line[1:]
26     return cs
27 
28 def expand(node, cs):
29     phase = True
30     for x in cs[node][:-1].split('@'):
31         if phase:    sys.stdout.write(x)
32         else:        expand(x, cs)
33         phase = not phase
34 
35 expand(sys.argv[1], findcode(sys.stdin))


hijacker
hijacker
hijacker
hijacker

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>


hijacker
hijacker
hijacker
hijacker