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

<channel>
	<title>odyniec.net blog</title>
	<atom:link href="http://www.odyniec.net/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.odyniec.net/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Mon, 30 Apr 2012 22:49:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Steve Jobs &#8211; Book Review</title>
		<link>http://www.odyniec.net/blog/2012/04/steve-jobs-book-review/</link>
		<comments>http://www.odyniec.net/blog/2012/04/steve-jobs-book-review/#comments</comments>
		<pubDate>Sat, 28 Apr 2012 13:08:54 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Books]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=840</guid>
		<description><![CDATA[I received Steve Jobs&#8217; biography as a present last Christmas. I was never a fan of him or of Apple, and always found it annoying that he was praised as a great inventor and visionary. When he died, I was one of those saying &#8220;Hey, you know who also died? Dennis Ritchie, and he deserves [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://books.simonandschuster.com/Steve-Jobs/Walter-Isaacson/9781451648539"><img class="alignleft size-full wp-image-841" title="Steve Jobs" src="http://odyniec.net/blog/wp-content/uploads/2012/04/steve_jobs_cover.jpg" alt="" width="164" height="250" /></a>I received Steve Jobs&#8217; biography as a present last Christmas. I was never a fan of him or of Apple, and always found it annoying that he was praised as a great inventor and visionary. When he died, I was one of those saying <em>&#8220;Hey, you know who also died? <a href="http://en.wikipedia.org/wiki/Dennis_Ritchie">Dennis Ritchie</a>, and he deserves way more recognition than Jobs.&#8221;</em></p>
<p>I expected the book to be another pile of adoration and I probably wouldn&#8217;t have even opened it if it wasn&#8217;t for a podcast that happened to pop up on my playlist a few weeks earlier. It was an interview with Walter Isaacson, the author of the biography, about his work on the book, and what it was like to work with Jobs when he was writing it.</p>
<p>In the interview, Isaacson told that Jobs asked him to write the biography a number of times, and he finally agreed under the condition that Jobs would not try to take control over it and would allow him to write a true story of his life. If this was true, I thought, then this could actually be a trustworthy biography and not another tribute to the greatest inventor of our times. So when the book got into my hands, I thought I might just as well read it and find out if Isaacson managed to keep it that way.</p>
<p>Well, he very much did. While it&#8217;s clear that Isaacson shows considerable respect to Jobs and all the things he managed to achieve, he also reveals his failures and weaknesses, and does not portray him as a superhero kind of figure. Jobs could be a real jerk to those around him, especially to the people that he worked with, and the biography does not pass over that.</p>
<p>The book also describes a good part of the history of home computers and technology in general. The first chapters, which cover the late seventies and early eighties, were almost a nostalgic read for me, since they brought back so many of my own memories from that time (well, the latter part of it, I&#8217;m not <em>that</em> old), when I was a little kid fascinated with those magical 8-bit machines.</p>
<p>But regardless of whether you get a kick out of early 80s computers or not, I recommend the biography, as if nothing else, it&#8217;s an excellently written, interesting, and sometimes even inspiring story. I truly enjoyed the read, and learned my lesson not to judge a book by how overrated and overpriced the products are that were created by its subject.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2012/04/steve-jobs-book-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>POD Functions Sort Greasemonkey Script</title>
		<link>http://www.odyniec.net/blog/2012/03/pod-functions-sort-greasemonkey-script/</link>
		<comments>http://www.odyniec.net/blog/2012/03/pod-functions-sort-greasemonkey-script/#comments</comments>
		<pubDate>Fri, 30 Mar 2012 10:52:24 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Greasemonkey]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=837</guid>
		<description><![CDATA[Being a Perl programmer, I frequently visit CPAN or MetaCPAN to read Perl module documentation. I often go there to look up a specific function or method, and many modules are kind enough to list their functions/methods in the table of contents, so it&#8217;s usually easy to quickly find the one I&#8217;m looking for. However, [...]]]></description>
			<content:encoded><![CDATA[<p>Being a Perl programmer, I frequently visit <a href="http://cpan.org/">CPAN</a> or <a href="https://metacpan.org/">MetaCPAN</a> to read Perl module documentation. I often go there to look up a specific function or method, and many modules are kind enough to list their functions/methods in the table of contents, so it&#8217;s usually easy to quickly find the one I&#8217;m looking for.</p>
<p>However, some of those kind modules list functions in non-alphabetical order, which is a bit less useful. Sure, that particular non-alphabetical order might make sense, for example when it groups functions by their purpose, but it still makes it harder to find a specific item on the list. Examples: <a href="http://search.cpan.org/perldoc?DBI">DBI</a>, <a href="http://search.cpan.org/perldoc?DBIx::Class::Schema">DBIx::Class::Schema</a>, <a href="http://search.cpan.org/perldoc?DBIx::Class::Storage">DBIx::Class::Storage</a>.</p>
<p>To cope with that, I wrote a small <a href="http://userscripts.org/scripts/show/129572">Greasemonkey script</a> which allows you to sort those lists in alphabetical order. It tries to recognize lists of functions or methods using simple heuristicts (such as having a &#8220;_&#8221; in the list item text, or having no spaces) and puts an icon next to the list, which, upon clicked, sorts the list.</p>
<p>If you&#8217;re a Perl programmer with <a href="http://en.wikipedia.org/wiki/Obsessive%E2%80%93compulsive_disorder">OCD</a>, I&#8217;m sure you&#8217;ll love this script. Tested to work on Firefox and Chrome/Chromium.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2012/03/pod-functions-sort-greasemonkey-script/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>File::PlainPath &#8211; Let Paths Be Paths Again</title>
		<link>http://www.odyniec.net/blog/2012/02/file-plainpath-let-paths-be-paths-again/</link>
		<comments>http://www.odyniec.net/blog/2012/02/file-plainpath-let-paths-be-paths-again/#comments</comments>
		<pubDate>Sun, 26 Feb 2012 22:06:45 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=830</guid>
		<description><![CDATA[The de facto standard way of constructing portable filesystem paths in Perl is through the use of File::Spec&#8216;s catfile and catdir functions. Example: This method, or a similar one involving Path::Class, is the most recommended approach and has been adopted by application development frameworks like Dancer (which has a wrapper method for it, named path) [...]]]></description>
			<content:encoded><![CDATA[<p>The de facto standard way of constructing portable filesystem paths in Perl is through the use of <a href="http://search.cpan.org/perldoc?File%3A%3ASpec">File::Spec</a>&#8216;s <a href="http://search.cpan.org/perldoc?File%3A%3ASpec#catfile">catfile</a> and <a href="http://search.cpan.org/perldoc?File%3A%3ASpec#catdir">catdir</a> functions. Example:</p>
<pre class="brush: perl; title: ; notranslate">my $path = File::Spec-&gt;catfile('dir', 'subdir', 'file.txt');</pre>
<p>This method, or a similar one involving <a href="http://search.cpan.org/dist/Path-Class">Path::Class</a>, is the most recommended approach and has been adopted by application development frameworks like <a href="http://perldancer.org/">Dancer</a> (which has a wrapper method for it, named <a href="http://search.cpan.org/~xsawyerx/Dancer/lib/Dancer.pm#path"><code>path</code></a>) and <a href="http://www.catalystframework.org/">Catalyst</a> (with its <a href="http://search.cpan.org/~mstrout/Catalyst-Runtime/lib/Catalyst.pm#$c-%3Epath_to%28@path%29"><code>path_to</code></a> method).</p>
<p>The slight problem that I see with this method is that it makes code a bit more complicated, and thus a bit less readable. Paths become lists of parameters and no longer <em>look</em> like paths.</p>
<p>I wrote a simple module that tries to address this by allowing you to write paths the traditional way &#8212; as strings, using a directory separator of your choice (<code>/</code> being the default), while the <code>catfile</code> stuff happens behind the scenes. You can just say:</p>
<pre class="brush: perl; title: ; notranslate">my $path = path 'dir/subdir/file.txt';</pre>
<p>What it does is it splits the path string on each occurrence of the forward slash and feeds the resulting list of path components to <code>File::Spec-&gt;catfile</code>, which reassembles them using the appropriate OS-specific directory separator, and constructs the OS-specific path that you want.</p>
<p>The module is up <a href="https://github.com/odyniec/File-PlainPath">on Github</a>, and should also be available on CPAN shortly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2012/02/file-plainpath-let-paths-be-paths-again/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Little Story of Opel</title>
		<link>http://www.odyniec.net/blog/2012/02/the-little-story-of-opel/</link>
		<comments>http://www.odyniec.net/blog/2012/02/the-little-story-of-opel/#comments</comments>
		<pubDate>Sat, 18 Feb 2012 16:12:44 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Cats]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=811</guid>
		<description><![CDATA[Yesterday was World Cat Day (as observed in Poland), so I thought this might be the perfect time to tell you a little cat story. More than two years ago, I posted the story of Rocket, a kitten that I found in my neighborhood &#8212; now a big, happy cat living with my parents. This [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday was World Cat Day (as observed in Poland), so I thought this might be the perfect time to tell you a little cat story.</p>
<p>More than two years ago, I posted <a title="Rocket" href="http://odyniec.net/blog/2009/10/rocket/">the story of Rocket</a>, a kitten that I found in my neighborhood &#8212; now a big, happy cat living with my parents. This story has a very similar beginning.</p>
<p>It was a cold September evening, I was walking home along a busy street, when I heard a kitten squeak. It was obviously coming from under a car parked near the street, so I started looking, but couldn&#8217;t see any kitten under the car. The squeaking continued, so I knew it must have been there, and I kept looking and reaching behind the wheels, but to no avail.</p>
<p>Since many people were passing by, my unusual activities attracted the attention of some of them. One man with an <em>&#8220;excuse me sir, what are you doing?&#8221;</em> look approached me, but before he even asked me a question, the kitten meowed again, so the man began searching with me.</p>
<p>After we both searched for a while with no success, the guy said &#8220;you know what, I live in this block here and I know the owner of this car, let me call him&#8221;. In a few minutes, the owner came and joined the search operation.</p>
<p>He looked inside the car just to be sure the kitten didn&#8217;t get in there in some miraculous way, but that was not the case. It was obvious that the little guy was somewhere in the car undercarriage, but the meowing seemed to be coming from different places and neither one of us was able to tell exactly where the kitten could be.</p>
<p>In the end, we lifted the car up with a jack, the owner crawled under it and saw some fur sticking out from a hollow spot next to the exhaust pipe. He reached in there and got the kitten out &#8212; the poor thing looked all dirty and miserable, but didn&#8217;t appear to be hurt in any way. The first guy called his wife, who brought some cat food (it turned out they had two Persian cats) and water for the rescuee.</p>
<p><span id="more-811"></span>I then took the little fellow home to take care of him. It was apparent that he wasn&#8217;t accustomed to humans and was afraid of them, because the moment he got out of the box in which I brought him, he got really frightened, started hissing at me, and tried to attack me if I got too close. But then my adult cats came to see what was going on, and the little one got much more comfortable around them.</p>
<p>The kitten was named &#8220;Opel&#8221; after the brand of the car (all of the search party agreed on that). I originally planned to keep him just for a week or two and find him a new home, but since he was getting along quite well with my two adult cats, I thought, what the hell, he can stay with me. So that&#8217;s how my cat crew got its newest member.</p>
<p>In addition to that, I made some new friends. The married couple who helped me with the search operation turned out to be really nice people, and now I visit them every once in a while to talk about how Opel is doing and share other cat stories.</p>
<p>Now, since you&#8217;ve made it that far in the story, let me reward you with some photos. Here&#8217;s Opel literally minutes after I brought him home (sorry, the image quality is as poor as he was that very moment):</p>
<p><img class="aligncenter size-full wp-image-812" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-09-22-21.33.33.jpg" alt="" width="640" height="480" /></p>
<p>And later that same night, feeling much more comfortable and hanging out with one of the older cats:</p>
<p><img class="aligncenter size-full wp-image-813" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-09-23-00.36.30.jpg" alt="" width="640" height="480" /></p>
<p>They became buddies pretty quickly:</p>
<p><img class="aligncenter size-full wp-image-814" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-09-28-20.22.24.jpg" alt="" width="640" height="480" /></p>
<p>To the point that sometimes Opel was literally sleeping <em>on</em> his big fellow:</p>
<p><img class="aligncenter size-full wp-image-815" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-10-04-01.38.08.jpg" alt="" width="640" height="480" /></p>
<p>And sometimes it was the other way around:</p>
<p><img class="aligncenter size-full wp-image-816" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-10-07-16.43.45.jpg" alt="" width="640" height="480" /></p>
<p>They were often getting really creative with their sleeping poses on that chair:</p>
<p><img class="aligncenter size-full wp-image-817" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-10-07-22.25.34.jpg" alt="" width="640" height="480" /></p>
<p>And here&#8217;s a later photo of Opel, just chilling on an old CRT monitor:</p>
<p><img class="aligncenter size-full wp-image-818" title="Opel" src="http://odyniec.net/blog/wp-content/uploads/2012/02/2011-12-01-09.48.14.jpg" alt="" width="640" height="480" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2012/02/the-little-story-of-opel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Six (Plus One) Android Apps that Make my Life Suck a bit Less</title>
		<link>http://www.odyniec.net/blog/2012/01/six-plus-one-android-apps-that-make-my-life-suck-a-bit-less/</link>
		<comments>http://www.odyniec.net/blog/2012/01/six-plus-one-android-apps-that-make-my-life-suck-a-bit-less/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 22:11:27 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=795</guid>
		<description><![CDATA[I planned to write an introductory paragrah about how everyone and their grandma now uses mobile apps, but everyone (and their grandma) already knows that. So let me jump straight to the point &#8212; here&#8217;s a list of the apps that I found essential since I got myself an Android phone about one and a [...]]]></description>
			<content:encoded><![CDATA[<p>I planned to write an introductory paragrah about how everyone and their grandma now uses mobile apps, but everyone (and their grandma) already knows that. So let me jump straight to the point &#8212; here&#8217;s a list of the apps that I found essential since I got myself an Android phone about one and a half year back.</p>
<h3>1. <a href="https://market.android.com/details?id=com.fsck.k9">K-9 Mail</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/k9mail1.png"><img class="alignleft size-full wp-image-801" title="K-9 Mail" src="http://odyniec.net/blog/wp-content/uploads/2012/01/k9mail1.png" alt="" width="62" height="62" /></a>A powerful e-mail client. Actually, it&#8217;s <em>the</em> e-mail client for your Android phone. Comes with a rich feature set that could put many desktop e-mail clients to shame. Has good support for multiple e-mail accounts, IMAP, signatures, PGP, searching &#8212; you name it. Highly recommended for everyone who wants to do some serious business with e-mail on their phone.</p>
<h3>2. <a href="https://market.android.com/details?id=mobi.beyondpod">BeyondPod</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/beyondpod.png"><img class="alignright size-full wp-image-802" title="BeyondPod" src="http://odyniec.net/blog/wp-content/uploads/2012/01/beyondpod.png" alt="" width="62" height="62" /></a>A podcatcher/player. I&#8217;ve tried quite a few, and this one is by far the best. It&#8217;s loaded with useful features, but is still maintaining a clean user interface. This app is the top reason why I&#8217;ve become a regular listener of a number of podcasts, listening every day while driving, exercising, or doing mundane house chores.</p>
<h3>3. <a href="https://market.android.com/details?id=com.headcode.ourgroceries">OurGroceries</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/ourgroceries.png"><img class="alignleft size-full wp-image-803" title="OurGroceries" src="http://odyniec.net/blog/wp-content/uploads/2012/01/ourgroceries.png" alt="" width="62" height="62" /></a>Dead simple app that aids you in putting together shopping lists. I was originally using the traditional paper and pen approach and thought that was all I&#8217;d ever need, but then I tried this app and it proved to be more effective. And, it adds that flavor of geekiness to the boring act of grocery shopping.</p>
<h3>4. <a href="https://market.android.com/details?id=com.twitter.android">Twitter</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/twitter.png"><img class="alignright size-full wp-image-804" title="Twitter" src="http://odyniec.net/blog/wp-content/uploads/2012/01/twitter.png" alt="" width="62" height="62" /></a>The official Twitter client for Android. People used to criticize it and say that the unofficial apps are way better, but I&#8217;ve tried all of the popular ones and none of them offered anything particularly interesting to me. The official app is simple, has a clean interface, and does its job quite well.</p>
<h3>5. <a href="https://market.android.com/details?id=cgeo.geocaching">c:geo</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/cgeo.png"><img class="alignleft size-full wp-image-805" title="c:geo" src="http://odyniec.net/blog/wp-content/uploads/2012/01/cgeo.png" alt="" width="62" height="62" /></a>A great <a href="http://en.wikipedia.org/wiki/Geocaching">geocaching</a> app with lots of useful features and a nice user interface. If you want to try geocaching with your Android phone and are looking for an app, look no further and get c:geo.</p>
<h3>6. <a href="https://market.android.com/details?id=com.codecarpet.apndroid.pro">APNdroid</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/apndroid.png"><img class="alignright size-full wp-image-806" title="APNdroid" src="http://odyniec.net/blog/wp-content/uploads/2012/01/apndroid.png" alt="" width="62" height="62" /></a>A tiny app with a very specific purpose. All it does is it lets you add a button to your home screen to toggle mobile data connection on and off, making a commonly used feature accessible immediately, instead of forcing you to find it buried somewhere in the settings menu.</p>
<h3>Honorable mention: <a href="https://market.android.com/details?id=org.dodgybits.android.shuffle">Shuffle</a></h3>
<p><a href="http://odyniec.net/blog/wp-content/uploads/2012/01/shuffle.png"><img class="alignleft size-full wp-image-807" title="Shuffle" src="http://odyniec.net/blog/wp-content/uploads/2012/01/shuffle.png" alt="" width="62" height="62" /></a>A simple but effective <a href="http://en.wikipedia.org/wiki/Getting_Things_Done">Getting Things Done</a> app. I started implementing GTD a while ago when a guy I worked with told me about it, and he also recommended this app. I didn&#8217;t place it on the list, because the current version has a significant flaw &#8212; it fails to properly synchronize with <a title="Tracks" href="http://getontracks.org/">Tracks</a>, a GTD web application that I use on the desktop machine, and I can&#8217;t really use it until that bug gets fixed (hopefully, soon).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2012/01/six-plus-one-android-apps-that-make-my-life-suck-a-bit-less/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alternative Dancer Templating Engines</title>
		<link>http://www.odyniec.net/blog/2011/12/alternative-dancer-templating-engines/</link>
		<comments>http://www.odyniec.net/blog/2011/12/alternative-dancer-templating-engines/#comments</comments>
		<pubDate>Sun, 18 Dec 2011 14:05:54 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Dancer]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=790</guid>
		<description><![CDATA[Dancer uses a simple model of interfacing with templating engines (based on Dancer::Template::Abstract) and makes it very easy to add support for new engines. Thanks to this, if you&#8217;re not happy with the default simple engine or with Template Toolkit, there is now a dozen different alternatives to choose from. Let&#8217;s take a look at [...]]]></description>
			<content:encoded><![CDATA[<p>Dancer uses a simple model of interfacing with templating engines (based on <a href="http://search.cpan.org/perldoc?Dancer::Template::Abstract">Dancer::Template::Abstract</a>) and makes it very easy to add support for new engines. Thanks to this, if you&#8217;re not happy with the default <code>simple</code> engine or with <a href="http://template-toolkit.org/index.html">Template Toolkit</a>, there is now a dozen different alternatives to choose from. Let&#8217;s take a look at some of them.</p>
<h3><a name="dancer__template__tiny" href="http://blogs.perl.org/mt/mt-static/html/editor-content.html?cs=utf-8"></a>Dancer::Template::Tiny</h3>
<p><a href="http://search.cpan.org/perldoc?Template::Tiny">Template::Tiny</a> is a lightweight engine which reimplements a subset of Template Toolkit features. As the name implies, it aims to accomplish this with as little code as possible. If you&#8217;re using just the basic functionality of Template Toolkit, you should be able to switch to Template::Tiny without any modifications to template files (and you can easily go back at any moment).</p>
<p><a href="http://search.cpan.org/perldoc?Dancer::Template::Tiny">Dancer::Template::Tiny</a> is going to replace <a href="http://search.cpan.org/perldoc?Dancer::Template::Simple">Dancer::Template::Simple</a> as the default templating engine in Dancer2.</p>
<p>Example template:</p>
<pre>&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Tiny Example&lt;/title&gt;
    &lt;link rel="stylesheet" href="[% request.uri_base %]/css/style.css" /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello, World! This is Dancer [% dancer_version %]!&lt;/h1&gt;
    &lt;p&gt;
      [% IF morning %]
        Good morning!
      [% ELSE %]
        Good afternoon!
      [% END %]
    &lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Route handler:</p>
<pre>use DateTime;
   
get '/hello' =&gt; sub {
    template 'hello', { morning =&gt; (localtime)[2] &lt; 12, now =&gt; DateTime-&gt;now };
};</pre>
<h3><a name="dancer__template__tenjin" href="http://blogs.perl.org/mt/mt-static/html/editor-content.html?cs=utf-8"></a>Dancer::Template::Tenjin</h3>
<p><a href="http://www.kuwata-lab.com/tenjin/">Tenjin</a> is a very fast templating engine with implementations for many languages &#8212; including, of course, Perl. Its great performance comes from the fact that it uses the underlying language&#8217;s constructs to process templates, instead of defining its own templating language and having to parse it. Support for this engine in Dancer is provided by  <a href="http://search.cpan.org/perldoc?Dancer::Template::Tenjin">Dancer::Template::Tenjin</a>.</p>
<p>Example template:</p>
<pre>&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Tenjin Example&lt;/title&gt;
    &lt;link rel="stylesheet" href="[== $request-&gt;uri_base =]/css/style.css" /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello, World! This is Dancer [= $dancer_version =]!&lt;/h1&gt;
    &lt;p&gt;
      &lt;?pl if ((localtime)[2] &lt; 12) { ?&gt;
        Good morning!
      &lt;?pl } else { ?&gt;
        Good afternoon!
      &lt;?pl } ?&gt;
    &lt;/p&gt;
    &lt;p&gt;
      Current time is: [== DateTime-&gt;now-&gt;hms =]
    &lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Route handler:</p>
<pre>use DateTime;
   
get '/hello' =&gt; sub {
    template 'hello';
};</pre>
<h3><a name="dancer__template__haml" href="http://blogs.perl.org/mt/mt-static/html/editor-content.html?cs=utf-8"></a>Dancer::Template::Haml</h3>
<p><a href="http://haml-lang.com/">Haml</a>, which stands for &#8220;HTML Abstraction Markup Language&#8221;, brings a fresh, different approach to templating. It aims at making templates short, clean, and as easy to read as well-formatted source code. <a href="http://search.cpan.org/perldoc?Dancer::Template::Haml">Dancer::Template::Haml</a> is a wrapper around <a href="http://search.cpan.org/perldoc?Text::Haml">Text::Haml</a> and lets you use Haml templates in Dancer applications.</p>
<p>Example template:</p>
<pre>%html
  %head
    %title Haml Example
    %link(rel="stylesheet" href="#{$request-&gt;uri_base}/css/style.css")
  %body
    %h1 Hello, World! This is Dancer #{$dancer_version}!
    %p
      - if ((localtime)[2] &lt; 12) {
        Good morning!
      - } else {
        Good afternoon!
      - }
    %p Current time is: #{DateTime-&gt;now-&gt;hms}</pre>
<p>Route handler:</p>
<pre>use DateTime;
   
get '/hello' =&gt; sub {
    template 'hello';
};</pre>
<h3><a name="more" href="http://blogs.perl.org/mt/mt-static/html/editor-content.html?cs=utf-8"></a>More</h3>
<p>There are many more interesting templating engines ready to be used with Dancer, such as <a href="http://www.masonhq.com/">Mason</a> (provided by <a href="http://search.cpan.org/perldoc?Dancer::Template::Mason">Dancer::Template::Mason</a>) or <a href="http://xslate.org/">Xslate</a> (<a href="http://search.cpan.org/perldoc?Dancer::Template::Xslate">Dancer::Template::Xslate</a>). Do a <a href="http://search.cpan.org/">CPAN</a> or <a href="https://metacpan.org/">MetaCPAN</a> search for &#8220;dancer template&#8221; to get a list of all the available engines, and choose the one that suits you best. In the true spirit of Perl, there&#8217;s more than one way to write a template!</p>
<p><em>This post was <a href="http://advent.perldancer.org/2011/18">originally published</a> as part of the <a href="http://advent.perldancer.org/2011">2011 Dancer Advent Calendar</a>.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2011/12/alternative-dancer-templating-engines/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serving Files with Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd</title>
		<link>http://www.odyniec.net/blog/2011/12/serving-files-with-dancer-plugin-directoryview-and-dancer-plugin-auth-htpasswd/</link>
		<comments>http://www.odyniec.net/blog/2011/12/serving-files-with-dancer-plugin-directoryview-and-dancer-plugin-auth-htpasswd/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 22:15:22 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Dancer]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=779</guid>
		<description><![CDATA[A while ago I was converting a simple PHP website to Dancer, and moving it from being deployed on Apache to Starman. There wasn&#8217;t a lot of code, so rewriting went quickly &#8212; but, the site used a few specific features of Apache, namely directory indexes (courtesy of mod_autoindex) to allow user access to directories/files [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>A while ago I was converting a simple PHP website to Dancer, and moving it from being deployed on Apache to Starman. There wasn&#8217;t a lot of code, so rewriting went quickly &#8212; but, the site used a few specific features of Apache, namely directory indexes (courtesy of <a href="http://search.cpan.org/perldoc?http%3A#%2Fhttpd.apache.org%2Fdocs%2Fcurrent%2Fmod%2Fmod_autoindex.html">mod_autoindex</a>) to allow user access to directories/files on the server, and <code>htpasswd</code> files to password-protect some of those directories.</p>
<p>I could just deploy the new Dancer website on Apache and keep using those goodies, but I thought that it would be nice if Dancer itself provided similar features. So, I created two plugins that do just that: <a href="http://search.cpan.org/perldoc?Dancer%3A%3APlugin%3A%3ADirectoryView">Dancer::Plugin::DirectoryView</a> and <a href="http://search.cpan.org/perldoc?Dancer%3A%3APlugin%3A%3AAuth%3A%3AHtpasswd">Dancer::Plugin::Auth::Htpasswd</a>. Let me now show you how to use them.</p>
<h3>Directory Indexes</h3>
<p>Let&#8217;s say we have a <code>files</code> directory under <code>public</code>, and we&#8217;d like to allow users to browse it and download files. Enabling directory access is as simple as including the plugin in our Dancer application:</p>
<pre class="brush: perl; title: ; notranslate">      package MyWebApp;

      ...

      use Dancer::Plugin::DirectoryView;</pre>
<p>And updating the configuration file (<code>config.yml</code>) to tell the plugin which directory should be made available, and at which URL:</p>
<pre class="brush: jscript; title: ; notranslate">      plugins:
          DirectoryView:
              url: /pub
              root_dir: files</pre>
<p>That&#8217;s it &#8212; now, if we launch our app and point the browser at the <code>/pub</code> URL, we&#8217;ll see the contents of the directory:</p>
<p><img class="aligncenter size-full wp-image-780" title="Browsing the /pub directory" src="http://odyniec.net/blog/wp-content/uploads/2011/12/screenshot-1-590.png" alt="" width="590" height="231" /></p>
<h3>Protecting Directories with Htpasswd Files</h3>
<p>As you might have noticed on the screenshot, there&#8217;s a <code>secret</code> directory under <code>files</code>.  It contains some super secret data that should only be available to  authorized users, so now we&#8217;re going to protect it using a <code>htpasswd</code> file.</p>
<p>First, let&#8217;s create the <code>htpasswd</code> file and an user, named &#8220;alice&#8221;:</p>
<pre>      $ htpasswd -c htpasswd alice</pre>
<p>Once it is created, we need to put the <code>htpasswd</code> file in a safe location outside of the public directory, so let&#8217;s create a new directory <code>passwd</code> and store the file in there.</p>
<p>(If you&#8217;re migrating from Apache and already have the <code>htpasswd</code> file, you just need to copy it to your Dancer application.)</p>
<p>In our Dancer application, we include the Auth::Htpasswd plugin:</p>
<pre class="brush: perl; title: ; notranslate">      package MyWebApp;

      ...

      use Dancer::Plugin::Auth::Htpasswd;</pre>
<p>Now, we need to update our configuration file and add settings for the plugin. We&#8217;ll tell it to protect the <code>/pub/secret</code> path, and to use the <code>htpasswd</code> file we just created:</p>
<pre class="brush: jscript; title: ; notranslate">      plugins:
         &quot;Auth::Htpasswd&quot;:
             paths:
                 &quot;/pub/secret&quot;:
                     realm: &quot;Secret Files&quot;
                     passwd_file: passwd/htpasswd</pre>
<p>The <code>realm</code> parameter lets us set the text that will be shown to the user in the login window displayed by the browser.</p>
<p>Let&#8217;s see if our protection works. We restart the application and try to access the <code>/pub/secret/</code> URL:</p>
<p><img class="aligncenter size-full wp-image-781" title="Browser authentication dialog" src="http://odyniec.net/blog/wp-content/uploads/2011/12/screenshot-2-590.png" alt="" width="590" height="137" /></p>
<p>Great, our confidential files are safe. Only when we log in as &#8220;Alice&#8221;, we&#8217;ll be able to access them:</p>
<p><img class="aligncenter size-full wp-image-782" title="Browsing the /pub/secret directory" src="http://odyniec.net/blog/wp-content/uploads/2011/12/screenshot-3-590.png" alt="" width="590" height="231" /></p>
<p><em>This post was <a href="http://advent.perldancer.org/2011/13">originally published</a> as part of the <a href="http://advent.perldancer.org/2011">2011 Dancer Advent Calendar</a>.</em></div>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2011/12/serving-files-with-dancer-plugin-directoryview-and-dancer-plugin-auth-htpasswd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GitHub-friendly README files with ExtUtils::MakeMaker and Module::Build</title>
		<link>http://www.odyniec.net/blog/2011/11/github-friendly-readme-files-with-extutils-makemaker-and-module-build/</link>
		<comments>http://www.odyniec.net/blog/2011/11/github-friendly-readme-files-with-extutils-makemaker-and-module-build/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 22:41:49 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[github]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=762</guid>
		<description><![CDATA[GitHub is a great place to host open-source projects and expose them to a wide community of developers, so it&#8217;s not surprising that more and more Perl modules are making it their home. One of the features of GitHub is that it checks if a repository has a README file in its root directory, and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/">GitHub</a> is a great place to host open-source projects and expose them to a wide community of developers, so it&#8217;s not surprising that more and more Perl modules are making it their home.</p>
<p>One of the features of GitHub is that it checks if a repository has a <code>README</code> file in its root directory, and displays it on the home page of the repository. This makes the <code>README</code> file a good place to introduce your project to the public.</p>
<p>GitHub also understands a number of markup languages, such as <a href="http://daringfireball.net/projects/markdown/">Markdown</a> and <a href="http://www.textism.com/tools/textile/">Textile</a>, and if the <code>README</code> file is in one of these formats, it will be transformed into nicely formatted HTML. One of the supported formats is <a href="http://perldoc.perl.org/perlpod.html">POD</a>, which means that the standard documentation of a Perl module can be used as its <code>README</code> file and serve as the repository&#8217;s home page (much like on <a href="http://www.cpan.org/">CPAN</a>).</p>
<p><a href="http://search.cpan.org/dist/Module-Starter/">Module::Starter</a>, which is <a href="http://perldoc.perl.org/perlnewmod.html#Step-by-step:-Making-the-module">Perl&#8217;s recommended tool for building modules</a>, does not create a GitHub-friendly <code>README</code> file &#8212; instead, the README that it produces contains installation instructions (the <code>"perl Makefile.PL; make..."</code> mantra) and a couple links to module resources. This means that if you want to have a GitHub-friendly <code>README</code> file in your module, you need to either create it yourself, or tweak your build script a bit to have it generate it for you automatically.</p>
<p>This article wouldn&#8217;t be particularly interesting if I told you to now go and make the <code>README</code> file yourself, would it? So let me show you how to do this automatically with <a href="http://search.cpan.org/perldoc?ExtUtils::MakeMaker">ExtUtils::MakeMaker</a> and <a href="http://search.cpan.org/perldoc?Module::Build">Module::Build</a> based modules (generated with Module::Starter). I will demonstrate how to create two <code>README</code> files: one being the POD version (named <code>README.pod</code>), the other one plain text (named just <code>README</code>).</p>
<h3>ExtUtils::MakeMaker</h3>
<p>Since ExtUtils::MakeMaker creates a <code>Makefile</code> with shell commands, you can tell it to generate the README files using two core Perl command-line utilities: <a href="http://perldoc.perl.org/perldoc.html">perldoc</a> (to generate POD from module&#8217;s source) and <a href="http://perldoc.perl.org/pod2text.html">pod2text</a> (to convert POD into plain text). Extend <code>Makefile.PL</code> by adding the shell commands as the <code>PREOP</code> attribute of the dist target configuration:</p>
<pre class="brush: perl; title: ; notranslate">my $preop =
    'perldoc -uT $(VERSION_FROM) | tee $(DISTVNAME)/README.pod &gt; README.pod;' .
    'pod2text README.pod | tee $(DISTVNAME)/README &gt; README';

WriteMakefile(
    NAME                =&gt; 'Foo::Bar',
    AUTHOR              =&gt; q{Michal Wojciechowski &lt;odyniec@cpan.org&gt;},
    VERSION_FROM        =&gt; 'lib/Foo/Bar.pm',
    ABSTRACT_FROM       =&gt; 'lib/Foo/Bar.pm',
    ($ExtUtils::MakeMaker::VERSION &gt;= 6.3002
      ? ('LICENSE'=&gt; 'perl')
      : ()),
    PL_FILES            =&gt; {},
    PREREQ_PM =&gt; {
        'Test::More' =&gt; 0,
    },
    dist                =&gt; {
        COMPRESS =&gt; 'gzip -9f',
        SUFFIX =&gt; 'gz',
        PREOP =&gt; $preop,
    },
    clean               =&gt; { FILES =&gt; 'Foo-Bar-*' },
);</pre>
<p>Now, when you run <code>perl Makefile.PL</code> and <code>make dist</code>, the two <code>README</code> files will be created for you.</p>
<p>Don&#8217;t worry if running <code>make dist</code> produces warnings that <code>README</code> and <code>README.pod</code> are missing &#8212; it&#8217;s no big deal, as the warnings will only be seen by you when making a distribution package, and not by the user building the module.</p>
<h3>Module::Build</h3>
<p>Module::Build defines a <code>docs</code> action, and it&#8217;s the appropriate place for the code that builds the <code>README</code> files. Two modules that you can use for this purpose are <a href="http://search.cpan.org/perldoc?Pod%3A%3ASelect">Pod::Select</a> and <a href="http://search.cpan.org/perldoc?Pod%3A%3AReadme">Pod::Readme</a>. In your <code>Build.PL</code> file, create a subclass of Module::Build, and define a subroutine named <code>ACTION_docs</code>, similar to the one shown below:</p>
<pre class="brush: perl; title: ; notranslate">my $class = Module::Build-&gt;subclass(
    class =&gt; 'My::Builder',
    code =&gt; q{
        sub ACTION_docs {
            use Pod::Readme;
            use Pod::Select;

            my $self = shift;

            podselect({ -output =&gt; 'README.pod' },
                'lib/Foo/Bar.pm');

            my $parser = Pod::Readme-&gt;new();
            $parser-&gt;parse_from_file('README.pod', 'README');

            return $self-&gt;SUPER::ACTION_docs;
        }
    }
);

my $builder = $class-&gt;new(
    module_name         =&gt; 'Foo::Bar',
    license             =&gt; 'perl',
    dist_author         =&gt; q{Michal Wojciechowski &lt;odyniec@cpan.org&gt;},
    dist_version_from   =&gt; 'lib/Foo/Bar.pm',
    requires =&gt; {
        ...
    },
    configure_requires =&gt; {
        'Pod::Readme' =&gt; 0,
        'Pod::Select' =&gt; 0,
    },
    build_requires =&gt; {
        'Pod::Readme' =&gt; 0,
        'Pod::Select' =&gt; 0,
        'Test::More' =&gt; 0,
    },
    add_to_cleanup      =&gt; [ 'Foo-Bar-*' ],
    create_makefile_pl =&gt; 'traditional',
);

$builder-&gt;create_build_script();</pre>
<p>You can now run <code>perl Build.PL</code>, and then <code>./Build docs</code>, to build the <code>README</code> files.</p>
<p>Remember to add the Pod::Select and Pod::Readme modules to <code>configure_requires</code> and <code>build_requires</code>, as shown in the above example.</p>
<h3>Installation instructions</h3>
<p>Since these methods overwrite the original README file provided by Module::Starter, the installation instructions in it are also lost. It&#8217;s a good practice to always include installation instructions, so go ahead and add an INSTALL file to your module&#8217;s distribution files. It can be really simple and straight to the point:</p>
<pre class="brush: plain; title: ; notranslate">Foo-Bar

INSTALLATION

To install this module, run the following commands:

    perl Build.PL
    ./Build
    ./Build test
    ./Build install</pre>
<p>Finally, remember to add <code>README.pod</code> and <code>INSTALL</code> to your module&#8217;s <code>MANIFEST</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2011/11/github-friendly-readme-files-with-extutils-makemaker-and-module-build/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Busy Busy Me</title>
		<link>http://www.odyniec.net/blog/2011/10/busy-busy-me/</link>
		<comments>http://www.odyniec.net/blog/2011/10/busy-busy-me/#comments</comments>
		<pubDate>Mon, 31 Oct 2011 22:49:18 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=759</guid>
		<description><![CDATA[Things have been slow with my projects in the past few weeks, and that&#8217;s because most of my time is now consumed by dayjob. I&#8217;m currently working on two part-time contracts, one being a telecommute Perl job for a client in London, the other one an enterprisey Java web project here in Warsaw. This translates [...]]]></description>
			<content:encoded><![CDATA[<p>Things have been slow with my projects in the past few weeks, and that&#8217;s because most of my time is now consumed by dayjob. I&#8217;m currently working on two part-time contracts, one being a telecommute Perl job for a client in London, the other one an enterprisey Java web project here in Warsaw. This translates to roughly 11-12 hours of work a day, and while I&#8217;m used to working this many hours, there&#8217;s obviously not much time left for other things.</p>
<p>I hope things will settle down a bit in the next couple of days (especially with the Java project, which should go out of the hot initiation phase it&#8217;s currently in), and I&#8217;ll have more time for my stuff &#8212; especially that I have a lot of updates planned for my jQuery plugins and CPAN modules. For now, I&#8217;m trying to squeeze out a few hours every week to at least do some minor updates. So yesterday, I managed to push out a new release of <a href="http://search.cpan.org/~odyniec/Dancer-Plugin-DirectoryView/">Dancer::Plugin::DirectoryView</a>.</p>
<p>Apologies to everyone who contacted me by e-mail (or other means) and didn&#8217;t get a reply, I promise in the next few days I&#8217;ll go through my mailbox and respond to any unanswered messages. As a general rule: if you don&#8217;t get a response from me in a day or two, feel free to write me again &#8212; it usually works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2011/10/busy-busy-me/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dancer::Plugin::Auth::Htpasswd</title>
		<link>http://www.odyniec.net/blog/2011/10/dancer-plugin-auth-htpasswd/</link>
		<comments>http://www.odyniec.net/blog/2011/10/dancer-plugin-auth-htpasswd/#comments</comments>
		<pubDate>Tue, 11 Oct 2011 20:50:51 +0000</pubDate>
		<dc:creator>Michal Wojciechowski</dc:creator>
				<category><![CDATA[Dancer]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://odyniec.net/blog/?p=754</guid>
		<description><![CDATA[I have developed a new Dancer plugin based on the recently-released Dancer::Plugin::Auth::Basic. The new one is called Dancer::Plugin::Auth::Htpasswd, and it serves the same purpose as Auth::Basic, which is adding basic HTTP authentication to a Dancer web app &#8212; the difference is that Auth::Htpasswd does this using Apache-style htpasswd files. The plugin might be useful if [...]]]></description>
			<content:encoded><![CDATA[<p>I have developed a new <a href="http://perldancer.org/">Dancer</a> plugin based on the <a title="Dancer::Plugin::Auth::Basic" href="http://odyniec.net/blog/2011/10/dancer-plugin-auth-basic/">recently-released Dancer::Plugin::Auth::Basic</a>. The new one is called Dancer::Plugin::Auth::Htpasswd, and it serves the same purpose as Auth::Basic, which is adding basic HTTP authentication to a Dancer web app &#8212; the difference is that Auth::Htpasswd does this using <a href="http://httpd.apache.org/docs/current/programs/htpasswd.html">Apache-style htpasswd files</a>.</p>
<p>The plugin might be useful if you&#8217;re migrating a web application from Apache to a different HTTP server and want to keep using the same htpasswd files, or if you don&#8217;t want to keep passwords written in plain text in configuration (as it is with Auth::Basic).</p>
<p>Get the plugin <a href="http://search.cpan.org/~odyniec/Dancer-Plugin-Auth-Htpasswd/">on CPAN</a> and <a href="https://github.com/odyniec/Dancer-Plugin-Auth-Htpasswd/">on Github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.odyniec.net/blog/2011/10/dancer-plugin-auth-htpasswd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Database Caching using disk

Served from: www.odyniec.net @ 2012-05-17 03:59:51 -->

<!-- W3 Total Cache: Page cache debug info:
Engine:             disk (enhanced)
Cache key:          blog/feed/_index.html
Caching:            enabled
Status:             not cached
Creation Time:      2.026s
Header info:
X-Pingback:         http://www.odyniec.net/blog/xmlrpc.php
ETag:               "54ea2e0db731c4d7634ee52d6d73c13d"
Content-Type:       text/xml; charset=UTF-8
Last-Modified:      Thu, 17 May 2012 01:59:51 GMT
Vary:               Cookie
X-Powered-By:       W3 Total Cache/0.9.2.3
-->
