First entry

Fri Aug 6 14:09:19 CEST 2010

The homepage is up and running. This all worked out better than expected. I still think that developing everything in perl would have been easier, but what the heck?

Implementation

The intention in developing this code was keeping it as simple as possible. This means a lot of static HTML files and some CGI scripts. I wanted the CGI scripts to run fast, and I wanted to try some Go. Hence I wrote the non-static parts in Go. The static parts are written in markdown, and converted to HTML on a as-needed basis.

So what do the static files look like? Well, the code of the index page looks as follows:

% title = Christian's home
% node  = Home

In Arbeit!
==========

New system
----------
Now this homepage works with [Google Go](http://www.golang.org) and markdown.

Wir sind umgezogen
------------------

Nun wohne ich in Aachen, in der benannten WG, und alles ist gut *Glocke schwing*


Wir ziehen um!
--------------

Ich ziehe auch endlich nach Aachen, zusammen mit meiner Freundin und
noch zwei Freunden werde ich eine WG bewohnen. Mittwoch kommen schon
unsere Möbel, und am Samstag will ich den Rest rüberschaffen.

Nix hat sich getan
------------------

Nach langer Abstinenz muss ich feststellen, dass sich nix getan hat.
Alles muss man selber machen. Aber dafür habe ich die Fotogalerie
angesehen und herausgefunden, was die Menschen dazu bewegt, Fotoalben anzulegen.
Vielleicht sollte ich auch mehr Fotos machen.

Note the header of the form % key = val. Each of the static files can have such a header, and this is used to configure how the page is rendered to HTML. The node field is used to specify where in the navigation we currently are. As you can see on the left, the currently selected node is highlighted, and node is used to determine where the page currently is.

The blog entries are written in a similar format.

But how much code was necessary?

Well, the actual server is lighttpd, so a lot of complicated code was not written by me.

Let’s see what wc says:

% wc -l `find ./ -iname '*.go' -or -iname 'Makefile'` 
  13 ./Makefile
  50 ./src/Makefile
  60 ./src/blog.go
  10 ./src/Test.go
  75 ./src/blogSingle.go
  25 ./bin/Makefile
  67 ./bin/Render.go
  23 ./lib/Makefile
  83 ./lib/blog.go
  13 ./lib/config.go
  42 ./lib/navigate.go
 117 ./lib/confText.go
  83 ./lib/render.go
 661 total

Pretty humble, all in all. And really fast.

How long does it take to build the site?

Everytime before I copy the site to htdocs, I build it completely anew.

On my AMD Athlon X2 4850e this looks as follows:

gmake --directory=lib all
gmake[1]: Entering directory `/home/christian/homepage/lib'
6g -I ./ navigate.go
6g -I ./ config.go
6g -I ./ render.go
6g -I ./ confText.go
6g -I ./ blog.go
gmake[1]: Leaving directory `/home/christian/homepage/lib'
gmake --directory=bin all
gmake[1]: Entering directory `/home/christian/homepage/bin'
6g -I ./ -I ../lib/ Render.go
6l -L ../lib/ -o Render Render.6
gmake[1]: Leaving directory `/home/christian/homepage/bin'
gmake --directory=src all
gmake[1]: Entering directory `/home/christian/homepage/src'
6g -I ./ -I ../lib/ blog.go
6l -L ../lib/ -o blog.cgi blog.6
6g -I ./ -I ../lib/ blogSingle.go
6l -L ../lib/ -o blogSingle.cgi blogSingle.6
../bin/Render homepage.md > homepage.html
../bin/Render me.md > me.html
../bin/Render index.md > index.html
rm blogSingle.6 blog.6
gmake[1]: Leaving directory `/home/christian/homepage/src'
gmake  1.02s user 0.13s system 93% cpu 1.234 total

Note that this does of course not include the blog pages. But rendering the blog is speedy, too: ./blog.cgi > /dev/null 0.01s user 0.01s system 84% cpu 0.019 total

Note that the markdown code is parsed everytime the blog is rendered. This could be sped up, of course, by prerendering the articles to html and including them in the generated page later, but the markdown processor I use (discount) is fast enough to make this unnecessary.


Google go templates

Tue Aug 10 11:25:35 CEST 2010

Until now, the homepage used HTML embedded in source code, rendered the content (which is in markdown format), concatenated the strings and printed that stuff to stdout.

Today I exported this code into templates. The main layout of the page as well as the layout of the blog are now contained in templates. The template files can be found here.

The template engine I use is the template package of Go.

The template package provides almost no control flow. A template is executed on some data, which may be a map m or some type t. Then a string of the form {field} is replaced by the contents of m[field] or t.field or t.field() respectively.

For deeper nested data structures, the template package provides a notion of a “current position” or a “cursor”, denoted by @. To go deeper into a data structure, {.section field} ... {.end} is used. The cursor then is set to m[field] or t.field etc. Any further substitution is then used on whatever m[field] is.

If we for example have the following map

m := map[string]string{
  "foo": map[string]string{
    "bar": "baz"}}

and the template string

{.section foo}
  {bar}
{.end}

then this is substituted by m["foo"]["bar"], i.e. by baz.

Finally, if you want to iterate over some data structure, then this is supported by {.repeated section field} ... {.end}, where m[field] is required to be some array or slice. The cursor is set to the element in question and the sub code is executed.

The template package also provides some other features, of which I will mention just one: filter. Some field can be passed through a filter, and the result is substituted. This is denoted by {field|filter}. There is, for example, the html filter provided by the template package. This filter html-escapes the contents of the field before substituting it.

A filter I implemented is the md filter, which pipes the content of the field through a markdown processor and inserts the result as a string.

This is used in the main template. This template is called with three fields:

  • title: The title of the page
  • menu: The rendered menu
  • content: The content to be rendered

The content is not substituted as is, though, but is first passed through the markdown processor. This is achieved via {content|md}.


Powered by Google go

Copyright © 2010 Christian von Essen < christian at mvonessen dot de >