<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>H3RALD - Tag 'programming' (RSS Feed)</title>
    <language>en-us</language>
    <lastBuildDate>Thu, 12 Nov 2009 12:34:29 -0000</lastBuildDate>
    <ttl>40</ttl>
    <link>http://www.h3rald.com</link>
    <description/>
    <item>
      <title>herald.vim 0.2.1 released</title>
      <description>&lt;p style="float:right;"&gt;&lt;img src="/images/herald.vim/0.2.1_release.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;span class="dropcap"&gt;I&lt;/span&gt; just updated the &lt;a href="/herald-vim-color-scheme/"&gt;Herald Vim color scheme&lt;/a&gt; to improve the readability of delimiters and search results.&lt;/p&gt;
&lt;p&gt;Delimiters are now red (the same color as operators) instead of yellow, so that you can tell the start and end of a string or regular expression more easily. Additionally, search results are no longer highlighted with black text on an orange background for two reasons:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;the orange background is a bit too strong&lt;/li&gt;
	&lt;li&gt;the black foreground causes letters to become &lt;em&gt;completely hidden&lt;/em&gt; by the &lt;em&gt;cursorline&lt;/em&gt; and &lt;em&gt;cursorcolumn&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Search results now have a gray background and a yellow background, as shown in the screenshot on the right.&lt;/p&gt;
&lt;p&gt;If you have any constructive suggestion on how to improve this color scheme, don&amp;#8217;t hesitate to add a comment to this post!&lt;/p&gt;</description>
      <pubDate>Thu, 12 Nov 2009 12:34:29 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/herald-vim-021/</guid>
      <link>http://www.h3rald.com/articles/herald-vim-021/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/herald-vim-021/#comments</comments>
      <category>programming</category>
      <category>vim</category>
    </item>
    <item>
      <title>Take back your site, with nanoc!</title>
      <description>&lt;p&gt;Back in 2004, when I bought the h3rald.com domain, this site was static. At the time I hardly knew &lt;span class="caps"&gt;HTML&lt;/span&gt; and &lt;span class="caps"&gt;CSS&lt;/span&gt;, nevermind server-side languages, so I remember creating a &lt;em&gt;pseudo-template&lt;/em&gt; for the web site layout and using it whenever I wanted to create a new page, to preserve the overall look-and-feel. This was a crude and inefficient strategy, of course: whenever I changed the layout I had to replicate the change in all the pages of the site &amp;ndash; the whole eight of them.&lt;/p&gt;
&lt;p&gt;Five years later, after rebuilding this web site &lt;a href="/h3rald/"&gt;seven times&lt;/a&gt; using different backends (&lt;span class="caps"&gt;PHP&lt;/span&gt; + CakePHP, Ruby + Rails + Typo, etc.), I decided to make it static again, this time with a twist. It all started when I read a &lt;a href="http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html"&gt;post&lt;/a&gt; by Tom Preston-Warner (&lt;a href="http://www.github.com"&gt;GitHub&lt;/a&gt; co-founder) that I finally decided to give it a try. Today, the 8th release of this web site is 100% static: if you load any page, there&amp;#8217;s no server-side interpretation going on, you&amp;#8217;re just browsing a plain &lt;span class="caps"&gt;HTML&lt;/span&gt; page, at most with a few &lt;span class="caps"&gt;AJAX&lt;/span&gt; calls. But let&amp;#8217;s start from the beginning&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Why I don&amp;#8217;t need a blog platform&lt;/h3&gt;
&lt;p&gt;There&amp;#8217;s nothing inherently wrong with blog platforms like Wordpress: they allow &lt;em&gt;anyone&lt;/em&gt; to publish content on the web using a user-friendly administration area. They were built with one thing in mind: make publishing content on the web something as simple as possible, even for people who don&amp;#8217;t know anything about &lt;span class="caps"&gt;HTML&lt;/span&gt;, let alone server-side scripting.&lt;/p&gt;
&lt;p&gt;What about people who &lt;em&gt;do&lt;/em&gt; know about web development though? Do they still need a blog platform? Depends. If you are comfortable with editing files using a text editor, if you enjoy using the command-line on a daily basis, if you like programming and &lt;em&gt;hacking&lt;/em&gt; a little bit, if you don&amp;#8217;t really care about fancy and user-friendly administration backends&amp;#8230; &lt;em&gt;then you probably don&amp;#8217;t&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;All you need is a system to transform a bunch of source files into a web site. The good news is that such system exists &amp;ndash; and you&amp;#8217;re also spoiled for choices!&lt;/p&gt;
&lt;h3&gt;Introducing site compilers&lt;/h3&gt;
&lt;p&gt;The first &lt;em&gt;site compiler&lt;/em&gt; I discovered was &lt;a href="http://webby.rubyforge.org/"&gt;Webby&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[&amp;#8230;] Webby works by combining the contents of a page with a layout to produce &lt;span class="caps"&gt;HTML&lt;/span&gt;. The layout contains everything common to all the pages &amp;mdash; &lt;span class="caps"&gt;HTML&lt;/span&gt; headers, navigation menu, footer, etc. &amp;mdash; and the page contains just the information for that page. You can use your favorite markup language to write your pages; Webby supports quite a few.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are quite a few applications like Webby, such as:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://nanoc.stoneship.org/"&gt;nanoc&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://snk.tuxfamily.org/lib/rassmalog/doc/guide.html"&gt;Rassmalog&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.jekyllrb.com/"&gt;Jeckyll&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://webgen.rubyforge.org/"&gt;WebGen&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://rog.rubyforge.org/"&gt;Rog&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://rote.rubyforge.org/"&gt;Rote&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://hobix.com/"&gt;Hobix&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://rakeweb.rubyforge.org/wiki/wiki.pl"&gt;RakeWeb&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.apeth.com/RubyFrontierDocs/default.html"&gt;RubyFrontier&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://staticmatic.rubyforge.org/"&gt;StaticMatic&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://staticweb.rubyforge.org/"&gt;StaticWeb&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.zenspider.com/ZSS/Products/ZenWeb/"&gt;ZenWeb&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://yurtcms.roberthahn.ca/"&gt;YurtCMS&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://nanoblogger.sourceforge.net/"&gt;NanoBlogger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are probably even more, with different features, but they all try to solve the same problem: provide a way to generate static web sites in an automated way.&lt;/p&gt;
&lt;p&gt;I spent some time reading about each one of them, &lt;a href="http://github.com/h3rald/h3rald/issues/closed#issue/1"&gt;evaluating the pros and cons&lt;/a&gt; and in the end I decided to go for &lt;a href="http://nanoc.stoneship.org/"&gt;nanoc&lt;/a&gt;, simply because it was the only one that seemed to fit all my needs.&lt;/p&gt;
&lt;h3&gt;A quick overview of nanoc&lt;/h3&gt;
&lt;p&gt;nanoc is a nifty tool written in Ruby suitable for &lt;em&gt;[&amp;#8230;] building small to medium-sized websites&lt;/em&gt;. In other words, anything which doesn&amp;#8217;t involve some fancy user interaction. For what concerns blogs, the only user interaction is &lt;em&gt;comments&lt;/em&gt; &amp;ndash; but that&amp;#8217;s fine, because there&amp;#8217;s more than one web service for that, such as &lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt; or &lt;a href="http://intensedebate.com/"&gt;IntenseDebate&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Some details on the project&lt;/h4&gt;
&lt;p&gt;Compared to the alternatives, nanoc is one of the most mature and most maintained, having hit just a few weeks ago its 3.0 release. Its creator, Denis Defreyne, uses it for his own &lt;a href="http://stoneship.org/"&gt;web site&lt;/a&gt; and is involved with the project on a daily basis, both coding and offering support to nanoc users like myself who regularly ask questions on the &lt;a href="http://groups.google.com/group/nanoc"&gt;nanoc user group&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Denis also seems very concerned about keeping documentation up-to-date &amp;ndash; something that really impressed me from a technical writer&amp;#8217;s point of view. The &lt;a href="http://nanoc.stoneship.org/tutorial/"&gt;tutorial&lt;/a&gt; he put together will get you started in no time, and the &lt;a href="http://nanoc.stoneship.org/manual/"&gt;manual&lt;/a&gt; will explain everything else you may possibly want to know. When release 3.0 came out he even put together a &lt;a href="http://nanoc.stoneship.org/migrating/"&gt;migration guide&lt;/a&gt;. If this is still not enough and you don&amp;#8217;t mind spending some time extending the system, nanoc&amp;#8217;s &lt;a href="http://nanoc.stoneship.org/doc/3.0.0/"&gt;RDoc documentation&lt;/a&gt; is very comprehensive compared to other Ruby projects.&lt;/p&gt;
&lt;h4&gt;Sites, Items and data sources&lt;/h4&gt;
&lt;p style="float:right;"&gt;&lt;img src="/img/pictures/nanoc-structure.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;nanoc ships with a really neat command line tool that can do most of the work for you. &lt;code&gt;Nanoc3 create_site h3rald&lt;/code&gt; will create a new web site in a folder called h3rald. The contents of this folder are laid out according to a particular logic (&lt;em&gt;convention over configuration&lt;/em&gt;, remember?) So:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;content&lt;/strong&gt; &amp;ndash; your articles, pages, stylesheets, images, &amp;#8230;all the site content and assets.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;layouts&lt;/strong&gt; &amp;ndash; the site layouts (and partial layouts)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;lib&lt;/strong&gt; &amp;ndash; place your custom ruby code and vendor libraries here&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;output&lt;/strong&gt; &amp;ndash; your &amp;#8220;compiled&amp;#8221; site, ready to be deployed&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;config.yaml&lt;/strong&gt; &amp;ndash; your site&amp;#8217;s configuration file. The only one (and it&amp;#8217;s just a few lines)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Rakefile&lt;/strong&gt; &amp;ndash; place any custom Rake task here&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Rules&lt;/strong&gt; &amp;ndash; defines the rules for compilation, layout and routing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;#8217;s the default &lt;code&gt;config.yaml&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="l-Scalar-Plain"&gt;data_sources&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; 
&lt;span class="p-Indicator"&gt;-&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;items_root&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;
  &lt;span class="l-Scalar-Plain"&gt;layouts_root&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;/&lt;/span&gt;
  &lt;span class="l-Scalar-Plain"&gt;type&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;filesystem_compact&lt;/span&gt;
  &lt;span class="l-Scalar-Plain"&gt;output_dir&lt;/span&gt;&lt;span class="p-Indicator"&gt;:&lt;/span&gt; &lt;span class="l-Scalar-Plain"&gt;output&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A &lt;em&gt;data source&lt;/em&gt; in nanoc defines where data is retrieved from to create the web site. By default, the &lt;a href="http://nanoc.stoneship.org/doc/3.0.0/Nanoc3/DataSources/FilesystemCompact.html"&gt;filesystem_compact&lt;/a&gt; data source requires that you create two files in the /content folder for each article or page of your web page:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;One containing the actual content of the page&lt;/li&gt;
	&lt;li&gt;Another for the page&amp;#8217;s arbitrary metadata&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By personal preference, I chose the &lt;a href="http://nanoc.stoneship.org/doc/3.0/Nanoc3/DataSources/FilesystemCombined.html"&gt;filesystem_combined&lt;/a&gt; data source, which allows you to combine the content and the metadata of a page in a single file.&lt;/p&gt;
&lt;p&gt;The source code for this very article, for example, starts like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;-----
type: article
tags:
- website
- ruby
- programming
- writing
date: 2009-09-15 13:32:51.049000 +02:00
permalink: take-back-your-site-with-nanoc
title: &amp;quot;Take back your site, with nanoc!&amp;quot;
toc: true
-----
Back in 2004, when I bought the h3rald.com domain, this site was static. At the time I hardly 
knew HTML and CSS, nevermind server-side languages, so I remember creating a _pseudo-template_ for
 the web site layout and using it whenever I wanted to create a new page, to preserve the overall look-and-feel. 
This was a crude and inefficient strategy, of course: whenever I changed the layout I had to replicate the change
 in all the pages of the site &amp;amp;ndash; the whole eight of them.
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;At run time, the content goes through a Textile filter and the metadata is used in layouts, to generate tag links automatically, for example.&lt;/p&gt;
&lt;h4&gt;Layouts, filters, and helpers&lt;/h4&gt;
&lt;p&gt;Layouts in nanoc are similar to layouts and views in Rails, but much simpler. The same applies to helpers. Here&amp;#8217;s a snippet from my &lt;a href="http://github.com/h3rald/h3rald/tree/master/layouts/default.erb"&gt;default layout&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;        &amp;lt;div id=&amp;quot;container&amp;quot;&amp;gt;
          &amp;lt;!-- CONTENT START --&amp;gt;
          &amp;lt;div id=&amp;quot;content&amp;quot; class=&amp;quot;clearfix&amp;lt;%= (@item[:permalink] == &amp;#39;home&amp;#39;) ? &amp;#39; home&amp;#39; : &amp;#39; standard&amp;#39; %&amp;gt;&amp;quot;&amp;gt;
            &amp;lt;h2&amp;gt;&amp;lt;%= @item[:title] %&amp;gt;&amp;lt;/h2&amp;gt;
            &amp;lt;%   case @item[:type]
                when &amp;#39;article&amp;#39; then%&amp;gt;
                &amp;lt;div id=&amp;quot;content-header&amp;quot;&amp;gt;
                  &amp;lt;%= render &amp;#39;article_meta&amp;#39;, :article =&amp;gt; @item %&amp;gt;
                &amp;lt;/div&amp;gt;
              &amp;lt;% end %&amp;gt;
              &amp;lt;hr /&amp;gt;
              &amp;lt;div id=&amp;quot;content-body&amp;quot;&amp;gt;
                &amp;lt;%= yield %&amp;gt;
              &amp;lt;/div&amp;gt;
              &amp;lt;div id=&amp;quot;content-footer&amp;quot;&amp;gt;
                &amp;lt;div class=&amp;quot;share&amp;quot;&amp;gt;
                  &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://w.sharethis.com/button/sharethis.js#publisher=6e34d60c-b14e-4c19-9b2f-7c35a9f0ab09&amp;amp;amp;type=website&amp;amp;amp;linkfg=%23a4282d&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
                  &amp;lt;% if @item[:feed] then %&amp;gt;
                  &amp;lt;a href=&amp;quot;&amp;lt;% @item[:feed_url] || @item[:feed]+&amp;quot;rss/&amp;quot; %&amp;gt;&amp;quot; type=&amp;quot;application/rss+xml&amp;quot; rel=&amp;quot;alternate&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;/images/theme/feed-icon-14x14.png&amp;quot; alt=&amp;quot;#&amp;quot;/&amp;gt;H3RALD - &amp;lt;%= @item[:feed_title]%&amp;gt;&amp;lt;/a&amp;gt;
                  &amp;lt;% end %&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;%= render &amp;#39;article_buttons&amp;#39; if @item[:type] == &amp;#39;article&amp;#39; %&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This source code snippet shows quite a few features of nanoc&amp;#8217;s layouts:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You can access the metadata of the page which is being rendered using the &lt;code&gt;@item&lt;/code&gt;, so &lt;code&gt;@item[:title]&lt;/code&gt; returns the page&amp;#8217;s title, for example.&lt;/li&gt;
	&lt;li&gt;Layouts can be nested, and behave like Rails&amp;#8217;s partials. The &lt;code&gt;render&lt;/code&gt; takes a string parameter (the name of the layout to render) and an optional hash parameter to pass variables to the layout.&lt;/li&gt;
	&lt;li&gt;The &lt;code&gt;yield&lt;/code&gt; method is used to include the content of a page.&lt;/li&gt;
	&lt;li&gt;Layouts support any kind of filter, like &lt;span class="caps"&gt;ERB&lt;/span&gt; for example. Go crazy.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Helpers can be used in layouts to perform common tasks, like creating links, feeds, navigation elements and so on. Check the &lt;a href="http://nanoc.stoneship.org/doc/3.0.0/"&gt;source code docs&lt;/a&gt; for more info, and of course feel free to create your own as you see fit.&lt;/p&gt;
&lt;p&gt;Finally, filters are used to filter content markup. nanoc ships with &lt;a href="http://nanoc.stoneship.org/manual/#list-of-built-in-filters"&gt;almost everything you need&lt;/a&gt;, from Textile to Haml to RDoc, but nobody forbids you to create your own, and it&amp;#8217;s dead easy.&lt;/p&gt;
&lt;h4&gt;Rules and tasks&lt;/h4&gt;
&lt;p&gt;While tasks (as in Rake tasks) do not constitute a huge part of nanoc (but as usual, you may need to create your own to perform custom operations), Rules became, as of version 3, one of the key concepts to grasp in order to make everything work. Rules are stored in the &lt;code&gt;Rules&lt;/code&gt; file of your nanoc site, they can be used to:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Define routes, i.e. where pages are deployed in the output folder.&lt;/li&gt;
	&lt;li&gt;Define how pages are compiled, which filters to apply to a particular set of pages, which layouts to use, etc.&lt;/li&gt;
	&lt;li&gt;Define how layout are handled, which filters to apply to a particular layout, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can find more information in the &lt;a href="http://nanoc.stoneship.org/manual/#rules"&gt;manual&lt;/a&gt;, along with other important information, but for now, let&amp;#8217;s say you should be familiar with &lt;em&gt;most&lt;/em&gt; of nanoc&amp;#8217;s jargon and how it works. Let&amp;#8217;s see what you can do with it, in practice.&lt;/p&gt;
&lt;h3&gt;Migrating from your blog platform&lt;/h3&gt;
&lt;p&gt;As of version 7, h3rald.com has been powered by the &lt;a href="http://www.typosphere.org"&gt;Typo&lt;/a&gt; blog platform. If you are not familiar with it, let&amp;#8217;s just say it&amp;#8217;s a sort of Wordpress built on top of Rails: database backend, pretty admin front-end, tags, comments, and all sort of things a blog may need. While Typo is pleasant enough to use, it has all the inherent disadvantages of any other similar platform:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It relies on a database&lt;/li&gt;
	&lt;li&gt;It relies on server-side scripting to render pages&lt;/li&gt;
	&lt;li&gt;It uses a complex caching mechanism to produce, ultimately, semi-static pages&lt;/li&gt;
	&lt;li&gt;It may be subject to exploits, attacks, high server loads, and similar&lt;/li&gt;
	&lt;li&gt;You can&amp;#8217;t really customize it beyond a certain point&lt;/li&gt;
	&lt;li&gt;You have to upgrade your backend frequently, and often is not as painless as you may expect&lt;/li&gt;
	&lt;li&gt;You can&amp;#8217;t use versioning tools like git for your content, as it&amp;#8217;s stored in a database&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;m not claiming that nanoc is blogging&amp;#8217;s silver bullet (it was not created for that), but for sure:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It &lt;em&gt;does not&lt;/em&gt; rely on a database&lt;/li&gt;
	&lt;li&gt;It &lt;em&gt;does not&lt;/em&gt; rely on server-side scripting to render pages (not in real-time, anyway)&lt;/li&gt;
	&lt;li&gt;It &lt;em&gt;does not&lt;/em&gt; need a complex caching mechanism simply because it produces static pages&lt;/li&gt;
	&lt;li&gt;It is definitely less prone to nasty things&lt;/li&gt;
	&lt;li&gt;It&amp;#8217;s extremely flexible and hackable with very little effort&lt;/li&gt;
	&lt;li&gt;You don&amp;#8217;t have to upgrade all the time, but it is &lt;em&gt;really&lt;/em&gt; painless if you decide to&lt;/li&gt;
	&lt;li&gt;You can use git and similar: your content is in plain old text files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Rants are beside the point, suffice to say I recently convinced myself that switching from Typo to nanoc was a &lt;em&gt;good thing&lt;/em&gt;, so let&amp;#8217;s see how it worked out.&lt;/p&gt;
&lt;h4&gt;Posts, pages and comments&lt;/h4&gt;
&lt;p&gt;Out of Typo&amp;#8217;s MySQL database, I just wanted to get the following data:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Pages and posts&lt;/li&gt;
	&lt;li&gt;Tags&lt;/li&gt;
	&lt;li&gt;Comments&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Following the approach used by &lt;a href="http://github.com/mojombo/jekyll"&gt;Jekyll&lt;/a&gt;, I decided to use the simple and powerful &lt;a href="http://sequel.rubyforge.org/"&gt;Sequel&lt;/a&gt; gem. I&amp;#8217;m sorry to disappoint you, but the whole migration process can be summarize with the following Rake task:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:migrate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:usr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:pwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:host&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Please provide :db, :usr, :pass&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:db&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:usr&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:pwd&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sequel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mysql&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:db&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:usr&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:password&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:pwd&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:host&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:host&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;localhost&amp;#39;&lt;/span&gt;
    &lt;span class="c1"&gt;# Remove all existing pages!&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Pathname&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rmtree&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exist?&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mkpath&lt;/span&gt;
    &lt;span class="c1"&gt;# Prepare page data&lt;/span&gt;
    &lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:contents&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;state = &amp;#39;published&amp;#39; || type = &amp;#39;Page&amp;#39;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt; 
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;total_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Migrating [&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]: &amp;#39;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39;...&amp;quot;&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;tags&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_tags&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:keywords&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;comments&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_comments&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;permalink&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:permalink&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;title&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;type&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:type&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;downcase&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;date&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:published_at&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;toc&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
      &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;filters_pre&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_filter&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:text_filter_id&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;convert_code_blocks&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:body&lt;/span&gt;&lt;span class="o"&gt;]+&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:extended&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;
      &lt;span class="n"&gt;write_page&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;extension&lt;/span&gt;
      &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;That&amp;#8217;s it. Well, almost: you can find the &lt;code&gt;get_comments&lt;/code&gt;, &lt;code&gt;get_tags&lt;/code&gt; and &lt;code&gt;get_filter&lt;/code&gt; methods in a separate &lt;a href="http://github.com/h3rald/h3rald/tree/master/lib/utils.rb"&gt;utility file&lt;/a&gt;. Nothing special really, just a few convenience methods wrapping queries or simply processing data. Note how all information, including tags and legacy comments, is saved in each page&amp;#8217;s metadata. The &lt;code&gt;write_page&lt;/code&gt; method simply creates a file in the &lt;code&gt;/contents&lt;/code&gt; folder.&lt;/p&gt;
&lt;h4&gt;Filters and highlighters&lt;/h4&gt;
&lt;p&gt;On my old site, I used mainly Textile and Markdown to write posts. However, some of my really old articles used BBCode, whose corresponding filter is not available in nanoc. No worries, I soon found out that creating a new nanoc filter came down to this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bb-ruby&amp;#39;&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BbcodeFilter&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;Nanoc3&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Filter&lt;/span&gt;
  &lt;span class="n"&gt;identifier&lt;/span&gt; &lt;span class="ss"&gt;:bbcode&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bbcode_to_html&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Yes, that&amp;#8217;s it. Granted, the &lt;code&gt;bb-ruby&lt;/code&gt; gem does all the work, but notice how easy it is to just plug in new Ruby code into nanoc&amp;#8217;s architecture!&lt;/p&gt;
&lt;p&gt;The next big challange was code highlighting. After a quick research, I found at least a half dozen of possible solutions to highlight source code. Some were javascript based, others were based on a server-side language like &lt;span class="caps"&gt;PHP&lt;/span&gt;, Ruby or Python. Again, I looked at Jekyll for inspiration and discovered they integrated the &lt;a href="http://www.pygments.org"&gt;Pygments&lt;/a&gt; &lt;em&gt;Python&lt;/em&gt; library. Why use a Python library for code highlighting in a Ruby-based project? Because there&amp;#8217;s nothing to stop you (if you can run Python on your server, that is), because it looks very neat and because it supports a lot of different programming languages.&lt;/p&gt;
&lt;p&gt;Lazy as I am, I more or less dropped &lt;a href="http://github.com/h3rald/h3rald/blob/master/lib/albino.rb"&gt;Chris Wanstrath&amp;#8217;s Ruby wrapper&lt;/a&gt; into my &lt;code&gt;/lib&lt;/code&gt; folder (I just used Open3 instead of Open4 for Windows compatibility), and monkey-patched nanoc&amp;#8217;s filtering helper as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Nanoc3::Helpers::Filtering&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;highlight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;syntax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Seamlessly ripped off from the filter method...&lt;/span&gt;
    &lt;span class="c1"&gt;# Capture block&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Reconvert &lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gsub!&lt;/span&gt; &lt;span class="sr"&gt;/&amp;lt;%/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="c1"&gt;# Filter captured data&lt;/span&gt;
    &lt;span class="n"&gt;filtered_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;notextile&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="no"&gt;Albino&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;colorize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;syntax&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;lt;/notextile&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; 
    &lt;span class="c1"&gt;# Append filtered data to buffer&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;_erbout&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;filtered_data&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Nanoc3&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Helpers&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Filtering&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;There you go, another thing sorted.&lt;/p&gt;
&lt;h4&gt;Tags and Feeds&lt;/h4&gt;
&lt;p&gt;Adding tagging support was a tiny bit more tricky. nanoc supports content tagging out-of-the-box though metadata and a simple helper, but I wanted to create tag pages (with feeds). Nothing too difficult though, it all came down to a simple Rake task:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:tags&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;site&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Nanoc3&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;.&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_data&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Pathname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;content/tags&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rmtree&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exist?&lt;/span&gt;
    &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mkpath&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="c1"&gt;# Collect tag and page data&lt;/span&gt;
    &lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="k"&gt;next&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
      &lt;span class="nb"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attributes&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
          &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;]+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="c1"&gt;# Write pages&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;each_pair&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;write_tag_page&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;
      &lt;span class="n"&gt;write_tag_feed_page&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;RSS&amp;#39;&lt;/span&gt;
      &lt;span class="n"&gt;write_tag_feed_page&lt;/span&gt; &lt;span class="n"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Atom&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Again, you can find all the other simple utility methods in my &lt;a href="http://github.com/h3rald/h3rald/tree/master/lib/utils.rb"&gt;utility file&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When it came to feeds, I decided to create a new method for the Blogging helper to create &lt;span class="caps"&gt;RSS&lt;/span&gt; feeds, although nanoc does come with an Atom feed generator:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rss_feed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;builder&amp;#39;&lt;/span&gt;
    &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;time&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;prepare_feed&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;
    &lt;span class="c1"&gt;# Create builder&lt;/span&gt;
    &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    &lt;span class="n"&gt;xml&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Builder&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;XmlMarkup&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:target&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:indent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# Build feed&lt;/span&gt;
    &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;instruct!&lt;/span&gt;
    &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:version&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;2.0&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;en-us&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lastBuildDate&lt;/span&gt; &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:last&lt;/span&gt;&lt;span class="o"&gt;][&lt;/span&gt;&lt;span class="ss"&gt;:date&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;rfc822&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ttl&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;40&amp;#39;&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="vi"&gt;@site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:base_url&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;
        &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:articles&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="vi"&gt;@item&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:content_proc&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pubDate&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:date&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;rfc822&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;guid&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="vi"&gt;@site&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:author_email&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
            &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="n"&gt;url_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#comments&amp;#39;&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:tags&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
              &lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;category&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="n"&gt;buffer&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Nothing too daunting, once you get used to Ruby&amp;#8217;s &lt;span class="caps"&gt;XML&lt;/span&gt; builder. I followed a similar approach for my &lt;a href="/archives"&gt;monthly archives&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;3rd-party services&lt;/h4&gt;
&lt;p&gt;Finally, the interactive bits. I basically turned to third-party services and a bit of jQuery for everything which required user-interaction or pulling data from other web sites. Here&amp;#8217;s a list of services and APIs I currently use:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://intensedebate.com/"&gt;IntenseDebate&lt;/a&gt;, for comments.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://code.google.com/apis/ajaxsearch/web.html"&gt;Google &lt;span class="caps"&gt;AJAX&lt;/span&gt; Search &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; for internal site-wide search.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://apiwiki.twitter.com/"&gt;Twitter &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; to fetch tweets.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://delicious.com/help/json"&gt;Delicious &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; to fetch delicious bookmarks.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.backtype.com/developers"&gt;BackType &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; to fetch comments from other sites.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://develop.github.com/"&gt;GitHub &lt;span class="caps"&gt;JSON&lt;/span&gt; &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/a&gt; to fetch GitHub commits for most of my &lt;a href="/projects"&gt;projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to know how I integrated them, check out my &lt;a href="http://github.com/h3rald/h3rald/tree/master/content/js"&gt;/js folder&lt;/a&gt;, it was very simple, really.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I was very happy of switching to nanoc. It didn&amp;#8217;t take me long, and I spent most of the time with non-nanoc issues (brushing up jQuery, &lt;span class="caps"&gt;CSS&lt;/span&gt;, graphics, etc.). Of course knowing the Ruby programming language helps, and if you&amp;#8217;re not comfortable with hacking your way a little bit, then maybe it&amp;#8217;s not for you.&lt;/p&gt;
&lt;p style="float:left;"&gt;&lt;img src="/img/pictures/nanoc-compile.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Personally, I&amp;#8217;ve been waiting for something like nanoc for a long time: its simple and yet powerful architecture makes you able to do virtually anything with it. For the first time in a long time, I feel like I&amp;#8217;m in complete control of my web site, I know every bits of it and if I want to change the way it works or looks I only have to touch a few files.&lt;/p&gt;
&lt;p&gt;nanoc&amp;#8217;s metadata is mindblowing for its simplicity and power: although you&amp;#8217;re not dealing with a database, you can query your content in the easiest ways possible. Whenever I needed a way to easily access pages, filter them, add extra logic to them, I just added metadata. If you forget something, you don&amp;#8217;t have to change your database tables, create new relationships or anything of the sort, you simply add metadata to pages.&lt;/p&gt;
&lt;p&gt;Be warned that tweaking nanoc gets addictive very quickly: you soon end up creating silly little tasks for making things just the way you want. For me, adding a new article to my blog now just means this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;$ rake site:article name=take-back-your-site-with-nanoc
$ vim content/articles/take-back-your-site-with-nanoc
... write &amp;amp; close the file ...
$ Nanoc3 compile 
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;&amp;#8230;Exactly what I need. Nothing more, nothing less.&lt;/p&gt;</description>
      <pubDate>Tue, 15 Sep 2009 11:32:51 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/take-back-your-site-with-nanoc/</guid>
      <link>http://www.h3rald.com/articles/take-back-your-site-with-nanoc/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/take-back-your-site-with-nanoc/#comments</comments>
      <category>website</category>
      <category>ruby</category>
      <category>programming</category>
      <category>writing</category>
    </item>
    <item>
      <title>Herald (Vim Color Scheme)</title>
      <description>&lt;p&gt;I use &lt;a href="http://www.vim.org"&gt;Vim&lt;/a&gt; a lot. It&amp;#8217;s my editor of choice when I code (mainly in Ruby), and also when I write my blog post and articles (mainly in Textile).&lt;br /&gt;
One thing I always liked about Vim was it powerful syntax highlighting: there&amp;#8217;s probably a syntax highlighting file for every programming language ever created, even the new ones (&lt;a href="http://force7.de/nimrod/index.html"&gt;Nimrod&lt;/a&gt;? Sure, &lt;a href="http://www.vim.org/scripts/script.php?script_id=2632"&gt;here&lt;/a&gt;!).&lt;/p&gt;
&lt;p&gt;Furthermore, Vim allows you to create color schemes, and that&amp;#8217;s surprisingly easy to do. Everything you need to do is in the &lt;a href="http://vimdoc.sourceforge.net/htmldoc/syntax.html"&gt;docs&lt;/a&gt;, but that may put you off, so you can just start by editing an existing one &amp;#8212; that&amp;#8217;s what I did.h3. InfiniteRed Black&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been using the &lt;a href="http://blog.infinitered.com/entries/show/8"&gt;ir_black&lt;/a&gt; color scheme for near enough a year. It&amp;#8217;s an excellent color scheme, recommended especially for writing Ruby code:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/herald.vim/ir_black_vim_example.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;I honestly thought this was the best Vim color scheme until I discovered Moria&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Moria&lt;/h3&gt;
&lt;p&gt;Recently I switched to &lt;a href="http://www.vim.org/scripts/script.php?script_id=1464"&gt;moria&lt;/a&gt;, mainly because I find it easier on the eyes. It&amp;#8217;s a matter of taste, of course:&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/herald.vim/moria_vim_example.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The trick is in the background: it&amp;#8217;s not completely black. Still, I didn&amp;#8217;t quite like the colors, so I decided to write my own&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Herald&lt;/h3&gt;
&lt;p&gt;Meet &lt;strong&gt; &lt;a href="/files/herald.vim"&gt;herald.vim&lt;/a&gt; &lt;/strong&gt; (this is a direct link to the raw file, but you may also want to check my &lt;a href="http://github.com/h3rald/stash/tree/master"&gt;stash&lt;/a&gt; on GitHub or the &lt;a href="http://www.vim.org/scripts/script.php?script_id=2684"&gt;script page&lt;/a&gt; on Vim.org):&lt;/p&gt;
&lt;p&gt;&lt;img src="/images/herald.vim/herald_vim_example.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;To sum up, here&amp;#8217;s the &lt;em&gt;features&lt;/em&gt; offered by this new color scheme:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It&amp;#8217;s easier to differentiate syntax elements; in particular reserved words like &lt;code&gt;if&lt;/code&gt; or &lt;code&gt;end&lt;/code&gt;, constants (symbols) and identifiers (instance variables).&lt;/li&gt;
	&lt;li&gt;Operators are highlighted and easier to notice.&lt;/li&gt;
	&lt;li&gt;Dark gray background and black column/row selectors.&lt;/li&gt;
	&lt;li&gt;Added highlight for titles (useful for Textile)&lt;/li&gt;
	&lt;li&gt;Comments do not stand out, unlike in most color schemes&lt;/li&gt;
	&lt;li&gt;Support for 256 color terminal (special thanks to &lt;a href="http://www.frexx.de/xterm-256-notes/"&gt;Wolfgang Frisch&lt;/a&gt; for providing all the info and tools required)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what do you think? Is it tool colorful perhaps? How would &lt;strong&gt;you&lt;/strong&gt; improve it?&lt;/p&gt;</description>
      <pubDate>Wed, 17 Jun 2009 04:11:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/herald-vim-color-scheme/</guid>
      <link>http://www.h3rald.com/articles/herald-vim-color-scheme/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/herald-vim-color-scheme/#comments</comments>
      <category>programming</category>
      <category>vim</category>
    </item>
    <item>
      <title>Personal Log - May 2009</title>
      <description>&lt;p&gt;Yet another extremely busy month, as you can see from the total absence of blog posts and lack of tweets even. Things are getting pretty hectic at work now I guess: less people, more work, more responsibility, same money. They call it &lt;cite&gt;contingency&lt;/cite&gt;; it&amp;#8217;s the latest trend in the Western World, didn&amp;#8217;t you know? I&amp;#8217;m really not impressed. I can&amp;#8217;t complain though I guess: I still enjoy my job very much and I know it could be much worse, so it&amp;#8217;s just a matter of enduring until autumn &amp;#8212; or so they say.&lt;/p&gt;
&lt;h3&gt;Star Trek Premiere&lt;/h3&gt;
&lt;p&gt;The month started with an event I&amp;#8217;d been looking for for months: the &lt;em&gt;premiere&lt;/em&gt; of Star Trek XI, aka &amp;#8220;Star Trek&amp;#8221;. It&amp;#8217;s not that J.J. Abrahms couldn&amp;#8217;t come up with a more original name (&lt;em&gt;Star Trek: Academy&lt;/em&gt; used to be the working title, at one point), he simply wanted to tell the world that this movie was a new beginning, an elaborate way to start from scratch, to reboot what was more than once dubbed &lt;em&gt;a dying franchise&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The movie was enjoyable &amp;#8211; daring and a bit flamboyant &amp;#8211; but still enjoyable nonetheless. I consider myself a Star Trek fan, and although it was &lt;em&gt;not&lt;/em&gt; the usual Star Trek movie, I somehow liked Abrahms&amp;#8217; bold revisitation of Roddenberry&amp;#8217;s universe. Take a bunch of unknowns (Chris Pine) or semi-unknowns (Zachary Quinto), then add some spicy British humor (Simon Pegg) and some old friend (Leonard Nimoy) and throw in an awful lot of &lt;span class="caps"&gt;XXI&lt;/span&gt; century special effects: what you get is not the usual, let&amp;#8217;s-all-rock-because-we&amp;#8217;re-hit traditional Star Trek, of course, it&amp;#8217;s an &lt;em&gt;alternate&lt;/em&gt; version of it.&lt;/p&gt;
&lt;p&gt;That&amp;#8217;s precisely what the movie is meant to be: what Star Trek would have look like if it had been created in the &lt;span class="caps"&gt;XXI&lt;/span&gt; century. The timeline feels disrupted since the very first minute (nevermind the end!), with a Jim Kirk stealing his stepfather&amp;#8217;s car. Chris Pine is an &lt;a href="http://memory-alpha.org/en/wiki/James_T._Kirk_(alternate_reality)"&gt;alternate&lt;/a&gt; Kirk, quite different from the original one, but not that bad. Zachary Quinto, on the other hand, is a true revelation: he definitely is the new Spock, and he couldn&amp;#8217;t have been cast better. So is Simon Pegg as Scotty, but unfortunately he&amp;#8217;s not involved enough.&lt;/p&gt;
&lt;p&gt;The baddies were a bit of a letdown. Nero is a bit too flat, and his ship is way too fancy, no matter where it comes from. Clearly some Hollywood junkie wanted a big, invulnerable dark ship to bring havoc in the galaxy, but that is &lt;span class="caps"&gt;NOT&lt;/span&gt; a Romulan ship, period.&lt;/p&gt;
&lt;p&gt;At any rate, I enjoyed the movie and I&amp;#8217;m looking forward to the second one, which I hope it will be followed by many others.&lt;/p&gt;
&lt;p&gt;Unfortunately in Italy Star Trek is not worshiped in Italy as in it is the US, which is very unfortunate&amp;#8230; Roxanne and I decided to play along and go to the cinema half-dressed-up, but our friends Elora and Michelle came with a full-blown Uhura uniform! The whole cinema kept staring at us. It was a bit freaky, but fun (check out the pics on Facebook &amp;#8212; if you can, that is, I won&amp;#8217;t post them here!).&lt;/p&gt;
&lt;h3&gt;Wedding Planning&lt;/h3&gt;
&lt;p&gt;Just over a month to my wedding. Scared? You bet. Stressed out? Indeed. Roxanne and I managed to get most of the things organized in the end, luckily. In particular, this month:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;We went to the British Consulate in Milan, and applied to get Roxanne&amp;#8217;s legal documents.&lt;/li&gt;
	&lt;li&gt;I bought and had the 7 vest sets delivered to Roxanne&amp;#8217;s brother&amp;#8217;s (Caspar) place, in London.&lt;/li&gt;
	&lt;li&gt;I ended up buying 8 (buy three, get one free) morning suits from &lt;a href="http://www.marksandspencer.com/gp/product/B000N65ELG?extid=pg_msf&amp;amp;247SEM"&gt;Marks and Spencer&lt;/a&gt;, and had them delivered to Caspar&amp;#8217;s place. He&amp;#8217;ll be sending all the stuff over soon, hopefully.&lt;/li&gt;
	&lt;li&gt;Roxanne got the dresses for the maids of honor, and apparently we have to collect them on monday.&lt;/li&gt;
	&lt;li&gt;We sent all the invites we needed to send, but we&amp;#8217;re still waiting for confirmations. It looks like it won&amp;#8217;t be a big wedding, probably around to 60-70 people mark.&lt;/li&gt;
	&lt;li&gt;We ordered the &lt;a href="http://weddings.about.com/cs/glossary/g/Bomboniere.htm"&gt;bomboniere&lt;/a&gt;, they should come through soon.&lt;/li&gt;
	&lt;li&gt;Uncle John told us he had the music for the church and the reception sorted out.&lt;/li&gt;
	&lt;li&gt;We got the rings!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We &lt;em&gt;still&lt;/em&gt; have to organize a few things, namely:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Write and print the prayer books&lt;/li&gt;
	&lt;li&gt;Book the flight for one of my ushers&lt;/li&gt;
	&lt;li&gt;Get some fancy gifts for the bestman and the rest of the people involved in the ceremony&lt;/li&gt;
	&lt;li&gt;Get married civilly here in Genoa&lt;/li&gt;
	&lt;li&gt;Organize a party at our place for the people who can&amp;#8217;t come to the wedding&lt;/li&gt;
	&lt;li&gt;Do something else I can&amp;#8217;t remember right now&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yes, we are still busy as hell. I&amp;#8217;m looking forward to it all, but I&amp;#8217;ll definitely be much more relaxed when it&amp;#8217;s all over!&lt;/p&gt;
&lt;h3&gt;Home Internet: Epilogue?&lt;/h3&gt;
&lt;p&gt;I got broadband at home, finally, after five months. Let&amp;#8217;s do a quick recap:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Last December I signed up to Libero Infostrada, and told them I wanted to disconnect from Telecom&lt;/li&gt;
	&lt;li&gt;In January I actually got disconnected from Telecom, got a new phone line contract, but the Internet was never activated.&lt;/li&gt;
	&lt;li&gt;I kept calling clueless operators on both ends pointlessly for 2-3 months.&lt;/li&gt;
	&lt;li&gt;I got pissed off with Libero, so in April I signed up to Tele2, telling them to disconnect me from Libero. They told me it would take at least 4 weeks.&lt;/li&gt;
	&lt;li&gt;Meanwhile, I signed up to 3g, and got an Internet &lt;span class="caps"&gt;USB&lt;/span&gt; key. At least I can go online, even if with a crappy &lt;span class="caps"&gt;UMTS&lt;/span&gt; connection.&lt;/li&gt;
	&lt;li&gt;After a month, Telecom rings me asking if I want to come back to them, promising I&amp;#8217;ll have the Internet back on &lt;em&gt;soon enough&lt;/em&gt;. Out of desperation, I accept and tell them to disconnect me from Tele2.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Just when I was about to write a long post cursing Telecom and their perverted schemes to force their customers to stay with them, I receive a call from Libero and they tell me that the Internet is now activated! Unbelievable. Now all I have to do is send letters to all the other ISPs (they don&amp;#8217;t do these things on the phone &amp;#8212; clueless operators, remember?) telling them I don&amp;#8217;t want anything to do with them anymore.&lt;/p&gt;
&lt;p&gt;This is how broadband Internet works in Italy. Jealous?&lt;/p&gt;
&lt;h3&gt;Nimrod&lt;/h3&gt;
&lt;p&gt;Last month I decided I would stop programming until after the wedding and so I did (at least at home). Nevertheless, I still keep strive to keep up-to-date with everything concerning technology and in particular programming.&lt;/p&gt;
&lt;p&gt;Out of all the tech news I came across throughout this month, the &lt;a href="http://force7.de/nimrod/"&gt;Nimrod&lt;/a&gt; programming language definitely struck me the most. A German guy came up with a new language &amp;#8212; that&amp;#8217;s not a big news, new programming languages are born every week, if not every day.&lt;/p&gt;
&lt;p&gt;I believe Nimrod is different though. Basically, here&amp;#8217;s why:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It&amp;#8217;s a mixture of Lisp, Python and C. It looks a bit like Python and it behaves like it (indentation matters), it allows the creation of macros, like in Lisp, and &amp;#8211; this is what &lt;em&gt;really&lt;/em&gt; matters to me &amp;#8211; it compiles to plain C (which can then be compiled using &lt;span class="caps"&gt;GCC&lt;/span&gt; or whatever).&lt;/li&gt;
	&lt;li&gt;It is open source and can be used to produce commercially distributed executables.&lt;/li&gt;
	&lt;li&gt;The &lt;a href="http://force7.de/nimrod/manual.html"&gt;manual&lt;/a&gt; is simple to read (but with a few rough edges), and the language looks simple to learn.&lt;/li&gt;
	&lt;li&gt;The language is not yet complete, but it&amp;#8217;s getting close to a 1.0 release. It works as advertised, nonetheless.&lt;/li&gt;
	&lt;li&gt;It offers a comprehensive standard library, and a &lt;em&gt;huge&lt;/em&gt; amount of libraries and wrappers from everything from Windows &lt;span class="caps"&gt;API&lt;/span&gt; to &lt;span class="caps"&gt;GTK&lt;/span&gt; and Cairo.&lt;/li&gt;
	&lt;li&gt;It is cross platform, the Windows version even comes with a one-click installer.&lt;/li&gt;
	&lt;li&gt;It has garbage collection &lt;em&gt;and&lt;/em&gt; it supports manual memory management, if you need it.&lt;/li&gt;
	&lt;li&gt;It&amp;#8217;s statically typed, with type inference&lt;/li&gt;
	&lt;li&gt;It can generate standalone executables, with very little overhead (90KB for an hello world program).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A language like this has been my secret dream for a long time. I thought no one would ever come up like this. I am really looking forward to give it a proper try someday. What&amp;#8217;s wrong with it? For now, a few bits are missing (like native serialization), other than that someone pointed out the weird, rather extreme case insensitiveness of the language. Basically, case &lt;em&gt;and underscores&lt;/em&gt; are ignored to &lt;cite&gt;allow programmers to use their own programming conventions&lt;/cite&gt;. &lt;br /&gt;
Personally I don&amp;#8217;t think this is that bad. After all, if you name your variables &amp;#8220;a_thing&amp;#8221; and &amp;#8220;aThing&amp;#8221; and you want them to mean different things, that&amp;#8217;s bad programming style anyway. Nevertheless, as far as I know it&amp;#8217;s the only language I know which offers such an extreme degree of flexibility in this sense.&lt;/p&gt;
&lt;h3&gt;Learning new things&lt;/h3&gt;
&lt;p&gt;This month I also found myself to be extremely eager to learn about new things. I&amp;#8217;m still faithful to Ruby and all that, but I&amp;#8217;m opening up to new possibility, for different things:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I decided to start listening to slightly more technical podcasts, which are _not_related to tech news. In this way, I don&amp;#8217;t have the pressure of having to listen to them on a regular basis. Other than &lt;a href="http://twit.tv/FLOSS"&gt;&lt;span class="caps"&gt;FLOSS&lt;/span&gt; Weekly&lt;/a&gt;, which is probably the best show about Open Source Software out there, I&amp;#8217;m going to try out &lt;a href="http://www.se-radio.net/"&gt;Software Engineering Radio&lt;/a&gt; and &lt;a href="http://thecommandline.net/"&gt;The Command Line&lt;/a&gt;, both slightly more technical.&lt;/li&gt;
	&lt;li&gt;Because I decided to put my personal programming projects on hold, I&amp;#8217;m having all sort of new ideas about even &lt;em&gt;more&lt;/em&gt; projects I could start as soon as I can. No anticipations until after my wedding, of course.&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;m using Vim all the time now, both at work and at home. I feel confident with it, but I feel I still have a lot to learn, especially when it comes to marks, registers, etc. And I&amp;#8217;m not yet ready to write an article about it &amp;#8212; not the kind of article I&amp;#8217;d like to write, anyway.&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;d like to learn more about Javascript and JQuery. I played around with it and &lt;em&gt;loved it&lt;/em&gt;, but I really never used it for anything serious yet. This, however, may change in the future.&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sun, 31 May 2009 04:35:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/log-may-2009/</guid>
      <link>http://www.h3rald.com/articles/log-may-2009/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/log-may-2009/#comments</comments>
      <category>personal_log</category>
      <category>programming</category>
      <category>wedding</category>
    </item>
    <item>
      <title>Concatenative programming in Ruby</title>
      <description>&lt;p&gt;A while ago, I sat down examining a few &lt;a href="http://www.h3rald.com/articles/10-programming-languages"&gt;alternative programming languages&lt;/a&gt; I might decide to learn someday. Each of those languages has its own peculiarities, and I didn&amp;#8217;t choose them randomly, I chose them based on their popularity, power, paradigm and how actively they are developed.&lt;/p&gt;
&lt;p&gt;I included &lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt; as the only representative for &lt;em&gt;concatenative programming&lt;/em&gt;, an interesting way to write programs, but seldom used in &amp;#8220;recent&amp;#8221; languages (except for Factor and a few others).&lt;/p&gt;
&lt;h3&gt;The Joy of concatenative programming&lt;/h3&gt;
&lt;p&gt;If you have absolutely no clue on what I&amp;#8217;m talking about, you should consider looking at the home page for the &lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy.html"&gt;Joy Programming Language&lt;/a&gt;, or maybe just the &lt;a href="http://www.latrobe.edu.au/philosophy/phimvt/joy/j00ovr.html"&gt;overview&lt;/a&gt;: it should be enough to tikle your curiosity.&lt;/p&gt;
&lt;p&gt;Joy is often considered the &lt;em&gt;canonical&lt;/em&gt; concatenative programming language: a basic &amp;mdash;but working&amp;mdash; implementation of a simple programming language to illustrate the fundamentals of concatenative programming. Joy looks like this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2  3  +  dup  *&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;This simple programs computes the sum of 2 and 3, pushes it on the stack, duplicates it (using the &lt;code&gt;dup&lt;/code&gt; combinator) and then multiplies the two values, obtaining 25 as a result.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s slow down a second. Here&amp;#8217;s what happens, exactly:&lt;/p&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;Element entered &lt;/th&gt;
		&lt;th&gt;Stack contents&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 2 &lt;/td&gt;
		&lt;td&gt; &lt;sup class="footnote" id="fnr2"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 3 &lt;/td&gt;
		&lt;td&gt; [2 3] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; + &lt;/td&gt;
		&lt;td&gt; &lt;sup class="footnote" id="fnr5"&gt;&lt;a href="#fn5"&gt;5&lt;/a&gt;&lt;/sup&gt; &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; dup &lt;/td&gt;
		&lt;td&gt; [5 5] &lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; * &lt;/td&gt;
		&lt;td&gt; &lt;sup class="footnote" id="fnr25"&gt;&lt;a href="#fn25"&gt;25&lt;/a&gt;&lt;/sup&gt; &lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Got it? Let&amp;#8217;s take it one step further. When you enter &lt;code&gt;dup&lt;/code&gt; and then &lt;code&gt;*&lt;/code&gt;, you are effectively computing the square of a number, so we can define the function &lt;code&gt;square&lt;/code&gt; simply as:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;square == dup *&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;In Ruby, this would be:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;square&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;What&amp;#8217;s unusual here? &amp;mdash; Simple, there are no &lt;em&gt;variables&lt;/em&gt; involved. Joy doesn&amp;#8217;t need any explicit variable or &lt;em&gt;formal parameters&lt;/em&gt; of any sort.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s more. Take the following code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;[1 2 3 4]  [dup *]  map&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;map&lt;/code&gt; combinator expects a list and a &lt;em&gt;quoted program&lt;/em&gt; (the same one used to compute the square) and produces a new list containing the result of that program applied to each element of the original list. Basically the equivalent of:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Do you notice anything different? &amp;mdash; Yes, Joy doesn&amp;#8217;t need blocks or lambdas either, it uses &lt;em&gt;quoted programs&lt;/em&gt; instead, which are nothing but slightly fancier lists (or arrays, as you like).&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s recap then, Joy doesn&amp;#8217;t need of:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;lambda functions or blocks (quotation does the trick)&lt;/li&gt;
	&lt;li&gt;explicit parameters (everything you need is on the stack)&lt;/li&gt;
	&lt;li&gt;variable assignments (same as above)&lt;/li&gt;
	&lt;li&gt;explicit recursion (provided you can use combinators like linrec, primrec, binrec, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I would consider this one of the best examples of &lt;em&gt;programming minimalism&lt;/em&gt;: an incredibly simple syntax, a very small set of rules, but a good deal of power.&lt;/p&gt;
&lt;h3&gt;Ruby objects on the stack&lt;/h3&gt;
&lt;p&gt;After reading about Joy, I realized that implementing something similar in Ruby would be an interesting mini-project (let&amp;#8217;s say a week of lunch breaks) to understand more about concatenative programming. It would also be pointless, too: a stack-based programming language implemented on top of one of the most high-level programming languages you can find isn&amp;#8217;t going to be fast, is it? Nevertheless, it would still be interesting.&lt;/p&gt;
&lt;p&gt;Ruby offers everything you need to build a Joy-like &lt;span class="caps"&gt;DSL&lt;/span&gt;:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You can use arrays as &amp;#8230;arrays, but also as quoted programs, and to model the stack itself.&lt;/li&gt;
	&lt;li&gt;You can use integers, strings, etc. as themselves&lt;/li&gt;
	&lt;li&gt;You can use Symbols as functions (we&amp;#8217;ll get to this in a minute)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you think about the following expression in postfix notation:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;2 2 +&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We &lt;em&gt;could&lt;/em&gt; translate it into infix notation (&lt;code&gt;2 + 2&lt;/code&gt;), because Ruby supports it, but it&amp;#8217;s not general enough. What you could do is this though:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:+&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Message sending. I can see all the SmallTalk sympathizers drooling already. Well yes, In Ruby, &lt;em&gt;everything&lt;/em&gt; is an object, so &lt;em&gt;everything&lt;/em&gt; has a receiver and maybe some parameters. In other words, every method call can be reduced to the following syntax:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;In this way, it is safe to assume that everything has a receiver, which could be understood as a function parameter, and may have 0 or more parameters. Take the following then:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:+&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;It&amp;#8217;s not too different from Joy, and it&amp;#8217;s still Ruby code. All you have to do is use something to do the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Take an array, and examine each item:
	&lt;ul&gt;
		&lt;li&gt;If it&amp;#8217;s an object (non-Symbol), then push it on top of the stack.&lt;/li&gt;
		&lt;li&gt;If it&amp;#8217;s a Symbol, then do something different, i.e.:
		&lt;ul&gt;
			&lt;li&gt;Find its receiver and its parameters and call a method.&lt;/li&gt;
			&lt;li&gt;Manipulate something on the stack.&lt;/li&gt;
		&lt;/ul&gt;&lt;/li&gt;
	&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this case, we have to find :+&amp;#8217;s receiver and its parameter and we&amp;#8217;re sorted.&lt;/p&gt;
&lt;p&gt;Unfortunately Ruby&amp;#8217;s &lt;code&gt;arity&lt;/code&gt; method isn&amp;#8217;t that reliable. For example: &lt;code&gt;"test".instance_method(:sub).arity&lt;/code&gt; returns -1, while it should return &amp;#8220;2&amp;#8221; to be useful. So we have no choice but find a way to pass the method&amp;#8217;s arity explicitly, in some cases.&lt;/p&gt;
&lt;p&gt;For example like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Ciao, Fabio&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sr"&gt; /Ciao/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:sub&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;If we define a | operator for the Symbol class, it&amp;#8217;s not too bad after all. It&amp;#8217;s heavy, but in this way we can use &lt;em&gt;any&lt;/em&gt; Ruby method in postfix notation.&lt;/p&gt;
&lt;h3&gt;Introducing the Concatenative Ruby &lt;span class="caps"&gt;DSL&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href="/concatenative"&gt;Concatenative&lt;/a&gt; is a simple Ruby &lt;span class="caps"&gt;DSL&lt;/span&gt; for concatenative programming. You can write concatenative programs inside ordinary Ruby arrays and execute them by calling either &lt;code&gt;Array#execute&lt;/code&gt; or &lt;code&gt;Kernel#concatenate&lt;/code&gt;, like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;concatenative&amp;#39;&lt;/span&gt;

&lt;span class="n"&gt;concatenate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:==&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:+&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:dup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:-&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:*&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;:linrec&lt;/span&gt;
 &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This simple program calculates the factorial of 10. As you can see, no matter how unusual it may look, it is perfectly valid Ruby code and it is equivalent to the following Joy code:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;
10 [0 =] [1 +] [dup 1 -] [*] linrec
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Granted, Joy looks better, but that&amp;#8217;s the tradeoff for not writing a parser for Joy syntax, after all. &lt;br /&gt;
Looking at the code above, there are a few things to keep in mind when programming with Concatenative:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You are using Ruby arrays, so you have to use commas, at least&lt;/li&gt;
	&lt;li&gt;functions, operators and combinators (let&amp;#8217;s just call them &lt;em&gt;words&lt;/em&gt;) are available as Ruby symbols&lt;/li&gt;
	&lt;li&gt;The arity of all Ruby infix operators has been already set to &amp;#8220;1&amp;#8221; by concatenative using the &lt;code&gt;set_arity&lt;/code&gt; method (which simply stores the arity of a particular symbol in a constant hash)&lt;/li&gt;
	&lt;li&gt;You can specify explicit arities using the | operator (&lt;code&gt;:gsub|2&lt;/code&gt;, or &lt;code&gt;:join|1&lt;/code&gt;)&lt;/li&gt;
	&lt;li&gt;Unless the arity has been specified, an arity of 0 is assumed.&lt;/li&gt;
	&lt;li&gt;You can define your own concatenative functions using the &lt;code&gt;Symbol#&amp;lt;=&lt;/code&gt; method, which expects a quoted concatenative program.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Performance issues&lt;/h3&gt;
&lt;p&gt;In its current form, Concatenative can be very slow, as show the &amp;#8220;benchmarks&amp;#8221; provided in the /examples folder, especially if you use recursive combinators. This is understandable because everything is implemented in pure Ruby, which is totally unsuitable for low level stuff.&lt;/p&gt;
&lt;p&gt;If you are interested, you are more than welcome to submit patches and suggestions to improve Concatenative&amp;#8217;s performance, or, if you feel brave enough, you could help me create a C extension instead: things would become much faster then.&lt;/p&gt;
&lt;p&gt;At any rate, feel free to play with it. You can get the source from &lt;a href="http://github.com/h3rald/concatenative/tree/master"&gt;GitHub&lt;/a&gt;, you can get the gem from &lt;a href="http://rubyforge.org/projects/concatenative/"&gt;RubyForge&lt;/a&gt; and you can submit ticket through &lt;a href="http://github.com/h3rald/concatenative/issues"&gt;GitHub&lt;/a&gt; as well.&lt;/p&gt;</description>
      <pubDate>Sat, 28 Mar 2009 06:24:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/concatenative-programming-in-ruby/</guid>
      <link>http://www.h3rald.com/articles/concatenative-programming-in-ruby/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/concatenative-programming-in-ruby/#comments</comments>
      <category>ruby</category>
      <category>concatenative</category>
      <category>programming</category>
    </item>
    <item>
      <title>10 programming languages worth checking out</title>
      <description>&lt;p&gt;If you program for fun or profit, chances are that you know C, C++, Java, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Perl, Python or Ruby. These programming languages are all widely known, and, to a different degree, used in commercial applications. At least some of them can safely be considered &lt;em&gt;mainstream&lt;/em&gt;, even if that word has become so overused and misused that has almost lost its original meaning, if it ever had one.&lt;/p&gt;
&lt;p&gt;If you are earning your living by coding, it&amp;#8217;s often one of these languages that pays the bills. Nevertheless, true hackers frequently meander in other directions, exploring and discovering different paradigms and methodologies, sometimes to the most &lt;a href="http://esolangs.org/wiki/Main_Page"&gt;esoteric&lt;/a&gt; extremes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;The most obvious common &amp;#8216;personality&amp;#8217; characteristics of hackers are high intelligence, consuming curiosity, and facility with intellectual abstractions. Also, most hackers are &amp;#8216;neophiles&amp;#8217;, stimulated by and appreciative of novelty (especially intellectual novelty). Most are also relatively individualistic and anti-conformist.&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style="padding-left:4em;"&gt;&amp;ndash; Eric S. Raymond, &lt;cite&gt;&lt;a href="http://catb.org/jargon/html/personality.html"&gt;The Jargon File&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Even if you&amp;#8217;re particularly devoted to one of the languages mentioned above, it is normal to be curious about what else is out there. As the end of the year approaches, I find myself thinking about learning &amp;ndash; or at least become acquainted with &amp;ndash; some less known, more experimental, programming languages.&lt;br /&gt;
I was originally planning on learning another programming language as a New Year&amp;#8217;s Resolution, which is quite common among programmers. The most difficult task turned out to be &lt;em&gt;choosing&lt;/em&gt; a particular language: there are so many out there which makes it very hard to decide.&lt;/p&gt;
&lt;p&gt;This article deals with ten possible candidates, and it&amp;#8217;s far from being an exhaustive list. The programming languages described henceforth are very different from each other, but they all have one thing in common: they all stimulate my curiosity in their own, very different ways.&lt;/p&gt;
&lt;h3 id="haskell"&gt;Haskell&lt;/h3&gt;
&lt;p&gt;I tried to learn Haskell in the past. Quietly, I started diving into the multitude of articles, tutorials, overviews and even books about this fascinating academic language which claims to achieve functional purity though remaining extremely useful, practical and efficient. Sadly, I&amp;#8217;m still not able to fully grasp some of its most crucial concepts, such as &lt;a href="http://en.wikibooks.org/wiki/Programming:Haskell_monads"&gt;monads&lt;/a&gt;, but this still doesn&amp;#8217;t put me off &lt;em&gt;wishing&lt;/em&gt; to learn the language.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve never enountered Haskell before, I find &lt;a href="http://www.willamette.edu/~fruehr/haskell/evolution.html"&gt;The Evolution of a Haskell Programmer&lt;/a&gt; an amusing and informative read. Although aiming to be humorous in a way, it serves a very important didascalic purpose: it is one of the most complete collections of the different paradigms and programming approaches Haskell allows.&lt;/p&gt;
&lt;p&gt;Besides its very elegant, pragmatic and almost-magical syntax, what really intrigues me about this language is what it offers, in terms of features:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;9 different &lt;a href="http://www.haskell.org/haskellwiki/Implementations"&gt;implementations&lt;/a&gt; (multiple compilers &lt;em&gt;and&lt;/em&gt; interpreters)&lt;/li&gt;
	&lt;li&gt;Countless &lt;a href="http://haskell.org/ghc/docs/latest/html/libraries/"&gt;standard libraries&lt;/a&gt; &lt;a href="http://hackage.haskell.org/packages/archive/pkg-list.html"&gt;packages&lt;/a&gt; which can be used to solve &lt;em&gt;any&lt;/em&gt; programming challenge&lt;/li&gt;
	&lt;li&gt;Abundant &lt;a href="http://www.haskell.org/haskellwiki/Books_and_tutorials"&gt;learning material&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.haskell.org/haskellwiki/Why_Haskell_matters#The_speed_of_Haskell"&gt;Speed&lt;/a&gt; that rivals C and C++&lt;/li&gt;
	&lt;li&gt;Very mature cross-platform compatibility&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The catch? It is likely to be very different from any other language you might have encountered before, and that&amp;#8217;s probably the reason why some people find it difficult to learn and master. That being said, if you are looking for a challenging (but very rewarding, I believe) New Year&amp;#8217;s Resolution, you should definitely go for this.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.haskell.org/"&gt;Official Haskell Wiki&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikibooks.org/wiki/Haskell"&gt;Haskell Wikibook&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://book.realworldhaskell.org/read/index.html"&gt;Real World Haskell&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://cdsmith.wordpress.com/2007/07/29/37-reasons-to-love-haskell-playing-off-the-ruby-article/"&gt;37 Reasons to Love Haskell&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://antoniocangiano.com/2007/03/13/haskell-eye-for-the-ruby-guy/"&gt;Haskell for the Ruby Guy&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.techworld.com.au/article/261007/-z_programming_languages_haskell"&gt;A-Z of Programming Languages: Haskell&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://learnyouahaskell.com/"&gt;Learn you a Haskell for Great Good!&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://cgi.cse.unsw.edu.au/~dons/blog/2008/05/16"&gt;Haskell Hacking&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Erlang&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://erlang.org/"&gt;Erlang&lt;/a&gt; is a concurrent programming language originally developed by Ericsson for their real-time applications. It goes without saying that with these premise, Erlang seems the most natural answer to all concurrency problems you may encounter in your life as a programmer.&lt;br /&gt;
Developing with concurrency in mind feels natural and easy in Erlang, and the performance of Erlang-powered systems can be unmatched.&lt;/p&gt;
&lt;p&gt;Quite a few interesting applications have been developed in this language, such as:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://couchdb.apache.org/"&gt;CouchDB&lt;/a&gt;, a popular distributed, document-oriented database&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://yaws.hyber.org/"&gt;Yaws&lt;/a&gt;, a high-performance web server&lt;/li&gt;
	&lt;li&gt;even &lt;a href="http://www.facebook.com/note.php?note_id=14218138919&amp;amp;id=9445547199"&gt;Facebook Chat&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The price Erlang adepts have to pay, as Damien Katz (CouchDB creator and Erlang enthusiast) &lt;a href="http://damienkatz.net/2008/03/what_sucks_abou.html"&gt;points out&lt;/a&gt;, is:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Awkward syntax, inspired by Prolog&lt;/li&gt;
	&lt;li&gt;Weird if expressions&lt;/li&gt;
	&lt;li&gt;Difficult string operations&lt;/li&gt;
	&lt;li&gt;No classes or namespaces&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;#8230;this list could go on. Damien&amp;#8217;s article is an interesting read, enough to put anyone off learning the language if read superficially. On the other hand, it provides an invaluable resource for newcomers who wish to be prepared before taking on the challenge of learning Erlang to build their next scalable, concurrent and industry-proof application.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.erlang.org/"&gt;Official Erlang Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.onlamp.com/pub/a/onlamp/2007/09/13/introduction-to-erlang.html"&gt;An Introduction to Erlang&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.defmacro.org/ramblings/concurrency.html"&gt;Erlang Style Concurrency&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.planeterlang.org/"&gt;PlanetErlang&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.erlang-projects.org/"&gt;Erlang Projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="io"&gt;Io&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://iolanguage.com/"&gt;Io&lt;/a&gt; is a relatively new programming language by Steve Dekorte which recently surfaced from Google&amp;#8217;s oblivion (if you tried googling for it a few months ago, you couldn&amp;#8217;t event find its home page) thanks to a short vut stimulating &lt;a href="http://hackety.org/2008/01/05/ioHasAVeryCleanMirror.html"&gt;article&lt;/a&gt; by &lt;a href="http://whytheluckystiff.net/"&gt;_why&lt;/a&gt;. It doesn&amp;#8217;t have the best name for a programming language, that&amp;#8217;s for sure, but it&amp;#8217;s definitely a breath of fresh air in terms of the way it works.&lt;/p&gt;
&lt;p&gt;Its unusual, minimalist and yet elegant and powerful syntax reminds of Smalltalk, but the language goes far beyond that. Io is an object-oriented, prototype-based, message-based and fully-reflective programming language. This means that you use messages like in Smalltalk, you create objects like in Javascript and every bit of your code can be inspected and passed around as you see fit.&lt;/p&gt;
&lt;p&gt;If you think Ruby allows fancy (and potentially dirty) tricks like metaprogramming and monkey-patching, Io takes this to a whole different level, imposing virtually no limitation to the programmer. What&amp;#8217;s truly amazing is that its grammar and syntax are so minimal that you can learn them in literally 10 minutes. After that, you can start experimenting, first with its extremely small core and then with its extension libraries and bindings.&lt;/p&gt;
&lt;p&gt;Io has indeed a lot of potential. Granted, it&amp;#8217;s still young and under development, but also already quite efficient and suitable for real-world tasks demanding high speed and concurrency. It is implemented in C, but Ola Bini started to design a similar language called &lt;a href="http://kenai.com/projects/ioke/"&gt;Ioke&lt;/a&gt; for the Java Virtual Machine.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://iolanguage.com/"&gt;Official Io Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/stevedekorte/io/tree/master"&gt;Io Repository on Github&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://tech.groups.yahoo.com/group/iolanguage/"&gt;Io user group&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://hackety.org/2008/01/05/ioHasAVeryCleanMirror.html"&gt;Io has a very clean mirror&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://iota.flowsnake.org/"&gt;Io Notes&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://wiki.type-z.org/index.php/Io/IoLanguage"&gt;Io Language Notes&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://ozone.wordpress.com/2006/03/15/blame-it-on-io/"&gt;Blame it on Io! A slow-paced introduction to the Io language&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://en.wikibooks.org/wiki/Programming:Io"&gt;Io Wikibook&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="plt-scheme"&gt;&lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme&lt;/h3&gt;
&lt;p&gt;I stumbled upon the &lt;a href="http://plt-scheme.org/"&gt;&lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme web site&lt;/a&gt; while browsing for different Lisp flavors about a year ago. At the time, I was determined to learn the rudiments of Lisp and I started reading a few articles and books on this old and yet still popular language.&lt;br /&gt;
Although I was originally put off by certain Common Lisp literature, which dismissed Scheme as an almost-heretic attempt to revitalize an venerable language, I soon found out that Scheme &amp;ndash; and &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme in particular &amp;ndash; is definitely worthy of attention and interest.&lt;/p&gt;
&lt;p&gt;Being a technical writer, I immediately became fond of the &lt;a href="http://docs.plt-scheme.org/guide/"&gt;&lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme Guide&lt;/a&gt;, one of the clearest and most well-organized examples of documentation available for a programming language I&amp;#8217;ve ever come across.&lt;br /&gt;
The manual is exquisitely crafted  as a Getting Started Manual and a Reference Book at the same time, though remaining pleasant to read sequentially: a rare trait in technical documentation. Best of all, it&amp;#8217;s free: you simply have no real excuse not to read it.&lt;/p&gt;
&lt;p&gt;Besides its excellent documentation, &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme feels like a fresh and modern implementation of one of the two most important dialects of Lisp. It&amp;#8217;s cross-platform, it has an extensive &lt;a href="http://planet.plt-scheme.org/"&gt;collection of packages&lt;/a&gt; and a very active community behind it. &lt;br /&gt;
After my first attempt to learn Haskell, I felt compelled to try out &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme and it immediately felt much easier and more user friendly to learn, partly because of &lt;a href="http://download.plt-scheme.org/drscheme/"&gt;DrScheme&lt;/a&gt; a dedicated &lt;span class="caps"&gt;IDE&lt;/span&gt;/learning tool optimized to get you started and feel comfortable with the language.&lt;br /&gt;
Caveats? None, unless you have an adversion for parenthesis, that is.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://plt-scheme.org/"&gt;Official &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://docs.plt-scheme.org/guide/index.html"&gt;&lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme Guide&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://planet.plt-scheme.org/"&gt;PLaneT&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://docs.plt-scheme.org/quick/"&gt;Quick: An Introduction to &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme with Pictures&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://docs.plt-scheme.org/more/"&gt;More: Systems Programming with &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="clojure"&gt;Clojure&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://clojure.org/"&gt;Clojure&lt;/a&gt; is the most recent and notable attempt to bring Lisp back to life and ready to face the challenges posed to IT systems by the new century: concurrency and scalability. Because it runs on the Java Virtual Machine, you also get Java interoperability for free, in a more Lispy flavour. Although I&amp;#8217;m a bit reluctant to deal with anything related to Java nowadays, Clojure&amp;#8217;s approach makes it more appealing.&lt;/p&gt;
&lt;p&gt;Unlike other Lisps (and Schemes) you may have encountered before, Clojure comes with some interesting additions:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://clojure.org/multimethods"&gt;Multimethods&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://clojure.org/agents"&gt;Agents asynchronous actions&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Some interestings &lt;a href="http://clojure.org/special_forms"&gt;special forms&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Many pre-built &lt;a href="http://clojure.org/data_structures"&gt;data structures&lt;/a&gt;, like Vectors, Maps, Sets, Collections, &amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Despite all this, Rich Hickey became increasingly popular both in the Lisp and Java world for creating such an interesting and well-designed language. Unlike with many new (and old) programming languages, I have yet to find a single blog post or article which is seriously criticizing Clojure in any way.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://clojure.org"&gt;Official Clojure Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://groups.google.com/group/clojure"&gt;Clojure User Group&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.infoq.com/presentations/hickey-clojure"&gt;Clojure presentation on InfoQ&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://netzhansa.blogspot.com/2008/10/trying-clojure.html"&gt;Trying Clojure&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://groups.google.com/group/clojure/msg/f038decc18c7da37"&gt;My first look at Clojure&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://enclojure.net/Index.html"&gt;Enclojure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="squeak"&gt;Squeak&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.squeak.org/"&gt;Squeak&lt;/a&gt; has become one of the most popular Smalltalk implementations available. It has been used in some very interesting projects:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://wiki.laptop.org/go/Smalltalk_Development_on_XO"&gt;EToys&lt;/a&gt;, a kids-oriented but powerful development environment built in Squeak, was included as part of the educational sofware suite of the &lt;a href="http://www.laptop.org"&gt;&lt;span class="caps"&gt;OLPC&lt;/span&gt;&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.seaside.st/"&gt;Seaside&lt;/a&gt; is a modern and very productive web framework running on Squeak.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.croquetproject.org/index.php/Main_Page"&gt;Croquet&lt;/a&gt; is a development solution to build complex, multi-user virtual worlds.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you ask &lt;a href="http://www.stonehenge.com/merlyn/"&gt;Randal Schwartz&lt;/a&gt;, he&amp;#8217;ll explain you &lt;a href="http://www.infoq.com/articles/smalltalk-comeback-schwartz"&gt;why&lt;/a&gt; Squeak and Smalltalk are at least worth a look. Personally, while I&amp;#8217;m attracted by Smalltalk&amp;#8217;s unique approach to programming and its friendly syntax, I am still a bit overwhelmed by the way it works. &lt;br /&gt;
Squeak, and Smalltalk in general, runs inside (literally) a virtual machine written in Squeak itself. This means that:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You write your code inside Squeak&lt;/li&gt;
	&lt;li&gt;You debug, inspect and interact your code inside squeak&lt;/li&gt;
	&lt;li&gt;You run your code inside Squeak&lt;/li&gt;
	&lt;li&gt;You can install Squeak on virtually any platform, including mobile phones, fairly easily&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Everything lives inside Squeak. It&amp;#8217;s very weird to picture this without actually trying it, so I suggest you &lt;a href="http://www.squeak.org/Download/"&gt;download it&lt;/a&gt; and give it a try: it will definitely be an unusual but intriguing experience.&lt;/p&gt;
&lt;p&gt;Smalltalk takes programming to a whole different level, which is simply unimaginable for other languages. In return, it asks you to fully embrace the Smalltalk way of doing things, according to which external text editors, external version control systems and other common tools familiar to traditional programmers simply loose their purpose.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.squeak.org/"&gt;Official Squeak Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://squeakbyexample.org/"&gt;Squeak by Example&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.squeakland.org/"&gt;SqueakLand&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.infoq.com/articles/smalltalk-comeback-schwartz"&gt;Ruby&amp;#8217;s Roots: Smalltalk Comeback and Randal Schwartz on Smalltalk&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://twit.tv/floss29"&gt;&lt;span class="caps"&gt;FLOSS&lt;/span&gt; Weekly 29: Dan Ingalls&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="ocaml"&gt;OCaml&lt;/h3&gt;
&lt;p&gt;Like Smalltalk, &lt;a href="http://caml.inria.fr/"&gt;OCaml&lt;/a&gt; has been getting more attention recently than in the past. Sure, not everyone is planning to learn is these days, but after reading &lt;a href="http://enfranchisedmind.com/blog/2008/04/14/useful-things-about-static-typing/"&gt;this article&lt;/a&gt; I admit I was eager to give it a proper try.&lt;/p&gt;
&lt;p&gt;Despite being statically typed, OCaml offers some of the features which are common in dynamically typed languages like Ruby, such as duck typing, the possibility of creating Domain-Specific Languages and even extending the language syntax with custom operators and constructs.&lt;/p&gt;
&lt;p&gt;Additionally, the  &lt;a href="http://batteries.forge.ocamlcore.org/"&gt;OCaml Batteries Included&lt;/a&gt; project was created as an attempt to bundle a standard set of commonly-used library together with the language core. Even if this project is still in alpha stage, it definitely &lt;a href="http://dutherenverseauborddelatable.wordpress.com/2008/11/07/a-taste-of-ocaml-batteries-included/"&gt;looks promising&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://caml.inria.fr/"&gt;Official Caml Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.ocaml-tutorial.org/"&gt;Objective Caml Tutorial&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.csc.villanova.edu/~dmatusze/resources/ocaml/ocaml.html"&gt;A Concise Introduction to Objective Caml&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://wiki.cocan.org/"&gt;The OCaml Alliance Network&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://ocamlnews.blogspot.com/"&gt;OCaml News&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://batteries.forge.ocamlcore.org/"&gt;OCaml Batteries Included&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Factor&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://factorcode.org/"&gt;Factor&lt;/a&gt; is to Forth what &lt;a href="http://clojure.org"&gt;Clojure&lt;/a&gt; is to Common Lisp: a reincarnation of an ancient language in a more modern and practical form. In the specific case, although it borrows from Lisp and Self as well, Factor retains the main characteristics of its ancestor: it&amp;#8217;s stack-based, concatenative and has postfix notation.&lt;br /&gt;
While this is enough to put some people off, if you digg deeper you&amp;#8217;ll discover that Factor offers all the most important features available in contemporary programming languages: garbage collection, dynamic typing, an object system, &amp;#8230; they&amp;#8217;re just presented in a very different way:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;#8220;Learning Factor is tough. One reason for this is that Factor is very different from other programming languages. Programmers today are used to imperative programming languages where data is stored and passed around in named variables (or function calls, which name their variables). Factor is the opposite of this. A lot of code tends to be written in a functional style, and even more jarringly, variables are rare, only referenced in a small fraction of words. Nobody intends to change any of this; it&amp;#8217;s a feature, not a bug!&amp;#8221;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style="padding-left:3em;"&gt;&amp;ndash; Daniel Ehrenberg, &lt;cite&gt;&lt;a href="http://useless-factor.blogspot.com/2008/01/learning-factor.html"&gt;Learning Factor&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;p&gt;Like Haskell, Factor demands a completely different programming approach to what you may be used to, but once you get past that, it can be as useful as any other language, if not more. The &lt;a href="http://docs.factorcode.org/content/article-furnace.html"&gt;Furnace&lt;/a&gt; web framework, which powers the &lt;a href="http://concatenative.org/"&gt;Concatenative&lt;/a&gt; wiki, is entirely built in Factor and runs on top of a Factor web server.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://factorcode.org/"&gt;Official Factor Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://concatenative.org/wiki/view/Factor"&gt;Factor on the Concatenative Wiki&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://docs.factorcode.org/"&gt;Factor Documentation&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://learnfactor.org/"&gt;Learn Factor&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://planet.factorcode.org/"&gt;Planet Factor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="lua"&gt;Lua&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.lua.org/"&gt;Lua&lt;/a&gt; (&amp;#8220;Moon&amp;#8221; in Portuguese), is a lightweight and fast scripting language which can be easily embedded in other systems. Compared to the other languages mentioned in this article, it is definitely the less alien of the lot: if you know a tiny bit of C or Java, you&amp;#8217;ll be able to understand (and possibly write) 80% of Lua code without reading a single line of its documentation.&lt;/p&gt;
&lt;p&gt;Despite its simplicity, Lua is considered a multi-paradigm language supporting imperative, functional and even object-oriented approaches. More specifically, Lua&amp;#8217;s &lt;em&gt;tables&lt;/em&gt; provide a simple but powerful way to create arrays, hashes and even classes (or better, prototypes). Simple (and multiple) inheritance is achieved through &lt;em&gt;metatables&lt;/em&gt;, which allow calls to undefined functions to be &lt;em&gt;transferred&lt;/em&gt; to parent tables.&lt;/p&gt;
&lt;p&gt;Lua programs are not interpreted in the traditional way: they are compiled to bytecode and then executed in the Lua Virtual Machine. As a result, Lua code tends to be executed much faster than other interpreted languages, so fast that &amp;#8220;as fast as Lua&amp;#8221; has become a proverbial expression.&lt;br /&gt;
Lua found its niche in embedded applications and games development, basically everywhere there&amp;#8217;s the need to provide a fast scripting language which is also very easy to learn and extend with C or other languages.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.lua.org/"&gt;Official Lua Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.lua.org/manual/"&gt;Lua Manual&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://lua-users.org/"&gt;Lua-users&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://icculus.org/~theoddone33/lua/"&gt;Learning Lua&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://lua.gts-stolberg.de/en/index.php?uml=1"&gt;Lua for Beginners&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="scala"&gt;Scala&lt;/h3&gt;
&lt;p&gt;You may not be happy to see &lt;a href="http://www.scala-lang.org/"&gt;Scala&lt;/a&gt; in this list instead of other very valid and equally powerful languages for the Java Virtual Machine such as &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;. While there was no doubt on whether Clojure should have been included or not, I was a bit hesitant to include Scala. In the end, I chose to do so simply because Scala fits better in this list than other languages: as you should have noticed by now, I am somehow more inclined to learn functional languages as opposed to their object-oriented counterparts.&lt;/p&gt;
&lt;p&gt;Scala is both object oriented and functional. It offers the best of both worlds: classes, traits and mixins which may be familiar to &lt;span class="caps"&gt;OOP&lt;/span&gt; lovers but also anonymous functions, currying and pattern matching which may please Haskell enthusiasts. Additionally, it&amp;#8217;s also compatible with Java: so if you use Java for work, trying out Scala for pleasure is definitely the most logical next step, especially if you want to experiment with functional programming in the meantime.&lt;/p&gt;
&lt;p&gt;Compared to learning a fully-functional (no pun intended) language like Haskell, Clojure or &lt;span class="caps"&gt;PLT&lt;/span&gt; Scheme, learning Scala is definitely easier and will feel less alien.&lt;/p&gt;
&lt;h4&gt;To get you started&amp;#8230;&lt;/h4&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.scala-lang.org/"&gt;Official Scala Web Site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://blogs.zdnet.com/Burnette/?p=690"&gt;The Case for Scala&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://scala.sygneca.com/"&gt;Scala Wiki&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://grok-code.com/75/learning-scala-with-project-euler/"&gt;Learning Scala with Project Euler&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.codecommit.com/blog/scala/roundup-scala-for-java-refugees"&gt;Roundup: Scala for Java Refugees&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Epilogue&lt;/h3&gt;
&lt;p&gt;There are so many interesting programming language out there that it&amp;#8217;s very hard to keep track of all of them. I hope this list can aid you in the right direction, whichever it may be. &lt;br /&gt;
Some people may debate over the very essence of this article: why &lt;em&gt;choosing&lt;/em&gt; a programming language? Why spending time and energy in a task which may lead to a lot of confusion in your mind and lead you nowhere? What&amp;#8217;s the purpose of learning something which may feel totally alien to you?&lt;/p&gt;
&lt;p&gt;A programming language is ultimately just a tool to get your job done. If you have to write an end-user, desktop &lt;span class="caps"&gt;GUI&lt;/span&gt; application which will always run on Windows and which needs to inteface with Microsoft technologies, you&amp;#8217;ll choose C# over Haskell, there&amp;#8217;s no doubt about that. Especially if 500 developers in your company already develop in C# and you don&amp;#8217;t, as a matter of fact, have a saying on the matter.&lt;/p&gt;
&lt;p&gt;But what if you &lt;em&gt;could&lt;/em&gt; choose? What if you wanted to develop your own geeky command line application to automate a particular task for yourself, and not because someone else tells you to do so? Would you be willing to experiment with something totally different and potentially difficult just for the sake of learning new things?&lt;/p&gt;
&lt;p&gt;If the answer is yes, then you should take a look at this list again. Not now, maybe not this month or this year, but when you feel the time is right, and give one of these languages a shot. It may not end well (so far I attempted to learn Haskell twice, with no luck), but I promise you it will be worthwhile, in the long run. &lt;br /&gt;
If you already mastered some of these languages already, or even all of them, be assured that they&amp;#8217;re plenty out there ready to be discovered and open your mind even more. Or, if you prefer, there are a lot of minds out there which may need guidance in learning and discovery. Help them. Write articles, tutorials, books, educate and evangelize: ultimately, that will be your greatest reward.&lt;/p&gt;</description>
      <pubDate>Sun, 21 Dec 2008 14:01:15 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/10-programming-languages/</guid>
      <link>http://www.h3rald.com/articles/10-programming-languages/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/10-programming-languages/#comments</comments>
      <category>programming</category>
    </item>
    <item>
      <title>Where does your Ruby code live?</title>
      <description>&lt;p&gt;Back when I wrote my &lt;a href="/articles/10-reasons-to-learn-ruby"&gt;10 reasons to learn Ruby&lt;/a&gt; article, I mentioned &lt;a href="http://www.rubygems.org/"&gt;RubyGems&lt;/a&gt; in &lt;em&gt;Reason #1&lt;/em&gt; as one of they key features of the Ruby programming languages.&lt;br /&gt;
Indeed, gems make getting Ruby programs as easy as typing &lt;code&gt;gem install &amp;lt;something&amp;gt;&lt;/code&gt; from the command line. When you want to distribute something new in Ruby, there&amp;#8217;s no need to give people download links, zip files or setup programs, just &lt;a href="http://adam.blog.heroku.com/past/2008/11/2/pony_the_express_way_to_send_email_from_ruby/"&gt;tell them to get the gem&lt;/a&gt;. That&amp;#8217;s perfectly normal, and extremely cool.&lt;/p&gt;
&lt;p&gt;Gems are normally stored on &lt;a href="http://rubyforge.org"&gt;RubyForge&lt;/a&gt;, so all you have to do is uploading your gem there, and it will be available to the rest of the universe. It&amp;#8217;s a nice feeling. I remember when I first uploaded &lt;a href="http://rubyforge.org/projects/rawline/"&gt;RawLine&lt;/a&gt; and then tried &lt;code&gt;gem install rawline&lt;/code&gt; just for the hell of it: it downloaded and installed the gem, as expected.&lt;/p&gt;
&lt;p&gt;Back in the day, if you wanted to find something written in Ruby, all you had to do is search through RubyForge, and you&amp;#8217;d eventually find it, with a bit of luck.&lt;/p&gt;
&lt;h3&gt;Can we just have git, please?&lt;/h3&gt;
&lt;p&gt;RubyForge had, until recently, one major problem: it only allowed &lt;span class="caps"&gt;CVS&lt;/span&gt; and &lt;span class="caps"&gt;SVN&lt;/span&gt; repositories, and you had to make your choice when creating the project, once and for all. So when the cool guys at &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; rolled out their &lt;em&gt;social code hosting&lt;/em&gt; web site, most of the &lt;em&gt;cr&#233;me de la cr&#233;me&lt;/em&gt; of RubyForge flocked there in mass migration: &lt;a href="http://github.com/rails/rails/tree/master"&gt;Rails&lt;/a&gt;, &lt;a href="http://github.com/wycats/merb-core/tree/master"&gt;Merb&lt;/a&gt;, &lt;a href="http://github.com/dchelimsky/rspec/tree/master"&gt;RSpec&lt;/a&gt;&amp;#8230; you name it.&lt;br /&gt;
Once the big guys made the switch, a lot jumped on the GitHub bandwagon of course. Result: we have a lot of projects still on RubyForge, but quite a few (and important ones) on GitHub.&lt;/p&gt;
&lt;p&gt;Why did people move there? Well, at first it was because they wanted a sleek-looking git host, and RubyForge didn&amp;#8217;t offer git at the time. But &lt;a href="http://drnicwilliams.com/2008/04/08/git-for-rubyforge-accounts/"&gt;git is now available on RubyForge&lt;/a&gt;, so why don&amp;#8217;t people use it? &lt;br /&gt;
I&amp;#8217;d like to know how many people use git on RubyForge. Apparently you can have your old &lt;span class="caps"&gt;SVN&lt;/span&gt; repository manually migrated to git, if you ask nicely (and RubyForge people are very helpful always, anyway). Still, I don&amp;#8217;t think many people use git there, and hardly anyone (if any) moved back from GitHub.&lt;/p&gt;
&lt;p&gt;What&amp;#8217;s so special about this new &amp;#8220;social code hosting&amp;#8221; site then? I guess just a few key features:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Fast and reliable git hosting&lt;/li&gt;
	&lt;li&gt;The ability to &amp;#8220;watch&amp;#8221; other people&amp;#8217;s repositories and interact with them &amp;#8220;the git way&amp;#8221;, also by forking.&lt;/li&gt;
	&lt;li&gt;There&amp;#8217;s a whole new and fresh community feeling to it: you can follow people, message them, etc.&lt;/li&gt;
	&lt;li&gt;The interface is much more neat than RubyForge&amp;#8217;s (OK, granted, it doesn&amp;#8217;t take much)&lt;/li&gt;
	&lt;li&gt;Really cool stats and graphs&lt;/li&gt;
	&lt;li&gt;A basic, but functional, wiki&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&amp;#8230;oh, and bug tracking, too!&lt;/h3&gt;
&lt;p&gt;GitHub has no bug tracking features. It tracks an awful lot of stuff about your repositories and people working on them, but &amp;#8220;batteries are sold separately&amp;#8221;. You can get batteries &lt;a href="http://lighthouseapp.com/"&gt;here&lt;/a&gt;, for example. Apparently, GitHub and LightHouse are seamlessly &lt;a href="http://github.com/blog/41-service-integration"&gt;integrated&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So now you can sign up to two cool brand new web applications with neat interfaces instead of sticking with the old-looking RubyForge (which comes with &amp;#8220;batteries included&amp;#8221;, after all). &lt;br /&gt;
Personally &lt;strong&gt;I&amp;#8217;m very confused now&lt;/strong&gt;. Fortunately I don&amp;#8217;t have any extremely cool projects used by thousands of people, so jumping from one source code hosting solution from another is not really an issue for me, but I imagine it would be for others! Correct?&lt;/p&gt;
&lt;p&gt;So, as far as I know, if you are a Rubyist, here&amp;#8217;s what you can do:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Stick with RubyForge: it&amp;#8217;s not so bad after all.&lt;/li&gt;
	&lt;li&gt;Embrace GitHub (and Lighthouse): it&amp;#8217;s extremely nice to use. Some people are not &lt;a href="http://groovie.org/2008/05/06/most-bizarre-git-service-and-other-stupid-rails-powered-businesses"&gt;too convinced&lt;/a&gt; that this is the best choice though.&lt;/li&gt;
	&lt;li&gt;Go for something in between, like &lt;a href="http://www.assembla.com/"&gt;Assembla&lt;/a&gt;, which actually has an &lt;em&gt;impressive&lt;/em&gt; list of features and is powered by Rails too, so you&amp;#8217;ll feel at home. &lt;a href="http://code.google.com/hosting/"&gt;Google Code&lt;/a&gt; used to be another common choice, but sadly they don&amp;#8217;t offer git yet.&lt;/li&gt;
	&lt;li&gt;Do-it-yourself, maybe using something like &lt;a href="http://gitorious.org/"&gt;Gitorius&lt;/a&gt; and some open source bug tracking/project management solution.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So&amp;#8230; what choice did &lt;em&gt;you&lt;/em&gt; make or are you planning to make?&lt;/p&gt;
&lt;h3&gt;Moving houses&lt;/h3&gt;
&lt;p&gt;There&amp;#8217;s one simple issue to consider when moving your code to a new place: what happens to your &lt;em&gt;old&lt;/em&gt; place. If have a relatively popular project, a lot of people may have bookmarked your project page on RubyForge, or the RubyForge subdomain which you may have used as the &amp;#8220;home page&amp;#8221; for your project (in truth, most of the ones who moved away still use it).&lt;/p&gt;
&lt;p&gt;You may setup a redirection to the new home page or put a notice saying that the project moved somewhere else and point visitors to GitHub and LightHouse, or to another web site, if you wish. When &lt;a href="http://weblog.rubyonrails.org/2008/4/11/rails-premieres-on-github"&gt;Rails moved to GitHub&lt;/a&gt;, that wasn&amp;#8217;t much of a problem as Rails has its own web site.&lt;/p&gt;
&lt;p&gt;What may become a problem is your old repository. In Rails&amp;#8217; case, they left the old &lt;span class="caps"&gt;SVN&lt;/span&gt; repository available on sourceforge for a while and then removed it altogether. Other project owners have just abandoned their old repositories, occasionally resulting in &lt;a href="http://webby.rubyforge.org/"&gt;someone else&lt;/a&gt; deciding to leave a note as their &lt;a href="http://webby.rubyforge.org/svn/trunk/"&gt;last &lt;span class="caps"&gt;SVN&lt;/span&gt; commit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These solutions all work (you eventually drive people to the new home of your project), but it&amp;#8217;s not very nice, that&amp;#8217;s all. What happens if someone comes up with something cooler than GitHub? In all honesty, you may end up moving house over and over again.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t forget the gems!&lt;/h3&gt;
&lt;p&gt;One thing I liked about RubyForge, as I wrote at the beginning, was that if you uploaded a gem there, it was immediately available to everyone typing &lt;code&gt;gem install &amp;lt;something&amp;gt;&lt;/code&gt;.  &lt;br /&gt;
Luckily, &lt;a href="http://gems.github.com/list.html"&gt;GitHub supports gems, too&lt;/a&gt;! We&amp;#8217;re saved. The page they put up is &lt;a href="http://gems.github.com/"&gt;utterly awful&lt;/a&gt;, but it does the job: you can have your gems hosted on GitHub.&lt;/p&gt;
&lt;p&gt;Good! So surely I can get Rails now, right? Yup: &lt;code&gt;gem install rails&lt;/code&gt; will get the latest version of Rails for you, straight from GitHub.&lt;/p&gt;
&lt;p&gt;Actually, no. It doesn&amp;#8217;t seem to work that way: sure you can get the latest rails in that way, but it will actually be downloaded from &lt;em&gt;RubyForge&lt;/em&gt; (go check the &lt;a href="http://rubyforge.org/frs/?group_id=307&amp;amp;release_id=27493"&gt;downloads&lt;/a&gt;, you&amp;#8217;ll see it there). &lt;br /&gt;
So even if technically you got Rails, you got it from RubyForge. If you want to get gem from GitHub, you have to add it as gem source first (that&amp;#8217;s an &lt;em&gt;una tantum&lt;/em&gt; operation, luckily): &lt;code&gt;gem sources -a http://gems.github.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So, yes, you can move to GitHub and you&amp;#8217;ll also get gem support: but please &lt;em&gt;remind the users&lt;/em&gt; that they have to add GitHub as gem source. Or, better, you should always remember to upload your latest gems to GitHub &lt;em&gt;and to RubyForge as well&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;The present&lt;/h3&gt;
&lt;p&gt;To sum up:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If you want, you can stay on RubyForge. It has git, it has gems, it&amp;#8217;s probably not nearly as prettier than competitors and is not as social, but it works.&lt;/li&gt;
	&lt;li&gt;You can opt for GitHub+LightHouse, have a slick interface, plenty of features and your project will be scattered in 2 different places + your home page, and you&amp;#8217;ll also have to keep uploading your gems to RubyForge.&lt;/li&gt;
	&lt;li&gt;At this point, you may even go for something completely different, like Assembla or your own setup, but still upload your gems to RubyForge.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The obvious solutions at this point would be that the folks who craft rubygems (the gem which makes the gems, to be clear) add GitHub as default source. Sure as hell when that happens other people will want that too (hey, I&amp;#8217;ll have gems.h3rald.com setup by then!). Is this the future? I hope not.&lt;/p&gt;
&lt;h3&gt;The future?&lt;/h3&gt;
&lt;p&gt;You know there&amp;#8217;s a domain called &lt;a href="http://www.rubygems.org/"&gt;www.rubygems.org&lt;/a&gt;? It&amp;#8217;s where the gem &lt;em&gt;manuals&lt;/em&gt; are! &lt;br /&gt;
As much as I love documentation, there&amp;#8217;s nothing wrong in moving all those documents and books to something like &lt;em&gt;docs.rubygems.org&lt;/em&gt;, right? &lt;br /&gt;
Then they could make RubyGems.org the &lt;em&gt;only&lt;/em&gt; official gem server and tell people they should upload their gems there if they want to distribute them efficiently (after manual approval, if necessary, like there is on RubyForge).&lt;/p&gt;
&lt;p&gt;In this way:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You wouldn&amp;#8217;t have to upload stuff to RubyForge anymore&lt;/li&gt;
	&lt;li&gt;You could have the clever folks at GitHub to create a simple script to automate the upload&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;d have virtually &lt;em&gt;all&lt;/em&gt; the gems in one place&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;d put a good domain name (currently almost forgotten) to good use&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While they are at it, &lt;strong&gt;the clever folks at RubyGems.org could also setup a &lt;em&gt;proper&lt;/em&gt; gem directory with a &lt;em&gt;proper&lt;/em&gt; search&lt;/strong&gt;. I&amp;#8217;m sure there would be plenty of people who could help, too!&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s not impossible, right? They said that making Rails/Ruby/RSpec documentation more accurate and accessible was impossible, but now there&amp;#8217;s &lt;a href="http://apidock.com/"&gt;APIdock&lt;/a&gt;, correct?&lt;/p&gt;
&lt;p&gt;Personally I&amp;#8217;d like it to be a collaborative effort of the Ruby community (like ruby-lang.org), rather than one private company showing off, but I think everyone will be happy as long as it works.&lt;br /&gt;
I&amp;#8217;m sure people will contribute, I would try at least (after finishing the Italian translation of ruby-lang.org, that is&amp;#8230; erhm, well, that&amp;#8217;s another story&amp;#8230;).&lt;/p&gt;
&lt;p&gt;Thoughts?&lt;/p&gt;</description>
      <pubDate>Sat, 08 Nov 2008 12:34:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/where-does-your-ruby-code-live/</guid>
      <link>http://www.h3rald.com/articles/where-does-your-ruby-code-live/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/where-does-your-ruby-code-live/#comments</comments>
      <category>ruby</category>
      <category>programming</category>
    </item>
    <item>
      <title>Git for the Locals</title>
      <description>&lt;p&gt;&lt;em&gt;&amp;#8220;This is a &lt;strong&gt;local&lt;/strong&gt; shop for &lt;strong&gt;local&lt;/strong&gt; people, we want no trouble here!&amp;#8221;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;mdash; Edward, &lt;a href="http://en.wikipedia.org/wiki/League_of_gentlemen"&gt;The League of Gentlemen&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m normally quite cautious when it comes to IT novelties like new frameworks, new methodologies and similar, especially when it feels like they&amp;#8217;re over-hyped. Especially nowadays, it is sometimes very hard to tell whether something new is over-hyped or really a Good Thing&amp;#8482; without spending some time looking into it. And especially nowadays, finding the time to look into something new can be a real challange.&lt;/p&gt;
&lt;p&gt;I deliberately didn&amp;#8217;t look into Git properly since it went &amp;#8220;mainstream&amp;#8221; (maybe I shouldn&amp;#8217;t use this word), but when &lt;a href="http://www.spheredev.org/wiki/Git_for_the_lazy"&gt;this tutorial&lt;/a&gt; came out I couldn&amp;#8217;t resist. Sure, I knew Git was an amazingly fast distributed version control system, that &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; offered free accounts, that all the cool guys were slowly starting to use it in place of Subversion, etc. etc.&lt;/p&gt;
&lt;p&gt;What I didn&amp;#8217;t realize though, that the most obvious advantage of this &lt;span class="caps"&gt;DVCS&lt;/span&gt; was the fact that it was &lt;strong&gt;distributed&lt;/strong&gt;, i.e., it &lt;em&gt;didn&amp;#8217;t need&lt;/em&gt; a centralized server.&lt;/p&gt;
&lt;p&gt;Let me repeat this: &lt;strong&gt;Git &lt;em&gt;doesn&amp;#8217;t need&lt;/em&gt; a centralized server.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Really.h3. &amp;#8230;But it&amp;#8217;s not user-friendly!&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re a Windows user and you used Subversion before, chances are that you got accustomed to &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt;, too. TortoiseSVN is &amp;mdash; in a way &amp;mdash; a nice graphical fron-end to &lt;span class="caps"&gt;SVN&lt;/span&gt; which provides seamless Windows Explorer integration. &lt;br /&gt;
Git doesn&amp;#8217;t have anything like that yet. There&amp;#8217;s something in the works, sure, but nothing really comparable to TortoiseSVN. Therefore, you are &lt;em&gt;kindly suggested&lt;/em&gt; to get on and use the command line for all your git stuff.&lt;/p&gt;
&lt;p&gt;Oh well, I personally love using command line interfaces for certain tasks, event if I spend more time on Windows than on any other OS and well, the &lt;span class="caps"&gt;DOS&lt;/span&gt; prompt is no way near to bash &amp;amp; Co.&lt;/p&gt;
&lt;p&gt;For the &lt;del&gt;lazy gits&lt;/del&gt; Windows users, &lt;a href="http://code.google.com/p/msysgit/"&gt;MSysGit&lt;/a&gt; is the answer to all your problems. &lt;em&gt;Officially&lt;/em&gt; you have to install Cygwin and all its crap to be able to use Git on Windows. Not that Cygwin is bad, but I personally don&amp;#8217;t like the extra layer it creates between you and an OS symulation which is not really what&amp;#8217;s on your machine.It would be great if you could get all the Bash goodies natively, without the hassle.&lt;/p&gt;
&lt;p&gt;that&amp;#8217;s basically what you get for free when you install MSysGit: the best (to date) version of Bash you could possibly dream of for Windows, along with a few handy Gnu tools and of course all git commands.&lt;br /&gt;
In a few click, you&amp;#8217;ll be able to use Git (and Bash!) right away: no tricks, no hassle, no kidding.&lt;/p&gt;
&lt;p&gt;And stop moaning about the command line not being user friendly. You want a new repository &lt;em&gt;anywhere&lt;/em&gt;? Just type in the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;git init
git add .
git commit
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This will create your new repository in the current directory, add all your files and filders recursively, and perform the initial commit. What&amp;#8217;s so hard in this? Nothing. And it&amp;#8217;s faster than &lt;span class="caps"&gt;SVN&lt;/span&gt;, for sure.&lt;/p&gt;
&lt;h3&gt;Are you local?&lt;/h3&gt;
&lt;p&gt;&amp;#8220;Being local&amp;#8221; has its own advantages: you know where you stand, you know what to expect, you don&amp;#8217;t depend on other people. What I didn&amp;#8217;t fully realize about Git is that it can be a 100% &lt;em&gt;local&lt;/em&gt; repository.&lt;/p&gt;
&lt;p&gt;The three Git commands I mentioned earlier can be used to create a repository &lt;em&gt;there&lt;/em&gt;, exactly where you are: not on a server far, far away.&lt;br /&gt;
Let&amp;#8217;s see what this means:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;You don&amp;#8217;t need an Internet connection anymore to use a &lt;span class="caps"&gt;VCS&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;You don&amp;#8217;t get a .svn folder in &lt;em&gt;every&lt;/em&gt; damn directory of your project, with a load of crappy files in it.&lt;/li&gt;
	&lt;li&gt;You get only a .git folder &lt;em&gt;at top level&lt;/em&gt;, and that&amp;#8217;s where your repository actually is. Granted, there are going to be quite a few files in there, but they&amp;#8217;re not going to be scattered all over the place&lt;/li&gt;
	&lt;li&gt;You can physically copy your repository anywhere and still use it&lt;/li&gt;
	&lt;li&gt;You don&amp;#8217;t need to signup to GitHub for an account, if you only want your own &lt;span class="caps"&gt;VCS&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;OK, this is an extreme scenario, but sometimes you may want your &lt;em&gt;own&lt;/em&gt; local repository for your stuff. You may want a place to version your documents, or a place to version your own little pet programming project nobody knows about.&lt;br /&gt;
With Git, you can get all the advantages of a &lt;span class="caps"&gt;VCS&lt;/span&gt; (and an &lt;em&gt;incredibly fast&lt;/em&gt; &lt;span class="caps"&gt;VCS&lt;/span&gt;) without having to setup any server infrastructure: just install Git on your machine, and you&amp;#8217;re done. No server processes, no hassle.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t connect, synchronize&lt;/h3&gt;
&lt;p&gt;All the information your repository needs is stored in that little .git folder, nowhere else. You can copy your files and that folder, and you&amp;#8217;ll still get your repository back wherever you are. Maybe you can zip it before copying it, and then unzip it where you need a &lt;span class="caps"&gt;VCS&lt;/span&gt;, event.&lt;/p&gt;
&lt;p&gt;I tried using some synchronization utilities like SyncToy or RoboCopy on Windows to keep my files synchronized on multiple computers: it all started off from the fact that I can&amp;#8217;t use &lt;span class="caps"&gt;SSH&lt;/span&gt; at work, so I wouldn&amp;#8217;t be able to push my commits back to a central repository online like GitHub.&lt;/p&gt;
&lt;p&gt;So here&amp;#8217;s what I did:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;I setup a local repository for my project on a local folder at work.&lt;/li&gt;
	&lt;li&gt;I started working on my project, did a few commits.&lt;/li&gt;
	&lt;li&gt;After performing the last commit for the day (you are encouraged to commit often by Git, really), I synchronized that folder with my &lt;span class="caps"&gt;USB&lt;/span&gt; key, via SyncToy.&lt;/li&gt;
	&lt;li&gt;Back at home, I used SyncToy again to synchronize my files (including the repository) between the &lt;span class="caps"&gt;USB&lt;/span&gt; key and my home computer.&lt;/li&gt;
	&lt;li&gt;Performing a &lt;code&gt;git status&lt;/code&gt; showed that some files have been modified (all of them, actually): that&amp;#8217;s because Git detected that they weren&amp;#8217;t the same files which were committed, presumably because of different timestamps etc.&lt;/li&gt;
	&lt;li&gt;All I did was a &lt;code&gt;git reset --hard&lt;/code&gt; to get &lt;em&gt;exactly&lt;/em&gt; the same files I committed at work, with absolutely no information loss.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Isn&amp;#8217;t it a bad thing to move your git folder back and forth and let another program to synchronize files within it? Maybe, but it seems to work so far. A safer option, in this case, may be zipping the folder before synchronizing it, just to be sure.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Git can do much more than this. Git offers some really interesting branching features, for example, which I didn&amp;#8217;t mention in this article, of course, like several dozens of other commands. What I tried to point out was that Git can be used by &lt;em&gt;anyone&lt;/em&gt;, as a fast, simple and very effective private &lt;em&gt;local&lt;/em&gt; repository. In case you need one, that is (if you are really &lt;em&gt;local&lt;/em&gt;).&lt;/p&gt;</description>
      <pubDate>Tue, 15 Jul 2008 04:18:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/git-for-the-locals/</guid>
      <link>http://www.h3rald.com/articles/git-for-the-locals/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/git-for-the-locals/#comments</comments>
      <category>programming</category>
    </item>
    <item>
      <title>I'm on Twitter, anyway...</title>
      <description>&lt;p&gt;I&amp;#8217;ve been neglecting my blog, I know. The truth is that I&amp;#8217;m quite busy in this period: I have more responsibilities in my daily full-time jobs, my lunch breaks are getting shorter and I don&amp;#8217;t have much free time. At any rate, here&amp;#8217;s what&amp;#8217;s going on:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I&amp;#8217;m writing a new article for an online magazine (assuming I&amp;#8217;m gonna finish it)&lt;/li&gt;
	&lt;li&gt;I signed up for a freelance technical reviewing job, for a new Ruby book which will come out soon-ish&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;m getting ready to finally visit Rome (again), this time with my fianc&#233;e, for our fifth anniversary.&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;m slowly preparing a version 1.0 of &lt;a href="http://code.google.com/p/redbook/"&gt;RedBook&lt;/a&gt;, which involves quite a lot of refactoring (and hopefully better documentation and tests).&lt;/li&gt;
	&lt;li&gt;I&amp;#8217;m trying to learn a little bit of Haskell: it seems to be one of the few non .&lt;span class="caps"&gt;NET&lt;/span&gt; languages able to produce standalone .exe files, nowadays&amp;#8230;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Last but not least, I now decided to use &lt;a href="http://twitter.com"&gt;Twitter&lt;/a&gt; regularly, so you can follow me &lt;a href="http://twitter.com/h3rald/"&gt;there&lt;/a&gt;, if you wish!&lt;/p&gt;</description>
      <pubDate>Sun, 18 May 2008 09:04:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/im-on-twitter-anyway/</guid>
      <link>http://www.h3rald.com/articles/im-on-twitter-anyway/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/im-on-twitter-anyway/#comments</comments>
      <category>personal</category>
      <category>review</category>
      <category>programming</category>
    </item>
    <item>
      <title>New Release: RawLine 0.2.0</title>
      <description>&lt;p&gt;&lt;del&gt;InLine&lt;/del&gt; RawLine 0.2.0 is out!&lt;/p&gt;
&lt;p&gt;*Raw*Line is the new name for InLine, in case you didn&amp;#8217;t guess. The name was changed to avoid name collision problems with the RubyInline project.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what&amp;#8217;s new:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Added /examples and /test directory to gem.&lt;/li&gt;
	&lt;li&gt;Escape codes can now be used in prompt.&lt;/li&gt;
	&lt;li&gt;It is now possible to use bind(key, &amp;amp;block) with a String as key, even if the corresponding escape sequence is not defined.&lt;/li&gt;
	&lt;li&gt;Added Editor#write_line(string) to print a any string (and &amp;#8220;hit return&amp;#8221;).&lt;/li&gt;
	&lt;li&gt;Library name changed to &amp;#8220;RawLine&amp;#8221; to avoid name collision issues (Bug &lt;a href="http://rubyforge.org/tracker/?func=detail&amp;amp;aid=18879&amp;amp;group_id=5622&amp;amp;atid=21788"&gt;18879&lt;/a&gt;).&lt;/li&gt;
	&lt;li&gt;Provided alternative implementation for left and right arrows if terminal&lt;br /&gt;
supports escape sequences (on Windows, it requires the Win32Console gem).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In particular, I decided to provide an &amp;#8220;optimized implementation&amp;#8221; for the left and right arrows using escape sequences rather than shameful hacks. This is now possible because the Win32Console gem now enables &lt;span class="caps"&gt;ANSI&lt;/span&gt; escape sequences on Windows as well (weehee!).&lt;/p&gt;
&lt;p&gt;So:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If you&amp;#8217;re on *nix all good, your terminal is smart and can understand escape sequences =&amp;gt; the new implementation will be used.&lt;/li&gt;
	&lt;li&gt;If you&amp;#8217;re on Windows and you installed Win32Console, your termnal is smart and can understand escape sequences =&amp;gt; the new implementation will be used.&lt;/li&gt;
	&lt;li&gt;If you&amp;#8217;re on Windows and you didn&amp;#8217;t install Win32Console, then your terminal is stupid and it doesn&amp;#8217;t understand escape sequences, so the old implementation will be used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The new implementation is significantly faster than the old one, on Windows at least, and the cursor now blinks properly when left or right arrows are pressed.&lt;/p&gt;
&lt;p&gt;I re-emplemented only cursor movement because I&amp;#8217;m still having some problems in getting the delete/insert escapes to work properly (or better: how I want them to work!).&lt;/p&gt;</description>
      <pubDate>Wed, 02 Apr 2008 03:33:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/rawline-020/</guid>
      <link>http://www.h3rald.com/articles/rawline-020/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/rawline-020/#comments</comments>
      <category>ruby</category>
      <category>programming</category>
      <category>opensource</category>
      <category>rawline</category>
    </item>
    <item>
      <title>InLine name change: what's your opinion?</title>
      <description>&lt;p&gt;I&amp;#8217;ve been kindly asked by the lead developer of &lt;a href="http://www.zenspider.com/ZSS/Products/RubyInline/"&gt;RubyInLine&lt;/a&gt; to change the name of my &lt;a href="http://rubyforge.org/projects/inline/"&gt;InLine&lt;/a&gt; project, due to potential confusion and conflicts.&lt;/p&gt;
&lt;p&gt;This makes sense, and I&amp;#8217;m ready to change the name of my project, although I&amp;#8217;m not that good at choosing original and &lt;em&gt;smart&lt;/em&gt; names, so well, any suggestion is more than welcome!&lt;/p&gt;
&lt;p&gt;I was thinking of something like:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;RawLine&lt;/li&gt;
	&lt;li&gt;EditLine&lt;/li&gt;
	&lt;li&gt;RawInput&lt;/li&gt;
	&lt;li&gt;RubyInput&lt;/li&gt;
	&lt;li&gt;RubyLine&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I personally think that &lt;strong&gt;RawLine&lt;/strong&gt; is probably the best option, but please, if have any better idea just speak up!&lt;/p&gt;
&lt;p&gt;P.S.: &amp;#8220;RedLine&amp;#8221; is taken, unfortunately, otherwise it would have been my first choice since the beginning.&lt;/p&gt;</description>
      <pubDate>Thu, 27 Mar 2008 05:30:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/inline-name-change/</guid>
      <link>http://www.h3rald.com/articles/inline-name-change/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/inline-name-change/#comments</comments>
      <category>ruby</category>
      <category>programming</category>
      <category>opensource</category>
      <category>rawline</category>
    </item>
    <item>
      <title>RawLine - a 100% Ruby solution for console inline editing</title>
      <description>&lt;p&gt;One of the many things I like about Ruby is its cross-platform nature: as a general rule, Ruby code runs on everything which supports Ruby, regardless of its architecture and platform (yes, there are quite a few exceptions, but let&amp;#8217;s accept this generalization for now).&lt;/p&gt;
&lt;p&gt;More specifically, I liked the fact that I could use the &lt;a href="http://tiswww.case.edu/php/chet/readline/rltop.html"&gt;&lt;span class="caps"&gt;GNU&lt;/span&gt; Readline library&lt;/a&gt; with Ruby seamlessly on both Windows and Linux.&lt;br /&gt;
Readline offers quite a lot of features which are useful for those people like me who enjoy creating command-line scripts, in a nutshell, it provides:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;File/Word completion&lt;/li&gt;
	&lt;li&gt;History support&lt;/li&gt;
	&lt;li&gt;Custom key bindings which can be modified via .inputrc&lt;/li&gt;
	&lt;li&gt;Emacs and Vi edit modes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Basically it makes your command-line interface fast and powerful, and that&amp;#8217;s not an overstatement. Ruby&amp;#8217;s own &lt;span class="caps"&gt;IRB&lt;/span&gt; can be enhanced by enabling readline and completion, and it works great &amp;#8212; at least on *nix systems.&lt;/p&gt;
&lt;p&gt;For some weird reason, some people had problems with Readline on Windows: in particular, things get nasty when you start editing long lines. Text gets garbled, the cursor goes up one or two lines and doesn&amp;#8217;t come back, and other similar leprechaun&amp;#8217;s tricks, which are not that funny after a while.&lt;/p&gt;
&lt;p&gt;Apparently there&amp;#8217;s no alternative to Readline in the Ruby world. If you wan&amp;#8217;t tab completion that&amp;#8217;s it, you&amp;#8217;re stuck. Would it be difficult to implement &lt;em&gt;some&lt;/em&gt; of Readline functionality natively in Ruby? Maybe, but the problem is that for some reason the Ruby Standard Library doesn&amp;#8217;t have low level methods to operate on keystrokes&amp;#8230;&lt;/p&gt;
&lt;p&gt;&amp;#8230;but luckily, the &lt;a href="http://highline.rubyforge.org/"&gt;HighLine&lt;/a&gt; gem does! James Edward Gray II keeps pointing out here and here that HighLine&amp;#8217;s own &lt;code&gt;get_character&lt;/code&gt; method does just that: it returns the corresponding character code(s) right when a key is pressed, unlike &lt;code&gt;IO#gets()&lt;/code&gt; which waits for the user to press &lt;span class="caps"&gt;ENTER&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Believe it or not, that tiny method can do wonders&amp;#8230;h2. Reverse-engineering escape codes&lt;/p&gt;
&lt;p&gt;So here&amp;#8217;s a little script which uses &lt;code&gt;get_character()&lt;/code&gt; in an endless loop, diligently printing the character codes corresponding to a keystroke:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;#!/usr/local/bin/ruby -w&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;highline/system_extensions&amp;#39;&lt;/span&gt;

&lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;HighLine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SystemExtensions&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Press a key to view the corresponding ASCII code(s) (or CTRL-X to exit).&amp;quot;&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

	&lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;=&amp;gt; &amp;quot;&lt;/span&gt;
	&lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_character&lt;/span&gt;
	&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt;
	&lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sc"&gt;?\C-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;print&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Exiting...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chr&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; [&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] (hex: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
	&lt;span class="k"&gt;end&lt;/span&gt;
	
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;A pretty harmless little thing. Try to run it and press some keys, and see what you get:&lt;/p&gt;
&lt;div style="font-family: Monospace"&gt;
&lt;p&gt;Press a key to view the corresponding &lt;span class="caps"&gt;ASCII&lt;/span&gt; code(s) (or &lt;span class="caps"&gt;CTRL&lt;/span&gt;-X to exit).&lt;/p&gt;
&lt;p&gt;=&amp;gt; a &lt;sup class="footnote" id="fnr96"&gt;&lt;a href="#fn96"&gt;96&lt;/a&gt;&lt;/sup&gt; (hex: 61)&lt;/p&gt;
&lt;p&gt;=&amp;gt; 1 &lt;sup class="footnote" id="fnr49"&gt;&lt;a href="#fn49"&gt;49&lt;/a&gt;&lt;/sup&gt; (hex: 31)&lt;/p&gt;
&lt;p&gt;=&amp;gt; Q &lt;sup class="footnote" id="fnr81"&gt;&lt;a href="#fn81"&gt;81&lt;/a&gt;&lt;/sup&gt; (hex: 51)&lt;/p&gt;
&lt;p&gt;=&amp;gt; &amp;alpha; &lt;sup class="footnote" id="fnr224"&gt;&lt;a href="#fn224"&gt;224&lt;/a&gt;&lt;/sup&gt; (hex: e0)&lt;/p&gt;
&lt;p&gt;=&amp;gt; K &lt;sup class="footnote" id="fnr75"&gt;&lt;a href="#fn75"&gt;75&lt;/a&gt;&lt;/sup&gt; (hex: 4b)&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Hang on, what are the last two codes? &lt;em&gt;A left arrow key on Windows&lt;/em&gt;, apparently.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Welcome to the wonderful world of input escape sequences!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To cut a long story short, both Windows and *nix system &amp;#8220;terminals&amp;#8221; translate special keystrokes into sequences of two or more codes. This applies to things like &lt;span class="caps"&gt;DEL&lt;/span&gt;, &lt;span class="caps"&gt;INSERT&lt;/span&gt;, arrows, etc. etc.&lt;br /&gt;
For some ideas, check out:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://www.microsoft.com/whdc/device/input/Scancode.mspx"&gt;Windows Scancodes&lt;/a&gt; (Thanks &lt;a href="http://64.223.189.234/node/92"&gt;Huff&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://www.connectrf.com/Documents/vt220.html"&gt;VT220 Terminal Input Sequences&lt;/a&gt; (Thanks &lt;a href="http://www.grayproductions.net/"&gt;James&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;#8217;s now assume that we&amp;#8217;re smart and we can write a program which can parse keystroke properly, including handling different input escape sequences according to the OS, what can it be used for?&lt;br /&gt;
Well:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;For normal characters, just print them back to the screen (&lt;code&gt;get_character&lt;/code&gt; doesn&amp;#8217;t print anything, it &amp;#8220;steals&amp;#8221; the keystroke)&lt;/li&gt;
	&lt;li&gt;For special characters, do something nice!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We could setup &lt;span class="caps"&gt;TAB&lt;/span&gt; to auto-complete the current word according to an array of matches, or bind the up arrow to load the last line typed in by the user, for example, that&amp;#8217;s basically something Readline does, right?&lt;/p&gt;
&lt;h2&gt;RawLine: how it works and what it does&lt;/h2&gt;
&lt;p&gt;I created a small project on RubyForge called &lt;a href="http://rubyforge.org/projects/rawline/"&gt;RawLine&lt;/a&gt; (not to be confused with RubyInline, a completely different thing altogether, sorry about that) to play around with the possibilities offered by the &lt;code&gt;get_character&lt;/code&gt; method. The library is just a preview of things which can be done, but it&amp;#8217;s already usable, provided that you&amp;#8217;re brave enough to try it out, that is.&lt;/p&gt;
&lt;p&gt;The basic idea behind RawLine is to be able to parse keystrokes properly on different platforms and re-bind them to a set of predefined, cross-platform actions or a user-defined code block.&lt;/p&gt;
&lt;h3&gt;Basic line-editing operations&lt;/h3&gt;
&lt;p&gt;The first challenge was to re-invent the wheel, i.e. re-bind keystrokes to their typical actions: a left arrow moves the cursor left, a backspace deletes the character at the left of the cursor and so on. Yes, because &lt;code&gt;get_characters&lt;/code&gt; gives you the right character codes at the price of &lt;em&gt;cancelling their normal effects&lt;/em&gt;, which is a great thing, as you&amp;#8217;ll soon find out.&lt;/p&gt;
&lt;p&gt;Printing a character on the screen was one of the easiest tasks (at first). &lt;code&gt;IO#putc&lt;/code&gt; does the job pretty well: it prints a character out.&lt;br /&gt;
What about moving left? Easy: print a non-descructive backspace (\b) and hope it is really not destructive. I did some tests and it seems to do as it&amp;#8217;s told and move the cursor back by one position.&lt;/p&gt;
&lt;p&gt;Moving right was a little trickier: the easiest thing I found was to re-print the character under the cursor, which will then move the cursor forward (as naive as it may seem, it does the job!). If there&amp;#8217;s nothing under the cursor, then we must be at the end of the line and it shouldn&amp;#8217;t move anywhere, so there we go.&lt;/p&gt;
&lt;p&gt;What if I move left a bit and then start typing normal characters? Well, everything is rewritten of course: this will be our &amp;#8220;character replace mode&amp;#8221;. Unfortunately users don&amp;#8217;t like this behavior that much, so what I did was this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Copy all characters from the one at the left of the cursor till the end of the line&lt;/li&gt;
	&lt;li&gt;Print the character to be inserted&lt;/li&gt;
	&lt;li&gt;Re-print the previously-copied characters&lt;/li&gt;
	&lt;li&gt;Move the cursor back at the right place&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Again, a primitive solution which works seamlessly on all platforms, and yes, it&amp;#8217;s fast enough that you don&amp;#8217;t notice the difference.&lt;/p&gt;
&lt;p&gt;As you may have guessed, this of course means that I always had to keep track of:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The cursor position within the line&lt;/li&gt;
	&lt;li&gt;The text currently printed to the screen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Backspace and delete were implemented in a similar way, you can figure it out yourself or look at the source code: I won&amp;#8217;t bore you any further!&lt;/p&gt;
&lt;h3&gt;History management&lt;/h3&gt;
&lt;p&gt;The next step was to implement a history for both the characters inputted by the user (to allow undoing and redoing operations) and for the whole lines. This was just an ordinary programming exercise: a simple buffer with some extra controls here and there, nothing too scary.&lt;/p&gt;
&lt;p&gt;So every &amp;#8220;modification&amp;#8221; to the current line being typed is saved in a line history buffer and all the lines entered are saved in another history buffer. All is left is to allow users to navigate through these buffers back and forth. &lt;br /&gt;
Nothing impossible: all I had to do was keeping track of the current element of the history being retrieved and then overwrite the current line with a new line stored in the buffer? How&amp;#8217;s this line overwriting done? Same old:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Move the cursor to the beginnig of the line&lt;/li&gt;
	&lt;li&gt;Print X spaces, where X is the line length, so that the characters are no longer displayed in the console&lt;/li&gt;
	&lt;li&gt;Move the cursor back to the beginning of the line&lt;/li&gt;
	&lt;li&gt;Print the new line.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Easy and naive, as usual. But again, it works well enough.&lt;/p&gt;
&lt;h3&gt;Word completion&lt;/h3&gt;
&lt;p&gt;The other challange was word completion. The current implementation can be summarized as follows:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If &lt;span class="caps"&gt;TAB&lt;/span&gt; (or another character, if you wish) is pressed, call a user-defined &lt;code&gt;completion_proc&lt;/code&gt; method which returns an array and show the first element of the array (in this case I actually used a cyclic RawLine::HistoryBuffer, not an array)&lt;/li&gt;
	&lt;li&gt;If the user presses &lt;span class="caps"&gt;TAB&lt;/span&gt; again, show another match, and so &lt;em&gt;ad infinitum&lt;/em&gt; if the user keeps pressing &lt;span class="caps"&gt;TAB&lt;/span&gt;.&lt;/li&gt;
	&lt;li&gt;If the user presses another key, accept the default completion and move on.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Obviously this means that:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;RawLine has to keep track of the current &amp;#8220;word&amp;#8221;. A word is everything separated by a user defined &lt;code&gt;word_separator&lt;/code&gt;, which can obviously modified at runtime, with care.&lt;/li&gt;
	&lt;li&gt;Regarding the &lt;code&gt;completion_proc&lt;/code&gt;, typically you may want to return only the elements matching the word which is currently being written, so that&amp;#8217;s given as default parameter for your proc. Exactly like with ReadLine, the only difference is that you can access other things like &lt;em&gt;the whole line&lt;/em&gt; and &lt;em&gt;the whole history&lt;/em&gt; in real time, which can be really handy at times!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;#8217;s a simple example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completion_proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;
		&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;select&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delete&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;destroy&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;	&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;h3&gt;Custom key bindings&lt;/h3&gt;
&lt;p&gt;All these pretty things are obviously bound to some keystrokes. If the key corresponds to only one code, everything is fine, but because special keys typically aren&amp;#8217;t so it was necessary to implement a mechanism to track an escape key (e.g. 0xE0 and 0 on Windows and \e on Linux) and listen to further characters, in case a known sequence is found. Anyhow, the final result of the method used for character binding is the following:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bind(key, &amp;amp;block)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Where key can be:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;A &lt;code&gt;Fixnum&lt;/code&gt; corresponding to a single character code&lt;/li&gt;
	&lt;li&gt;An &lt;code&gt;Array&lt;/code&gt; of one or more character codes&lt;/li&gt;
	&lt;li&gt;A &lt;code&gt;String&lt;/code&gt; corresponding to an escape sequence&lt;/li&gt;
	&lt;li&gt;A &lt;code&gt;Symbol&lt;/code&gt; corresponding to a known escape sequence or key&lt;/li&gt;
	&lt;li&gt;A &lt;code&gt;Hash&lt;/code&gt; to define a new key or escape sequences&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, in the end you can do things like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:left_arrow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;move_left&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="se"&gt;\e&lt;/span&gt;&lt;span class="s2"&gt;test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;overwrite_line&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Test!!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;?\C-z&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;undo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;Which, for Rubyists, it&amp;#8217;s far sexier and more flexible than editing an .inputrc file.&lt;/p&gt;
&lt;h3&gt;How do I use it, anyway?&lt;/h3&gt;
&lt;p&gt;A code example is better than a thousand words, right? So here you are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;#!/usr/local/bin/ruby -w&lt;/span&gt;

&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rubygems&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;rawline&amp;#39;&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;*** Inline Editor Test Shell ***&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; * Press CTRL+X to exit&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; * Press CTRL+C to clear command history&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; * Press CTRL+D for line-related information&amp;quot;&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot; * Press CTRL+E to view command history&amp;quot;&lt;/span&gt;

&lt;span class="n"&gt;editor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;RawLine&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;

&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ctrl_c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear_history&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ctrl_d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;debug_line&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ctrl_e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;show_history&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ctrl_x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;Exiting...&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completion_proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
	&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;word&lt;/span&gt;
		&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;select&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;update&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;delete&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;debug&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;destroy&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;find_all&lt;/span&gt;	&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
	&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
	&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;You typed: [&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;=&amp;gt; &amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chomp!&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;This example can be found in examples/rawline_shell.rb within the RawLine source code or gem package.&lt;/p&gt;
&lt;h2&gt;Current status and availability&lt;/h2&gt;
&lt;p&gt;I currently &lt;a href="http://rubyforge.org/forum/forum.php?forum_id=22543"&gt;released&lt;/a&gt; RawLine 0.1.0 on &lt;a href="http://rubyforge.org/projects/rawline"&gt;SourceForge&lt;/a&gt;, and it can be installed via:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;gem install -r rawline&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The RDoc documentation is available &lt;a href="http://rawline.rubyforge.org/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Feel free to try it out. First of all try the &lt;code&gt;rawline_shell.rb&lt;/code&gt; example, and see if it works on your machine. If it doesn&amp;#8217;t than maybe you try re-binding some keys (use &lt;code&gt;key_tester.rb&lt;/code&gt; to &amp;#8220;reverse-engineer&amp;#8221; your terminal&amp;#8217;s input escape sequences), and let me know!&lt;/p&gt;
&lt;p&gt;Status information and limitations:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It has been tested on Windows (XP, using the usual command prompt) and on Linux (ZenWalk, using &lt;span class="caps"&gt;XFCE&lt;/span&gt; Terminal).&lt;/li&gt;
	&lt;li&gt;It can handle lines no longer than the maximum terminal width &amp;#8211; 2. This is to ensure that the cursor never &amp;#8220;falls down&amp;#8221; to the next line.&lt;/li&gt;
	&lt;li&gt;On Windows, the cursor doesn&amp;#8217;t blink immedialy when moving left, but it moves, don&amp;#8217;t worry.&lt;/li&gt;
	&lt;li&gt;On Linux, you should really consider installing the &lt;a href="http://raa.ruby-lang.org/project/ruby-termios/"&gt;Termios&lt;/a&gt; library for a faster experience (otherwise &lt;code&gt;get_character&lt;/code&gt; won&amp;#8217;t parse characters correctly if you press and hold a key, and that, trust me, is a real mess!).&lt;/li&gt;
	&lt;li&gt;RawLine is very far from being a complete replacement for the ReadLine library, and it is currently in alpha stage.&lt;/li&gt;
	&lt;li&gt;Release 0.1.0 has been created after 2 weeks of sporadic coding during lunch breaks and week-ends.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For any ideas on where to go from here, comments and feedback, just reply below or send an email to my usual email address.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Mar 2008 05:59:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/inline-introduction/</guid>
      <link>http://www.h3rald.com/articles/inline-introduction/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/inline-introduction/#comments</comments>
      <category>ruby</category>
      <category>programming</category>
      <category>opensource</category>
      <category>rawline</category>
    </item>
    <item>
      <title>A closer look at Komodo Edit</title>
      <description>&lt;p&gt;&lt;a href="http://digg.com/programming/A_closer_look_at_Komodo_Edit"&gt;&lt;br /&gt;
&lt;img src="http://digg.com/img/badges/180x35-digg-button.png" width="180" height="35" alt="Digg!" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;What&amp;#8217;s your favorite code editor?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is a common question which still keeps popping up on community boards, mailing lists, comments, etc. Every programmer who writes code in some programming language normally has an editor of choice. Being realistic, most of the times it&amp;#8217;s not only one program but several, depending on the language and on the features needed at the time.&lt;br /&gt;
Yes, great, but how do you choose your favorite editor?&lt;br /&gt;
By trying a lot of them of course: that&amp;#8217;s what I&amp;#8217;ve been doing since I started programming. Lately I&amp;#8217;ve become fond of &lt;a href="http://www.vim.org"&gt;Vim&lt;/a&gt; (or better, gVim), although I have a few other editors I may recommend, e.g.:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://notepad-plus.sourceforge.net/uk/site.htm"&gt;Notepad++&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://intype.info/home/index.php"&gt;Intype&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://scintilla.sourceforge.net/SciTE.html"&gt;SciTE&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Recently, however, I came across my &lt;em&gt;n^th^&lt;/em&gt; &amp;#8220;what&amp;#8217;s your favorite editor&amp;#8221; thread and someone mentioned &lt;a href="http://www.activestate.com/Products/komodo_edit/"&gt;Komodo Edit&lt;/a&gt;. I knew of it already, actually, but I never had a chance to give it a &lt;em&gt;proper&lt;/em&gt; try. &lt;br /&gt;
ActiveState is well known mainly for two things:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Their effort in offering a lot of commercial, windows-based Perl libraries&lt;/li&gt;
	&lt;li&gt;Their commercial &lt;span class="caps"&gt;IDE&lt;/span&gt;, Komodo &lt;span class="caps"&gt;IDE&lt;/span&gt;, which I personally tried quite a long time ago&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The problems of Komodo &lt;span class="caps"&gt;IDE&lt;/span&gt; are foundamentally two:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It costs money &amp;#8211; this is not great in a world where Eclipse and Netbeans are free&lt;/li&gt;
	&lt;li&gt;It is an &lt;span class="caps"&gt;IDE&lt;/span&gt; &amp;#8211; which normally means &lt;em&gt;&amp;#8216;heavy as hell&amp;#8217;&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;#8217;s a matter of taste and needs: some people feel more confortable with using an editor for certain tasks, while sometimes an &lt;span class="caps"&gt;IDE&lt;/span&gt; may be the best solution, despite its potential slowness and bulk.&lt;/p&gt;
&lt;p&gt;Komodo Edit solves the above-mentioned problems because:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It&amp;#8217;s free&lt;/li&gt;
	&lt;li&gt;It&amp;#8217;s an editor&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Actually I wouldn&amp;#8217;t call it an editor, because it offers quite a lot of features which are normally absent in editors &amp;#8212; it&amp;#8217;s something in-between, which definitely deserves a try.&lt;/p&gt;
&lt;h2&gt;User interface&lt;/h2&gt;
&lt;p&gt;Komodo Edit&amp;#8217;s interface is one of the most clear I&amp;#8217;ve ever come across. It is organized in four main areas plus the top menu and toolbar (which only has the buttons you &lt;span class="caps"&gt;REALLY&lt;/span&gt; need, unlike Notepad++&amp;#8217;s 31-button-bar).&lt;/p&gt;
&lt;p&gt;&lt;img src="/files/komodo_main.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The central area is for editing, the left pane is for the Project browser, the right one is for the Toolbox and the bottom pane is for command output. Luckily enough, a set of handy little buttons is provided in the toolbar to show and hide each pane. I normally only use the Project Browser and the main editing area, leaving the Toolbox and Command Output panes hidden, but that&amp;#8217;s up to you really.&lt;/p&gt;
&lt;p style="float:left;"&gt;&lt;img src="/files/komodo_show-hide_pane.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;Komodo Edit allows symultaneous editing of multiple documents, which means that it has tabs like most of the best editors out there. Furthermore, it is possible to have Komodo re-open the files edited in the last editing session, saving you a lot of time. Granted, a lot of &lt;span class="caps"&gt;IDE&lt;/span&gt; do, but this is &lt;strong&gt;&lt;span class="caps"&gt;NOT&lt;/span&gt;&lt;/strong&gt; an &lt;span class="caps"&gt;IDE&lt;/span&gt;, remember? It&amp;#8217;s an &lt;em&gt;editor&lt;/em&gt;, or at least it is advertised as such.&lt;/p&gt;
&lt;p&gt;In reality it has &lt;em&gt;most&lt;/em&gt; of the power of a full-blown &lt;span class="caps"&gt;IDE&lt;/span&gt; though normally remaining under the 60K memory usage (out of 2GB of total &lt;span class="caps"&gt;RAM&lt;/span&gt;) &amp;#8212; which is not that bad, considering what Eclipse and NetBeans need.&lt;br /&gt;
Out of all the &lt;a href="http://www.activestate.com/Products/komodo_edit/edit_vs_ide.plex"&gt;extra features&lt;/a&gt; offered by Komodo &lt;span class="caps"&gt;IDE&lt;/span&gt;, the only one I truly miss is the Code Browser. Other than that, it quickly became my editor/&lt;span class="caps"&gt;IDE&lt;/span&gt; of choice (when gVim isn&amp;#8217;t looking, of course&amp;#8230;)&lt;/p&gt;
&lt;p&gt;Lets find out why&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Editing features&lt;/h2&gt;
&lt;p&gt;Komodo Edit comes with all the editing features of ever average editor, so &lt;em&gt;&amp;#8220;[&amp;#8230;] Code commenting, auto-indent and outdent, block selection, incremental search, reflow paragraph, join lines, enter next character as raw literal, repeat next keystroke and clean line endings on &amp;#8220;save&amp;#8221;.&amp;quot;&lt;/em&gt;, it uses Scintilla as main editing component, which makes it a close relative of Notepad++, Notepad2 and of course SciTE when it comes to understanding languages and syntax highlighting.&lt;/p&gt;
&lt;p&gt;This is good, of course, as Scintilla is an excellent editing component, but &amp;#8211; I have to say this &amp;#8211; not as good as Vim when it comes to syntax highlighting (nothing is as good as Vim though, so I can&amp;#8217;t really complain!).&lt;br /&gt;
As you can see from the screenshot I included earlier on, it is possible to change the default black-on-white color scheme to something more stimulating and energy-saving. This doesn&amp;#8217;t mean I have to manually re-set the color of each element, it actually comes with a black-background scheme, which is handy.&lt;/p&gt;
&lt;h3&gt;Supported Languages &amp;amp; Syntax Highlighting&lt;/h3&gt;
&lt;p&gt;Komodo Edit supports quite a few programming languages, which means it can recognize the most common ones (C, C++, Java, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Python, Ruby, Perl) but it also smart enough to notice framework-specific syntaxes like Smarty, Django or &lt;span class="caps"&gt;RHTML&lt;/span&gt;.&lt;br /&gt;
Like every scintilla-based editors, it sports a nice &lt;span class="caps"&gt;HTML&lt;/span&gt; multi-highlighter which allows you to keep putting all the Javascript, &lt;span class="caps"&gt;CSS&lt;/span&gt; and server-side scripting into the same file, &lt;span class="caps"&gt;GREAT&lt;/span&gt;! No, you probably wouldn&amp;#8217;t want to do that, but it&amp;#8217;s a good thing to have.&lt;/p&gt;
&lt;h3&gt;Auto-completion&lt;/h3&gt;
&lt;p&gt;What makes this editor a really handy tool is its auto-completion capabilities. Why? well, because it supports:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Ruby: require, class modules (on . and ::), class variables and methods, method calltips.&lt;/li&gt;
	&lt;li&gt;Python&lt;/li&gt;
	&lt;li&gt;Perl&lt;/li&gt;
	&lt;li&gt;&lt;span class="caps"&gt;PHP&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span class="caps"&gt;XSLT&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;span class="caps"&gt;XML&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;Tcl&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why is this so special? Well, because if you want this you normally need an &lt;span class="caps"&gt;IDE&lt;/span&gt;, and if you want it for Ruby &lt;span class="caps"&gt;AND&lt;/span&gt; Python &lt;span class="caps"&gt;AND&lt;/span&gt; Perl your choices are very limited. &lt;br /&gt;
I played with the Ruby auto-completion features quite a bit, and I&amp;#8217;m actually really impressed.&lt;/p&gt;
&lt;p style="float:right;"&gt;&lt;img src="/files/komodo_auto-completion.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;It can suggest what to write through calltips after a &lt;code&gt;require&lt;/code&gt; directive, after a . and a ::, and hitting CTRL+SPACE (or just tab if you configure the right option) will auto-complete what you&amp;#8217;re writing, be it a language keyword, a variable of any kind or a method. Additionally, it comes with &amp;#8220;soft characters support&amp;#8221;, which means it will try to match ( [ { when possible, allowing you to &lt;em&gt;write over&lt;/em&gt; the completed character if you want to.&lt;/p&gt;
&lt;h3&gt;Syntax Checking, Vi/Emacs key bindings and code folding&lt;/h3&gt;
&lt;p&gt;The heading is almost self-explanatory here: Komodo Edit supports code folding (you can even chose the folding chracters!) for all its supported languages, syntax checking (it can detect and display errors before running the script, very useful in Ruby, and hard to find in other editors) and Vi/Emacs key bindings. &lt;br /&gt;
It also offers &amp;#8220;vi emulation&amp;#8221;, which is constantly improving through every release &amp;#8211; so you won&amp;#8217;t forget Vim&amp;#8217;s keys when I don&amp;#8217;t use it: very nice, and again, hard to find in other editors, nevermind IDEs!&lt;/p&gt;
&lt;h2&gt;Projects and Tools&lt;/h2&gt;
&lt;p style="float:right;"&gt;&lt;img src="/files/komodo_toolbox.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The Project Browser and Toolbox are two features which are normally presents in IDEs and which are normally not found in editors. Granted, some editors like &lt;a href="http://www.pspad.com/en/"&gt;PSPad&lt;/a&gt; do indeed have &amp;#8220;projects&amp;#8221;, but most of the others don&amp;#8217;t. A &lt;em&gt;project&lt;/em&gt; in Komodo Edit is normally composed by:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Some &lt;em&gt;Live Folders&lt;/em&gt; including all the source files of the application you&amp;#8217;re developing&lt;/li&gt;
	&lt;li&gt;An optional set of tools, commands, snippets and other goodies which may help you coding that particular application.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is possible to create these tools by clicking the &lt;strong&gt;Add Item to current project&lt;/strong&gt; button in the Projects toolbar or by clicking the &lt;strong&gt;Add Item to Toolbox&lt;/strong&gt; button just over the toolbox. &lt;br /&gt;
Either way, you can choose among the following:&lt;/p&gt;
&lt;h4&gt;File/Remote File&lt;/h4&gt;
&lt;p&gt;Add a file on your local machine or a remote file hosted on a server you configured via &lt;strong&gt;Edit &amp;gt; Preferences &amp;gt; Servers&lt;/strong&gt;. Supported protocols are: &lt;span class="caps"&gt;FTP&lt;/span&gt;,&lt;span class="caps"&gt;FTPS&lt;/span&gt;, &lt;span class="caps"&gt;SFTP&lt;/span&gt;, &lt;span class="caps"&gt;SCP&lt;/span&gt;.&lt;/p&gt;
&lt;h4&gt;Folder&lt;/h4&gt;
&lt;p&gt;This will &lt;em&gt;not&lt;/em&gt; link to a folder and import local files in Komodo, instead, it will create a container for other tools, not for local files.&lt;/p&gt;
&lt;h4&gt;Live Folder&lt;/h4&gt;
&lt;p&gt;On the contrary, a live folder links to an actual folder on your machines, and all files and directories inside it are automatically imported. Note that it is possible to choose to include or exclude certain files or directories from being imported by right-clicking the folder and editing its properties.&lt;/p&gt;
&lt;h4&gt;Command&lt;/h4&gt;
&lt;p&gt;This will create a shortcut to a command to execute. It is possible to specify its parameters, the directory where it will be run, whether its output will be displayed in the Command Output or in a newly-spawned console window, etc. etc.&lt;/p&gt;
&lt;h4&gt;Snippet&lt;/h4&gt;
&lt;p&gt;TextMate fans will love this. Komodo will let you create a code snippet for later use. Furthermore, it is possible to specify &amp;#8220;tabstops&amp;#8221; to automatically select certain words when tab is pressed (so you can effectively fill in only particular fields of the snippet).&lt;/p&gt;
&lt;h4&gt;Template&lt;/h4&gt;
&lt;p&gt;A simple but effective way to create code templates.&lt;/p&gt;
&lt;h4&gt;Url&lt;/h4&gt;
&lt;p&gt;A link which will open a given url.&lt;/p&gt;
&lt;h4&gt;Open&amp;#8230; Shortcut&lt;/h4&gt;
&lt;p&gt;This will popup an &lt;strong&gt;Open File&lt;/strong&gt; dialog in a direcxtory of your choice.&lt;/p&gt;
&lt;h4&gt;Macro&lt;/h4&gt;
&lt;p&gt;For those who require even more customization, it is also possible to record or code macros in Python or javascript, and then configure their key bindings and triggers.&lt;/p&gt;
&lt;h4&gt;Custom Menu/Custom toolbar&lt;/h4&gt;
&lt;p&gt;This was really impressive. Sure you can group all your tools in folders in your current project or you can create them in the toolbox to make them available all the time, but it would be cool if &lt;em&gt;the editor itself&lt;/em&gt; could make those tools available by default in a toolbar or a menu. Well, that&amp;#8217;s possible: all you need to do is create a new custom menu or toolbar and populate it with your tools by drag and drop. Very, very nice!&lt;/p&gt;
&lt;p&gt;This mini-framework to create custom tools can be used to create project templates in a blink. To show this concept, Komodo Edit comes with a Rails template with almost all the tools you need when coding a Ruby on Rails application:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Create/delete database&lt;/li&gt;
	&lt;li&gt;Generators&lt;/li&gt;
	&lt;li&gt;Migrations&lt;/li&gt;
	&lt;li&gt;Run server&lt;/li&gt;
	&lt;li&gt;Example view snippets&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Komodo Edit is an interesting editor which offers a lot of features which are normally only available in IDEs at a smaller memory footprint. Granted, when I want to jot something down I still prefer to fire up gVim, but for a serious coding session, Komodo is the right choice.&lt;br /&gt;
Its close attention to details and its ease of use make developing an even more pleasant experience, although perhaps there&amp;#8217;s still room for improvement, if you&amp;#8217;re really fussy.&lt;/p&gt;
&lt;p&gt;Sometimes when you start getting used of its advanced features, the lack of a code browser seems a real shame, but after all, ActiveState must sell their &lt;span class="caps"&gt;IDE&lt;/span&gt; to someone at some point!&lt;/p&gt;
&lt;p&gt;Another thing which I would have liked is the ability to create new syntax highlighting schemes, which Notepad++ and &lt;span class="caps"&gt;VIM&lt;/span&gt; both offer. Whydoes it bothers me so much? Well, because I&amp;#8217;d like a &lt;a href="http://textism.com/tools/textile/"&gt;Textile&lt;/a&gt; syntax highlighting scheme for writing blogs and articles. &lt;span class="caps"&gt;VIM&lt;/span&gt; and Intype seem to be the only ones which offer it out-of-the-box, but there&amp;#8217;s no trace of it in Komodo Edit.&lt;/p&gt;
&lt;p&gt;Actually it is possible to create new syntax highlighting schemes and extend Komodo Edit via &lt;a href="http://community.activestate.com/addons"&gt;&lt;span class="caps"&gt;XUL&lt;/span&gt; extensions&lt;/a&gt;, exactly like Firefox. After a closer look, the Django syntax was added in this way.&lt;/p&gt;
&lt;p&gt;Unfortunately there aren&amp;#8217;t that many extensions available for Komodo Edit, yet, but the &lt;a href="http://community.activestate.com/"&gt;Activestate Community&lt;/a&gt; seems very active, so you never know. Additionally, the recently-started &lt;a href="http://www.openkomodo.com/"&gt;OpenKomodo&lt;/a&gt; is a new project created by ActiveState to &amp;#8220;[&amp;#8230;] create an open source platform for building developer environments. ActiveState has open-sourced elements of Komodo Edit, a free multi-language editor for dynamic languages based on Komodo &lt;span class="caps"&gt;IDE&lt;/span&gt;, to create the Open Komodo code base&amp;#8221;. A new competitor for Eclipse and Netbeans will be available soon?&lt;/p&gt;
&lt;p&gt;&lt;a href="http://digg.com/programming/A_closer_look_at_Komodo_Edit"&gt;&lt;br /&gt;
&lt;img src="http://digg.com/img/badges/180x35-digg-button.png" width="180" height="35" alt="Digg!" /&gt;&lt;br /&gt;
&lt;/a&gt;&lt;/p&gt;</description>
      <pubDate>Sun, 25 Nov 2007 06:23:00 -0000</pubDate>
      <guid>http://www.h3rald.com/articles/komodo-edit-review/</guid>
      <link>http://www.h3rald.com/articles/komodo-edit-review/</link>
      <author>h3rald@h3rald.com</author>
      <comments>http://www.h3rald.com/articles/komodo-edit-review/#comments</comments>
      <category>review</category>
      <category>programming</category>
      <category>software</category>
    </item>
  </channel>
</rss>
