Browse files

removed use of database and elephant. filesystem only now.

  • Loading branch information...
1 parent f8e5305 commit 6ad43cfb66bcf61b2d7ee9469e8bbf89ebfd428d @hugoduncan committed Feb 19, 2010
View
2 cl-blog-generator.asd
@@ -13,7 +13,7 @@
:maintainer "Hugo Duncan <hugo@hugoduncan.org>"
:licence "BSD Open Source"
:description "A generator for blog sites."
- :depends-on (:cxml :cl-fad :elephant :local-time :flexi-streams :mel-base :cl-ppcre :babel)
+ :depends-on (:cxml :cl-fad :local-time :flexi-streams :mel-base :cl-ppcre :babel)
:components
((:module "src"
:components
View
12 content/published/post/2010/the_database_has_gone.post
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://hugoduncan.org/xmlns/post">
+<head>
+ <title>The database has gone!</title>
+ <tag>lisp</tag>
+ <tag>blog</tag>
+ <tag>cl-blog-generator</tag>
+<when day="19" month="2" year="2010"/><linkname>the_database_has_gone</linkname><template>post</template><meta name="description" content="I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required."/></head>
+<body>
+<p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</body>
+</html>
View
23 content/site/index.atom
@@ -9,9 +9,10 @@
<author><name>Hugo Duncan</name></author>
<subtitle>Development Blog</subtitle>
<rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
- <updated>2009-03-31T00:43:21.776272-04:00</updated>
+ <updated>2010-02-19T22:51:32.538602-05:00</updated>
-<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>The database has gone!</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
<p>The comment system was inspired by <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address. Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client. The comment emails are then processed in CL using <a href="http://common-lisp.net/project/mel-base/">mel-base</a> and written to the local filesystem. Moderation can optionally occur on the CL side, if that is preferable to using the email client.</p>
@@ -65,6 +66,15 @@ However, having <a href="http://common-lisp.net/project/elephant/">Elephant</a>
<li> <code>Chronicle</code> has a spooler for posting pre-written content at specific times</li>
</ul>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Design</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p>
+
+<p>The blog site is generated from file based posts, using an augmented version of xhtml as the input format. The input format has a DTD, as well as a Relax NG compressed schema generated using <a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a> which is used in the provided schemas.xml file to allow validation in Emacs <a href="http://www.thaiopensource.com/nxml-mode/">nXML mode</a>.</p>
+
+<p>When ready, the drafts are merged into a post template, in standard xhtml, to produce a site that can be rsync'd to a web host. The merging of the templates is done using <a href="http://www.sbcl.org/">SBCL</a> and <a href="http://common-lisp.net/project/cxml/">CXML</a>. The generator maintains a database of posts, so that it can generate the index page, etc, and uses <a href="http://common-lisp.net/project/elephant/">Elephant</a>. The whole site can be re-generated from the input post files, so a revision control system, such as git, can be used to manage the posts, and we don't have to worry about backing up the the database too frequently.</p>
+
+<p>An Emacs minor-mode can be used to trigger the publishing and site generation.</p>
+
+<p>The generator is intended to produce a personol blog, with one user. I am however misusing it here to provide a sort of update blog for the software itself.</p>
</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Configuration</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p>
<h2>Prerequisites</h2>
@@ -91,13 +101,4 @@ However, having <a href="http://common-lisp.net/project/elephant/">Elephant</a>
</ul>
<p>For the Atom feed, the <code>updated</code> element is filled out correctly, and the posts are automatically inserted, ie. there are no special id's.</p>
-</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Design</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p>
-
-<p>The blog site is generated from file based posts, using an augmented version of xhtml as the input format. The input format has a DTD, as well as a Relax NG compressed schema generated using <a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a> which is used in the provided schemas.xml file to allow validation in Emacs <a href="http://www.thaiopensource.com/nxml-mode/">nXML mode</a>.</p>
-
-<p>When ready, the drafts are merged into a post template, in standard xhtml, to produce a site that can be rsync'd to a web host. The merging of the templates is done using <a href="http://www.sbcl.org/">SBCL</a> and <a href="http://common-lisp.net/project/cxml/">CXML</a>. The generator maintains a database of posts, so that it can generate the index page, etc, and uses <a href="http://common-lisp.net/project/elephant/">Elephant</a>. The whole site can be re-generated from the input post files, so a revision control system, such as git, can be used to manage the posts, and we don't have to worry about backing up the the database too frequently.</p>
-
-<p>An Emacs minor-mode can be used to trigger the publishing and site generation.</p>
-
-<p>The generator is intended to produce a personol blog, with one user. I am however misusing it here to provide a sort of update blog for the software itself.</p>
</div></content></entry></feed>
View
17 content/site/index.xhtml
@@ -15,25 +15,30 @@
<div id="centercontent">
<div class="posts">
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml">The database has gone!</a></span> ·
+ <span class="post-synopsis"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></span>
+ </div>
+
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
<span class="post-synopsis"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
<span class="post-synopsis"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="post/2009/blog_generator_configuration.xhtml">Blog Generator Configuration</a></span> ·
- <span class="post-synopsis"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></span>
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
+ <span class="post-synopsis"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
- <span class="post-synopsis"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></span>
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml">Blog Generator Configuration</a></span> ·
+ <span class="post-synopsis"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></span>
</div>
</div>
</div>
View
2 content/site/post/2009/blog_generator_configuration.xhtml
@@ -5,7 +5,7 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
-<title>cl-blog-generator : Blog Generator Configuration</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml" title="Blog Generator Design"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml" title="Blog Site Generators"/><meta name="description" content="The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation."/><meta name="keywords" content="lisp"/>
+<title>cl-blog-generator : Blog Generator Configuration</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml" title="Blog Generator Design"/><meta name="description" content="The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation."/><meta name="keywords" content="lisp"/>
</head>
<body>
<div id="container">
View
2 content/site/post/2009/blog_generator_design.xhtml
@@ -5,7 +5,7 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
-<title>cl-blog-generator : Blog Generator Design</title><link rel="next" href="/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml" title="Blog Generator Configuration"/><meta name="description" content="I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own."/><meta name="keywords" content="generator,blog,lisp"/>
+<title>cl-blog-generator : Blog Generator Design</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml" title="Blog Site Generators"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml" title="Blog Generator Configuration"/><meta name="description" content="I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own."/><meta name="keywords" content="generator,blog,lisp"/>
</head>
<body>
<div id="container">
View
2 content/site/post/2009/blog_site_generators.xhtml
@@ -5,7 +5,7 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
-<title>cl-blog-generator : Blog Site Generators</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml" title="Blog Generator Configuration"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml" title="cl-blog-generator Gets Comments"/><meta name="description" content="&#10;I recently uploaded some links to my cl-blog-generator project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as Steve Kemp's Chronicle, or Jekyll as used on GitHub Pages. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that Charles Stewart suggested might be worth exploring. I look forward to any comments you might have.&#10;"/><meta name="keywords" content="cl-blog-generator,lisp,blog"/>
+<title>cl-blog-generator : Blog Site Generators</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml" title="cl-blog-generator Gets Comments"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml" title="Blog Generator Design"/><meta name="description" content="&#10;I recently uploaded some links to my cl-blog-generator project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as Steve Kemp's Chronicle, or Jekyll as used on GitHub Pages. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that Charles Stewart suggested might be worth exploring. I look forward to any comments you might have.&#10;"/><meta name="keywords" content="cl-blog-generator,lisp,blog"/>
</head>
<body>
<div id="container">
View
2 content/site/post/2009/cl_blog_generator_gets_comments.xhtml
@@ -5,7 +5,7 @@
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
-<title>cl-blog-generator : cl-blog-generator Gets Comments</title><link rel="prev" href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml" title="Blog Site Generators"/><meta name="description" content="I have now added a comment system to cl-blog-generator. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated."/><meta name="keywords" content="advogato,cl-blog-generator,lisp"/>
+<title>cl-blog-generator : cl-blog-generator Gets Comments</title><link rel="prev" href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml" title="The database has gone!"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml" title="Blog Site Generators"/><meta name="description" content="I have now added a comment system to cl-blog-generator. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated."/><meta name="keywords" content="advogato,cl-blog-generator,lisp"/>
</head>
<body>
<div id="container">
View
54 content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
+<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
+<title>cl-blog-generator : Benchmarking Clojure Code with Criterium</title><link rel="prev" href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml" title="The database has gone!"/><link rel="next" href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml" title="cl-blog-generator Gets Comments"/><meta name="description" content="I have released Criterium, a new project for benchmarking code in Clojure. I found Brent Broyer's article on Java benchmarking which explains many of the pitfalls of benchmarking on the JVM, and Criterion, a benchmarking library in Haskell."/><meta name="keywords" content="jvm,criterium,benchmarking,benchmark,clojure"/>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1><span id="post-title">Benchmarking Clojure Code with Criterium</span></h1></div>
+<div id="centercontent">
+<div id="post"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="../../index.xhtml" id="to-home"><span id="home">home</span></a></div>
+ <a href="" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+<div id="post-data">
+<hr/>
+<div id="post-title">Benchmarking Clojure Code with Criterium</div>
+<div>Written: <span id="post-when">19-2-2010</span></div>
+<div><span id="post-updated"/></div>
+Tags: <div id="post-tags">
+<ul class="post-tags">
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/jvm.xhtml">jvm</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/criterium.xhtml">criterium</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/benchmarking.xhtml">benchmarking</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/benchmark.xhtml">benchmark</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/clojure.xhtml">clojure</a></li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+</div>
+</body>
+</html>
View
46 content/site/post/2010/the_database_has_gone.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="../../style.css" title="sans" media="screen" type="text/css" rel="stylesheet"/>
+<link href="../../feed.atom" title="Atom (full content)" type="application/atom+xml" rel="alternate"/>
+<title>cl-blog-generator : The database has gone!</title><link rel="next" href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml" title="cl-blog-generator Gets Comments"/><meta name="description" content="I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required."/><meta name="keywords" content="cl-blog-generator,blog,lisp"/>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1><span id="post-title">The database has gone!</span></h1></div>
+<div id="centercontent">
+<div id="post"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="../../index.xhtml" id="to-home"><span id="home">home</span></a></div>
+ <a href="" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+<div id="post-data">
+<hr/>
+<div id="post-title">The database has gone!</div>
+<div>Written: <span id="post-when">19-2-2010</span></div>
+<div><span id="post-updated"/></div>
+Tags: <div id="post-tags">
+<ul class="post-tags">
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/clbloggenerator.xhtml">cl-blog-generator</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/blog.xhtml">blog</a></li>
+
+ <li class="post-tag"><a href="/cl-blog-generator/content/site/tag/lisp.xhtml">lisp</a></li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+</div>
+</body>
+</html>
View
19 content/site/tag/benchmark.atom
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
+ <title>cl-blog-generatorcl-blog-generator Development Blog : benchmark</title>
+ <id>http://hugoduncan.github.com/cl-blog-generator/http://hugoduncan.github.com/cl-blog-generator/content/site/tag/benchmark.xhtml</id>
+ <link href="./"/>
+ <link href="" rel="self"/>
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <author><name>Hugo Duncan</name></author>
+ <subtitle>Development Blog</subtitle>
+ <rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
+ <updated>2010-02-19T16:15:05.977883-05:00</updated>
+
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Benchmarking Clojure Code with Criterium</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="jvm"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="criterium"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmarking"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmark"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="clojure"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div></content></entry></feed>
View
39 content/site/tag/benchmark.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="style.css" title="style" media="screen" type="text/css" rel="stylesheet"/>
+<meta content="lisp,blog" name="keywords"/>
+<meta content="Development blog for lisp based blog site generator" name="description"/>
+<link rel="alternate" type="application/atom+xml" title="Atom (full content)" href="/cl-blog-generator/content/site/tag/benchmark.atom"/>
+<title>cl-blog-generator: benchmark</title>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1>cl-blog-generator :</h1></div>
+<div id="centercontent">
+<div class="posts">
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml">Benchmarking Clojure Code with Criterium</a></span> ·
+ <span class="post-synopsis"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></span>
+ </div>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="/" id="to-home"><span id="home">home</span></a></div>
+ <a href="http://github.com/hugoduncan/cl-blog-generator/" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+</div>
+<hr/>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clojure.xhtml">clojure</a></li><li><a href="/cl-blog-generator/content/site/tag/jvm.xhtml">jvm</a></li><li><a href="/cl-blog-generator/content/site/tag/criterium.xhtml">criterium</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmarking.xhtml">benchmarking</a></li></ul></div>
+</div>
+</div>
+</body>
+</html>
View
19 content/site/tag/benchmarking.atom
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
+ <title>cl-blog-generatorcl-blog-generator Development Blog : benchmarking</title>
+ <id>http://hugoduncan.github.com/cl-blog-generator/http://hugoduncan.github.com/cl-blog-generator/content/site/tag/benchmarking.xhtml</id>
+ <link href="./"/>
+ <link href="" rel="self"/>
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <author><name>Hugo Duncan</name></author>
+ <subtitle>Development Blog</subtitle>
+ <rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
+ <updated>2010-02-19T16:15:05.992179-05:00</updated>
+
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Benchmarking Clojure Code with Criterium</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="jvm"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="criterium"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmarking"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmark"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="clojure"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div></content></entry></feed>
View
39 content/site/tag/benchmarking.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="style.css" title="style" media="screen" type="text/css" rel="stylesheet"/>
+<meta content="lisp,blog" name="keywords"/>
+<meta content="Development blog for lisp based blog site generator" name="description"/>
+<link rel="alternate" type="application/atom+xml" title="Atom (full content)" href="/cl-blog-generator/content/site/tag/benchmarking.atom"/>
+<title>cl-blog-generator: benchmarking</title>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1>cl-blog-generator :</h1></div>
+<div id="centercontent">
+<div class="posts">
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml">Benchmarking Clojure Code with Criterium</a></span> ·
+ <span class="post-synopsis"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></span>
+ </div>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="/" id="to-home"><span id="home">home</span></a></div>
+ <a href="http://github.com/hugoduncan/cl-blog-generator/" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+</div>
+<hr/>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clojure.xhtml">clojure</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmark.xhtml">benchmark</a></li><li><a href="/cl-blog-generator/content/site/tag/jvm.xhtml">jvm</a></li><li><a href="/cl-blog-generator/content/site/tag/criterium.xhtml">criterium</a></li></ul></div>
+</div>
+</div>
+</body>
+</html>
View
5 content/site/tag/blog.atom
@@ -9,9 +9,10 @@
<author><name>Hugo Duncan</name></author>
<subtitle>Development Blog</subtitle>
<rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
- <updated>2009-03-31T00:43:22.027729-04:00</updated>
+ <updated>2010-02-19T22:50:54.463907-05:00</updated>
-<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Site Generators</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml</id><published>2009-03-26T20:00:00.000000-04:00</published><updated>2009-03-26T20:00:00.000000-04:00</updated><published>2009-03-26T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>The database has gone!</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Site Generators</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml</id><published>2009-03-26T20:00:00.000000-04:00</published><updated>2009-03-26T20:00:00.000000-04:00</updated><published>2009-03-26T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
View
11 content/site/tag/blog.xhtml
@@ -15,14 +15,19 @@
<div id="centercontent">
<div class="posts">
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml">The database has gone!</a></span> ·
+ <span class="post-synopsis"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></span>
+ </div>
+
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
<span class="post-synopsis"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
<span class="post-synopsis"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></span>
</div>
</div>
@@ -39,7 +44,7 @@ I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-bl
</a></div>
</div>
<hr/>
-Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/advogato.xhtml">advogato</a></li><li><a href="/cl-blog-generator/content/site/tag/clbloggenerator.xhtml">cl-blog-generator</a></li><li><a href="/cl-blog-generator/content/site/tag/generator.xhtml">generator</a></li><li><a href="/cl-blog-generator/content/site/tag/lisp.xhtml">lisp</a></li></ul></div>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clbloggenerator.xhtml">cl-blog-generator</a></li><li><a href="/cl-blog-generator/content/site/tag/lisp.xhtml">lisp</a></li></ul></div>
</div>
</div>
</body>
View
5 content/site/tag/clbloggenerator.atom
@@ -9,9 +9,10 @@
<author><name>Hugo Duncan</name></author>
<subtitle>Development Blog</subtitle>
<rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
- <updated>2009-03-31T00:43:21.859845-04:00</updated>
+ <updated>2010-02-19T22:50:54.477837-05:00</updated>
-<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>The database has gone!</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
<p>The comment system was inspired by <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address. Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client. The comment emails are then processed in CL using <a href="http://common-lisp.net/project/mel-base/">mel-base</a> and written to the local filesystem. Moderation can optionally occur on the CL side, if that is preferable to using the email client.</p>
View
11 content/site/tag/clbloggenerator.xhtml
@@ -15,12 +15,17 @@
<div id="centercontent">
<div class="posts">
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml">The database has gone!</a></span> ·
+ <span class="post-synopsis"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></span>
+ </div>
+
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
<span class="post-synopsis"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
<span class="post-synopsis"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
</p></span>
@@ -39,7 +44,7 @@ I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-bl
</a></div>
</div>
<hr/>
-Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/advogato.xhtml">advogato</a></li><li><a href="/cl-blog-generator/content/site/tag/blog.xhtml">blog</a></li><li><a href="/cl-blog-generator/content/site/tag/generator.xhtml">generator</a></li><li><a href="/cl-blog-generator/content/site/tag/lisp.xhtml">lisp</a></li></ul></div>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/blog.xhtml">blog</a></li><li><a href="/cl-blog-generator/content/site/tag/lisp.xhtml">lisp</a></li></ul></div>
</div>
</div>
</body>
View
19 content/site/tag/clojure.atom
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
+ <title>cl-blog-generatorcl-blog-generator Development Blog : clojure</title>
+ <id>http://hugoduncan.github.com/cl-blog-generator/http://hugoduncan.github.com/cl-blog-generator/content/site/tag/clojure.xhtml</id>
+ <link href="./"/>
+ <link href="" rel="self"/>
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <author><name>Hugo Duncan</name></author>
+ <subtitle>Development Blog</subtitle>
+ <rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
+ <updated>2010-02-19T16:15:05.968153-05:00</updated>
+
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Benchmarking Clojure Code with Criterium</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="jvm"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="criterium"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmarking"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmark"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="clojure"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div></content></entry></feed>
View
39 content/site/tag/clojure.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="style.css" title="style" media="screen" type="text/css" rel="stylesheet"/>
+<meta content="lisp,blog" name="keywords"/>
+<meta content="Development blog for lisp based blog site generator" name="description"/>
+<link rel="alternate" type="application/atom+xml" title="Atom (full content)" href="/cl-blog-generator/content/site/tag/clojure.atom"/>
+<title>cl-blog-generator: clojure</title>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1>cl-blog-generator :</h1></div>
+<div id="centercontent">
+<div class="posts">
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml">Benchmarking Clojure Code with Criterium</a></span> ·
+ <span class="post-synopsis"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></span>
+ </div>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="/" id="to-home"><span id="home">home</span></a></div>
+ <a href="http://github.com/hugoduncan/cl-blog-generator/" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+</div>
+<hr/>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/jvm.xhtml">jvm</a></li><li><a href="/cl-blog-generator/content/site/tag/criterium.xhtml">criterium</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmarking.xhtml">benchmarking</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmark.xhtml">benchmark</a></li></ul></div>
+</div>
+</div>
+</body>
+</html>
View
19 content/site/tag/criterium.atom
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
+ <title>cl-blog-generatorcl-blog-generator Development Blog : criterium</title>
+ <id>http://hugoduncan.github.com/cl-blog-generator/http://hugoduncan.github.com/cl-blog-generator/content/site/tag/criterium.xhtml</id>
+ <link href="./"/>
+ <link href="" rel="self"/>
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <author><name>Hugo Duncan</name></author>
+ <subtitle>Development Blog</subtitle>
+ <rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
+ <updated>2010-02-19T16:15:06.013943-05:00</updated>
+
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Benchmarking Clojure Code with Criterium</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="jvm"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="criterium"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmarking"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmark"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="clojure"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div></content></entry></feed>
View
39 content/site/tag/criterium.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="style.css" title="style" media="screen" type="text/css" rel="stylesheet"/>
+<meta content="lisp,blog" name="keywords"/>
+<meta content="Development blog for lisp based blog site generator" name="description"/>
+<link rel="alternate" type="application/atom+xml" title="Atom (full content)" href="/cl-blog-generator/content/site/tag/criterium.atom"/>
+<title>cl-blog-generator: criterium</title>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1>cl-blog-generator :</h1></div>
+<div id="centercontent">
+<div class="posts">
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml">Benchmarking Clojure Code with Criterium</a></span> ·
+ <span class="post-synopsis"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></span>
+ </div>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="/" id="to-home"><span id="home">home</span></a></div>
+ <a href="http://github.com/hugoduncan/cl-blog-generator/" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+</div>
+<hr/>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clojure.xhtml">clojure</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmark.xhtml">benchmark</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmarking.xhtml">benchmarking</a></li><li><a href="/cl-blog-generator/content/site/tag/jvm.xhtml">jvm</a></li></ul></div>
+</div>
+</div>
+</body>
+</html>
View
19 content/site/tag/jvm.atom
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-us" xmlns="http://www.w3.org/2005/Atom">
+ <title>cl-blog-generatorcl-blog-generator Development Blog : jvm</title>
+ <id>http://hugoduncan.github.com/cl-blog-generator/http://hugoduncan.github.com/cl-blog-generator/content/site/tag/jvm.xhtml</id>
+ <link href="./"/>
+ <link href="" rel="self"/>
+ <logo>rsslogo.jpg</logo>
+ <icon>/favicon.ico</icon>
+ <author><name>Hugo Duncan</name></author>
+ <subtitle>Development Blog</subtitle>
+ <rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
+ <updated>2010-02-19T16:15:06.021275-05:00</updated>
+
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Benchmarking Clojure Code with Criterium</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="jvm"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="criterium"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmarking"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="benchmark"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="clojure"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p>
+
+<p>The main issues with benchmarking on the JVM are associated with garbage collection, and with JIT compilation. It seems from Broyer's articles that we can mitigate the effects but not completely eliminate them, and Criterium follows his advice. Both of the above libraries use the <a href="http://en.wikipedia.org/wiki/Bootstrapping_(statistics)">bootstrap</a> technique to estimate mean execution time and provide a confidence interval, and Criterium does likewise. At the moment the confidence intervals are biased and I still need to implement BCa or ABC to improve these.</p>
+
+<p>One of the functions that I wanted to benchmark originally involved reading a file. Criterium does not yet address clearing I/O buffer cache, and I am not sure on the best way forward on this. On Mac OS X, the <code>purge</code> command can be used to clear the caches, and on Linux this can be achieved by writing to /proc/sys/vm/drop_caches. On the Mac at least, this causes everything to grind to halt for about five seconds, and there are then some file reads as whatever processes are running read things in again. This sort of behaviour doesn't lend itself to inclusion in a timing loop... Any suggestions?</p>
+</div></content></entry></feed>
View
39 content/site/tag/jvm.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+<link href="style.css" title="style" media="screen" type="text/css" rel="stylesheet"/>
+<meta content="lisp,blog" name="keywords"/>
+<meta content="Development blog for lisp based blog site generator" name="description"/>
+<link rel="alternate" type="application/atom+xml" title="Atom (full content)" href="/cl-blog-generator/content/site/tag/jvm.atom"/>
+<title>cl-blog-generator: jvm</title>
+</head>
+<body>
+<div id="container">
+<div id="banner"><h1>cl-blog-generator :</h1></div>
+<div id="centercontent">
+<div class="posts">
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/benchmarking_clojure_code_with_criterium.xhtml">Benchmarking Clojure Code with Criterium</a></span> ·
+ <span class="post-synopsis"><p>I have released <a href="http://github.com/hugoduncan/criterium">Criterium</a>, a new project for benchmarking code in <a href="http://clojure.org">Clojure</a>. I found Brent Broyer's <a href="http://www.ibm.com/developerworks/java/library/j-benchmark1.html">article on Java benchmarking</a> which explains many of the pitfalls of benchmarking on the JVM, and <a href="http://www.serpentine.com/blog/2009/09/29/criterion-a-new-benchmarking-library-for-haskell">Criterion</a>, a benchmarking library in Haskell.</p></span>
+ </div>
+</div>
+</div>
+
+<div id="rightcontent">
+<div class="oo"><a href="/" id="to-home"><span id="home">home</span></a></div>
+ <a href="http://github.com/hugoduncan/cl-blog-generator/" rel="me">source</a>
+ <a href="http://hugoduncan.org" rel="me">Hugo Duncan</a>
+<div class="vcard">
+ <a href="http://hugoduncan.org/" class="fn url">Hugo Duncan</a>
+ <div><a href="mailto:blogen@hugoduncan.org" class="email">
+ <span class="type">pref</span><span>erred email</span>
+ </a></div>
+</div>
+<hr/>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clojure.xhtml">clojure</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmark.xhtml">benchmark</a></li><li><a href="/cl-blog-generator/content/site/tag/benchmarking.xhtml">benchmarking</a></li><li><a href="/cl-blog-generator/content/site/tag/criterium.xhtml">criterium</a></li></ul></div>
+</div>
+</div>
+</body>
+</html>
View
23 content/site/tag/lisp.atom
@@ -9,9 +9,10 @@
<author><name>Hugo Duncan</name></author>
<subtitle>Development Blog</subtitle>
<rights>All content written by Hugo Duncan and photos by Hugo Duncan Copyright Hugo Duncan, all rights reserved.</rights>
- <updated>2009-03-31T00:43:21.924992-04:00</updated>
+ <updated>2010-02-19T22:50:54.445056-05:00</updated>
-<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
+<entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>The database has gone!</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml</id><published>2010-02-18T19:00:00.000000-05:00</published><updated>2010-02-18T19:00:00.000000-05:00</updated><published>2010-02-18T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>cl-blog-generator Gets Comments</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml</id><published>2009-03-30T20:00:00.000000-04:00</published><updated>2009-03-30T20:00:00.000000-04:00</updated><published>2009-03-30T20:00:00.000000-04:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="advogato"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="cl-blog-generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p>
<p>The comment system was inspired by <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>'s, with a slight modification in approach - the comments are never saved on the web server, and are just sent by email to a dedicated email address. Spam filtering is delegated to the whatever spam filtering is implemented on the mail server, or in your email client. The comment emails are then processed in CL using <a href="http://common-lisp.net/project/mel-base/">mel-base</a> and written to the local filesystem. Moderation can optionally occur on the CL side, if that is preferable to using the email client.</p>
@@ -65,6 +66,15 @@ However, having <a href="http://common-lisp.net/project/elephant/">Elephant</a>
<li> <code>Chronicle</code> has a spooler for posting pre-written content at specific times</li>
</ul>
+</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Design</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p>
+
+<p>The blog site is generated from file based posts, using an augmented version of xhtml as the input format. The input format has a DTD, as well as a Relax NG compressed schema generated using <a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a> which is used in the provided schemas.xml file to allow validation in Emacs <a href="http://www.thaiopensource.com/nxml-mode/">nXML mode</a>.</p>
+
+<p>When ready, the drafts are merged into a post template, in standard xhtml, to produce a site that can be rsync'd to a web host. The merging of the templates is done using <a href="http://www.sbcl.org/">SBCL</a> and <a href="http://common-lisp.net/project/cxml/">CXML</a>. The generator maintains a database of posts, so that it can generate the index page, etc, and uses <a href="http://common-lisp.net/project/elephant/">Elephant</a>. The whole site can be re-generated from the input post files, so a revision control system, such as git, can be used to manage the posts, and we don't have to worry about backing up the the database too frequently.</p>
+
+<p>An Emacs minor-mode can be used to trigger the publishing and site generation.</p>
+
+<p>The generator is intended to produce a personol blog, with one user. I am however misusing it here to provide a sort of update blog for the software itself.</p>
</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Configuration</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p>
<h2>Prerequisites</h2>
@@ -91,13 +101,4 @@ However, having <a href="http://common-lisp.net/project/elephant/">Elephant</a>
</ul>
<p>For the Atom feed, the <code>updated</code> element is filled out correctly, and the posts are automatically inserted, ie. there are no special id's.</p>
-</div></content></entry><entry xml:base="http://hugoduncan.github.com/cl-blog-generator/content/site/"><title>Blog Generator Design</title><link href="http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml"/><id>http://hugoduncan.github.com/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml</id><published>2009-03-03T19:00:00.000000-05:00</published><updated>2009-03-03T19:00:00.000000-05:00</updated><published>2009-03-03T19:00:00.000000-05:00</published><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="generator"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="blog"/><category scheme="http://hugoduncan.github.com/cl-blog-generator/content/site/tags" term="lisp"/><summary type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></div></summary><content type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p>
-
-<p>The blog site is generated from file based posts, using an augmented version of xhtml as the input format. The input format has a DTD, as well as a Relax NG compressed schema generated using <a href="http://www.thaiopensource.com/relaxng/trang.html">Trang</a> which is used in the provided schemas.xml file to allow validation in Emacs <a href="http://www.thaiopensource.com/nxml-mode/">nXML mode</a>.</p>
-
-<p>When ready, the drafts are merged into a post template, in standard xhtml, to produce a site that can be rsync'd to a web host. The merging of the templates is done using <a href="http://www.sbcl.org/">SBCL</a> and <a href="http://common-lisp.net/project/cxml/">CXML</a>. The generator maintains a database of posts, so that it can generate the index page, etc, and uses <a href="http://common-lisp.net/project/elephant/">Elephant</a>. The whole site can be re-generated from the input post files, so a revision control system, such as git, can be used to manage the posts, and we don't have to worry about backing up the the database too frequently.</p>
-
-<p>An Emacs minor-mode can be used to trigger the publishing and site generation.</p>
-
-<p>The generator is intended to produce a personol blog, with one user. I am however misusing it here to provide a sort of update blog for the software itself.</p>
</div></content></entry></feed>
View
19 content/site/tag/lisp.xhtml
@@ -15,25 +15,30 @@
<div id="centercontent">
<div class="posts">
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2010/the_database_has_gone.xhtml">The database has gone!</a></span> ·
+ <span class="post-synopsis"><p>I removed all dependencies on a database. No more elephant. I was updating versions of lisp, elephant, etc, and got fed up of juggling clbuild, uffi, cffi, and elephant. Anyway cl-blog-generator is much easier to use now, and is completely filesystem based. I had always designed the database to be redundant. Now it is. Any existing blog should continue to just work, no migration required.</p></span>
+ </div>
+
+ <div class="post-link-with-synopsis">
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/cl_blog_generator_gets_comments.xhtml">cl-blog-generator Gets Comments</a></span> ·
<span class="post-synopsis"><p>I have now added a comment system to <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a>. My requirements were for a simple, low overhead, commenting system, preferable one that could possibly be fully automated.</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_site_generators.xhtml">Blog Site Generators</a></span> ·
<span class="post-synopsis"><p>
I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-blog-generator">cl-blog-generator</a> project, and have been getting some feedback with comparisons to other blog site generators, or compilers, such as <a href="http://www.advogato.org/person/Stevey/">Steve Kemp</a>'s <a href="http://www.steve.org.uk/Software/chronicle/">Chronicle</a>, or <a href="http://github.com/mojombo/jekyll">Jekyll</a> as used on <a href="http://github.com/blog/272-github-pages">GitHub Pages</a>. Compared to these, cl-blog-generator is immature, but takes a different approach in several areas that <a href="http://advogato.org/person/chalst/">Charles Stewart</a> suggested might be worth exploring. I look forward to any comments you might have.
</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_generator_configuration.xhtml">Blog Generator Configuration</a></span> ·
- <span class="post-synopsis"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></span>
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
+ <span class="post-synopsis"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></span>
</div>
<div class="post-link-with-synopsis">
- <span class="post-link"><a href="/Users/duncan/projects/blog/content/site/post/2009/blog_generator_design.xhtml">Blog Generator Design</a></span> ·
- <span class="post-synopsis"><p>I want to be able publish posts easily to a statically served site. I am sure that there are lots of blog site generators out there, but I could not find one that I liked, and which was in a language I would enjoy hacking, and so I wrote my own.</p></span>
+ <span class="post-link"><a href="/cl-blog-generator/content/site/post/2009/blog_generator_configuration.xhtml">Blog Generator Configuration</a></span> ·
+ <span class="post-synopsis"><p>The blog generator is intended to be quite flexible, within the design constraints, which has lead to a large number of possible configurations, both on the lisp side, and for Emacs. Drafts can be written using any editor, but I shall describe use with Emacs. The package has only been tested with SBCL, but should work with any common lisp implentation.</p></span>
</div>
</div>
</div>
@@ -49,7 +54,7 @@ I recently uploaded some links to my <a href="http://github.com/hugoduncan/cl-bl
</a></div>
</div>
<hr/>
-Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/advogato.xhtml">advogato</a></li><li><a href="/cl-blog-generator/content/site/tag/blog.xhtml">blog</a></li><li><a href="/cl-blog-generator/content/site/tag/clbloggenerator.xhtml">cl-blog-generator</a></li><li><a href="/cl-blog-generator/content/site/tag/generator.xhtml">generator</a></li></ul></div>
+Related Tags: <div class="tags-related"><ul><li><a href="/cl-blog-generator/content/site/tag/clbloggenerator.xhtml">cl-blog-generator</a></li><li><a href="/cl-blog-generator/content/site/tag/blog.xhtml">blog</a></li></ul></div>
</div>
</div>
</body>
View
1 dtd/schemas.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<locatingRules xmlns="http://thaiopensource.com/ns/locating-rules/1.0">
+ <uri resource="../../artfox/src/artfox_bugfixes/app/views/profiles/edit.html.erb" typeId="XHTML"/>
<uri pattern="*.post" uri="xhtml-post.rnc"/>
<namespace ns="http://hugoduncan.org/xmlns/post" uri="xhtml-post.rnc"/>
</locatingRules>
View
3 src/comment-mail.lisp
@@ -10,8 +10,7 @@
;;; Top level moderate function
(defun moderate ()
- (with-open-store ()
- (process-mailbox)))
+ (process-mailbox))
;;;# Process Mailbox
;;; Processes all incoming comments
View
2 src/configure.lisp
@@ -26,6 +26,8 @@ environment active."
(let ((alist-cons (assoc environment *environments*)))
(unless alist-cons
(error "Request for unknown configuration environment ~A" environment))
+ (setf *blog* nil)
+ (setf *index-page* nil)
(loop for item in (cdr alist-cons)
for key = (car item)
for symbol = (symbol-for-key key)
View
1 src/package.lisp
@@ -10,6 +10,7 @@
#:*blog-db-spec*
#:*blog-domain*
#:*blog-root-path*
+ #:*comment-path*
#:*site-path*
#:*published-path*
#:*template-path*
View
1,432 src/post.lisp
@@ -16,11 +16,6 @@
;;; These are the special variables used to control the blog generator's
;;; behaviour.
-;;; Database connection specification for Elephant. See Elephant documentation
-;;; for syntax.
-(defvar *blog-db-spec* nil
- "The database connection")
-
;;; The blog's title.
(defvar *blog-title* nil
"The blog's title.")
@@ -171,23 +166,32 @@
(defparameter *rel-alternate* "alternate")
(defparameter *href* "href")
+(defparameter *comment-ip* "ip")
+(defparameter *comment-name* "name")
+(defparameter *comment-email* "email")
+(defparameter *comment-uri* "uri")
+(defparameter *comment-when* "when")
+(defparameter *comment-text* "text")
+
(defparameter *atom-mime* "application/atom+xml")
(defparameter *feed-title* "title")
(defparameter *feed-uri* "id")
(defparameter *feed-updated* "updated")
-
;;;# Helpers
-;;; We use the post title as both the file system name of the published post,
+;;; We use the post title as both the file system name of the published post
;;; and the uri in the generated site. To do this requires that we sanitise
;;; the name.
(defun %sanitise-title (title)
"Sanitise a title for use as a file system path or as a http uri"
(flet ((remove-character-p (char)
- (find char "!.,/\\|+=`~-@#$%^&*{}[]()\"':;<>")))
- (let ((sane (remove-if #'remove-character-p
- (string-downcase (substitute #\_ #\Space title)))))
+ (find char "!.,/\\|+=`~-@#$%^&*{}[]()\"':;<>")))
+ (let ((sane (remove-if
+ #'remove-character-p
+ (string-trim
+ '(#\Space #\Tab #\Newline)
+ (string-downcase (substitute #\_ #\Space title))))))
(values sane))))
(defun %sanitise-synopsis (synopsis)
@@ -196,10 +200,10 @@
(source (cxml:make-source synopsis :entity-resolver #'null-resolver))
(with-output-to-string (output)
(loop
- for (key ns lname) = (multiple-value-list (klacks:peek-next source))
- while key
- do (when (eql key :characters)
- (format output (klacks:current-characters source)))))))
+ for (key ns lname) = (multiple-value-list (klacks:peek-next source))
+ while key
+ do (when (eql key :characters)
+ (format output (klacks:current-characters source)))))))
(defun merge-assoc (a b &key (test #'eql))
"Merge association lists A and B, such that values from B take precedence."
@@ -208,8 +212,8 @@
for assoc = (assoc (car kv) a :test test)
do
(if assoc
- (setf (cdr assoc) (cdr kv))
- (setf result (acons (car kv) (cdr kv) result)))
+ (setf (cdr assoc) (cdr kv))
+ (setf result (acons (car kv) (cdr kv) result)))
finally
(return result)))
@@ -218,8 +222,8 @@
(defun %template-path (key)
"Find the path to a template for the specified KEY."
(make-pathname :name key
- :type (if (string= key "atom") "xml" "xhtml")
- :defaults *template-path*))
+ :type (if (string= key "atom") "xml" "xhtml")
+ :defaults *template-path*))
@@ -233,8 +237,8 @@
"Modified invoke-with-xml-output"
(let ((cxml::*sink* sink)
(cxml::*current-element* nil)
- (cxml::*unparse-namespace-bindings* cxml::*initial-namespace-bindings*)
- (cxml::*current-namespace-bindings* nil))
+ (cxml::*unparse-namespace-bindings* cxml::*initial-namespace-bindings*)
+ (cxml::*current-namespace-bindings* nil))
(funcall fn)))
@@ -254,6 +258,16 @@
(string= element target)
(string= ns *post-xmlns*)))
+(defun start-comment-element-p (key ns element target)
+ (declare (ignore ns))
+ (and (eql key :start-element)
+ (string= element target)))
+
+(defun end-comment-element-p (key ns element target)
+ (declare (ignore ns))
+ (and (eql key :end-element)
+ (string= element target)))
+
;;; DTD faking resolver - Had problems with using the real DTD - it output
;;; xmlns attribues on each element. http://paste.lisp.org/display/76827
(defun null-resolver (pubid sysid)
@@ -269,9 +283,9 @@ The end-element event will be consumed but not output."
for key = (klacks:peek source)
do
(when (and (eql key :end-element) (zerop (decf depth)))
- (return nil))
+ (return nil))
(when (eql key :start-element)
- (incf depth))
+ (incf depth))
(klacks:serialize-event source sink))
;; (klacks:consume source)
)
@@ -282,9 +296,9 @@ The end-element event will be consumed but not output."
for key = (klacks:peek source)
do
(when (and (eql key :end-element) (zerop (decf depth)))
- (return nil))
+ (return nil))
(when (eql key :start-element)
- (incf depth))
+ (incf depth))
(klacks:serialize-event source sink))
(klacks:serialize-event source sink))
@@ -294,9 +308,9 @@ The end-element event will be consumed but not output."
(loop with depth = 1
for key = (klacks:consume source)
do (when (and (eql key :end-element) (zerop (decf depth)))
- (return nil))
+ (return nil))
(when (eql key :end-element)
- (incf depth))))
+ (incf depth))))
(defun %skip-preamble (source)
"Skips any XML preamble before a documents first content."
@@ -308,8 +322,8 @@ The end-element event will be consumed but not output."
"Capture the attributes od the element as an a-list."
(let (attribs)
(flet ((attribute-mapper (ns lname qname attrib-value explicit-p)
- (declare (ignore ns qname explicit-p))
- (push (cons lname attrib-value) attribs)))
+ (declare (ignore ns qname explicit-p))
+ (push (cons lname attrib-value) attribs)))
(klacks:map-attributes #'attribute-mapper source)
(values attribs))))
@@ -322,7 +336,7 @@ The end-element event will be consumed but not output."
while key
do
(when (string= lname name)
- (return nil))
+ (return nil))
(klacks:consume source)))
(defun %copy-to-next-start-element (source sink lname)
@@ -332,7 +346,7 @@ to SINK. Returns the attributes of the element found."
while key
do
(when (and (eql key :start-element) (string= lname ln))
- (return (%capture-attributes source)))
+ (return (%capture-attributes source)))
(klacks:serialize-event source sink)))
(defun %skip-to-next-start-element (source lname)
@@ -341,7 +355,7 @@ to SINK. Returns the attributes of the element found."
while key
do
(when (and (eql key :start-element) (string= lname ln))
- (return key))
+ (return key))
(klacks:consume source)))
@@ -403,17 +417,29 @@ to SINK. Returns the attributes of the element found."
;;;# Database
+(defvar *blog* nil)
+
+(defun %blog-add (where instance)
+ (push instance (gethash where (%blog)))
+ (when (find where '(:posts :pages :index-page))
+ (setf (gethash where *blog*)
+ (sort (gethash where *blog*) '> :key 'content-when)))
+ (when (equal where :tag-pages)
+ (setf (gethash where *blog*)
+ (sort (gethash where *blog*) 'string> :key 'tag-page-tag))))
;;;## Generated Content Persistent Classes
;;; The various types of pages are handled by their own class. The generated
;;; content class serves as a base class for our protocol, and enables querying
;;; for all dirty content.
(defclass generated-content ()
- ((dirty :initform t :accessor dirty :type boolean :indexed t))
- (:index t)
- (:metaclass elephant:persistent-metaclass)
+ ((dirty :initform t :accessor dirty :type boolean))
(:documentation "Base for anything that can be generated."))
+(defmethod shared-initialize :after
+ ((generated-content generated-content) slot-names &key &allow-other-keys)
+ (%blog-add :all generated-content))
+
;;;### Atom feed
(defclass atom-feed ()
((title :initarg :title :accessor atom-feed-title)
@@ -423,16 +449,15 @@ to SINK. Returns the attributes of the element found."
(defmethod site-file-path-for ((atom-feed atom-feed))
(make-pathname :type "atom"
- :defaults (site-file-path-for (content-page atom-feed))))
+ :defaults (site-file-path-for (content-page atom-feed))))
(defmethod path-for ((atom-feed atom-feed))
(make-pathname :type "atom" :defaults (path-for (content-page atom-feed))))
;;;### Index page
(defclass index-page (generated-content)
- ((feed :accessor content-feed :transient t))
- (:metaclass elephant:persistent-metaclass)
+ ((feed :accessor content-feed))
(:documentation "Page for the main index."))
(defmethod site-file-path-for ((index-page index-page))
@@ -442,19 +467,21 @@ to SINK. Returns the attributes of the element found."
(defmethod path-for ((index-page index-page))
(format nil "~Aindex.xhtml" *blog-root-path*))
+(defvar *index-page* nil)
(defun index-page ()
"Obtain the singleton index page."
- (or (first (elephant:get-instances-by-class 'index-page))
- (make-instance 'index-page)))
+ (or *index-page*
+ (setf *index-page* (make-instance 'index-page))))
(defmethod shared-initialize :after
((index-page index-page) slot-names &key &allow-other-keys)
(with-slots (feed) index-page
(setf feed
- (make-instance 'atom-feed
- :title *blog-title*
- :uri (base-url)
- :content-page index-page))))
+ (make-instance 'atom-feed
+ :title *blog-title*
+ :uri (base-url)
+ :content-page index-page)))
+ (%blog-add :index-page index-page))
(defmethod content-title ((index-page index-page))
"The blog title is returned as empty in the expectation that it is specified
@@ -464,11 +491,10 @@ in the template"
;;;### Tag pages
(defclass tag-page (generated-content)
((filename :initarg :filename :reader content-filename)
- (tag :initarg :tag :initform nil :reader tag-page-tag :index t)
+ (tag :initarg :tag :initform nil :reader tag-page-tag)
(related-tags :initarg :related-tags :initform nil
- :accessor tag-page-related-tags)
- (feed :accessor content-feed :transient t))
- (:metaclass elephant:persistent-metaclass)
+ :accessor tag-page-related-tags)
+ (feed :accessor content-feed))
(:documentation "Page for content matching a tag."))
(defmethod shared-initialize :after
@@ -477,10 +503,11 @@ in the template"
(setf filename (%sanitise-title tag))
(unless (and (slot-boundp tag-page 'feed) feed)
(setf feed
- (make-instance 'atom-feed
- :title (format nil "~A : ~A" *blog-title* tag)
- :uri (url-for tag-page)
- :content-page tag-page)))))
+ (make-instance 'atom-feed
+ :title (format nil "~A : ~A" *blog-title* tag)
+ :uri (url-for tag-page)
+ :content-page tag-page))))
+ (%blog-add :tag-pages tag-page))
(defmethod relative-path-for ((tag-page tag-page))
@@ -489,16 +516,16 @@ in the template"
(defmethod path-for ((tag-page tag-page))
(format nil "~A~A~A.xhtml" *blog-root-path*
- (relative-namestring-for tag-page)
- (content-filename tag-page)))
+ (relative-namestring-for tag-page)
+ (content-filename tag-page)))
(defmethod site-file-path-for ((tag-page tag-page))
"Find the site file path for the specified TAG-PAGE."
(ensure-directories-exist
(merge-pathnames
(make-pathname :directory (relative-directory-for tag-page)
- :name (content-filename tag-page)
- :type "xhtml") *site-path*)))
+ :name (content-filename tag-page)
+ :type "xhtml") *site-path*)))
(defmethod content-title ((tag-page tag-page))
(tag-page-tag tag-page))
@@ -507,63 +534,62 @@ in the template"
;;;### Templated content
;;; All content that uses a template to merge user written content.
(defclass templated-content (generated-content)
- ((filename :initarg :filename :reader content-filename :index t)
- (title :initarg :title :accessor content-title :index t)
- (tags :initarg :tags :initform nil :accessor content-tags :index t)
+ ((filename :initarg :filename :reader content-filename)
+ (title :initarg :title :accessor content-title)
+ (tags :initarg :tags :initform nil :accessor content-tags)
(when :initarg :when :initform nil :reader content-when
- :type unsigned-byte :index t
- :documentation "When post was originally written.")
+ :type unsigned-byte
+ :documentation "When post was originally written.")
(updated :initarg :updated :initform nil :accessor content-updated
- :type unsigned-byte :index t
- :documentation "Last update time")
+ :type unsigned-byte
+ :documentation "Last update time")
(description :initarg :description :initform nil
- :accessor content-description)
+ :accessor content-description)
(synopsis :initarg :synopsis :initform nil :accessor content-synopsis))
- (:metaclass elephant:persistent-metaclass)
(:documentation "Metadata for templated user content"))
(defmethod shared-initialize :after
((templated-content templated-content) slot-names &key &allow-other-keys)
(with-slots (filename title when description synopsis) templated-content
;; create a sanitised filename
(setf filename
- (if filename
- (%sanitise-title filename)
- (%sanitise-title title)))
+ (if filename
+ (%sanitise-title filename)
+ (%sanitise-title title)))
;; default when to current day
(unless when
(setf when (encode-date (decode-local-date (get-universal-time)))))
;; create a description
(unless (and (slot-boundp templated-content 'description) description)
(when synopsis
- (setf description (%sanitise-synopsis synopsis))))))
+ (setf description (%sanitise-synopsis synopsis))))))
(defmethod published-file-path-for (published-content)
"Find the publish file path for the specified TEMPLATED-CONTENT."
(let ((type (cdr (assoc (type-of published-content)
- *templated-content-file-types*))))
+ *templated-content-file-types*))))
(assert type)
(ensure-directories-exist
(merge-pathnames
(make-pathname :directory (relative-directory-for published-content)
- :name (content-filename published-content)
- :type type)
+ :name (content-filename published-content)
+ :type type)
*published-path*))))
(defmethod site-file-path-for ((templated-content templated-content))
"Find the site file path for the specified TEMPLATED-CONTENT."
(ensure-directories-exist
(merge-pathnames
(make-pathname :directory (relative-directory-for templated-content)
- :name (content-filename templated-content)
- :type "xhtml") *site-path*)))
+ :name (content-filename templated-content)
+ :type "xhtml") *site-path*)))
(defmethod path-for ((templated-content templated-content))
(format nil "~A~A~A.xhtml" *blog-root-path*
- (relative-namestring-for templated-content)
- (content-filename templated-content)))
+ (relative-namestring-for templated-content)
+ (content-filename templated-content)))
(defun content-year (templated-content)
"Returns the year of the blog post."
@@ -579,9 +605,11 @@ in the template"
;;; A user written page that is meant to be updated over time, and is not a blog post
(defclass page (templated-content)
((template :initarg :template :initform nil :reader content-template))
- (:metaclass elephant:persistent-metaclass)
(:documentation "Metadata for pages"))
+(defmethod shared-initialize :after
+ ((page page) slot-names &key &allow-other-keys)
+ (%blog-add :pages page))
(defmethod relative-path-for ((page page))
"Relative path for PAGE."
@@ -604,7 +632,6 @@ in the template"
(email :initarg :email :reader comment-email)
(uri :initarg :uri :reader comment-uri)
(when :initarg :when :reader comment-when))
- (:metaclass elephant:persistent-metaclass)
(:documentation "Metadata for comments"))
(defmethod shared-initialize :after
@@ -614,39 +641,42 @@ in the template"
(unless when
(setf when (get-universal-time)))
;; create a sanitised filename
- (setf filename (format nil "~A_~A" when (%sanitise-title name)))))
+ (setf filename (format nil "~A_~A" when (%sanitise-title name))))
+ (%blog-add :comments comment))
(defmethod relative-path-for ((comment comment))
"Relative path for a comment."
(append *comment-path*
- (list (content-filename (content-page comment)))))
+ (list (content-filename (content-page comment)))))
(defmethod path-for ((comment comment))
(concatenate 'simple-string (path-for (content-page comment))
- "#" (content-filename comment)))
+ "#" (content-filename comment)))
;;;### Blog post
;;; A blog post is content with a template of "post" which is the default
;;; template.
(defclass blog-post (templated-content)
((template :initform *blog-post-template* :reader content-template
- :allocation :class :transient t)
- (comments :initform (elephant:make-btree) :reader content-comments))
- (:metaclass elephant:persistent-metaclass)
+ :allocation :class)
+ (comments :initform nil :accessor content-comments))
(:documentation "Metadata for blog-posts"))
+(defmethod shared-initialize :after
+ ((blog-post blog-post) slot-names &key &allow-other-keys)
+ (%blog-add :posts blog-post))
+
(defmethod print-object ((object blog-post) stream)
"Print a blog post instance showing date and filename"
(print-unreadable-object (object stream :type t)
(with-slots (filename when) object
- (format stream "(~{~A~^-~}) ~A " (decode-date when) filename))
- (format stream " oid:~D" (elephant::oid object))))
+ (format stream "(~{~A~^-~}) ~A " (decode-date when) filename))))
(defmethod relative-path-for ((blog-post blog-post))
"Relative path for a blog post"
(append *blog-post-path*
- (list (format nil "~A" (content-year blog-post)))))
+ (list (format nil "~A" (content-year blog-post)))))
(defmethod link-for ((blog-post blog-post) &key url)
(cxml:with-element "a"
@@ -682,85 +712,121 @@ in the template"
(subseq (multiple-value-list (decode-universal-time utime)) 3 6))
;;;## Database Utilities
-(defmacro with-open-store (() &body body)
- `(elephant:with-open-store (*blog-db-spec*)
- (elephant:with-transaction ()
- ,@body)))
+(defun scan-post (pathname)
+ (format t "scan-post ~A~%" pathname)
+ (multiple-value-bind
+ (title post-when post-updated tags linkname description synopsis
+ template)
+ (%parse-post-info pathname)
+ ;(format t "~A ~A ~A ~A ~A ~A~%" title post-when post-updated tags linkname template)
+ (make-metadata title post-when post-updated tags linkname
+ description synopsis template)))
+
+(defun scan-comment (pathname)
+ (format t "scan-comment ~A~%" pathname)
+ (multiple-value-bind (ip name email uri when)
+ (%parse-comment pathname)
+ (let* ((post-filename (car (last (pathname-directory pathname))))
+ (filename (pathname-name pathname))
+ (id (subseq filename 0 (position #\_ filename)))
+ (post (%blog-find-by :posts 'content-filename post-filename))
+ (comment (make-instance 'comment
+ :content-page post
+ :ip ip
+ :id id
+ :when when
+ :name name
+ :email email
+ :uri uri)))
+ (push comment (content-comments post)))))
+
+
+(defun scan-directory (pathname)
+ (format t "scan-directory ~A~%" pathname)
+ (loop
+ with post-type = (cdr (assoc 'blog-post *templated-content-file-types*))
+ with page-type = (cdr (assoc 'page *templated-content-file-types*))
+ with comment-type = (cdr (assoc 'comment *templated-content-file-types*))
+ for file in (directory pathname)
+ do
+ (cond ((zerop (length (file-namestring file)))
+ (scan-directory (make-pathname :name :wild :type :wild :defaults file)))
+ ((string= post-type (pathname-type file))
+ (scan-post file))
+ ((string= page-type (pathname-type file))
+ (scan-post file))
+ ((string= comment-type (pathname-type file))
+ (scan-comment file))
+ (t
+ (format t "unrecognised type ~A~%" (pathname-type file))))))
+
+(defun scan-blog-files ()
+ "Scan posts and build an in memory representation."
+ (flet ((directory-for (path)
+ (merge-pathnames
+ (make-pathname :directory (apply 'list :relative path) :name :wild)
+ *published-path*)))
+ (setf *blog* (make-hash-table :test 'equalp))
+ (setf (gethash :posts *blog*) (list))
+ (setf (gethash :pages *blog*) (list))
+ (setf (gethash :comments *blog*) (list))
+ (setf (gethash :all *blog*) (list))
+
+ (scan-directory (make-pathname :type :wild :defaults (directory-for *blog-post-path*)))
+ (scan-directory (make-pathname :type :wild :defaults (directory-for *page-path*)))
+ (scan-directory (make-pathname :type :wild :defaults (directory-for *comment-path*))))
+
+ ;; *tag-page-path*
+ ;; *comment-path*
+
+ *blog*)
+
+(defun %blog ()
+ "Return the in memory representation of the blog"
+ (or *blog* (scan-blog-files)))
+
+(defun blog (key)
+ (gethash key (%blog)))
+
(defun %recent-posts (&key (n 10))
"Create a list of recent posts."
- (elephant:with-btree-cursor
- (cursor (elephant:find-inverted-index 'blog-post 'when))
- (let (has-pair key value)
- (multiple-value-setq (has-pair key value)
- (elephant:cursor-last cursor))
- (loop
- for i from 0 below n
- while has-pair
- collect (elephant::controller-recreate-instance
- elephant:*store-controller* value)
- do
- (multiple-value-setq (has-pair key value)
- (elephant:cursor-prev cursor))))))
+ (let ((posts (blog :posts)))
+ (if (> (length posts) n)
+ (subseq posts 0 n)
+ posts)))
(defun %tag-posts (tag)
"Create a list of recent posts for a given tag."
- (let ((posts))
- (elephant:map-class
- #'(lambda (x)
- (when (find tag (content-tags x) :test #'string=)
- (push x posts)))
- 'blog-post)
- posts))
+ (flet ((has-tag (post)
+ (find tag (content-tags post) :test 'string=)))
+ (remove-if-not #'has-tag (blog :posts))))
(defun %map-dirty-content (fn)
- "Map all dirty conent."
- (labels ((wrapped-fn (key value)
- (declare (ignore key))
- (when value
- (funcall fn value)))
- (fn-for-class (class)
- (elephant:map-inverted-index #'wrapped-fn class 'dirty :value t)))
- (mapc #'fn-for-class (list 'blog-post 'page 'index-page 'tag-page))))
-
+ "Map all dirty content for side effects only."
+ (mapc fn (remove-if-not 'dirty (blog :all))))
(defun %adjacent-posts (blog-post)
"Return post before and after the given post."
(assert blog-post)
- (elephant:with-btree-cursor
- (cursor (elephant:find-inverted-index 'blog-post 'when))
- (let (has-pair key value prior next
- (when (content-when blog-post))
- (oid (elephant::oid blog-post)))
- (multiple-value-setq (has-pair key value)
- (elephant:cursor-set cursor when))
- (assert has-pair)
+ (if (= (length (blog :posts)) 1)
+ (values)
(loop
- while (and has-pair (not (= oid value)))
- do (multiple-value-setq (has-pair key value)
- (elephant:cursor-next cursor)))
- (assert (= oid value))
- (multiple-value-setq (has-pair key value) (elephant:cursor-prev cursor))
- (if has-pair
- (setf prior (elephant::controller-recreate-instance
- elephant:*store-controller* value)))
- (multiple-value-setq (has-pair key value) (elephant:cursor-next cursor))
- (assert (= oid value))
- (multiple-value-setq (has-pair key value) (elephant:cursor-next cursor))
- (if has-pair
- (setf next (elephant::controller-recreate-instance
- elephant:*store-controller* value)))
- (values prior next))))
-
-
-(defun %btree-length (btree)
- "Counts the number of entries in BTREE"
- (let ((count 0))
- (flet ((inc-counter (key value)
- (declare (ignore key value))
- (incf count)))
- (elephant:map-btree #'inc-counter btree)
- count)))
+ for m2 = nil then m1
+ for m1 = nil then post
+ for post in (blog :posts)
+ until (eq blog-post m1)
+ finally (return (if (eq post blog-post)
+ (values m2)
+ (values m2 post))))))
+
+(defun %blog-find-by (kind key value)
+ "find an item in the kind collection, with key = value"
+ (find value (blog kind) :key key :test #'equal))
+
+(defun %blog-remove (item)
+ "Remove item"
+ (remove item (blog :all)))
;;;# Publishing
@@ -771,115 +837,110 @@ in the template"
(defun publish-draft (path &key (generate-site nil))
"Publish the draft post at the specified filesystem PATH. Returns a list with
the path to the published file and the site path."
- (with-open-store ()
- (multiple-value-bind (output-path templated-content)
- (%publish-draft (pathname path))
- (if generate-site
- (generate-site)
- (generate templated-content))
- (list (namestring output-path)
- (namestring (site-file-path-for templated-content))
- (url-for templated-content)
- (path-for templated-content)))))
+ (multiple-value-bind (output-path templated-content)
+ (%publish-draft (pathname path))
+ (if generate-site
+ (generate-site)
+ (generate templated-content))
+ (list (namestring output-path)
+ (namestring (site-file-path-for templated-content))
+ (url-for templated-content)
+ (path-for templated-content))))
;;; Republishing uses the "updated" element in the "head" to set the updated time
;;; on the post. If no "updated" is present, then one is added eith the current
;;; date.
(defun publish-updated-post (path &key (generate-site nil))
"Publish an updated post at the specified filesystem PATH. Returns a list with
the path to the published file and the site path."
- (with-open-store ()
- (multiple-value-bind (output-path templated-content)
- (%publish-updated-post (pathname path))
- (if generate-site
- (generate-site)
- (generate templated-content))
- (list (namestring output-path)
- (namestring (site-file-path-for templated-content))
- (url-for templated-content)
- (path-for templated-content)))))
+ (multiple-value-bind (output-path templated-content)
+ (%publish-updated-post (pathname path))
+ (if generate-site
+ (generate-site)
+ (generate templated-content))
+ (list (namestring output-path)
+ (namestring (site-file-path-for templated-content))
+ (url-for templated-content)
+ (path-for templated-content))))
;;;## Add a comment
;;; Adds comment metadata to the database and writes a published comment file
(defun add-comment (post-slug ip name email uri when text)
"Create a comment TEXT on the post identified by POST-SLUG, originating from
NAME with EMAIL and URI. TEXT is plain text."
(macrolet ((with-each-paragraph ((var text) &body body)
- (let ((paras (gensym)))
- `(let ((,paras
- (cl-ppcre:split "(?:\\r\\n|\\n|\\r){2,}" ,text)))
- (loop for ,var in ,paras
- do ,@body)))))
+ (let ((paras (gensym)))
+ `(let ((,paras
+ (cl-ppcre:split "(?:\\r\\n|\\n|\\r){2,}" ,text)))
+ (loop for ,var in ,paras
+ do ,@body)))))
(labels ((htmlify (para)
- (let ((i 0))
- (cl-ppcre:do-scans
- (ms me rs re "(https?|mailto)://[\\S-/]+/\\S*" para)
- (when (> ms i)
- (cxml:text (subseq para i ms)))
- (let ((link (subseq para ms me)))
- (cxml:with-element "a"
- (cxml:attribute "href" link)
- (cxml:attribute "rel" "nofollow")
- (cxml:text link)))
- (setf i me))
- (when (< i (length para))
- (cxml:text (subseq para i)))))
- (output-text-as-html (text)
- "Output text converted to simple HTML"
- (with-each-paragraph (paragraph text)
- (cxml:with-element "p"
- (htmlify paragraph)))))
- (let ((blog-post
- (elephant::get-instance-by-value 'blog-post 'filename post-slug)))
- (unless blog-post
- (error "Unknown post ~A" post-slug))
- (let ((comment
- (make-instance 'comment :content-page blog-post :ip ip
- :name name :email email :uri uri :when when)))
- (setf (elephant:get-value (content-filename comment)
- (content-comments blog-post))
- comment)
- (setf (dirty blog-post) t)
- (with-open-file (stream (published-file-path-for comment)
- :element-type '(unsigned-byte 8)
- :direction :output
- :if-does-not-exist :create)
- (let ((output
- (cxml:make-octet-stream-sink
- stream :canonical nil :indentation nil
- :omit-xml-declaration-p t)))
- (cxml:with-xml-output output
- (cxml:with-element "comment"
- (cxml:with-element "ip"
- (cxml:text ip))
- (cxml:with-element "name"
- (cxml:text name))
- (cxml:with-element "email"
- (cxml:text email))
- (cxml:with-element "uri"
- (cxml:text uri))
- (cxml:with-element "when"
- (cxml:text (local-time:format-rfc3339-timestring
- nil (local-time:universal-to-timestamp when))))
- (cxml:with-element "text"
- (output-text-as-html text))))))
- (values comment))))))
+ (let ((i 0))
+ (cl-ppcre:do-scans
+ (ms me rs re "(https?|mailto)://[\\S-/]+/\\S*" para)
+ (when (> ms i)
+ (cxml:text (subseq para i ms)))
+ (let ((link (subseq para ms me)))
+ (cxml:with-element "a"
+ (cxml:attribute "href" link)
+ (cxml:attribute "rel" "nofollow")
+ (cxml:text link)))
+ (setf i me))
+ (when (< i (length para))
+ (cxml:text (subseq para i)))))
+ (output-text-as-html (text)
+ "Output text converted to simple HTML"
+ (with-each-paragraph (paragraph text)
+ (cxml:with-element "p"
+ (htmlify paragraph)))))
+ (let ((blog-post (%blog-find-by :posts #'content-filename post-slug)))
+ (unless blog-post
+ (error "Unknown post ~A" post-slug))
+ (let ((comment
+ (make-instance 'comment :content-page blog-post :ip ip
+ :name name :email email :uri uri :when when)))
+ (push comment (content-comments blog-post))
+ (setf (dirty blog-post) t)
+ (with-open-file (stream (published-file-path-for comment)
+ :element-type '(unsigned-byte 8)
+ :direction :output
+ :if-does-not-exist :create)
+ (let ((output
+ (cxml:make-octet-stream-sink
+ stream :canonical nil :indentation nil
+ :omit-xml-declaration-p t)))
+ (cxml:with-xml-output output
+ (cxml:with-element (cdr (assoc 'comment *templated-content-file-types*))
+ (cxml:with-element *comment-ip*
+ (cxml:text ip))
+ (cxml:with-element *comment-name*
+ (cxml:text name))
+ (cxml:with-element *comment-email*
+ (cxml:text email))
+ (cxml:with-element *comment-uri*
+ (cxml:text uri))
+ (cxml:with-element *comment-when*
+ (cxml:text (local-time:format-rfc3339-timestring
+ nil (local-time:universal-to-timestamp when))))
+ (cxml:with-element *comment-text*
+ (output-text-as-html text))))))
+ (values comment))))))
(defun make-metadata (title when updated tags filename description
- synopsis template)
+ synopsis template)
"Create metadata of the appropriate type"
(unless template
(setf template *default-template*))
(let ((class (if (string= template *blog-post-template*) 'blog-post 'page)))
(make-instance class
- :title title
- :when (if when (encode-date when))
- :updated (if updated (encode-date updated))
- :tags tags
- :filename filename
- :description description
- :synopsis synopsis
- :template template)))
+ :title title
+ :when (if when (encode-date when))
+ :updated (if updated (encode-date updated))
+ :tags tags
+ :filename filename
+ :description description
+ :synopsis synopsis
+ :template template)))
;;; Publish a draft. This puts the draft into publish, and creates database meta
;;; info for it. Returns the published file path and the blog-post metadata. If
@@ -889,28 +950,27 @@ the path to the published file and the site path."
(defun %publish-draft (path)
"Publish the draft at the filesystem PATH."
(multiple-value-bind
- (title post-when post-updated tags linkname description synopsis
- template)
+ (title post-when post-updated tags linkname description synopsis
+ template)
(%parse-post-info path)
(let ((existing-post
- (or
- (elephant:get-instances-by-value 'blog-post 'title title)
- (elephant:get-instances-by-value 'page 'title title))))
+ (or (%blog-find-by :posts #'content-title title)
+ (%blog-find-by :pages #'content-title title))))
(if existing-post
- (restart-case
- (error "This content already exists.")
- (delete-existing-entry ()
- (elephant:drop-instances existing-post)))))
+ (restart-case
+ (error "This content already exists.")
+ (delete-existing-entry ()
+ (%blog-remove existing-post)))))
(let ((content
- (make-metadata title post-when post-updated tags linkname
- description synopsis template)))
+ (make-metadata title post-when post-updated tags linkname
+ description synopsis template)))
(let* ((output-path (published-file-path-for content)))
- (%publish-draft-updating-post-metadata path output-path content)
- (%ensure-tag-pages-for content)
- (%mark-connected-posts-dirty content)
- (values output-path content)))))
+ (%publish-draft-updating-post-metadata path output-path content)
+ (%ensure-tag-pages-for content)
+ (%mark-connected-posts-dirty content)
+ (values output-path content)))))
@@ -919,26 +979,22 @@ the path to the published file and the site path."
(defun %publish-updated-post (path)