<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>lua nova &#187; Wiki</title>
	<atom:link href="http://www.luanova.org/tag/wiki/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.luanova.org</link>
	<description>welcome to the moon</description>
	<lastBuildDate>Thu, 23 Sep 2010 12:46:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Sputnik: An Introduction I</title>
		<link>http://www.luanova.org/sputnik/</link>
		<comments>http://www.luanova.org/sputnik/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 06:08:07 +0000</pubDate>
		<dc:creator>stevejdonovan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[web frameworks]]></category>
		<category><![CDATA[Wiki]]></category>

		<guid isPermaLink="false">http://luanova.org/?p=21</guid>
		<description><![CDATA[Beyond WikiWiki Sputnik is a second-generation extensible wiki engine written in Lua. First generation wikis (like the original WikiWIki) opened our eyes to the possibility of easy collaborative content generation, with automatic revision control. However, anybody who has been involved with a Wiki knows that they are not self-organizing, and so behind any Wiki is [...]]]></description>
			<content:encoded><![CDATA[<h2>Beyond WikiWiki</h2>

<p><a href="http://sputnik.freewisdom.org/">Sputnik</a> is a second-generation extensible wiki engine written in Lua. First generation wikis (like the original <a href="http://c2.com/cgi/wiki">WikiWIki</a>) opened our eyes to the possibility of easy collaborative content generation, with automatic revision control.  However, anybody who has been involved with a Wiki knows that they are not self-organizing, and so behind any Wiki is a core of busy elves correcting and &#8216;refactoring&#8217; content.  Plus, all content is usually in the form of marked-up text, plus uploaded binary data like images.  For instance,  Wiki pages often turn into discussions, but there is usually no way to structure these discussions and no support for creating them.</p>

<p>A second-generation wiki allows for &#8216;virtual&#8217; pages, pages with explicit data fields, structured discussions, complete control of permissions, and namespace management.  The site designer can choose the right balance between freedom and structure that is appropriate for the community and its common purpose.</p>

<h2>Frameworks and Libraries</h2>

<p>There are two basic approaches to software development; either start small, pulling as much functionality in using libraries, or to start with a framework, which does most of the job, and customize it to fit your functionality.  Frameworks have a bad <a href="http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12">reputation</a> because framework developers can get just a little mad in the process of writing them.  But if you want something that can do wiki-like things, manage the content and control the revisions, handle authentication, then it&#8217;s time to get a Wiki framework, because these are not easy applications to get right. As the <a href="http://gitorious.org/sputnik?page=4">Sputnik git page</a> says, &#8220;Sputnik provides a good foundation for anything that&#8217;s kind of like a wiki but not quite.&#8221;</p>

<p>It is true that the first trade-off is the freedom to do things <em>your</em> way, since you must learn how the framework does things, and cooperate with it. In a way, it is like collaboration with another developer on a project which you have just joined.  I am assuming here that you want to get something done, which is not a million miles from a Wiki, and don&#8217;t want to rewrite a whole bunch of wheels, just maybe update the hubcaps.  A better analogy would be this: if you want to equip a kitchen, then using a framework that includes the kitchen sink is appropriate (and not just a joke). Maybe you just want different fittings for your kitchen sink.</p>

<h2>Getting Sputnik</h2>

<p><a href="http://sputnik.freewisdom.org/en/Installation">Installing Sputnik</a> is straightforward, providing you are on a Unix-like platform (like Linux or OS X) although it does also run on Windows.  In this introduction, I assume that it is an Unix environment (although out of convenience, not religious fervour; it is very easy to get a Linux virtual machine and set it up for Sputnik testing.)   After following instructions, you will have a Sputnik install in <strong>~/sputnik</strong>, no special permissions necessary.  Starting the webserver is then just:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~<span style="color: #000000; font-weight: bold;">/</span>sputnik$ .<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sputnik.lua start-xavante sputnik.ws</pre></div></div>


<p>Sputnik comes with the <a href="http://www.keplerproject.org">Kepler stack</a>, including the Lua webserver Xavante.  This is quite good enough for testing and experimentation.</p>

<p>A useful change is to first edit <strong>sputnik.ws</strong> and set <strong>BASE_URL</strong> to &#8216;/&#8217; and to add <strong>SHOW_STACK_TRACE = true</strong>. Sputnik will then give you Lua error traces when some hitch occurs. Then just open <strong>http://localhost:8080</strong> in your favourite browser and start playing. Create a special user <strong>Admin</strong> to view and edit the configuration nodes.</p>

<p>All Sputnik configuration is via nodes with Lua content. For instance, <strong>sputnik/config</strong>  assigns a set of fields to values. If you are editing this file (as Admin) and make a syntax error (such as <strong>&#8216;Sputnik&#8221;</strong>, mismatching string delimiters) the edit field will turn pink. <strong>sputnik/navigation</strong> controls the navigation bar menu:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  NAVIGATION <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
     <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;index&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Start&quot;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;snippets&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Snippets&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tags&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Tags&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;sputnik&quot;</span>,title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Configure&quot;</span><span style="color: #66cc66;">&#125;</span>,
     <span style="color: #66cc66;">&#125;</span>,
     <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;News&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Timeline&quot;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;News&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Future Plans&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;history&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Recent Wiki Edits&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;history/edits_by_recent_users&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Edits by Recent Users&quot;</span><span style="color: #66cc66;">&#125;</span>,
       <span style="color: #66cc66;">&#123;</span>id<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;history.rss&quot;</span>, title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;RSS Feed&quot;</span><span style="color: #66cc66;">&#125;</span>,
     <span style="color: #66cc66;">&#125;</span>,
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>Creating a new node is easy; if you ask for a node <strong>test</strong> then it will tell you that this node does not exist, but then will give you several types to choose from.  The &#8216;Basic&#8217; type is a plain Wiki page, and the link provided is something like <strong>http://localhost:8080/?p=test.edit&amp;prototype=</strong>.  In general, a Sputnik request has a <em>node id</em> (&#8216;test&#8217;), an <em>action</em> (&#8216;edit&#8217;) and <em>parameters</em> (&#8216;prototype=&#8217;)</p>

<p>If you click on this link you can edit your new Wiki node.  The markup used is <a href="http://daringfireball.net/projects/markdown/">Markdown</a> which has a clean, readable syntax. In addition, Sputnik supports Wiki links; a link to your new page would be <strong>[[test]]</strong> and a link with some text would be <strong>[[test|My First Page]]</strong> . There is a convenient toolbar providing the most common operations when editing.</p>

<h2>Customizing Sputnik</h2>

<p>A lot can be done with basic Sputnik, just by editing the configuration nodes.  (And, yes, the configuration nodes are Wiki nodes, so you can revert to an earlier version.)  Also, like any modern Web framework, style and functionality are kept separate as CSS and HTML; these <a href="http://sputnik.freewisdom.org/en/Sightings">Sputnik sites</a> show that you can get just about any look and feel.</p>

<p>Since the configuration is done with Lua data, it <em>technically</em> involves programming, but not in any serious sense of the word.  Lua is particularly well-suited to expressing configuration, since it was originally conceived as a data-description language.  This data is converted into Lua table structures using Lua itself, using a <a href="http://lua-users.org/wiki/SandBoxes">sandbox</a> so that it will not execute any dangerous stuff.</p>

<p>The first &#8216;real&#8217; customization we will do is make a whole set of pages default to a particular node type. That is, any node like <strong>pages/GeneralInfo</strong> or <strong>pages/Introduction</strong> will be created as &#8216;Basic&#8217; nodes.</p>

<p>If Sputnik cannot find a node, it will first attempt to find a <em>node default</em> with that name.  The request for &#8216;pages&#8217; results in Sputnik attempting to load a Lua module like so: <strong>require &#8220;sputnik.node_defaults.pages&#8221;</strong>. So we have to create a file <strong>pages.lua</strong> in a directory so that Sputnik can resolve this module.</p>

<p>Sputnik itself is distributed as a <a href="www.luarocks.org">LuaRocks</a> application. In my system, the Sputnik package sits at <strong>~/sputnik/rocks/sputnik/9.03.16-0/lua</strong> &#8211; call this <strong>$SPUTNIK</strong>.  The relevant package directory structure is:</p>

<pre><code>    sputnik
        actions
        hooks
        node_defaults
        ....
</code></pre>

<p>It <em>is</em> possible to customize Sputnik by putting a suitable <strong>pages.lua</strong> in <strong>$SPUTNIK/sputnik/node_defaults</strong>, but that is a road of misery that will end in tears.  However, it&#8217;s useful to acquaint yourself with the contents of this directory because it defines the standard namespaces.</p>

<p>The best quick solution is to add directories to the <strong>LUA_PATH</strong> environment variable before launching Sputnik:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~<span style="color: #000000; font-weight: bold;">/</span>sputnik$ <span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">LUA_PATH</span>=<span style="color: #ff0000;">&quot;;;<span style="color: #007800;">$HOME</span>/sputnik/examples/?.lua&quot;</span></pre></div></div>


<p>Then create a directory <strong>~/sputnik/examples/sputnik/node_defaults</strong> containing this file, <strong>pages.lua</strong>:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
     title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Pages&quot;</span>,
     content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
     child_defaults <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          any<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'prototype = &quot;&quot;'</span>
      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>,
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>It is structured as a Lua module, which contains a single exported table, <strong>NODE</strong> .  The definition of the field <strong>child_defaults</strong> may appear a little hairy at first, but it&#8217;s now time to get the three different ways to do string literals in Lua straight.  Whether you use single or double quotes for a string, does not matter; it is a convenience so that you can embed the other kind of quotes: <strong>&#8216;prototype = &#8220;&#8221;&#8216;</strong>. This string is then further embedded in a Lua &#8216;long string&#8217; literal.</p>

<p>After restarting Sputnik, go to <strong>pages</strong>: nothing much to see at this point &#8211; but note that Sputnik can find the node. If you go to <strong>pages/Introduction</strong> you will get another blank page with a title, which you can edit directly as a Wiki page.  The <strong>child_defaults</strong> field tells Sputnik that any &#8216;child&#8217; of <strong>pages</strong> like <strong>pages/Introduction</strong> has a particular prototype value which corresponds to the &#8216;Basic&#8217; node type.</p>

<p>If you enter this text</p>

<pre><code>    Some text for the Introduction node. See [[pages/Basic]]
</code></pre>

<p>and save, the result will have a link to a new page, which you can in turn edit.</p>

<p>To see how Sputnik saves pages by default, look at the <strong>~/sputnik/wiki-data</strong> directory. There will be a subdirectory <strong>pages%2FIntroduction</strong> with files <strong>000001</strong> and <strong>index</strong>. (The subdirectory is just the URL-encoded form of &#8216;pages/Introduction&#8217; ).  <strong>index</strong> will contain something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  add_version<span style="color: #66cc66;">&#123;</span>
  version   <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;000001&quot;</span>,
  timestamp <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;2009-11-01 14:33:07&quot;</span>,
  author    <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
  comment   <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
   <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">&quot;minor&quot;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
   <span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">&quot;ip&quot;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;127.0.0.1&quot;</span>,
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>And <strong>000001</strong> contains the node text:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  title          <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;pages/Introduction&quot;</span>
  category       <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>
  content        <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>Some text <span style="color: #b1b100;">for</span> the Introduction node. See <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>pages<span style="color: #66cc66;">/</span>Basic<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#93;</span>
  breadcrumb     <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span></pre></div></div>


<p>As the node is edited, each revision is saved in a similar format, <strong>000002</strong>, etc.  In this way, edit history is managed in a simple way, easily readable by humans, as opposed to being stored in some relational database. However, using a database for storage is also supported by the Sputnik content manager, which is called <a href="http://sputnik.freewisdom.org/en/Saci">Saci</a>.</p>

<h2>Custom Output</h2>

<p>Before actually starting with code, it&#8217;s useful to have a handy shortcut to the Lua executable used by Sputnik.  I suggest creating a little executable script like this on your path:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  $<span style="color: #000000; font-weight: bold;">&gt;</span> <span style="color: #c20cb9; font-weight: bold;">cat</span> ~<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>slua
  ~<span style="color: #000000; font-weight: bold;">/</span>sputnik<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>lua -lluarocks.require <span style="color: #007800;">$*</span></pre></div></div>


<p>Before we actually get round to generating dynamic content, here is a quick review of <a href="http://cosmo.luaforge.net/">Cosmo</a>,  which is a powerful template engine used by Sputnik.</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~$ slua</pre></div></div>



<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  Lua 5.1.4  Copyright <span style="color: #66cc66;">&#40;</span>C<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">1994</span>-<span style="color: #cc66cc;">2008</span> Lua.org, PUC-Rio
  <span style="color: #66cc66;">&gt;</span> <span style="color: #b1b100;">require</span> <span style="color: #ff0000;">&quot;cosmo&quot;</span>
  <span style="color: #66cc66;">&gt;</span> template <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;$rank of $suit&quot;</span>
  <span style="color: #66cc66;">&gt;</span> values <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>rank<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Ace&quot;</span>,suit<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Spades&quot;</span><span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&gt;</span> <span style="color: #66cc66;">=</span> cosmo.fill<span style="color: #66cc66;">&#40;</span>template,values<span style="color: #66cc66;">&#41;</span>
  Ace of Spades</pre></div></div>


<p>That&#8217;s useful, although only a little more friendly than Lua&#8217;s <strong>string.format</strong> function.  However, Cosmo goes way beyond simple <a href="http://lua-users.org/wiki/StringInterpolation">string interpolation</a>.</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  <span style="color: #808080; font-style: italic;">-- testcosmo.lua</span>
  <span style="color: #b1b100;">require</span> <span style="color: #ff0000;">&quot;cosmo&quot;</span>
  template <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">==</span><span style="color: #66cc66;">&#91;</span>
  <span style="color: #66cc66;">&lt;</span>h1<span style="color: #66cc66;">&gt;</span>$list_name<span style="color: #66cc66;">&lt;/</span>h1<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&lt;</span>ul<span style="color: #66cc66;">&gt;</span>
   $do_items<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&lt;</span>li<span style="color: #66cc66;">&gt;</span>$item<span style="color: #66cc66;">&lt;/</span>li<span style="color: #66cc66;">&gt;</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&lt;/</span>ul<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">==</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #b1b100;">print</span><span style="color: #66cc66;">&#40;</span>cosmo.fill<span style="color: #66cc66;">&#40;</span>template, <span style="color: #66cc66;">&#123;</span>
      list_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;My List&quot;</span>,
      do_items  <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
          <span style="color: #b1b100;">for</span> i<span style="color: #66cc66;">=</span><span style="color: #cc66cc;">1</span>,<span style="color: #cc66cc;">5</span> <span style="color: #b1b100;">do</span>
             cosmo.yield <span style="color: #66cc66;">&#123;</span> item <span style="color: #66cc66;">=</span> i <span style="color: #66cc66;">&#125;</span>
          <span style="color: #b1b100;">end</span>
      <span style="color: #b1b100;">end</span>
  <span style="color: #66cc66;">&#125;</span>
  <span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span></pre></div></div>



<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~$ slua testcosmo.lua</pre></div></div>



<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">  &lt;h1&gt;My List&lt;/h1&gt;
  &lt;ul&gt;
   &lt;li&gt;1&lt;/li&gt;&lt;li&gt;2&lt;/li&gt;&lt;li&gt;3&lt;/li&gt;&lt;li&gt;4&lt;/li&gt;&lt;li&gt;5&lt;/li&gt;
  &lt;/ul&gt;</pre></div></div>


<p><em>Subtemplates</em> are a powerful feature which makes generating HTML straightforward.</p>

<p>Now, we create a node which creates custom HTML output.  First, put <strong>Memory.lua</strong> in your  <strong>node_defaults</strong> directory:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
      title <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Lua Memory&quot;</span>,
      content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
      actions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          show<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Memory.show_memory&quot;</span>
      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>,
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>Create a directory <strong>actions</strong> (that is, <strong>~/sputnik/examples/sputnik/actions</strong>) and put this <strong>Memory.lua</strong> in it:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  actions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">local</span> template <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>
     <span style="color: #66cc66;">&lt;</span>h2<span style="color: #66cc66;">&gt;</span>Memory used by Lua is $mem kb<span style="color: #66cc66;">&lt;/</span>h2<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #b1b100;">function</span> actions.show_memory <span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
      node.inner_html <span style="color: #66cc66;">=</span> cosmo.f<span style="color: #66cc66;">&#40;</span>template<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
          mem <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'%6.0f'</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #b1b100;">format</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">collectgarbage</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'count'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
      <span style="color: #66cc66;">&#125;</span>
      <span style="color: #b1b100;">return</span> node.wrappers.default<span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">end</span></pre></div></div>


<p>The convention is that any <em>action</em> functions are in the <strong>actions</strong> directory; these functions must be in a nested <strong>actions</strong> table.  Visiting the node <strong>Memory</strong> will show the memory managed by Lua (as returned by the <strong>collectgarbage(&#8216;count&#8217;)</strong> call).</p>

<p>The node&#8217;s <strong>inner_html</strong> is the source for the node&#8217;s display area, that is, not including the menu and all other frame decorations.  <strong>node.wrappers.default</strong> is the actual function which generates the source for the <em>whole</em> page.</p>

<p>So, we now have a customized node with generated output.  Please note that it does not appear in <strong>wiki-data</strong>; the node is fully &#8216;virtual&#8217; and has no storage associated with it.</p>

<p>To take this example further, let us wrap the output of the <strong>ps</strong> command:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~$ <span style="color: #c20cb9; font-weight: bold;">ps</span> aux <span style="color: #660033;">--cols</span> <span style="color: #000000;">256</span>
  USER       PID <span style="color: #000000; font-weight: bold;">%</span>CPU <span style="color: #000000; font-weight: bold;">%</span>MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
  ...
  sdonovan  <span style="color: #000000;">2867</span>  <span style="color: #000000;">0.8</span>  <span style="color: #000000;">2.3</span>  <span style="color: #000000;">41972</span> <span style="color: #000000;">15932</span> pts<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1</span>    Sl   <span style="color: #000000;">10</span>:<span style="color: #000000;">47</span>   <span style="color: #000000;">3</span>:<span style="color: #000000;">57</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>sdonovan<span style="color: #000000; font-weight: bold;">/</span>lua<span style="color: #000000; font-weight: bold;">/</span>scite<span style="color: #000000; font-weight: bold;">/</span>SciTE
  sdonovan  <span style="color: #000000;">2902</span>  <span style="color: #000000;">1.2</span> <span style="color: #000000;">12.4</span> <span style="color: #000000;">179152</span> <span style="color: #000000;">83160</span> ?        Sl   <span style="color: #000000;">10</span>:<span style="color: #000000;">48</span>   <span style="color: #000000;">5</span>:<span style="color: #000000;">19</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>iceweasel<span style="color: #000000; font-weight: bold;">/</span>firefox-bin <span style="color: #660033;">-a</span> firefox
  sdonovan  <span style="color: #000000;">5993</span>  <span style="color: #000000;">0.0</span>  <span style="color: #000000;">0.4</span>   <span style="color: #000000;">5360</span>  <span style="color: #000000;">2844</span> pts<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2</span>    Ss   <span style="color: #000000;">16</span>:<span style="color: #000000;">13</span>   <span style="color: #000000;">0</span>:00 <span style="color: #c20cb9; font-weight: bold;">bash</span>
  sdonovan  <span style="color: #000000;">7118</span>  <span style="color: #000000;">0.0</span>  <span style="color: #000000;">0.3</span>   <span style="color: #000000;">5360</span>  <span style="color: #000000;">2024</span> pts<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">0</span>    S+   <span style="color: #000000;">18</span>:03   <span style="color: #000000;">0</span>:00 <span style="color: #c20cb9; font-weight: bold;">bash</span>
  sdonovan  <span style="color: #000000;">7119</span>  <span style="color: #000000;">0.4</span>  <span style="color: #000000;">1.1</span>   <span style="color: #000000;">8384</span>  <span style="color: #000000;">7380</span> pts<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">0</span>    S+   <span style="color: #000000;">18</span>:03   <span style="color: #000000;">0</span>:01 <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>sdonovan<span style="color: #000000; font-weight: bold;">/</span>sputnik<span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>lua -lluarocks.require <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>sdonovan<span style="color: #000000; font-weight: bold;">/</span>sputnik<span style="color: #000000; font-weight: bold;">/</span>rocks<span style="color: #000000; font-weight: bold;">/</span>sputnik<span style="color: #000000; font-weight: bold;">/</span>9.03.16-<span style="color: #000000;">0</span><span style="color: #000000; font-weight: bold;">/</span>bin<span style="color: #000000; font-weight: bold;">/</span>sputnik.lua start-xavante sputnik.ws</pre></div></div>


<p>(The <strong>&#8211;cols</strong> flag is necessary to prevent <strong>ps</strong> from thoughtfully truncating the line length to fit the terminal screen)</p>

<p>Chopping lines up is easy using <strong>sputnik.util.split</strong> &#8211; notice that it returns multiple values, not a table:</p>


<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">  ~$ slua</pre></div></div>



<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  Lua 5.1.4  Copyright <span style="color: #66cc66;">&#40;</span>C<span style="color: #66cc66;">&#41;</span> <span style="color: #cc66cc;">1994</span>-<span style="color: #cc66cc;">2008</span> Lua.org, PUC-Rio
  <span style="color: #66cc66;">&gt;</span> util <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">require</span> <span style="color: #ff0000;">'sputnik.util'</span>
  <span style="color: #66cc66;">&gt;</span> <span style="color: #66cc66;">=</span> util.split<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'one two three'</span>,<span style="color: #ff0000;">'%s+'</span><span style="color: #66cc66;">&#41;</span>
  one     two     three</pre></div></div>


<p>With this, a more exciting version of <strong>actions/Memory.lua</strong> can be written:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">local</span> util <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">require</span> <span style="color: #ff0000;">'sputnik.util'</span>
  actions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">local</span> template <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>
     <span style="color: #66cc66;">&lt;</span>h2<span style="color: #66cc66;">&gt;</span>Memory used by Lua is $mem kb<span style="color: #66cc66;">&lt;/</span>h2<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;</span>h2<span style="color: #66cc66;">&gt;</span>Processes<span style="color: #66cc66;">&lt;/</span>h2<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;</span>table<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;</span>tr<span style="color: #66cc66;">&gt;</span>
      <span style="color: #66cc66;">&lt;</span>th<span style="color: #66cc66;">&gt;</span>User<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;&lt;</span>th<span style="color: #66cc66;">&gt;</span>CPU<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;&lt;</span>th<span style="color: #66cc66;">&gt;</span>Mem<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;&lt;</span>th<span style="color: #66cc66;">&gt;</span>Command<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;/</span>tr<span style="color: #66cc66;">&gt;</span>
     $do_processes<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          <span style="color: #66cc66;">&lt;</span>tr<span style="color: #66cc66;">&gt;</span>
          <span style="color: #66cc66;">&lt;</span>td<span style="color: #66cc66;">&gt;</span>$user<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;&lt;</span>td<span style="color: #66cc66;">&gt;</span>$cpu<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;&lt;</span>td<span style="color: #66cc66;">&gt;</span>$mem<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;&lt;</span>td<span style="color: #66cc66;">&gt;</span>$cmd<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;</span>
          <span style="color: #66cc66;">&lt;/</span>tr<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
     <span style="color: #66cc66;">&lt;/</span>table<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #b1b100;">function</span> actions.show_memory <span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
      node.inner_html <span style="color: #66cc66;">=</span> cosmo.f<span style="color: #66cc66;">&#40;</span>template<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
          mem <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'%6.0f'</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #b1b100;">format</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">collectgarbage</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'count'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,
          do_processes <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #b1b100;">local</span> user <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">os.getenv</span> <span style="color: #ff0000;">'USER'</span>
              <span style="color: #808080; font-style: italic;">-- this works on LInux, may need some mods for BSD/OS X.</span>
              <span style="color: #b1b100;">local</span> f <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">io</span>.popen<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'ps --cols 256 aux'</span>,<span style="color: #ff0000;">'r'</span><span style="color: #66cc66;">&#41;</span>
              f:<span style="color: #b1b100;">read</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #808080; font-style: italic;">-- not interested in column headers</span>
              <span style="color: #b1b100;">for</span> line <span style="color: #b1b100;">in</span> f:lines<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">do</span>
                  <span style="color: #b1b100;">local</span> fields <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>util.split<span style="color: #66cc66;">&#40;</span>line,<span style="color: #ff0000;">'%s+'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#125;</span>
                  <span style="color: #b1b100;">if</span> fields<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">==</span> user <span style="color: #b1b100;">then</span>
                      cosmo.yield <span style="color: #66cc66;">&#123;</span>
                          user <span style="color: #66cc66;">=</span> fields<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span>, cpu <span style="color: #66cc66;">=</span> fields<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">3</span><span style="color: #66cc66;">&#93;</span>, mem <span style="color: #66cc66;">=</span> fields<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #66cc66;">&#93;</span>, cmd <span style="color: #66cc66;">=</span> fields<span style="color: #66cc66;">&#91;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#93;</span>,
                      <span style="color: #66cc66;">&#125;</span>
                  <span style="color: #b1b100;">end</span>
              <span style="color: #b1b100;">end</span>
          <span style="color: #b1b100;">end</span>
      <span style="color: #66cc66;">&#125;</span>
      <span style="color: #b1b100;">return</span> node.wrappers.default<span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">end</span></pre></div></div>


<p>Now the node <strong>Memory</strong> is actually useful for the administrator of the website &#8211; but probably not a good idea to expose to the world!</p>

<h2>Permissions</h2>

<p>The node <strong>Memory</strong> should be restricted; only the Admin user should be able to view it. Also, it does not make sense to edit it, even as an administrator.  <strong>actions/Memory.lua</strong> needs to have a <em>permissions</em> field:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
      title <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;Lua Memory&quot;</span>,
      content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
      actions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          show<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Memory.show_memory&quot;</span>
      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>,
      permissions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          deny<span style="color: #66cc66;">&#40;</span>all_users,all_actions<span style="color: #66cc66;">&#41;</span>
          allow<span style="color: #66cc66;">&#40;</span>Admin,show<span style="color: #66cc66;">&#41;</span>
      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>We start by prohibiting <em>everything</em>, and then only let Admin view the page.  Notice that all of the usual little action icons on the right-hand side have disappeared.</p>

<p>To get back to the <strong>pages</strong> example; we may insist that only authenticated users can edit the pages.  There are two kinds of solution to this, make it site-wide policy or only for children of <strong>pages</strong>.  The first solution requires no code; as Admin, go to the <strong>@Root</strong> node, and choose the &#8216;configure&#8217; action (which is usually the little gear icon next to &#8216;edit&#8217; on the actions toolbar)  Now open the &#8216;Advanced Fields&#8217; section, and you can then edit the &#8216;Permissions&#8217; field.  By default, Sputnik comments out this line:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  <span style="color: #808080; font-style: italic;">-- deny(Anonymous, edit_and_save)</span></pre></div></div>


<p>Remove the comment and save.  Now anonymous users have lost their power to make edits anywhere on the site.</p>

<p>We&#8217;ve already seen with <strong>Memory</strong> how to enforce permissions for a single node. But how to do this for a group of nodes?  Sputnik <em>prototypes</em> provide the solution.  A prototype acts as the &#8216;type&#8217; of a node. When a node is retrieved from storage, Sputnik copies default values from its prototype node.  The basic prototype of all nodes is <strong>@Root</strong>.</p>

<p>Previously, the <strong>pages</strong> node has insisted that its children have an &#8216;empty&#8217; prototype.  The idea is to create an explicit prototype that will apply to the children, which will be called <strong>@pages</strong>. (By convention, all prototypes begin with &#8216;@&#8217;)</p>

<p><strong>node_defaults/pages.lua</strong> becomes:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
     title<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Pages&quot;</span>,
     content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
     child_defaults <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          any<span style="color: #66cc66;">=</span><span style="color: #ff0000;">'prototype = &quot;@pages&quot;'</span>
      <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>and create a new file <strong>node_defaults/@pages.lua</strong> to define the <strong>@pages</strong> prototype:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
     content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
     permissions<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          deny<span style="color: #66cc66;">&#40;</span>Anonymous,edit_and_save<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>It does very little, just explicitly overrides the permissions.</p>

<h2>Hooks</h2>

<p>Continuing with the <strong>pages</strong> example, it would be useful if we could track the author of a particular page, defined simply as the user that first edited it.  Also, we would like to track the creation date.  So the prototype for all pages must include these new_fields and define a <em>save hook</em> which will be called when the node is saved:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  <span style="color: #808080; font-style: italic;">-- node_defaults/@pages.lua</span>
  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  NODE <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span>
     content <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>,
     permissions<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          deny<span style="color: #66cc66;">&#40;</span>Anonymous,edit_and_save<span style="color: #66cc66;">&#41;</span>
     <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>,
     fields <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
        author <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #cc66cc;">1.1</span><span style="color: #66cc66;">&#125;</span>
        creation_time <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #cc66cc;">1.2</span><span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>,
     save_hook <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;pages.save_page&quot;</span>
  <span style="color: #66cc66;">&#125;</span></pre></div></div>


<p>Create a directory &#8216;sputnik/hooks&#8217; as before, and put <strong>pages.lua</strong> in it:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  <span style="color: #808080; font-style: italic;">-- hooks/pages.lua</span>
  module<span style="color: #66cc66;">&#40;</span>..., package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  <span style="color: #b1b100;">function</span> save_page<span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #b1b100;">not</span> node.creation_time <span style="color: #b1b100;">then</span>
         <span style="color: #b1b100;">local</span> params <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
         params.author <span style="color: #66cc66;">=</span> request.user
         params.creation_time <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">tostring</span><span style="color: #66cc66;">&#40;</span><span style="color: #b1b100;">os.time</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>
         node <span style="color: #66cc66;">=</span> sputnik:update_node_with_params<span style="color: #66cc66;">&#40;</span>node, params<span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">end</span>
      <span style="color: #b1b100;">return</span> node
  <span style="color: #b1b100;">end</span></pre></div></div>


<p>When a node&#8217;s <strong>save_hook</strong> field is set to <strong>MODULE.FUNCTION</strong> , then Sputnik will try to load <strong>sputnik.hooks.MODULE</strong> and use the <strong>FUNCTION</strong> defined by that module.  In this case, the save hook is only interested in a new node, where the author and creation time fields have not been assigned yet.  It uses the <strong>update_node_with_params</strong> method to write the new key/value pairs into the node.</p>

<p>Now, after saving <strong>pages/fred</strong>, the revision in the <strong>pages%2Ffred</strong> directory will look like this:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  title          <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;pages/fred&quot;</span>
  category       <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>
  prototype      <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;@pages&quot;</span>
  content        <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>Some content<span style="color: #66cc66;">!</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
  breadcrumb     <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;&quot;</span>
  author         <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;sdonovan&quot;</span>
  creation_time  <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">&quot;1257157113&quot;</span></pre></div></div>


<p>This shows that we are saving the new information, although these fields are not displayed yet.</p>

<h2>Wrapping up</h2>

<p>Currently, <strong>pages</strong> is blank, and like <strong>Memory</strong>  we can output something sensible by defining a &#8216;show&#8217; action that will display a table of the existing pages.</p>

<p>If you are accustomed to regular Web frameworks, you are probably tempted to maintain and use a relational database at this point.  Sputnik does not exclude that, you are free to store things as you wish, but it&#8217;s best to work with the underlying &#8216;document-oriented&#8217; database machinery provided by Saci.</p>

<p>The existing pages can be found by querying Saci, which provides a <strong>get_nodes_by_prefix</strong> method. The prefix identifies the <em>namespace</em> for the nodes, which is <strong>pages</strong> in this case. This method returns a table where the keys are the <em>identifiers</em> (e.g. <strong>pages/fred</strong>) and the values are the node objects. Here is code that creates a list of nodes from this table, and sorts it by creation time.</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  <span style="color: #b1b100;">local</span> <span style="color: #b1b100;">function</span> pages_in_order <span style="color: #66cc66;">&#40;</span>sputnik<span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">local</span> pages <span style="color: #66cc66;">=</span> sputnik.saci:get_nodes_by_prefix <span style="color: #ff0000;">'pages'</span>
      <span style="color: #b1b100;">local</span> res <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
      <span style="color: #b1b100;">for</span> id,page <span style="color: #b1b100;">in</span> <span style="color: #b1b100;">pairs</span><span style="color: #66cc66;">&#40;</span>pages<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">do</span>
          res<span style="color: #66cc66;">&#91;</span>#res+<span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">=</span> page
      <span style="color: #b1b100;">end</span>
      <span style="color: #b1b100;">table.sort</span><span style="color: #66cc66;">&#40;</span>res,<span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span>p1,p2<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">return</span> p1.creation_time <span style="color: #66cc66;">&lt;</span> p2.creation_time <span style="color: #b1b100;">end</span><span style="color: #66cc66;">&#41;</span>
      <span style="color: #b1b100;">return</span> res
  <span style="color: #b1b100;">end</span></pre></div></div>


<p><strong>node_defaults/pages.lua</strong> gets an actions field, just as with <strong>node_defaults/Memory.lua</strong>:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  actions<span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
      show<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;pages.show_pages&quot;</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span></pre></div></div>


<p>And <strong>actions/pages.lua</strong> will be:</p>


<div class="wp_syntax"><div class="code"><pre class="lua" style="font-family:monospace;">  module <span style="color: #66cc66;">&#40;</span>...,package.seeall<span style="color: #66cc66;">&#41;</span>
&nbsp;
  actions <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">local</span> template <span style="color: #66cc66;">=</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#91;</span>
     <span style="color: #66cc66;">&lt;</span>h2<span style="color: #66cc66;">&gt;</span>Existing Pages<span style="color: #66cc66;">&lt;/</span>h2<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;</span>table<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;</span>tr<span style="color: #66cc66;">&gt;</span>
      <span style="color: #66cc66;">&lt;</span>th<span style="color: #66cc66;">&gt;</span>Page<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;&lt;</span>th<span style="color: #66cc66;">&gt;</span>Author<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;&lt;</span>th<span style="color: #66cc66;">&gt;</span>Created<span style="color: #66cc66;">&lt;/</span>th<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&lt;/</span>tr<span style="color: #66cc66;">&gt;</span>
     $do_pages<span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#91;</span>
          <span style="color: #66cc66;">&lt;</span>tr<span style="color: #66cc66;">&gt;</span>
          <span style="color: #66cc66;">&lt;</span>td<span style="color: #66cc66;">&gt;&lt;</span>a href<span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;?p=$id&quot;</span><span style="color: #66cc66;">&gt;</span>$name<span style="color: #66cc66;">&lt;/</span>a<span style="color: #66cc66;">&gt;&lt;/</span>td<span style="color: #66cc66;">&gt;&lt;</span>td<span style="color: #66cc66;">&gt;</span>$author<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;&lt;</span>td<span style="color: #66cc66;">&gt;</span>$created<span style="color: #66cc66;">&lt;/</span>td<span style="color: #66cc66;">&gt;</span>
          <span style="color: #66cc66;">&lt;/</span>tr<span style="color: #66cc66;">&gt;</span>
     <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#93;</span>
     <span style="color: #66cc66;">&lt;/</span>table<span style="color: #66cc66;">&gt;</span>
  <span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">=</span><span style="color: #66cc66;">&#93;</span>
&nbsp;
  <span style="color: #b1b100;">local</span> <span style="color: #b1b100;">function</span> pages_in_order<span style="color: #66cc66;">&#40;</span>sputnik<span style="color: #66cc66;">&#41;</span>
  ....
  <span style="color: #b1b100;">end</span>
&nbsp;
  <span style="color: #b1b100;">function</span> actions.show_pages<span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
      node.inner_html <span style="color: #66cc66;">=</span> cosmo.f<span style="color: #66cc66;">&#40;</span>template<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
          do_pages <span style="color: #66cc66;">=</span> <span style="color: #b1b100;">function</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
              <span style="color: #b1b100;">local</span> pages <span style="color: #66cc66;">=</span> pages_in_order<span style="color: #66cc66;">&#40;</span>sputnik<span style="color: #66cc66;">&#41;</span>
              <span style="color: #b1b100;">for</span> _,page <span style="color: #b1b100;">in</span> <span style="color: #b1b100;">ipairs</span><span style="color: #66cc66;">&#40;</span>pages<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">do</span>
                  cosmo.yield<span style="color: #66cc66;">&#123;</span>
                      id <span style="color: #66cc66;">=</span> page.id,
                      name <span style="color: #66cc66;">=</span> page.id:<span style="color: #b1b100;">gsub</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'pages/'</span>,<span style="color: #ff0000;">''</span><span style="color: #66cc66;">&#41;</span>,
                      author <span style="color: #66cc66;">=</span> page.author,
                      created <span style="color: #66cc66;">=</span> sputnik:format_time<span style="color: #66cc66;">&#40;</span>page.creation_time,<span style="color: #ff0000;">&quot;%d %b %Y&quot;</span><span style="color: #66cc66;">&#41;</span>
                  <span style="color: #66cc66;">&#125;</span>
              <span style="color: #b1b100;">end</span>
          <span style="color: #b1b100;">end</span>
      <span style="color: #66cc66;">&#125;</span>
      <span style="color: #b1b100;">return</span> node.wrappers.default<span style="color: #66cc66;">&#40;</span>node, request, sputnik<span style="color: #66cc66;">&#41;</span>
  <span style="color: #b1b100;">end</span></pre></div></div>


<h2>Beyond the Basics</h2>

<p>If you are curious about how Sputnik creates the whole page, note that <strong>node.wrappers.default</strong>
is usually implemented by the <strong>wrappers.default</strong> function in <strong>sputnik/actions/wiki.lua</strong> which does a Cosmo expansion of the <strong>node.html_main</strong> template (see <strong>NODE.html_main</strong> in <strong>sputnik/node_defaults/@Root.lua</strong>)</p>

<p>If you don&#8217;t like a visual feature, then it is often easy to remove it.  For instance, editing <strong>@Root</strong> as Admin (using <strong>@Root.configure</strong> as before) you can open up the &#8216;HTML Fields&#8217; and modify the templates directly. Removing the menu bar is as easy as clearing out the text in the &#8216;Menu&#8217; field.</p>

<p>For a good overview of Sputnik permissions, see this <a href="http://sputnik.freewisdom.org/en/list/Way_to_lockdown_editing_features_">list question</a> and its reply.</p>

<p>The next part of this tutorial will deal with further customizations, like internationalization, providing a custom form for editing a node&#8217;s fields, and using the built-in <strong>@Collection</strong> prototype to simplify the common pattern of groups of content nodes.  And Sputnik&#8217;s ability to create custom actions will change the way you look at file extensions forever.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luanova.org/sputnik/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lua and the web: an overview</title>
		<link>http://www.luanova.org/lua-web-overview/</link>
		<comments>http://www.luanova.org/lua-web-overview/#comments</comments>
		<pubDate>Sun, 16 Mar 2008 01:50:03 +0000</pubDate>
		<dc:creator>nathany</dc:creator>
				<category><![CDATA[Lua]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Kepler]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[Wiki]]></category>

		<guid isPermaLink="false">http://luanova.wordpress.com/?p=11</guid>
		<description><![CDATA[Lua is among the top 20 most popular programming languages, according to the TIOBE Programming Community index. Lua is also faster and has a smaller memory footprint than other interpreted scripting languages (compare with Ruby, Python, PHP and JavaScript SpiderMonkey). We haven&#8217;t heard a lot about Lua on the web, even though there are a [...]]]></description>
			<content:encoded><![CDATA[<p>Lua is among the top 20 most popular programming languages, according to the <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html">TIOBE Programming Community index</a>. Lua is also faster and has a smaller memory footprint than other interpreted scripting languages (compare with <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;lang=lua&amp;lang2=ruby">Ruby</a>, <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;lang=lua&amp;lang2=python">Python</a>, <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;lang=lua&amp;lang2=php">PHP</a> and <a href="http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&amp;lang=lua&amp;lang2=javascript">JavaScript SpiderMonkey</a>).</p>

<p>We haven&#8217;t heard a lot about Lua on the web, even though
there are a number of developers working with Lua on the server-side. Lets take a brief look.</p>

<h2>The Kepler Project</h2>

<p><a href="http://www.keplerproject.org/">Kepler</a> is a &#8220;web development platform&#8221; named after astronomer Johannes Kepler. It looks to be the most ambitious project of the bunch. Kepler is written as a number of modules that fit together, and includes its&#8217; own web server named Xavante.</p>

<p>There is also an endeavor to build <em>WSAPI,</em> in similar fashion to
Python&#8217;s <a href="http://www.python.org/dev/peps/pep-0333/">WSGI</a> interface, that support pretty much any web server and configuration (CGI, FastCGI, SCGI, etc, etc.)</p>

<h2>Nanoki</h2>

<p>When I joined to Kepler mailing list, &#8220;Petite Abeille&#8221; was the first person to respond. He has been developing a Wiki called <a href="http://alt.textdrive.com/nanoki/">Nanoki</a>.</p>

<p>However, it is not built on top of Kepler. Instead there is a small built-in web server or will run atop the Unix tcp command. All the source code is released under a MIT license, and is instructive in building a light, focussed web application vs. the broad scope of Kepler.</p>

<h2>mod_wombat</h2>

<p><a href="http://kasparov.skife.org/blog/">Brian McCallister</a> spear-headed a project to embed Lua in an Apache HTTP Server module. Going through Brian&#8217;s <a href="http://kasparov.skife.org/wombat_ac_us_07.pdf">slides</a> is quite inspiring as to just how good a fit this is. Apache does all the heavy-lifting, such as providing a fully multi-threaded &#8220;worker MPM&#8221; (multi-processing module) and a portable runtime (APR) environment. Lua is a thread-safe language, with &#8220;share-nothing&#8221; Lua <em>states</em>, so it fits right in and is super-efficient.</p>

<p>Skimming through <a href="http://www.informit.com/store/product.aspx?isbn=0132409674">The Apache Modules Book</a> is even more inspiring, as you can see the potential of mod_wombat if it took advantage of Apache&#8217;s database connection pooling (DBD) and the various other facilities of Apache HTTP Server.</p>

<p>Wombat is still a little rough around the edges, but you can find the Apache-licensed source code at:
<a href="http://svn.apache.org/repos/asf/httpd/mod_wombat/trunk">http://svn.apache.org/repos/asf/httpd/mod_wombat/trunk</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.luanova.org/lua-web-overview/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

