"Cause a little auk awk
goes a long way."

 »  table of contents
 »  featured topics
 »  page tags

About Awk
 »  advocacy
 »  learning
 »  history
 »  Wikipedia entry
 »  mascot
 »  Awk (rarely used)
 »  Nawk (the-one-true, old)
 »  Gawk (widely used)
 »  Mawk
 »  Xgawk (gawk + xml + ...)
 »  Spawk (SQL + awk)
 »  Jawk (Awk in Java JVM)
 »  QTawk (extensions to gawk)
 »  Runawk (a runtime tool)
 »  platform support
 »  one-liners
 »  ten-liners
 »  tips
 »  the Awk 100
 »  read our blog
 »  read/write the awk wiki
 »  discussion news group

 »  Gawk
 »  Xgawk
 »  the Lawker library
Online doc
 »  reference card
 »  cheat sheet
 »  manual pages
 »  FAQ

 »  articles
 »  books:


Mar 01: Michael Sanders demos an X-windows GUI for AWK.

Mar 01: Awk100#24: A. Lahm and E. de Rinaldis' patent search, in AWK

Feb 28: Tim Menzies asks this community to write an AWK cookbook.

Feb 28: Arnold Robbins announces a new debugger for GAWK.

Feb 28: Awk100#23: Premysl Janouch offers a IRC bot, In AWK

Feb 28: Updated: the AWK FAQ

Feb 28: Tim Menzies offers a tiny content management system, in Awk.

Jan 31: Comment system added to For example, see discussion bottom of ?keys2awk

Jan 31: Martin Cohen shows that Gawk can handle massively long strings (300 million characters).

Jan 31: The AWK FAQ is being updated. For comments/ corrections/ extensions, please mail

Jan 31: Martin Cohen finds Awk on the Android platform.

Jan 31: Aleksey Cheusov released a new version of runawk.

Jan 31: Hirofumi Saito contributes a candidate Awk mascot.

Jan 31: Michael Sanders shows how to quickly build an AWK GUI for windows.

Jan 31: Hyung-Hwan Chung offers QSE, an embeddable Awk Interpreter.

[More ...]

Bookmark and Share

categories: CMS,Tools,Mar,2010,Timm

TinyTim: a Content Management System

TINY TIM is a tiny web-site manager written in AWK. For a live demo of the site, see The site supports runtime content generation; e.g. the quote shown top right of the demo site is auto-generated each time you refresh the page.

The site was written to demonstrate that a little AWK goes a long way. At the time of this writing, the current system is under 100 lines of code (excluding a seperate formatter, that is another 170 lines of code). It took longer to write this doco and the various HTML/CSS theme files, than the actual code itself (fyi: 6 hours for the themes/doc and 3 hours for the code).

TINY TIM has the following features:

  • Pages can be accessed by their (lowercase) name, or by their (uppercase) tags.
  • Pages can be displayed using a set of customizable themes.
  • Page contents can be written using a HTML shorthand language called MARKUP.
  • Pages can be searched using a Google search box.
  • Source code is auto-displayed using a syntax highlighter.
  • Page content can be auto-created via programmer-modifable plugins.


In a web accessible directory, type

 svn export 

In the resulting directory, perform the local juju required to make index.cgi web-runnable (e.g. on my ISP, chmod u+rx index.cgi).

Follow the directions in the next section to customize the site.



TINY TIM is controlled by the following index.cgi file. To select a theme, comment out all but one of the last lines (using the "#" character). For a screen-shots of the current themes, see below.

[ -n "$1" ] && export QUERY_STRING="$1"
tinytim() {
  cat content/* themes/$1/theme.txt |
  gawk -f lib/tinytim.awk |
  sed 's/^<pre>/<script type="syntaxhighlighter" class="brush: cpp"><![CDATA[/' |
  sed 's/^<\/pre>/<\/script>/'
 #tinytim auklet
 #tinytim trendygreen
 tinytim wink


  • The sed commands: these render normal <pre> using Alex Gorbatchev's excellent syntax highlighter. To change the highlighting rules for a different language, change brush: cpp to one of the supported aliases.
  • The cat command: this assembles the content for the system. Multiple authors can write multiple files in the sub-directorty content.


Themes are defined in the sub-directory themes/themename. Each theme is defined by a theme.txt file that holds:

  • The HTML template for the theme.
  • The in-line style sheet for the theme.
  • The page contents with pre-defined string names marked with ``; e.g. ``title``. To change those strings, see the instructions at the end of this page.
  • If a `` entry contains a semi-colon (e.g. ``quotes;``) then it is a plugin. Plugin content is generated at runtime using a method described at the end of this document.

To write a new theme:

  1. Create a new folder themes/new.
  2. Copy (e.g.) wink/theme.txt to new.
  3. Using the copied theme as a template, start tinkering.

The following themes are defined in the directory themes.


Trendygreen (adapted from GetTemplates):


Defining String Values

The first entry in the content defines strings that can slip into the theme templates. For example, the following slots define the title of a site; the name of formatter script that renders each page; the url of the home directory of the site; a menu to add top of each page; a footer to add to the bottom of each page; and a web-accessible directory for storing images.

 ``title``       Just another Tiny Tim demo
 ``formatter``   lib/markup.awk
 ``description`` (simple cms)
 ``menu``        <a href="?index">Home</a> | 
                 <a href="?contact">Contact</a>  |
                 <a href="?about">About</a>
 ``footer``      <p>Powered by <a href="?tinytim">TINY TIM</a>. 
                                 © 2010 by Tim Menzies 

Note the following important convention. TINY TIM auto-generates some of its own strings. The names of these strings start with an uppercase letter. To avoid confusion of your strings with those that are auto-generated, it is best to start your strings with a lower-case letter (e.g. like all those in the above example.

Adding a Search Engine

Google offers a nice free site-specific search engine. It takes a few days for the spiders to find the site but after that, it works fine. To set this up, follow the instructions at Google custom search, then

  • Add the appropriate magic strings into the first entry of the content (usually content/0config.txt).
  • Add references to those strings to your template.

For example, look for google-search in the current templates and content/0config.txt.

Writing pages

After the first entry, the rest of the entries in the content/* define the pages of a site. Each entry must begin with the magic string

  • Each entry must begin with the magic string #12345
  • The entry consists of paragraphs (separated by blank lines.
  • Paragraph one contains the (short) page name (on line one) following by the page tags (on line two).
      • Note that the page name must start with a lower case letter.
      • And the tags must start with an upper case letter.
  • Paragraph two contains the heading of the page.
  • The remaining paragraphs are the page contents.

For example, this site contains a missing page report. This page is defined as follows. In the following definition of that page, the name is "404"; the tags are "Admin Feb10" and the title is "Sorry".

 Admin Feb10
 I have bad news:

The contents can contain HTML and MARKUP tags.


MARKUP is a shorthand for writing HTML pages based on MARKDOWN:

  • Italics, bold, typerwritter font are marked by matching _, *, and ` characters (respectively).
  • Lists are marked by leading "+" characters.
  • Numbered lists are marked by leading "1." strings.
  • Links are enclosed in [square brackets]. The first word in the bracket is the URL and subsequent words are the text for the URL link.
  • Images are marked up with the same [square brackets], but the first work must end in one of .png, .gif, .jpg. Any subsequent words are passed as tags to the <img> tag.

Also, in MARKUP, major, minor, sub-, and sub-sub- headings are two line paragraphs where the second line contains two or more "=", "-", "+", "_" (respectively). MARKUP collects these headings as a table of contents, which is added to the top of the page.

Note that MARKUP is separate to TINY TIM. To change the formatting of pages, write your own AWK code and change the string ``formatter`` in the first entry of content/0config.txt.


If a `` entry contains a semi-colon (e.g. ``quotes;``) then it is a plugin. Plugin content is generated at runtime. To write a plugin, modify the file lib/plugins.awk. Currently, that file looks like this:

 function slotsPlugIns(str,slots,   tmp) {
    if (tmp[1]=="quotes")
        return quotes(str,slots)
    return str
 function quotes(str,slots,    n,tmp) {
    srand(systime() + PROCINFO["pid"])
    return tmp[int(rand()*n) + 1]

The function slotsPlugIns is a "traffic-cop" who decides what plugin to call (in the above, there is only one current plugin: quotes).

Each plugin function (e.g. quotes) is passed the string from the template (see str) and an array of key/value pairs holding all the defined string values (see slots). These functions must return a string to be inserted into the rendered HTML.

In the example above, quotes just returns a random quote. It assumes that the predefined strings includes a set of quotes, one per line:

 ``quotes`` Small  things with great love. <br>-- Mother Teresa
     It's hard work to it look effortless.<br>-- Katarina Witt
    "God bless us every one!".<br>-- Tiny Tim

The quote generated by this plug in can be view, top right of this page.

blog comments powered by Disqus