posts: 095
authorLucian Mogosanu <lucian@mogosanu.ro>
Fri, 5 Jul 2019 15:00:31 +0000 (18:00 +0300)
committerLucian Mogosanu <lucian@mogosanu.ro>
Fri, 5 Jul 2019 15:00:31 +0000 (18:00 +0300)
drafts/000-cl-who-ii.markdown [deleted file]
posts/y05/095-cl-who-ii.markdown [new file with mode: 0644]
uploads/2019/07/cl-who-demo/c-demo.lisp.html [new file with mode: 0644]
uploads/2019/07/cl-who-demo/c-prelude.lisp.html [new file with mode: 0644]
uploads/2019/07/cl-who-demo/demo-dir/c-placeholder.html [new file with mode: 0644]
uploads/2019/07/cl-who-demo/demo-dir/index.html [new file with mode: 0644]
uploads/2019/07/cl-who-demo/index.html [new file with mode: 0644]

diff --git a/drafts/000-cl-who-ii.markdown b/drafts/000-cl-who-ii.markdown
deleted file mode 100644 (file)
index 58d1bf8..0000000
+++ /dev/null
@@ -1,230 +0,0 @@
----
-postid: 000
-title: CL-WHO demo: The Coad Pit
-date: June 29, 2019
-author: Lucian MogoČ™anu
-tags: tech, tmsr
----
-
-In the midst of an [ongoing battle][btcbase-1919627] with the monster
-that is [Hunchentoot][hunchentoot-i], I have received the suggestion
-that I can easily communicate intermediate results by simply posting
-said code on the web in an [annotatable form][btcbase-1919634]. I
-judge this to be a great idea, even though the items in question
-represent merely coad[^1]. Moreover, I've previously promised to
-provide examples for [other WWWisms][cl-who], and it occurs to me that
-this is just the right occasion to do so.
-
-Thus this post answers the following couple of questions: a. how can
-one use CL-WHO to generate a simple web site? and b. given a code base
-consisting of source code, how can we turn that into a HTMListic
-representation with per-line references, *using our tool*[^2]?
-
-[As previously described][cl-who-again] CL-WHO gives us a template
-language, wrapped around the `with-html-output` macro. For example, to
-write a simple web page to `*standard-output*`, one would write:
-
-~~~~ {.commonlisp}
-(cl-who:with-html-output (*standard-output*)
-  (:html (:body
-          (:b (cl-who:str "Hello, world!")))))
-~~~~
-
-which yields the output:
-
-~~~~
-<html><body><b>Hello, world!</b></body></html>
-~~~~
-
-First, let's make some sense of what we just wrote. The full
-description of the template language can be found in [the
-docs][cl-who-syntax], but in short, we: 1. define a context for HTML
-output; in which we 2. generate a HTML whose body contains; 3. a
-"bold" context, containing 4. the string (`str`) "Hello, world!".
-
-Now let's say we want to do something fancier, such as looping over a
-list of items:
-
-~~~~ {.commonlisp}
-(cl-who:with-html-output (*standard-output* nil)
-   (:html (:body
-           (:ul
-            (loop for x in '(a b c d e f)
-                for i = 1 then (1+ i) do
-                (cl-who:htm
-                 (:li (cl-who:esc
-                       (format nil "[~d] ~s" i x))))))))))
-~~~~
-
-gives us:
-
-~~~~
-<html><body><ul><li>[1] A</li><li>[2] B</li><li>[3] C</li><li>[4] D</li><li>[5] E</li><li>[6] F</li></ul></body></html>
-~~~~
-
-In addition to the loop itself, this example has two unknowns, namely
-the `htm` and the `esc` keywords. Firstly, `esc` is very similar to
-the previously-presented `str`, only that it does a HTML escape (of
-e.g. ">" into "&gt;").
-
-Secondly, `htm` is a sort of a shorthand for `with-html-output` that
-is necessary for the following reason: the HTML generation mechanism
-of WHO looks at cons cells whose first element is a keyword
-(interpreted as a HTML tag), and it collects them, until it reaches
-something else (e.g. our loop construct above). When it gets there, it
-treats the input as a standard S-expression, to be evaluated by the
-Lisp evaluator as-is. However, this S-expression now also contains the
-definition of `htm` in its macro-scope, which causes further
-occurences of `htm` to be expanded, which allows nested
-HTML-in-Lisp-in-HTML-... expressions.
-
-To put this convoluted[^3] explanation in simpler words:
-`with-html-output` throws us into a HTML template context; `loop` gets
-us out of there, but `htm` brings us back in, which is precisely the
-"mix HTML and CL" machinery at work. Use it wisely, and it shall serve
-you well.
-
-Now that we have these basics fixed, we can get to what really
-interests us, that is, a HTML representation of source code with
-line-by-line references. For the sake of simplicity and modularity, we
-are going to break this into a set of macros, each doing one
-thing. For example, the CL-WHO template for a line number:
-
-~~~~ {.commonlisp}
-(defmacro tcp-line-number (n &optional (padding 0))
-  "Template for the line number."
-  `(cl-who:str (format nil "~vd " ,padding ,n)))
-~~~~
-
-Note: the `~vd` format string allows us to do variable padding with
-spaces, which is quite useful here to keep our lines aligned. Next,
-the line content and the actual line:
-
-~~~~ {.commonlisp}
-(defmacro tcp-line-content (line)
-  "Template for the line content."
-  `(cl-who:esc ,line))
-
-(defmacro tcp-line (number padding content)
-  "Template for the line."
-  `(cl-who:htm
-    (:span :class "line"
-          :id (format nil "L~d" ,number)
-          (:a :href  (format nil "#L~d" ,number)
-              :class "lineno"
-              (tcp-line-number ,number ,padding))
-          (:span :class "linecont"
-                 (tcp-line-content ,content)))
-    (:br)))
-~~~~
-
-Next we need to put all the lines together in a code block, which for
-our convenience will be a `pre` tag:
-
-~~~~ {.commonlisp}
-(defmacro tcp-block (lines)
-  "Template for generating a code block out of a list of lines."
-  (with-gensyms (i padding line)
-   `(cl-who:htm
-     (:pre :class "coadblock"
-      (loop for ,padding = (length (format nil "~d" (length ,lines)))
-        for ,i = 1 then (1+ ,i)
-        for ,line in ,lines do
-          (tcp-line ,i ,padding ,line))))))
-~~~~
-
-... and, for even more convenience, we'll output a HTML header with
-some CSS to bellify the coad loox:
-
-~~~~ {.commonlisp}
-(defmacro tcp-html-header (title)
-  `(cl-who:htm
-    (:title (cl-who:str ,title))
-    (:style :type "text/css"
-           (cl-who:str "
-.coadblock {background-color:#e8e8e8;
-            border-style:solid;border-width:1px;padding-left:5px;}
-.line {float:left; width:100%;}
-.lineno {font-weight:bold;text-decoration:none;color:black;}
-.lineno:visited {color:black;}
-:target {background-color:lightyellow;}"))))
-~~~~
-
-Finally, we put everything together in a function that receives a page
-title, a list of strings, each string a line in the source file, and
-outputs them into a file:
-
-~~~~ {.commonlisp}
-(defun write-code-page (title lines out-path)
-  "Write LINES to OUT-PATH as a HTML file."
-  (with-open-file (out out-path
-                      :direction :output
-                      :if-exists :supersede)
-    (cl-who:with-html-output (out nil
-                                 :prologue t
-                                 :indent nil)
-      (cl-who:htm
-       (:html (:head (tcp-html-header title))
-             (:body (:b (cl-who:str title))
-                    (tcp-block lines)))))))
-~~~~
-
-That's it, really, our coad-pit-generating coad. Go ahead and test
-it. This isn't quite the whole thing, but I'm deliberately omitting it
-since there's a lot of it that's out of the scope of a CL-WHO demo: we
-need to a. take a code base given as input, and; b. based on its input
-path and output path and; c. based on its path inside the website
-we're deploying to; d. we must process the code tree; and e. for each
-source file, output the generated page, and f. for each directory,
-create the output directory and output an index page. I initially
-thought this would fit in about two hundred lines of Lisp, but it runs
-a bit over three hundred, so I'm illustrating the demo by having it
-generate itself.
-
-The full coad can be examined on this [demo page][cl-who-demo]. For
-the future, I am preparing a new site, The Coad Pit, that will be soon
-available over at [coad.thetarpit.org][coad], containing e.g. CL-WHO,
-Hunchentoot and other coads and codes that I've gathered over time.
-
-[^1]: "Coad" is a TMSR term of art, representing, well... [let's
-      see][btcbase-1760554]:
-
-      > **mircea_popescu**: is "coad" code ?  
-      > **asciilifeform**: yea, but think 'with lower case c'  
-      > **asciilifeform**: i.e snippets
-
-      In other words, coad is code that comes with no guarantees that
-      it does what the author says it does, nor, in some cases, that
-      it does anything useful at all, nor that it's usable, readable,
-      fittable in head and so on -- making its value as a published
-      item somewhat questionable. However, [some] coad may have the
-      potential to be turned into actual code, i.e. into something
-      that I for example could sign without thinking twice, which is
-      why putting coad on the 'net in some form or the other is not at
-      all a useless endeavour.
-
-[^2]: There's nothing fundamentally new in "code sites". Shithub does
-      it, owing to ye olde [LXR][lxr]; meanwhile, Phf's btcbase has a
-      very neat [V patch explorer][btcbase-patches] that's been in
-      Republican use for years now.
-
-      So the only thing I'm adding to it is the didactic aspect, I
-      guess.
-
-[^3]: The reader might get a reasonably good insight on what happens
-      behind the scenes by running `macroexpand-1` on the example
-      presented. Other than that, it's just CL macros all the way
-      down, and this unfortunately can't be properly explained in this
-      humble article.
-
-[btcbase-1919627]: http://btcbase.org/log/2019-06-23#1919627
-[hunchentoot-i]: /posts/y05/093-hunchentoot-i.html
-[btcbase-1919634]: http://btcbase.org/log/2019-06-23#1919634
-[btcbase-1760554]: http://btcbase.org/log/2017-12-29#1760554
-[cl-who]: /posts/y05/092-cl-who.html#selection-71.157-75.46
-[lxr]: http://archive.is/O6l48
-[btcbase-patches]: http://btcbase.org/patches
-[cl-who-again]: http://thetarpit.org/posts/y05/092-cl-who.html#selection-67.223-67.610
-[cl-who-syntax]: http://archive.is/3kH5V#selection-835.0-835.20
-[cl-who-demo]: /uploads/2019/06/cl-who-demo/
-[coad]: http://coad.thetarpit.org/
diff --git a/posts/y05/095-cl-who-ii.markdown b/posts/y05/095-cl-who-ii.markdown
new file mode 100644 (file)
index 0000000..24f9734
--- /dev/null
@@ -0,0 +1,231 @@
+---
+postid: 095
+title: CL-WHO demo: The Coad Pit
+date: July 5, 2019
+author: Lucian MogoČ™anu
+tags: tech, tmsr
+---
+
+In the midst of an [ongoing battle][btcbase-1919627] with the monster
+that is [Hunchentoot][hunchentoot-i], I have received the suggestion
+that I can easily communicate intermediate results by simply posting
+said code on the web in an [annotatable form][btcbase-1919634]. I
+judge this to be an excellent idea, even though the items in question
+represent merely coad[^1]. Moreover, since I've previously promised to
+provide examples for [other CL WWWisms][cl-who], it occurs to me that
+this is just the right occasion to do so.
+
+Thus this post answers the following couple of questions: a. how can
+one use CL-WHO to generate a simple web site? and b. given a code base
+consisting of source code, how can we turn that into a HTMListic
+representation with per-line references, *using our tool*[^2]?
+
+[As previously described][cl-who-again], CL-WHO gives us a template
+language, wrapped around the `with-html-output` macro. For example, to
+print a simple web page to standard output, one would write:
+
+~~~~ {.commonlisp}
+(cl-who:with-html-output (*standard-output*)
+  (:html (:body
+          (:b (cl-who:str "Hello, world!")))))
+~~~~
+
+which yields the output:
+
+~~~~
+<html><body><b>Hello, world!</b></body></html>
+~~~~
+
+First, let's make some sense of what we just wrote. The full
+description of the template language can be found in [the
+docs][cl-who-syntax], but in short, we: 1. define a context for HTML
+output; in which we 2. generate a "&lt;html&gt;" whose body
+contains; 3. a "bold" context, containing 4. the string (`str`)
+"Hello, world!".
+
+Now let's say we want to do something fancier, such as mechanically
+generating a list of items. Then:
+
+~~~~ {.commonlisp}
+(cl-who:with-html-output (*standard-output* nil)
+   (:html (:body
+           (:ul
+            (loop for x in '(a b c d e f)
+                for i = 1 then (1+ i) do
+                (cl-who:htm
+                 (:li (cl-who:esc
+                       (format nil "[~d] ~s" i x))))))))))
+~~~~
+
+gives us:
+
+~~~~
+<html><body><ul><li>[1] A</li><li>[2] B</li><li>[3] C</li><li>[4] D</li><li>[5] E</li><li>[6] F</li></ul></body></html>
+~~~~
+
+In addition to the loop construct, this example has two new elements,
+namely the `htm` and the `esc` symbols. Firstly, `esc` is very similar
+to the previously-presented `str`, only that it does a HTML escape (of
+e.g. "&gt;" into "&amp;gt;").
+
+Secondly, `htm` is a sort of a shorthand for `with-html-output` that
+is useful for the following: the HTML generation mechanism of WHO
+looks at cons cells whose first element is a keyword (interpreted as a
+HTML tag) and it collects them, until it reaches another form --
+e.g. our loop construct above. When it gets there, it treats the input
+as a standard S-expression, to be evaluated by the Lisp evaluator
+as-is. However, this S-expression now also contains the definition of
+`htm` in its macro-scope, which causes further occurences of `htm` to
+be expanded, which allows nested HTML-in-Lisp-in-HTML-... expressions.
+
+To put this convoluted[^3] explanation in simpler words:
+`with-html-output` throws us into a HTML template context; `loop` (or
+some other CL control structure) gets us out of there, but `htm`
+brings us back in, which is precisely the "mix HTML and CL" machinery
+at work. Use it wisely, and it shall serve you well.
+
+Now that we have these basics settled, we can get to what really
+interests us, that is, a HTML representation of source code with
+line-by-line references. For the sake of simplicity and modularity, we
+are going to break this into a set of macros, each doing one
+thing. For example, the CL-WHO template for a line number:
+
+~~~~ {.commonlisp}
+(defmacro tcp-line-number (n &optional (padding 0))
+  "Template for the line number."
+  `(cl-who:str (format nil "~vd " ,padding ,n)))
+~~~~
+
+Note: the `~vd` format string allows us to do variable padding with
+spaces, which is quite useful here to keep our lines aligned. Next,
+the line content and the actual line:
+
+~~~~ {.commonlisp}
+(defmacro tcp-line-content (line)
+  "Template for the line content."
+  `(cl-who:esc ,line))
+
+(defmacro tcp-line (number padding content)
+  "Template for the line."
+  `(cl-who:htm
+    (:span :class "line"
+          :id (format nil "L~d" ,number)
+          (:a :href  (format nil "#L~d" ,number)
+              :class "lineno"
+              (tcp-line-number ,number ,padding))
+          (:span :class "linecont"
+                 (tcp-line-content ,content)))
+    (:br)))
+~~~~
+
+Next we need to put all the lines together in a code block, which for
+our convenience will be delimited by a "&lt;pre&gt;" tag:
+
+~~~~ {.commonlisp}
+(defmacro tcp-block (lines)
+  "Template for generating a code block out of a list of lines."
+  (with-gensyms (i padding line)
+   `(cl-who:htm
+     (:pre :class "coadblock"
+      (loop for ,padding = (length (format nil "~d" (length ,lines)))
+        for ,i = 1 then (1+ ,i)
+        for ,line in ,lines do
+          (tcp-line ,i ,padding ,line))))))
+~~~~
+
+... and, for even more convenience, we'll output a HTML header with
+some CSS to bellify the coad loox:
+
+~~~~ {.commonlisp}
+(defmacro tcp-html-header (title)
+  `(cl-who:htm
+    (:title (cl-who:str ,title))
+    (:style :type "text/css"
+           (cl-who:str "
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}"))))
+~~~~
+
+Finally, we put everything together in a function that receives a page
+title, a list of strings, each string a line in the source file, and
+outputs them into a file:
+
+~~~~ {.commonlisp}
+(defun write-code-page (title lines out-path)
+  "Write LINES to OUT-PATH as a HTML file."
+  (with-open-file (out out-path
+                      :direction :output
+                      :if-exists :supersede)
+    (cl-who:with-html-output (out nil
+                                 :prologue t
+                                 :indent nil)
+      (cl-who:htm
+       (:html (:head (tcp-html-header title))
+             (:body (:b (cl-who:str title))
+                    (tcp-block lines)))))))
+~~~~
+
+That's it, really, our coad-pit-generating coad. Go ahead and test
+it. This isn't quite the whole thing, but I'm deliberately omitting
+the rest since there's a lot of functionality going beyond our CL-WHO
+demo: we need to a. take a code base given as input, and; b. based on
+its input path and output path and; c. based on its path inside the
+website we're deploying to; d. we must process the code tree; and
+e. for each source file, output the generated page, and f. for each
+directory, create the output directory and output an index page. I
+initially thought this would fit in about two hundred lines of Lisp,
+but it runs a bit over three hundred, so I'm illustrating the demo by
+having it generate itself.
+
+The full demo coad can be examined on [this page][cl-who-demo]. For
+the future I am preparing a new site, The Coad Pit, available over at
+[coad.thetarpit.org][coad], containing e.g. CL-WHO, Hunchentoot and
+other coads and codes that I've gathered over time. It's still very
+rough around the edges, but don't hesitate to play with it.
+
+[^1]: "Coad" is a term of art, representing, well... [let's
+      see][btcbase-1760554]:
+
+      > **mircea_popescu**: is "coad" code ?  
+      > **asciilifeform**: yea, but think 'with lower case c'  
+      > **asciilifeform**: i.e snippets
+
+      In other words, coad is code that comes with no guarantees that
+      it does what the author says it does, nor, in some cases, that
+      it does anything useful at all, nor that it's usable, readable,
+      fittable in head and so on -- making its value as a published
+      item somewhat questionable. However, (some) coad may have the
+      potential to be turned into actual code, i.e. into something
+      that I for example could sign without thinking twice, which is
+      why putting coad on the 'net in some form or the other is not at
+      all a useless endeavour.
+
+[^2]: There's nothing fundamentally new in "code sites". Shithub does
+      it, owing to ye olde [LXR][lxr]; meanwhile, Phf's btcbase has a
+      very neat [V patch explorer][btcbase-patches] that's been in
+      Republican use for years now.
+
+      So the only thing I'm adding to it is the didactic aspect, I
+      guess.
+
+[^3]: The reader might get a reasonably good insight on what happens
+      behind the scenes by running `macroexpand-1` on the example
+      presented. Other than that, it's just CL macros all the way
+      down, which exercise unfortunately goes way beyond the scope of
+      this humble article.
+
+[btcbase-1919627]: http://btcbase.org/log/2019-06-23#1919627
+[hunchentoot-i]: /posts/y05/093-hunchentoot-i.html
+[btcbase-1919634]: http://btcbase.org/log/2019-06-23#1919634
+[btcbase-1760554]: http://btcbase.org/log/2017-12-29#1760554
+[cl-who]: /posts/y05/092-cl-who.html#selection-71.157-75.46
+[lxr]: http://archive.is/O6l48
+[btcbase-patches]: http://btcbase.org/patches
+[cl-who-again]: http://thetarpit.org/posts/y05/092-cl-who.html#selection-67.223-67.610
+[cl-who-syntax]: http://archive.is/3kH5V#selection-835.0-835.20
+[cl-who-demo]: /uploads/2019/07/cl-who-demo/
+[coad]: http://coad.thetarpit.org/
diff --git a/uploads/2019/07/cl-who-demo/c-demo.lisp.html b/uploads/2019/07/cl-who-demo/c-demo.lisp.html
new file mode 100644 (file)
index 0000000..0d23961
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html><head><title>demo.lisp</title><style type='text/css'>
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}</style></head><body><b>demo.lisp</b><pre class='coadblock'><span class='line' id='L1'><a href='#L1' class='lineno'>  1 </a><span class='linecont'>;; CL-WHO demo: The Coad Pit (TCP).</span></span><br /><span class='line' id='L2'><a href='#L2' class='lineno'>  2 </a><span class='linecont'></span></span><br /><span class='line' id='L3'><a href='#L3' class='lineno'>  3 </a><span class='linecont'>;; Utilities:</span></span><br /><span class='line' id='L4'><a href='#L4' class='lineno'>  4 </a><span class='linecont'>(defmacro with-gensyms ((&amp;rest names) &amp;body body)</span></span><br /><span class='line' id='L5'><a href='#L5' class='lineno'>  5 </a><span class='linecont'>  `(let ,(loop for n in names collect `(,n (gensym)))</span></span><br /><span class='line' id='L6'><a href='#L6' class='lineno'>  6 </a><span class='linecont'>     ,@body))</span></span><br /><span class='line' id='L7'><a href='#L7' class='lineno'>  7 </a><span class='linecont'></span></span><br /><span class='line' id='L8'><a href='#L8' class='lineno'>  8 </a><span class='linecont'>(defun concatenate-pathname-dirs (pathname1 pathname2)</span></span><br /><span class='line' id='L9'><a href='#L9' class='lineno'>  9 </a><span class='linecont'>  &quot;The result will be a file with the directories of PATHNAME1 and</span></span><br /><span class='line' id='L10'><a href='#L10' class='lineno'> 10 </a><span class='linecont'>PATHNAME2 concatenated.</span></span><br /><span class='line' id='L11'><a href='#L11' class='lineno'> 11 </a><span class='linecont'></span></span><br /><span class='line' id='L12'><a href='#L12' class='lineno'> 12 </a><span class='linecont'>File names and types of PATHNAMEs are ignored.&quot;</span></span><br /><span class='line' id='L13'><a href='#L13' class='lineno'> 13 </a><span class='linecont'>  (let ((dir1 (pathname-directory pathname1))</span></span><br /><span class='line' id='L14'><a href='#L14' class='lineno'> 14 </a><span class='linecont'>    (dir2 (pathname-directory pathname2)))</span></span><br /><span class='line' id='L15'><a href='#L15' class='lineno'> 15 </a><span class='linecont'>    (make-pathname :directory</span></span><br /><span class='line' id='L16'><a href='#L16' class='lineno'> 16 </a><span class='linecont'>              (append dir1 (cdr dir2))</span></span><br /><span class='line' id='L17'><a href='#L17' class='lineno'> 17 </a><span class='linecont'>                   :name (pathname-name pathname2)</span></span><br /><span class='line' id='L18'><a href='#L18' class='lineno'> 18 </a><span class='linecont'>            :type (pathname-type pathname2))))</span></span><br /><span class='line' id='L19'><a href='#L19' class='lineno'> 19 </a><span class='linecont'></span></span><br /><span class='line' id='L20'><a href='#L20' class='lineno'> 20 </a><span class='linecont'>(defun read-file-lines (pathspec)</span></span><br /><span class='line' id='L21'><a href='#L21' class='lineno'> 21 </a><span class='linecont'>  &quot;Read lines in file pointed to by PATHSPEC one by one and return</span></span><br /><span class='line' id='L22'><a href='#L22' class='lineno'> 22 </a><span class='linecont'>them in a list.&quot;</span></span><br /><span class='line' id='L23'><a href='#L23' class='lineno'> 23 </a><span class='linecont'>  (with-open-file (in pathspec)</span></span><br /><span class='line' id='L24'><a href='#L24' class='lineno'> 24 </a><span class='linecont'>    (loop for line = (read-line in nil :eof)</span></span><br /><span class='line' id='L25'><a href='#L25' class='lineno'> 25 </a><span class='linecont'>         until (eq line :eof)</span></span><br /><span class='line' id='L26'><a href='#L26' class='lineno'> 26 </a><span class='linecont'>       collect line)))</span></span><br /><span class='line' id='L27'><a href='#L27' class='lineno'> 27 </a><span class='linecont'></span></span><br /><span class='line' id='L28'><a href='#L28' class='lineno'> 28 </a><span class='linecont'>;; Part one: code page generation</span></span><br /><span class='line' id='L29'><a href='#L29' class='lineno'> 29 </a><span class='linecont'></span></span><br /><span class='line' id='L30'><a href='#L30' class='lineno'> 30 </a><span class='linecont'>;; A line has two components: a number and its content.</span></span><br /><span class='line' id='L31'><a href='#L31' class='lineno'> 31 </a><span class='linecont'>(defmacro tcp-line-number (n &amp;optional (padding 0))</span></span><br /><span class='line' id='L32'><a href='#L32' class='lineno'> 32 </a><span class='linecont'>  &quot;Template for the line number.&quot;</span></span><br /><span class='line' id='L33'><a href='#L33' class='lineno'> 33 </a><span class='linecont'>  `(cl-who:str (format nil &quot;~vd &quot; ,padding ,n)))</span></span><br /><span class='line' id='L34'><a href='#L34' class='lineno'> 34 </a><span class='linecont'></span></span><br /><span class='line' id='L35'><a href='#L35' class='lineno'> 35 </a><span class='linecont'>(defmacro tcp-line-content (line)</span></span><br /><span class='line' id='L36'><a href='#L36' class='lineno'> 36 </a><span class='linecont'>  &quot;Template for the line content.&quot;</span></span><br /><span class='line' id='L37'><a href='#L37' class='lineno'> 37 </a><span class='linecont'>  `(cl-who:esc ,line))</span></span><br /><span class='line' id='L38'><a href='#L38' class='lineno'> 38 </a><span class='linecont'></span></span><br /><span class='line' id='L39'><a href='#L39' class='lineno'> 39 </a><span class='linecont'>(defmacro tcp-line (number padding content)</span></span><br /><span class='line' id='L40'><a href='#L40' class='lineno'> 40 </a><span class='linecont'>  &quot;Template for the line.&quot;</span></span><br /><span class='line' id='L41'><a href='#L41' class='lineno'> 41 </a><span class='linecont'>  `(cl-who:htm</span></span><br /><span class='line' id='L42'><a href='#L42' class='lineno'> 42 </a><span class='linecont'>    (:span :class &quot;line&quot;</span></span><br /><span class='line' id='L43'><a href='#L43' class='lineno'> 43 </a><span class='linecont'>        :id (format nil &quot;L~d&quot; ,number)</span></span><br /><span class='line' id='L44'><a href='#L44' class='lineno'> 44 </a><span class='linecont'>           (:a :href  (format nil &quot;#L~d&quot; ,number)</span></span><br /><span class='line' id='L45'><a href='#L45' class='lineno'> 45 </a><span class='linecont'>               :class &quot;lineno&quot;</span></span><br /><span class='line' id='L46'><a href='#L46' class='lineno'> 46 </a><span class='linecont'>          (tcp-line-number ,number ,padding))</span></span><br /><span class='line' id='L47'><a href='#L47' class='lineno'> 47 </a><span class='linecont'>    (:span :class &quot;linecont&quot;</span></span><br /><span class='line' id='L48'><a href='#L48' class='lineno'> 48 </a><span class='linecont'>                (tcp-line-content ,content)))</span></span><br /><span class='line' id='L49'><a href='#L49' class='lineno'> 49 </a><span class='linecont'>    (:br)))</span></span><br /><span class='line' id='L50'><a href='#L50' class='lineno'> 50 </a><span class='linecont'></span></span><br /><span class='line' id='L51'><a href='#L51' class='lineno'> 51 </a><span class='linecont'>;; A code block is a list of lines.</span></span><br /><span class='line' id='L52'><a href='#L52' class='lineno'> 52 </a><span class='linecont'>(defmacro tcp-block (lines)</span></span><br /><span class='line' id='L53'><a href='#L53' class='lineno'> 53 </a><span class='linecont'>  &quot;Template for generating a code block out of a list of lines.&quot;</span></span><br /><span class='line' id='L54'><a href='#L54' class='lineno'> 54 </a><span class='linecont'>  (with-gensyms (i padding line)</span></span><br /><span class='line' id='L55'><a href='#L55' class='lineno'> 55 </a><span class='linecont'>   `(cl-who:htm</span></span><br /><span class='line' id='L56'><a href='#L56' class='lineno'> 56 </a><span class='linecont'>     (:pre :class &quot;coadblock&quot;</span></span><br /><span class='line' id='L57'><a href='#L57' class='lineno'> 57 </a><span class='linecont'>      (loop for ,padding = (length (format nil &quot;~d&quot; (length ,lines)))</span></span><br /><span class='line' id='L58'><a href='#L58' class='lineno'> 58 </a><span class='linecont'>        for ,i = 1 then (1+ ,i)</span></span><br /><span class='line' id='L59'><a href='#L59' class='lineno'> 59 </a><span class='linecont'>    for ,line in ,lines do</span></span><br /><span class='line' id='L60'><a href='#L60' class='lineno'> 60 </a><span class='linecont'>       (tcp-line ,i ,padding ,line))))))</span></span><br /><span class='line' id='L61'><a href='#L61' class='lineno'> 61 </a><span class='linecont'></span></span><br /><span class='line' id='L62'><a href='#L62' class='lineno'> 62 </a><span class='linecont'>;; The header contains a title and some CSS.</span></span><br /><span class='line' id='L63'><a href='#L63' class='lineno'> 63 </a><span class='linecont'>(defmacro tcp-html-header (title)</span></span><br /><span class='line' id='L64'><a href='#L64' class='lineno'> 64 </a><span class='linecont'>  `(cl-who:htm</span></span><br /><span class='line' id='L65'><a href='#L65' class='lineno'> 65 </a><span class='linecont'>    (:title (cl-who:str ,title))</span></span><br /><span class='line' id='L66'><a href='#L66' class='lineno'> 66 </a><span class='linecont'>    (:style :type &quot;text/css&quot;</span></span><br /><span class='line' id='L67'><a href='#L67' class='lineno'> 67 </a><span class='linecont'>            (cl-who:str &quot;</span></span><br /><span class='line' id='L68'><a href='#L68' class='lineno'> 68 </a><span class='linecont'>.coadblock {background-color:#e8e8e8;</span></span><br /><span class='line' id='L69'><a href='#L69' class='lineno'> 69 </a><span class='linecont'>            border-style:solid;border-width:1px;padding-left:5px;}</span></span><br /><span class='line' id='L70'><a href='#L70' class='lineno'> 70 </a><span class='linecont'>.line {float:left; width:100%;}</span></span><br /><span class='line' id='L71'><a href='#L71' class='lineno'> 71 </a><span class='linecont'>.lineno {font-weight:bold;text-decoration:none;color:black;}</span></span><br /><span class='line' id='L72'><a href='#L72' class='lineno'> 72 </a><span class='linecont'>.lineno:visited {color:black;}</span></span><br /><span class='line' id='L73'><a href='#L73' class='lineno'> 73 </a><span class='linecont'>:target {background-color:lightyellow;}&quot;))))</span></span><br /><span class='line' id='L74'><a href='#L74' class='lineno'> 74 </a><span class='linecont'></span></span><br /><span class='line' id='L75'><a href='#L75' class='lineno'> 75 </a><span class='linecont'>;; Print this to output file.</span></span><br /><span class='line' id='L76'><a href='#L76' class='lineno'> 76 </a><span class='linecont'>(defun write-code-page (title lines out-path)</span></span><br /><span class='line' id='L77'><a href='#L77' class='lineno'> 77 </a><span class='linecont'>  &quot;Write LINES to OUT-PATH as a HTML file.&quot;</span></span><br /><span class='line' id='L78'><a href='#L78' class='lineno'> 78 </a><span class='linecont'>  (with-open-file (out out-path</span></span><br /><span class='line' id='L79'><a href='#L79' class='lineno'> 79 </a><span class='linecont'>                      :direction :output</span></span><br /><span class='line' id='L80'><a href='#L80' class='lineno'> 80 </a><span class='linecont'>                 :if-exists :supersede)</span></span><br /><span class='line' id='L81'><a href='#L81' class='lineno'> 81 </a><span class='linecont'>    (cl-who:with-html-output (out nil</span></span><br /><span class='line' id='L82'><a href='#L82' class='lineno'> 82 </a><span class='linecont'>                              :prologue t</span></span><br /><span class='line' id='L83'><a href='#L83' class='lineno'> 83 </a><span class='linecont'>                                :indent nil)</span></span><br /><span class='line' id='L84'><a href='#L84' class='lineno'> 84 </a><span class='linecont'>      (cl-who:htm</span></span><br /><span class='line' id='L85'><a href='#L85' class='lineno'> 85 </a><span class='linecont'>       (:html (:head (tcp-html-header title))</span></span><br /><span class='line' id='L86'><a href='#L86' class='lineno'> 86 </a><span class='linecont'>           (:body (:b (cl-who:str title))</span></span><br /><span class='line' id='L87'><a href='#L87' class='lineno'> 87 </a><span class='linecont'>                    (tcp-block lines)))))))</span></span><br /><span class='line' id='L88'><a href='#L88' class='lineno'> 88 </a><span class='linecont'></span></span><br /><span class='line' id='L89'><a href='#L89' class='lineno'> 89 </a><span class='linecont'>;; Example:</span></span><br /><span class='line' id='L90'><a href='#L90' class='lineno'> 90 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L91'><a href='#L91' class='lineno'> 91 </a><span class='linecont'>;; (lines-to-file</span></span><br /><span class='line' id='L92'><a href='#L92' class='lineno'> 92 </a><span class='linecont'>;;     &quot;A Testes&quot;</span></span><br /><span class='line' id='L93'><a href='#L93' class='lineno'> 93 </a><span class='linecont'>;;     (loop for i from 1 to 20 collect (format nil &quot;line ~d&quot; i))</span></span><br /><span class='line' id='L94'><a href='#L94' class='lineno'> 94 </a><span class='linecont'>;;     &quot;/virtual/sites/lucian.mogosanu.ro/randomio/test-who.html&quot;)</span></span><br /><span class='line' id='L95'><a href='#L95' class='lineno'> 95 </a><span class='linecont'></span></span><br /><span class='line' id='L96'><a href='#L96' class='lineno'> 96 </a><span class='linecont'>;; Part two: code tree processing</span></span><br /><span class='line' id='L97'><a href='#L97' class='lineno'> 97 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L98'><a href='#L98' class='lineno'> 98 </a><span class='linecont'>;; We need to:</span></span><br /><span class='line' id='L99'><a href='#L99' class='lineno'> 99 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L100'><a href='#L100' class='lineno'>100 </a><span class='linecont'>;; - turn filesystem paths into a walkable tree format;</span></span><br /><span class='line' id='L101'><a href='#L101' class='lineno'>101 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L102'><a href='#L102' class='lineno'>102 </a><span class='linecont'>;; - for each directory, be able to generate an index file containing</span></span><br /><span class='line' id='L103'><a href='#L103' class='lineno'>103 </a><span class='linecont'>;;   links to files and subdirectories; and</span></span><br /><span class='line' id='L104'><a href='#L104' class='lineno'>104 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L105'><a href='#L105' class='lineno'>105 </a><span class='linecont'>;; - walk said tree and generate code and index pages.</span></span><br /><span class='line' id='L106'><a href='#L106' class='lineno'>106 </a><span class='linecont'></span></span><br /><span class='line' id='L107'><a href='#L107' class='lineno'>107 </a><span class='linecont'>;; A tree is one of the following two things:</span></span><br /><span class='line' id='L108'><a href='#L108' class='lineno'>108 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L109'><a href='#L109' class='lineno'>109 </a><span class='linecont'>;; - a pathname with the NAME set to a string; or</span></span><br /><span class='line' id='L110'><a href='#L110' class='lineno'>110 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L111'><a href='#L111' class='lineno'>111 </a><span class='linecont'>;; - a list whose first element is a pathname with the DIRECTORY set</span></span><br /><span class='line' id='L112'><a href='#L112' class='lineno'>112 </a><span class='linecont'>;;   to a path and the NAME is not set; the other list elements are</span></span><br /><span class='line' id='L113'><a href='#L113' class='lineno'>113 </a><span class='linecont'>;;   trees.</span></span><br /><span class='line' id='L114'><a href='#L114' class='lineno'>114 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L115'><a href='#L115' class='lineno'>115 </a><span class='linecont'>;; For example: (#p&quot;/&quot; #p&quot;a&quot; (#p&quot;/dir/&quot; #p&quot;b&quot; #p&quot;c&quot;) #p&quot;d&quot;)</span></span><br /><span class='line' id='L116'><a href='#L116' class='lineno'>116 </a><span class='linecont'></span></span><br /><span class='line' id='L117'><a href='#L117' class='lineno'>117 </a><span class='linecont'>(defun extract-tree (pathspec)</span></span><br /><span class='line' id='L118'><a href='#L118' class='lineno'>118 </a><span class='linecont'>  &quot;Recursively extract a tree from PATHSPEC.&quot;</span></span><br /><span class='line' id='L119'><a href='#L119' class='lineno'>119 </a><span class='linecont'></span></span><br /><span class='line' id='L120'><a href='#L120' class='lineno'>120 </a><span class='linecont'>  ;; If PATHSPEC is not a pathname, turn it into one.</span></span><br /><span class='line' id='L121'><a href='#L121' class='lineno'>121 </a><span class='linecont'>  (when (stringp pathspec)</span></span><br /><span class='line' id='L122'><a href='#L122' class='lineno'>122 </a><span class='linecont'>    (setq pathspec (pathname pathspec)))</span></span><br /><span class='line' id='L123'><a href='#L123' class='lineno'>123 </a><span class='linecont'></span></span><br /><span class='line' id='L124'><a href='#L124' class='lineno'>124 </a><span class='linecont'>  ;; Determine the type of node we&#039;re dealing with</span></span><br /><span class='line' id='L125'><a href='#L125' class='lineno'>125 </a><span class='linecont'>  (let ((dir (pathname-directory pathspec))</span></span><br /><span class='line' id='L126'><a href='#L126' class='lineno'>126 </a><span class='linecont'>    (name (pathname-name pathspec))</span></span><br /><span class='line' id='L127'><a href='#L127' class='lineno'>127 </a><span class='linecont'>  (type (pathname-type pathspec)))</span></span><br /><span class='line' id='L128'><a href='#L128' class='lineno'>128 </a><span class='linecont'>    (cond</span></span><br /><span class='line' id='L129'><a href='#L129' class='lineno'>129 </a><span class='linecont'>      (name (make-pathname :name name :type type))</span></span><br /><span class='line' id='L130'><a href='#L130' class='lineno'>130 </a><span class='linecont'>      (dir (let ((files (directory (make-pathname :directory dir</span></span><br /><span class='line' id='L131'><a href='#L131' class='lineno'>131 </a><span class='linecont'>                                           :name :wild</span></span><br /><span class='line' id='L132'><a href='#L132' class='lineno'>132 </a><span class='linecont'>                                              :type :wild))))</span></span><br /><span class='line' id='L133'><a href='#L133' class='lineno'>133 </a><span class='linecont'>             (cons pathspec</span></span><br /><span class='line' id='L134'><a href='#L134' class='lineno'>134 </a><span class='linecont'>                 (mapcar #&#039;extract-tree files)))))))</span></span><br /><span class='line' id='L135'><a href='#L135' class='lineno'>135 </a><span class='linecont'></span></span><br /><span class='line' id='L136'><a href='#L136' class='lineno'>136 </a><span class='linecont'>(defun normalized-tree (tree)</span></span><br /><span class='line' id='L137'><a href='#L137' class='lineno'>137 </a><span class='linecont'>  &quot;Normalize TREE by removing the common part of the path in all</span></span><br /><span class='line' id='L138'><a href='#L138' class='lineno'>138 </a><span class='linecont'>directories.</span></span><br /><span class='line' id='L139'><a href='#L139' class='lineno'>139 </a><span class='linecont'></span></span><br /><span class='line' id='L140'><a href='#L140' class='lineno'>140 </a><span class='linecont'>This function assumes TREE was obtained using EXTRACT-TREE.&quot;</span></span><br /><span class='line' id='L141'><a href='#L141' class='lineno'>141 </a><span class='linecont'>  (let ((root-pathspec (car tree)))</span></span><br /><span class='line' id='L142'><a href='#L142' class='lineno'>142 </a><span class='linecont'>    (labels ((recurse (tree)</span></span><br /><span class='line' id='L143'><a href='#L143' class='lineno'>143 </a><span class='linecont'>               ;; This doesn&#039;t do anything for non-directory files.</span></span><br /><span class='line' id='L144'><a href='#L144' class='lineno'>144 </a><span class='linecont'>        (when (pathnamep tree)</span></span><br /><span class='line' id='L145'><a href='#L145' class='lineno'>145 </a><span class='linecont'>             (return-from recurse tree))</span></span><br /><span class='line' id='L146'><a href='#L146' class='lineno'>146 </a><span class='linecont'>            (let ((dircopy (copy-list</span></span><br /><span class='line' id='L147'><a href='#L147' class='lineno'>147 </a><span class='linecont'>                        (pathname-directory root-pathspec)))</span></span><br /><span class='line' id='L148'><a href='#L148' class='lineno'>148 </a><span class='linecont'>                   (curr-dir (pathname-directory (car tree))))</span></span><br /><span class='line' id='L149'><a href='#L149' class='lineno'>149 </a><span class='linecont'>          ;; Get rid of common parts...</span></span><br /><span class='line' id='L150'><a href='#L150' class='lineno'>150 </a><span class='linecont'>            (loop until (null dircopy) do</span></span><br /><span class='line' id='L151'><a href='#L151' class='lineno'>151 </a><span class='linecont'>                 (pop dircopy)</span></span><br /><span class='line' id='L152'><a href='#L152' class='lineno'>152 </a><span class='linecont'>                    (pop curr-dir))</span></span><br /><span class='line' id='L153'><a href='#L153' class='lineno'>153 </a><span class='linecont'>             ;; Set normalized path</span></span><br /><span class='line' id='L154'><a href='#L154' class='lineno'>154 </a><span class='linecont'>           (push :absolute curr-dir)</span></span><br /><span class='line' id='L155'><a href='#L155' class='lineno'>155 </a><span class='linecont'>                ;; Now recurse into the rest of the tree</span></span><br /><span class='line' id='L156'><a href='#L156' class='lineno'>156 </a><span class='linecont'>                 (cons (make-pathname :directory curr-dir)</span></span><br /><span class='line' id='L157'><a href='#L157' class='lineno'>157 </a><span class='linecont'>                      (mapcar #&#039;(lambda (tree)</span></span><br /><span class='line' id='L158'><a href='#L158' class='lineno'>158 </a><span class='linecont'>                                (recurse tree))</span></span><br /><span class='line' id='L159'><a href='#L159' class='lineno'>159 </a><span class='linecont'>                              (cdr tree))))))</span></span><br /><span class='line' id='L160'><a href='#L160' class='lineno'>160 </a><span class='linecont'>      (recurse tree))))</span></span><br /><span class='line' id='L161'><a href='#L161' class='lineno'>161 </a><span class='linecont'></span></span><br /><span class='line' id='L162'><a href='#L162' class='lineno'>162 </a><span class='linecont'>(defmacro tcp-html-path (dir name type)</span></span><br /><span class='line' id='L163'><a href='#L163' class='lineno'>163 </a><span class='linecont'>  `(make-pathname :directory ,dir</span></span><br /><span class='line' id='L164'><a href='#L164' class='lineno'>164 </a><span class='linecont'>                  :name (format nil &quot;c-~a~@[.~a~]&quot; ,name ,type)</span></span><br /><span class='line' id='L165'><a href='#L165' class='lineno'>165 </a><span class='linecont'>                  :type &quot;html&quot;))</span></span><br /><span class='line' id='L166'><a href='#L166' class='lineno'>166 </a><span class='linecont'></span></span><br /><span class='line' id='L167'><a href='#L167' class='lineno'>167 </a><span class='linecont'>;; Links to files...</span></span><br /><span class='line' id='L168'><a href='#L168' class='lineno'>168 </a><span class='linecont'>(defmacro tcp-file-link (parent-pathspec pathspec &amp;key (uri-prefix #p&quot;/&quot;))</span></span><br /><span class='line' id='L169'><a href='#L169' class='lineno'>169 </a><span class='linecont'>  (with-gensyms (dir name type)</span></span><br /><span class='line' id='L170'><a href='#L170' class='lineno'>170 </a><span class='linecont'>    `(let ((,dir (pathname-directory ,parent-pathspec))</span></span><br /><span class='line' id='L171'><a href='#L171' class='lineno'>171 </a><span class='linecont'>     (,name (pathname-name ,pathspec))</span></span><br /><span class='line' id='L172'><a href='#L172' class='lineno'>172 </a><span class='linecont'>        (,type (pathname-type ,pathspec)))</span></span><br /><span class='line' id='L173'><a href='#L173' class='lineno'>173 </a><span class='linecont'>       (cl-who:htm</span></span><br /><span class='line' id='L174'><a href='#L174' class='lineno'>174 </a><span class='linecont'>   (:em (cl-who:str &quot;[f] &quot;))</span></span><br /><span class='line' id='L175'><a href='#L175' class='lineno'>175 </a><span class='linecont'>      (:a :class &quot;filelink&quot;</span></span><br /><span class='line' id='L176'><a href='#L176' class='lineno'>176 </a><span class='linecont'>      :href (namestring (merge-pathnames</span></span><br /><span class='line' id='L177'><a href='#L177' class='lineno'>177 </a><span class='linecont'>                          (concatenate-pathname-dirs ,uri-prefix</span></span><br /><span class='line' id='L178'><a href='#L178' class='lineno'>178 </a><span class='linecont'>                                                      ,parent-pathspec)</span></span><br /><span class='line' id='L179'><a href='#L179' class='lineno'>179 </a><span class='linecont'>                             (tcp-html-path ,dir ,name, type)))</span></span><br /><span class='line' id='L180'><a href='#L180' class='lineno'>180 </a><span class='linecont'>            (cl-who:esc</span></span><br /><span class='line' id='L181'><a href='#L181' class='lineno'>181 </a><span class='linecont'>       (format nil &quot;~a~@[.~a~]&quot; ,name ,type)))))))</span></span><br /><span class='line' id='L182'><a href='#L182' class='lineno'>182 </a><span class='linecont'></span></span><br /><span class='line' id='L183'><a href='#L183' class='lineno'>183 </a><span class='linecont'>;; and to directories.</span></span><br /><span class='line' id='L184'><a href='#L184' class='lineno'>184 </a><span class='linecont'>(defmacro tcp-directory-link (pathspec &amp;key (uri-prefix #p&quot;/&quot;)</span></span><br /><span class='line' id='L185'><a href='#L185' class='lineno'>185 </a><span class='linecont'>                                            custom-name)</span></span><br /><span class='line' id='L186'><a href='#L186' class='lineno'>186 </a><span class='linecont'>  `(cl-who:htm</span></span><br /><span class='line' id='L187'><a href='#L187' class='lineno'>187 </a><span class='linecont'>    (:em (cl-who:str &quot;[d] &quot;))</span></span><br /><span class='line' id='L188'><a href='#L188' class='lineno'>188 </a><span class='linecont'>    (:a :class &quot;dirlink&quot;</span></span><br /><span class='line' id='L189'><a href='#L189' class='lineno'>189 </a><span class='linecont'>     :href (namestring (concatenate-pathname-dirs ,uri-prefix ,pathspec))</span></span><br /><span class='line' id='L190'><a href='#L190' class='lineno'>190 </a><span class='linecont'>     (cl-who:esc (or ,custom-name</span></span><br /><span class='line' id='L191'><a href='#L191' class='lineno'>191 </a><span class='linecont'>                     (car (last (pathname-directory ,pathspec))))))))</span></span><br /><span class='line' id='L192'><a href='#L192' class='lineno'>192 </a><span class='linecont'></span></span><br /><span class='line' id='L193'><a href='#L193' class='lineno'>193 </a><span class='linecont'>(defun parent-dir (pathspec)</span></span><br /><span class='line' id='L194'><a href='#L194' class='lineno'>194 </a><span class='linecont'>  &quot;Given PATHSPEC to directory, get parent node, e.g.:</span></span><br /><span class='line' id='L195'><a href='#L195' class='lineno'>195 </a><span class='linecont'></span></span><br /><span class='line' id='L196'><a href='#L196' class='lineno'>196 </a><span class='linecont'>- /home/bubu/ -&gt; /home/</span></span><br /><span class='line' id='L197'><a href='#L197' class='lineno'>197 </a><span class='linecont'>- /           -&gt; /</span></span><br /><span class='line' id='L198'><a href='#L198' class='lineno'>198 </a><span class='linecont'></span></span><br /><span class='line' id='L199'><a href='#L199' class='lineno'>199 </a><span class='linecont'>Only the DIRECTORY component of PATHSPEC is considered, all others are</span></span><br /><span class='line' id='L200'><a href='#L200' class='lineno'>200 </a><span class='linecont'>ignored.&quot;</span></span><br /><span class='line' id='L201'><a href='#L201' class='lineno'>201 </a><span class='linecont'>  (labels ((all-but-last (L)</span></span><br /><span class='line' id='L202'><a href='#L202' class='lineno'>202 </a><span class='linecont'>          (cond</span></span><br /><span class='line' id='L203'><a href='#L203' class='lineno'>203 </a><span class='linecont'>              ((null L) (error &quot;Empty list.&quot;))</span></span><br /><span class='line' id='L204'><a href='#L204' class='lineno'>204 </a><span class='linecont'>               (t (loop for curr-L on L</span></span><br /><span class='line' id='L205'><a href='#L205' class='lineno'>205 </a><span class='linecont'>               while (cdr curr-L)</span></span><br /><span class='line' id='L206'><a href='#L206' class='lineno'>206 </a><span class='linecont'>               collect (car curr-L))))))</span></span><br /><span class='line' id='L207'><a href='#L207' class='lineno'>207 </a><span class='linecont'>   (let ((dir (pathname-directory pathspec)))</span></span><br /><span class='line' id='L208'><a href='#L208' class='lineno'>208 </a><span class='linecont'>     (make-pathname :directory</span></span><br /><span class='line' id='L209'><a href='#L209' class='lineno'>209 </a><span class='linecont'>              (if (null (cdr dir))</span></span><br /><span class='line' id='L210'><a href='#L210' class='lineno'>210 </a><span class='linecont'>                 dir</span></span><br /><span class='line' id='L211'><a href='#L211' class='lineno'>211 </a><span class='linecont'>                      (all-but-last dir))))))</span></span><br /><span class='line' id='L212'><a href='#L212' class='lineno'>212 </a><span class='linecont'></span></span><br /><span class='line' id='L213'><a href='#L213' class='lineno'>213 </a><span class='linecont'>;; Generate an index for a given directory.</span></span><br /><span class='line' id='L214'><a href='#L214' class='lineno'>214 </a><span class='linecont'>(defmacro tcp-index (tree &amp;optional (uri-prefix #p&quot;/&quot;))</span></span><br /><span class='line' id='L215'><a href='#L215' class='lineno'>215 </a><span class='linecont'>  (with-gensyms (parent-pathspec curr-pathspec children subtree)</span></span><br /><span class='line' id='L216'><a href='#L216' class='lineno'>216 </a><span class='linecont'>    `(let* ((,curr-pathspec (car ,tree))</span></span><br /><span class='line' id='L217'><a href='#L217' class='lineno'>217 </a><span class='linecont'>           (,children (cdr ,tree))</span></span><br /><span class='line' id='L218'><a href='#L218' class='lineno'>218 </a><span class='linecont'>          (,parent-pathspec (parent-dir ,curr-pathspec)))</span></span><br /><span class='line' id='L219'><a href='#L219' class='lineno'>219 </a><span class='linecont'>       (cl-who:htm</span></span><br /><span class='line' id='L220'><a href='#L220' class='lineno'>220 </a><span class='linecont'>     (:pre :class &quot;coadblock&quot;</span></span><br /><span class='line' id='L221'><a href='#L221' class='lineno'>221 </a><span class='linecont'>             ;; First link is self</span></span><br /><span class='line' id='L222'><a href='#L222' class='lineno'>222 </a><span class='linecont'>            (tcp-directory-link ,curr-pathspec</span></span><br /><span class='line' id='L223'><a href='#L223' class='lineno'>223 </a><span class='linecont'>                           :uri-prefix ,uri-prefix</span></span><br /><span class='line' id='L224'><a href='#L224' class='lineno'>224 </a><span class='linecont'>                                  :custom-name &quot;.&quot;)</span></span><br /><span class='line' id='L225'><a href='#L225' class='lineno'>225 </a><span class='linecont'>          (:br)</span></span><br /><span class='line' id='L226'><a href='#L226' class='lineno'>226 </a><span class='linecont'>            ;; Second link is the parent</span></span><br /><span class='line' id='L227'><a href='#L227' class='lineno'>227 </a><span class='linecont'>             (tcp-directory-link ,parent-pathspec</span></span><br /><span class='line' id='L228'><a href='#L228' class='lineno'>228 </a><span class='linecont'>                                 :uri-prefix ,uri-prefix</span></span><br /><span class='line' id='L229'><a href='#L229' class='lineno'>229 </a><span class='linecont'>                                  :custom-name&quot;..&quot;)</span></span><br /><span class='line' id='L230'><a href='#L230' class='lineno'>230 </a><span class='linecont'>          (:br)</span></span><br /><span class='line' id='L231'><a href='#L231' class='lineno'>231 </a><span class='linecont'></span></span><br /><span class='line' id='L232'><a href='#L232' class='lineno'>232 </a><span class='linecont'>             ;; All the others are the files/subdirectories</span></span><br /><span class='line' id='L233'><a href='#L233' class='lineno'>233 </a><span class='linecont'>           (loop for ,subtree in ,children do</span></span><br /><span class='line' id='L234'><a href='#L234' class='lineno'>234 </a><span class='linecont'>            (cond</span></span><br /><span class='line' id='L235'><a href='#L235' class='lineno'>235 </a><span class='linecont'>              ((pathnamep ,subtree) (tcp-file-link</span></span><br /><span class='line' id='L236'><a href='#L236' class='lineno'>236 </a><span class='linecont'>                                            ,curr-pathspec</span></span><br /><span class='line' id='L237'><a href='#L237' class='lineno'>237 </a><span class='linecont'>                                           ,subtree</span></span><br /><span class='line' id='L238'><a href='#L238' class='lineno'>238 </a><span class='linecont'>                                         :uri-prefix ,uri-prefix))</span></span><br /><span class='line' id='L239'><a href='#L239' class='lineno'>239 </a><span class='linecont'>                 ((listp ,subtree) (tcp-directory-link</span></span><br /><span class='line' id='L240'><a href='#L240' class='lineno'>240 </a><span class='linecont'>                                       (car ,subtree)</span></span><br /><span class='line' id='L241'><a href='#L241' class='lineno'>241 </a><span class='linecont'>                                   :uri-prefix ,uri-prefix))</span></span><br /><span class='line' id='L242'><a href='#L242' class='lineno'>242 </a><span class='linecont'>                     (t (error &quot;Not a tree.&quot;)))</span></span><br /><span class='line' id='L243'><a href='#L243' class='lineno'>243 </a><span class='linecont'>                   (cl-who:htm (:br))))))))</span></span><br /><span class='line' id='L244'><a href='#L244' class='lineno'>244 </a><span class='linecont'></span></span><br /><span class='line' id='L245'><a href='#L245' class='lineno'>245 </a><span class='linecont'>;; To generate HTML pages for a given codebase, we need the following</span></span><br /><span class='line' id='L246'><a href='#L246' class='lineno'>246 </a><span class='linecont'>;; information:</span></span><br /><span class='line' id='L247'><a href='#L247' class='lineno'>247 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L248'><a href='#L248' class='lineno'>248 </a><span class='linecont'>;; - the (relative, normalized) path information for all the files;</span></span><br /><span class='line' id='L249'><a href='#L249' class='lineno'>249 </a><span class='linecont'>;; - an optional URI prefix for hrefs residing downstream in the site;</span></span><br /><span class='line' id='L250'><a href='#L250' class='lineno'>250 </a><span class='linecont'>;; - the path to the root of the input directory; and</span></span><br /><span class='line' id='L251'><a href='#L251' class='lineno'>251 </a><span class='linecont'>;; - the path to the root of the output directory.</span></span><br /><span class='line' id='L252'><a href='#L252' class='lineno'>252 </a><span class='linecont'>;;</span></span><br /><span class='line' id='L253'><a href='#L253' class='lineno'>253 </a><span class='linecont'>;; We capture those in the tcp-info struct:</span></span><br /><span class='line' id='L254'><a href='#L254' class='lineno'>254 </a><span class='linecont'>(defstruct (tcp-info (:constructor make-tcp-info%))</span></span><br /><span class='line' id='L255'><a href='#L255' class='lineno'>255 </a><span class='linecont'>  in-pathspec out-pathspec uri-prefix tree)</span></span><br /><span class='line' id='L256'><a href='#L256' class='lineno'>256 </a><span class='linecont'></span></span><br /><span class='line' id='L257'><a href='#L257' class='lineno'>257 </a><span class='linecont'>(defun make-tcp-info (in-pathspec out-pathspec &amp;optional (uri-prefix #p&quot;/&quot;))</span></span><br /><span class='line' id='L258'><a href='#L258' class='lineno'>258 </a><span class='linecont'>  &quot;Create info structre for HTML coadpage generation.&quot;</span></span><br /><span class='line' id='L259'><a href='#L259' class='lineno'>259 </a><span class='linecont'>  (let ((in-tree (extract-tree in-pathspec)))</span></span><br /><span class='line' id='L260'><a href='#L260' class='lineno'>260 </a><span class='linecont'>   (make-tcp-info% :in-pathspec in-pathspec</span></span><br /><span class='line' id='L261'><a href='#L261' class='lineno'>261 </a><span class='linecont'>               :out-pathspec out-pathspec</span></span><br /><span class='line' id='L262'><a href='#L262' class='lineno'>262 </a><span class='linecont'>               :uri-prefix uri-prefix</span></span><br /><span class='line' id='L263'><a href='#L263' class='lineno'>263 </a><span class='linecont'>                   :tree (normalized-tree in-tree))))</span></span><br /><span class='line' id='L264'><a href='#L264' class='lineno'>264 </a><span class='linecont'></span></span><br /><span class='line' id='L265'><a href='#L265' class='lineno'>265 </a><span class='linecont'>;; Write index page, using all the above helpers.</span></span><br /><span class='line' id='L266'><a href='#L266' class='lineno'>266 </a><span class='linecont'>(defun write-index-page (tree tcp-info)</span></span><br /><span class='line' id='L267'><a href='#L267' class='lineno'>267 </a><span class='linecont'>  &quot;Write TREE to HTML file given by OUT-PATHSPEC in TCP-INFO.&quot;</span></span><br /><span class='line' id='L268'><a href='#L268' class='lineno'>268 </a><span class='linecont'>  ;; Do nothing if TREE is a regular file.</span></span><br /><span class='line' id='L269'><a href='#L269' class='lineno'>269 </a><span class='linecont'>  (when (pathnamep tree)</span></span><br /><span class='line' id='L270'><a href='#L270' class='lineno'>270 </a><span class='linecont'>    (return-from write-index-page))</span></span><br /><span class='line' id='L271'><a href='#L271' class='lineno'>271 </a><span class='linecont'></span></span><br /><span class='line' id='L272'><a href='#L272' class='lineno'>272 </a><span class='linecont'>  ;; Do something only if we have a subtree.</span></span><br /><span class='line' id='L273'><a href='#L273' class='lineno'>273 </a><span class='linecont'>  (assert (listp tree))</span></span><br /><span class='line' id='L274'><a href='#L274' class='lineno'>274 </a><span class='linecont'>  (let ((out-path (merge-pathnames</span></span><br /><span class='line' id='L275'><a href='#L275' class='lineno'>275 </a><span class='linecont'>                (concatenate-pathname-dirs (tcp-info-out-pathspec tcp-info)</span></span><br /><span class='line' id='L276'><a href='#L276' class='lineno'>276 </a><span class='linecont'>                                         (car tree))</span></span><br /><span class='line' id='L277'><a href='#L277' class='lineno'>277 </a><span class='linecont'>                   &quot;index.html&quot;))</span></span><br /><span class='line' id='L278'><a href='#L278' class='lineno'>278 </a><span class='linecont'>      (title (format nil &quot;Index for ~a:&quot; (namestring (car tree)))))</span></span><br /><span class='line' id='L279'><a href='#L279' class='lineno'>279 </a><span class='linecont'>    (with-open-file (out out-path</span></span><br /><span class='line' id='L280'><a href='#L280' class='lineno'>280 </a><span class='linecont'>                   :direction :output</span></span><br /><span class='line' id='L281'><a href='#L281' class='lineno'>281 </a><span class='linecont'>                       :if-exists :supersede</span></span><br /><span class='line' id='L282'><a href='#L282' class='lineno'>282 </a><span class='linecont'>                    :if-does-not-exist :create)</span></span><br /><span class='line' id='L283'><a href='#L283' class='lineno'>283 </a><span class='linecont'>      (cl-who:with-html-output (out nil</span></span><br /><span class='line' id='L284'><a href='#L284' class='lineno'>284 </a><span class='linecont'>                                   :prologue t</span></span><br /><span class='line' id='L285'><a href='#L285' class='lineno'>285 </a><span class='linecont'>                              :indent nil)</span></span><br /><span class='line' id='L286'><a href='#L286' class='lineno'>286 </a><span class='linecont'> (cl-who:htm</span></span><br /><span class='line' id='L287'><a href='#L287' class='lineno'>287 </a><span class='linecont'>       (:html (:head (tcp-html-header title))</span></span><br /><span class='line' id='L288'><a href='#L288' class='lineno'>288 </a><span class='linecont'>          (:body (:b (cl-who:str title))</span></span><br /><span class='line' id='L289'><a href='#L289' class='lineno'>289 </a><span class='linecont'>                  (tcp-index tree (tcp-info-uri-prefix tcp-info)))))))))</span></span><br /><span class='line' id='L290'><a href='#L290' class='lineno'>290 </a><span class='linecont'></span></span><br /><span class='line' id='L291'><a href='#L291' class='lineno'>291 </a><span class='linecont'>;; Now we have the basic ammo to generate everything.</span></span><br /><span class='line' id='L292'><a href='#L292' class='lineno'>292 </a><span class='linecont'>(defun generate-coad-pit (tcp-info)</span></span><br /><span class='line' id='L293'><a href='#L293' class='lineno'>293 </a><span class='linecont'>  &quot;Given TCP-INFO, generate code site.&quot;</span></span><br /><span class='line' id='L294'><a href='#L294' class='lineno'>294 </a><span class='linecont'>  (labels</span></span><br /><span class='line' id='L295'><a href='#L295' class='lineno'>295 </a><span class='linecont'>      ((recurse (tree parent-pathspec)</span></span><br /><span class='line' id='L296'><a href='#L296' class='lineno'>296 </a><span class='linecont'>   ;; Are we on a leaf, or...?</span></span><br /><span class='line' id='L297'><a href='#L297' class='lineno'>297 </a><span class='linecont'>      (cond</span></span><br /><span class='line' id='L298'><a href='#L298' class='lineno'>298 </a><span class='linecont'>      ;; Read lines and generate code page. Careful, if you&#039;re</span></span><br /><span class='line' id='L299'><a href='#L299' class='lineno'>299 </a><span class='linecont'>    ;; reading from binary files, you&#039;re fucked.</span></span><br /><span class='line' id='L300'><a href='#L300' class='lineno'>300 </a><span class='linecont'>        ((pathnamep tree)</span></span><br /><span class='line' id='L301'><a href='#L301' class='lineno'>301 </a><span class='linecont'>         (let* ((dir (pathname-directory tree))</span></span><br /><span class='line' id='L302'><a href='#L302' class='lineno'>302 </a><span class='linecont'>                  (name (pathname-name tree))</span></span><br /><span class='line' id='L303'><a href='#L303' class='lineno'>303 </a><span class='linecont'>              (type (pathname-type tree))</span></span><br /><span class='line' id='L304'><a href='#L304' class='lineno'>304 </a><span class='linecont'>              (htm-pathspec (tcp-html-path dir name type))</span></span><br /><span class='line' id='L305'><a href='#L305' class='lineno'>305 </a><span class='linecont'>             (in-pathspec</span></span><br /><span class='line' id='L306'><a href='#L306' class='lineno'>306 </a><span class='linecont'>              (concatenate-pathname-dirs (tcp-info-in-pathspec tcp-info)</span></span><br /><span class='line' id='L307'><a href='#L307' class='lineno'>307 </a><span class='linecont'>                                          (merge-pathnames parent-pathspec</span></span><br /><span class='line' id='L308'><a href='#L308' class='lineno'>308 </a><span class='linecont'>                                                          tree)))</span></span><br /><span class='line' id='L309'><a href='#L309' class='lineno'>309 </a><span class='linecont'>             (out-pathspec</span></span><br /><span class='line' id='L310'><a href='#L310' class='lineno'>310 </a><span class='linecont'>             (concatenate-pathname-dirs (tcp-info-out-pathspec tcp-info)</span></span><br /><span class='line' id='L311'><a href='#L311' class='lineno'>311 </a><span class='linecont'>                                         (merge-pathnames parent-pathspec</span></span><br /><span class='line' id='L312'><a href='#L312' class='lineno'>312 </a><span class='linecont'>                                                          htm-pathspec)))</span></span><br /><span class='line' id='L313'><a href='#L313' class='lineno'>313 </a><span class='linecont'>             (title (namestring tree))</span></span><br /><span class='line' id='L314'><a href='#L314' class='lineno'>314 </a><span class='linecont'>                (lines (read-file-lines in-pathspec)))</span></span><br /><span class='line' id='L315'><a href='#L315' class='lineno'>315 </a><span class='linecont'>              (write-code-page title lines out-pathspec)))</span></span><br /><span class='line' id='L316'><a href='#L316' class='lineno'>316 </a><span class='linecont'>          ((listp tree)</span></span><br /><span class='line' id='L317'><a href='#L317' class='lineno'>317 </a><span class='linecont'>     (let* ((pathspec (car tree))</span></span><br /><span class='line' id='L318'><a href='#L318' class='lineno'>318 </a><span class='linecont'>            (children (cdr tree))</span></span><br /><span class='line' id='L319'><a href='#L319' class='lineno'>319 </a><span class='linecont'>            (out-pathspec</span></span><br /><span class='line' id='L320'><a href='#L320' class='lineno'>320 </a><span class='linecont'>             (concatenate-pathname-dirs (tcp-info-out-pathspec tcp-info)</span></span><br /><span class='line' id='L321'><a href='#L321' class='lineno'>321 </a><span class='linecont'>                                         pathspec)))</span></span><br /><span class='line' id='L322'><a href='#L322' class='lineno'>322 </a><span class='linecont'>             (ensure-directories-exist out-pathspec)</span></span><br /><span class='line' id='L323'><a href='#L323' class='lineno'>323 </a><span class='linecont'>          (write-index-page tree tcp-info)</span></span><br /><span class='line' id='L324'><a href='#L324' class='lineno'>324 </a><span class='linecont'>         (loop for subtree in children do</span></span><br /><span class='line' id='L325'><a href='#L325' class='lineno'>325 </a><span class='linecont'>              (recurse subtree pathspec))))</span></span><br /><span class='line' id='L326'><a href='#L326' class='lineno'>326 </a><span class='linecont'>    (t (error &quot;Not a tree.&quot;)))))</span></span><br /><span class='line' id='L327'><a href='#L327' class='lineno'>327 </a><span class='linecont'>    (recurse (tcp-info-tree tcp-info) #p&quot;/&quot;)))</span></span><br /></pre></body></html>
\ No newline at end of file
diff --git a/uploads/2019/07/cl-who-demo/c-prelude.lisp.html b/uploads/2019/07/cl-who-demo/c-prelude.lisp.html
new file mode 100644 (file)
index 0000000..9835f88
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html><head><title>prelude.lisp</title><style type='text/css'>
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}</style></head><body><b>prelude.lisp</b><pre class='coadblock'><span class='line' id='L1'><a href='#L1' class='lineno'> 1 </a><span class='linecont'>;; CL-WHO demo, a prelude</span></span><br /><span class='line' id='L2'><a href='#L2' class='lineno'> 2 </a><span class='linecont'>(require &#039;asdf)</span></span><br /><span class='line' id='L3'><a href='#L3' class='lineno'> 3 </a><span class='linecont'></span></span><br /><span class='line' id='L4'><a href='#L4' class='lineno'> 4 </a><span class='linecont'>;; Change this to whatever helps you import CL-WHO.</span></span><br /><span class='line' id='L5'><a href='#L5' class='lineno'> 5 </a><span class='linecont'>(defvar *stolen* &quot;/home/stolen/&quot;)</span></span><br /><span class='line' id='L6'><a href='#L6' class='lineno'> 6 </a><span class='linecont'>(pushnew (concatenate &#039;string</span></span><br /><span class='line' id='L7'><a href='#L7' class='lineno'> 7 </a><span class='linecont'>                *stolen* &quot;cl-who/&quot;)</span></span><br /><span class='line' id='L8'><a href='#L8' class='lineno'> 8 </a><span class='linecont'>    asdf:*central-registry*</span></span><br /><span class='line' id='L9'><a href='#L9' class='lineno'> 9 </a><span class='linecont'>       :test #&#039;string=)</span></span><br /><span class='line' id='L10'><a href='#L10' class='lineno'>10 </a><span class='linecont'>(asdf:load-system :cl-who)</span></span><br /><span class='line' id='L11'><a href='#L11' class='lineno'>11 </a><span class='linecont'></span></span><br /><span class='line' id='L12'><a href='#L12' class='lineno'>12 </a><span class='linecont'>;; Below goes whatever example code you may wish to test:</span></span><br /></pre></body></html>
\ No newline at end of file
diff --git a/uploads/2019/07/cl-who-demo/demo-dir/c-placeholder.html b/uploads/2019/07/cl-who-demo/demo-dir/c-placeholder.html
new file mode 100644 (file)
index 0000000..6cf8936
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html><head><title>placeholder</title><style type='text/css'>
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}</style></head><body><b>placeholder</b><pre class='coadblock'><span class='line' id='L1'><a href='#L1' class='lineno'>1 </a><span class='linecont'>this is where we put files in a subdirectory.</span></span><br /></pre></body></html>
\ No newline at end of file
diff --git a/uploads/2019/07/cl-who-demo/demo-dir/index.html b/uploads/2019/07/cl-who-demo/demo-dir/index.html
new file mode 100644 (file)
index 0000000..c050678
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html><head><title>Index for /demo-dir/:</title><style type='text/css'>
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}</style></head><body><b>Index for /demo-dir/:</b><pre class='coadblock'><em>[d] </em><a class='dirlink' href='/uploads/2019/07/cl-who-demo/demo-dir/'>.</a><br /><em>[d] </em><a class='dirlink' href='/uploads/2019/07/cl-who-demo/'>..</a><br /><em>[f] </em><a class='filelink' href='/uploads/2019/07/cl-who-demo/demo-dir/c-placeholder.html'>placeholder</a><br /></pre></body></html>
\ No newline at end of file
diff --git a/uploads/2019/07/cl-who-demo/index.html b/uploads/2019/07/cl-who-demo/index.html
new file mode 100644 (file)
index 0000000..f7bc3d0
--- /dev/null
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html><head><title>Index for /:</title><style type='text/css'>
+.coadblock {background-color:#e8e8e8;
+            border-style:solid;border-width:1px;padding-left:5px;}
+.line {float:left; width:100%;}
+.lineno {font-weight:bold;text-decoration:none;color:black;}
+.lineno:visited {color:black;}
+:target {background-color:lightyellow;}</style></head><body><b>Index for /:</b><pre class='coadblock'><em>[d] </em><a class='dirlink' href='/uploads/2019/07/cl-who-demo/'>.</a><br /><em>[d] </em><a class='dirlink' href='/uploads/2019/07/cl-who-demo/'>..</a><br /><em>[d] </em><a class='dirlink' href='/uploads/2019/07/cl-who-demo/demo-dir/'>demo-dir</a><br /><em>[f] </em><a class='filelink' href='/uploads/2019/07/cl-who-demo/c-demo.lisp.html'>demo.lisp</a><br /><em>[f] </em><a class='filelink' href='/uploads/2019/07/cl-who-demo/c-prelude.lisp.html'>prelude.lisp</a><br /></pre></body></html>
\ No newline at end of file