Yanick's Journal http://use.perl.org/~Yanick/journal/ Yanick's use Perl Journal en-us use Perl; is Copyright 1998-2006, Chris Nandor. Stories, comments, journals, and other submissions posted on use Perl; are Copyright their respective owners. 2012-01-25T02:23:29+00:00 pudge pudge@perl.org Technology hourly 1 1970-01-01T00:00+00:00 Yanick's Journal http://use.perl.org/images/topics/useperl.gif http://use.perl.org/~Yanick/journal/ Breaking off from the use.perl.org mothership http://use.perl.org/~Yanick/journal/38951?from=rss <p> For the last couple of months, as a concession between visibility and control, I'd been double-posting my blog entries both here and on my personal blog. But now that my blog is registered on both the <a href="http://perlsphere.net/">Perlsphere</a> and <a href="http://ironman.enlightenedperl.org/">IronMan</a> aggregators, the need for the second posts here has dwindled. So... I'm going on a limb and tentatively turn off the echoing. See y'all on <a href="http://babyl.dyndns.org/techblog">Hacking Thy Fearful Symmetry</a>!</p> Yanick 2009-05-10T23:40:55+00:00 journal Ruhr.pm: Die Meister des Psycho-Lamas http://use.perl.org/~Yanick/journal/38840?from=rss <p> <i>reposted from <a href="http://babyl.dyndns.org/techblog">Hacking Thy Fearful Symmetry</a> </i> </p><p>Last month, thanks to a concerted effort of German Perl Mongers[1] I was able to meet with the wonderful folks of <a href="http://ruhr.pm.org/">Ruhr.pm</a>. </p><p>It turns out that not only the Ruhr-area mongers are a superlatively friendly bunch, but they have pretty <a href="http://ruhr.pm.org/material.psp">cool presentations</a> too. </p><p>The feature presentation of the night was <a href="http://ruhr.pm.org/files/fuse/docshot/">Fuse mit Perl</a>, by Simon Wilper. After he was done, I also got treated with a quick replay of two previous presentations dealing with image manipulation. <a href="http://ruhr.pm.org/files/opencv/docshot">One</a> was about openCV, a facial recognition software, and its Perl interface, and the other one was about the <a href="http://ruhr.pm.org/files/imagemagick/docshot">uses of Image::Magick</a>, including the detailed instructions on how to create a psycho-llama. That last bit, I daresay, was worth the trip to Germany all by itself. The script to create the thing is in the <a href="http://ruhr.pm.org/files/imagemagick/imagemagick-beispiele.tar.gz">presentation companion tarball</a>, check it out (well, unless you suffer from epilepsy, in which case you want to stay as far away as possible).</p><p>So, bottom-line: Ruhr.pm rocks big time. If you're ever passing in the vicinity, I highly recommend paying them a visit.<nobr> <wbr></nobr>:-)</p><p>[1] Ren&#233;e B&#228;cker saw my use.perl.org blog entry and forwarded the information to Ruhr.pm, Veit Wahlich -- fearless leader of the Ruhrgebiet mongers -- contacted me and arranged the details, and Ren&#233; Knopp was dispatched to pick me up from the train station. Many thanks to the whole bunch!</p> Yanick 2009-04-22T00:31:18+00:00 journal Just another Perl Ausl&#228;nder http://use.perl.org/~Yanick/journal/38591?from=rss <p>(cross-posted from <a href="http://babyl.dyndns.org/techblog">Hacking Thy Fearful Symmetry</a>)</p><p>Ever since I've learned about the existence of <a href="http://www.perl-magazin.de/">$foo - Perl Magazin</a>, I've been awfully curious to take a peek at it. Unfortunately, they don't ship subscriptions internationally. So I went for the obvious workaround: I hunted high and low for the loveliest German lass I could find, asked her to marry me, and coaxed her family to get and forward me a subscription for the magazine as this year's Christmas gift. Worked like a charm.</p><p> And it was worth it too. The magazine is even better than I expected, and it's high praises to the authors that I learned quite a few things from the articles even though my German is still at a protozoic stage. Whether you're a German wanting to learn Perl, or a Perl hacker wanting to learn German, I heartily recommend it.</p><p>And talking of Germany, I'll embark tomorrow on a three-week vacation trip across the republic. If there are any Perl mongers meeting this month around Duisburg, Morsbach or Schwieberdigen who wouldn't mind having an Ausl&#228;nder in their midst, please feel free to drop me an email.<nobr> <wbr></nobr>:-)</p> Yanick 2009-03-04T18:28:37+00:00 journal Variation on the Faces of CPAN http://use.perl.org/~Yanick/journal/38186?from=rss <p>Faces of CPAN + GD::Image + blissfully idle holiday morning = <a href="http://babyl.dyndns.org/perl/faces_of_cpan/">this</a>.</p> Yanick 2008-12-30T18:26:27+00:00 journal CPAN Patching with Git http://use.perl.org/~Yanick/journal/38180?from=rss <p>A few months ago, brian posted a blog entry about <a href="http://use.perl.org/~brian_d_foy/journal/37664">patching modules using Git</a>. In the ensuing discussion, I pointed at a possible way to automatise the process a step further by punting the generated patch to rt.cpan.org. The hack was well-received and, with (very) minimal coaxing, I was subsequently convinced to expand on the idea for the Perl Review.</p><p>The resulting piece is now available in <a href="http://theperlreview.com/">TPR 5.1</a>. In the article, the initial command-line hack has morphed into four scripts -- <code>git-cpan-init</code>, <code>git-cpan-clone</code>, <code>git-cpan-update</code> and <code>git-cpan-sendpatch</code> -- that pretty much take care of all the administrative overhead of module patching. In most cases, grabbing a distro, fixing a bug and sending the patch can be done in four lines:</p><blockquote><div><p> <tt>&nbsp; &nbsp; $ git cpan-init Some::Module<br>&nbsp; &nbsp; $ git checkout -b mypatch<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...hack hack hack...<br>&nbsp; &nbsp; $ git rebase -i cpan<br>&nbsp; &nbsp; $ git cpan-sendpatch</tt></p></div> </blockquote><p>And, no, the lack of hyphen between <code>git</code> and <code>cpan-X</code> isn't a typo; the article also covers how to seamlessly integrate the new scripts into the git infrastructure (as Edna Mode would say, <i>it's a non-feature, dahling</i>).</p><p>Of course, I'm burning to say more, but I'll have to stop here. To know the whole story, you'll have to wait for The Perl Review to land in your mailbox (you are subscribed to TPR, <i>right?</i>).</p><p> <i>cross-posted from <a href="http://babyl.dyndns.org/techblog">Hacking Thy Fearful Symmetry</a>.</i> </p> Yanick 2008-12-29T18:32:52+00:00 journal introducing Dist::Release http://use.perl.org/~Yanick/journal/37852?from=rss <p>(<i>cross-posted from <a href="http://babyl.dyndns.org/techblog">Hacking Thy Fearful Symmetry</a> </i>) </p><p>I know, I know, there's already more module release managers out there than there are Elvis impersonators in Vegas. Still, module releasing seems to be a very personal kind of itch, and like so many before I couldn't resist and came up with my very own scratching stick.</p><p>Of course, I've tried Module::Release. But, although it is intended to be customized to suit each author's specific needs, one has to dig fairly deep in the module's guts to do so. What I really wanted was something even more plug'n'play, something that would be brain-dead easy to plop new components in. Hence Dist::Release.</p><p>In Dist::Release, the release process is seen as a sequence of steps. There are two different kind of steps: checks and actions. Checks are non-intrusive verifications (i.e., they're not supposed to touch anything), and actions are the steps that do the active part of the release. When one launches a release, checks are done first. If some fail, we abort the process. If they all pass, then we are good to go and the actions are done as well. </p><p> <b>Implementing a check</b> </p><div><p>To create a check, all that is needed is one module with a 'check' method. For example, here is the code to verify that the distribution's MANIFEST is up-to-date:</p><blockquote><div><p> <tt>&nbsp; &nbsp; package Dist::Release::Check::Manifest::Build;<br> <br>&nbsp; &nbsp; use Moose;<br> <br>&nbsp; &nbsp; use IPC::Cmd 'run';<br> <br>&nbsp; &nbsp; extends 'Dist::Release::Step';<br> <br>&nbsp; &nbsp; sub check {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;diag( q{running 'Build distcheck'} )<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; my ( $success, $error_code, $full_buf, $stdout_buf, $stderr_buf ) =<br>&nbsp; &nbsp; &nbsp; &nbsp; run( command =&gt; [qw#<nobr> <wbr></nobr>./Build distcheck #] );<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; return $self-&gt;error( join '', @$full_buf )<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if not $success or grep<nobr> <wbr></nobr>/not in sync/ =&gt; @$stderr_buf;<br>&nbsp; &nbsp; }<br> <br>&nbsp; &nbsp; 1;</tt></p></div> </blockquote><p>Dist::Release considers the check to have failed if there is any call made to <code>error()</code>. If there is no complain, then it assumes that everything is peachy.</p></div><p> <b>Implementing an action</b> </p><div><p>Actions are only marginally more complicated than checks. The module implementing the action can have an optional <code>check()</code> method, which is going to be run with all the other checks, and must have a <code>release()</code>, which make the release-related changes.</p><p>For example, here's the CPANUpload action:</p><blockquote><div><p> <tt>&nbsp; &nbsp; package Dist::Release::Action::CPANUpload;<br> <br>&nbsp; &nbsp; use Moose;<br> <br>&nbsp; &nbsp; use CPAN::Uploader;<br> <br>&nbsp; &nbsp; extends 'Dist::Release::Action';<br> <br>&nbsp; &nbsp; sub check {<br>&nbsp; &nbsp; &nbsp; &nbsp; my ($self) = @_;<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; # do we have a pause id?<br>&nbsp; &nbsp; &nbsp; &nbsp; unless ($self-&gt;distrel-&gt;config-&gt;{pause}{id}<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; and $self-&gt;distrel-&gt;config-&gt;{pause}{password} ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;error('pause id or password missing from config file');<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br> <br>&nbsp; &nbsp; sub release {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $self = shift;<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;diag('verifying that the tarball is present');<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; my @archives = &lt;*.tar.gz&gt; or return $self-&gt;error('no tarball found');<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; if ( @archives &gt; 1 ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $self-&gt;error( 'more than one tarball file found: ' . join ',',<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @archives );<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; my $tarball = $archives[0];<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;diag(&amp;quot;found tarball: $tarball&amp;quot;);<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;diag(&amp;quot;uploading tarball '$tarball' to CPAN&amp;quot;);<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; my ( $id, $password ) =<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map { $self-&gt;distrel-&gt;config-&gt;{pause}{$_} } qw/ id password<nobr> <wbr></nobr>/;<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; $self-&gt;diag(&amp;quot;using user '$id'&amp;quot;);<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; my $args = { user =&gt; $id, password =&gt; $password };<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; unless ( $self-&gt;distrel-&gt;pretend ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CPAN::Uploader-&gt;upload_file( $tarball, $args );<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br> <br>&nbsp; &nbsp; 1;</tt></p></div> </blockquote><p>As for the <code>check()</code>, Dist::Release figures out that a <code>release()</code> failed if there's a call to <code>error()</code>. </p></div><p> <b>Configuring for a module</b> </p><div><p>Configuration is done via a 'distrelease.yml' file dropped in the root directory of the project. The file looks like this:</p><blockquote><div><p> <tt>&nbsp; &nbsp; pause:<br>&nbsp; &nbsp; &nbsp; &nbsp; id: yanick<br>&nbsp; &nbsp; &nbsp; &nbsp; password: hush<br>&nbsp; &nbsp; checks:<br>&nbsp; &nbsp; &nbsp; &nbsp; - VCS::WorkingDirClean<br>&nbsp; &nbsp; &nbsp; &nbsp; - Manifest<br>&nbsp; &nbsp; actions:<br>&nbsp; &nbsp; &nbsp; &nbsp; - GenerateDistribution<br>&nbsp; &nbsp; &nbsp; &nbsp; - CPANUpload<br>&nbsp; &nbsp; &nbsp; &nbsp; - Github</tt></p></div> </blockquote><p>It's pretty self-explanatory. The checks and actions are applied in the order they are given in the file.</p></div><p> <b>Crying havoc...</b> </p><div><p>And once the configuration file is present, all that remains to be done is to run <code>distrelease</code>, sit back and enjoy the show:</p><blockquote><div><p> <tt>&nbsp; &nbsp; $ distrelease<br>&nbsp; &nbsp; Dist::Release will only pretend to perform the actions (use --doit for the real deal)<br>&nbsp; &nbsp; running check cycle...<br>&nbsp; &nbsp; regular checks<br>&nbsp; &nbsp; VCS::WorkingDirClean&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [failed]<br>&nbsp; &nbsp; working directory is not clean<br>&nbsp; &nbsp; # On branch master<br>&nbsp; &nbsp; # Changed but not updated:<br>&nbsp; &nbsp; #&nbsp; &nbsp;(use &amp;quot;git add &lt;file&gt;...&amp;quot; to update what will be committed)<br>&nbsp; &nbsp; #<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;Build.PL<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;Changes<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;README<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;distrelease.yml<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;lib/Dist/Release/Check/Manifest.pm<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;modified:&nbsp; &nbsp;script/distrelease<br>&nbsp; &nbsp; #<br>&nbsp; &nbsp; # Untracked files:<br>&nbsp; &nbsp; #&nbsp; &nbsp;(use &amp;quot;git add &lt;file&gt;...&amp;quot; to include in what will be committed)<br>&nbsp; &nbsp; #<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;STDOUT<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;a<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;blog<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;xml<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;xt/dependencies.t<br>&nbsp; &nbsp; #&nbsp; &nbsp; &nbsp; &nbsp;xxx<br>&nbsp; &nbsp; no changes added to commit (use &amp;quot;git add&amp;quot; and/or &amp;quot;git commit -a&amp;quot;)<br>&nbsp; &nbsp; Manifest&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [failed]<br>&nbsp; &nbsp; No such file: lib/Dist/Release/Action/DoSomething.pm<br>&nbsp; &nbsp; Not in MANIFEST: a<br>&nbsp; &nbsp; Not in MANIFEST: blog<br>&nbsp; &nbsp; Not in MANIFEST: lib/Dist/Release/Action/Github.pm<br>&nbsp; &nbsp; Not in MANIFEST: STDOUT<br>&nbsp; &nbsp; Not in MANIFEST: xml<br>&nbsp; &nbsp; Not in MANIFEST: xt/dependencies.t<br>&nbsp; &nbsp; Not in MANIFEST: xxx<br>&nbsp; &nbsp; MANIFEST appears to be out of sync with the distribution<br>&nbsp; &nbsp; pre-action checks<br>&nbsp; &nbsp; GenerateDistribution&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [passed]<br>&nbsp; &nbsp; no check implemented<br>&nbsp; &nbsp; CPANUpload&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [passed]<br>&nbsp; &nbsp; Github&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; [passed]<br>&nbsp; &nbsp; 2 checks failed<br>&nbsp; &nbsp; some checks failed, aborting the release</tt></p></div> </blockquote></div><p> <b>Getting the good</b> </p><div><p>A <a href="http://search.cpan.org/dist/Dist-Release/">first release of Dist::Release</a> is already waiting for you on CPAN. It's beta, has no documentation, is probably buggy as hell, but it's there. And the code is also available on <a href="http://github.com/yanick/dist-release/tree/master">Github</a>. Comments, suggestions, forks and patches are welcome, as always.<nobr> <wbr></nobr>:-)</p></div> Yanick 2008-11-11T04:01:41+00:00 journal Me at OsBootCamp 8 http://use.perl.org/~Yanick/journal/37373?from=rss <p> <a href="http://www.osbootcamp.org/">OS Bootcamp</a> is a cool initiative to inform and initiate university students to the wonders of the Open Source world.</p><p> <a href="http://www.osbootcamp.org/index.php?page=yow8">OsBootCamp 8</a>, which took place on August 28th, was about interpreted programming languages. On the agenda were short introductions of the three big kids on the block (Perl, Python and Ruby). And yup, the honor to ramble about Perl was given to li'll old me. For the morbidly curious, there's a <a href="http://www.virtualvernisage.com/archives/2008_aug29_633556336613281250/?hideSocial=false&amp;archiveID=85">video</a> of the resulting show.<nobr> <wbr></nobr>:-) </p> Yanick 2008-09-06T15:06:01+00:00 journal Pasting repository info on CPAN page http://use.perl.org/~Yanick/journal/37168?from=rss <p>Out of the comments generated by a post by <a href="http://use.perl.org/~grink/journal/37141">grink</a>, I've learned that the location of the distribution's repository can be inserted in the <a href="http://module-build.sourceforge.net/META-spec-current.html#resources">META.yml</a>. Neato! </p><p>And when grink asked if someone could come up with a Greasemonkey script to extract that information and show it on the distro's page... well, that's no simian fun I could let pass untackled. The resulting greasemonkey script can be found <a href="http://userscripts.org/scripts/show/31660">here</a>.</p> Yanick 2008-08-13T01:58:05+00:00 journal Mohlohpoly game http://use.perl.org/~Yanick/journal/37095?from=rss <p>While working on <a href="http://search.cpan.org/~yanick/WWW-Ohloh-API/">WWW::Ohloh::API</a>, I caught myself wondering how one could use <a href="http://www.ohloh.com/">Ohloh</a> for some kind of game. A few bus trips later with no book to keep my mind out of trouble, I came up with the variant of Monopoly given below. I'm recording it here to get it out of my system. Maybe one day, when I'll have time (ah!), I'll implement it. It'd be worth it just for the fun of collecting famous hackers like Pok&#233;mons.<nobr> <wbr></nobr>:-)</p><p> Rules </p><ul> <li>Every player start with a given amount of &quot;money&quot; (or moohlah). </li><li>Developers can be bought for a price inversely proportional to their Ohloh rank. A developer can only be owned by a single player at any given time. </li><li>A player can sell one of his developers at market price at any time. The player can also sell a developer directly to another player for any agreed price between them. Or he can auction the developer in an open auction to the rest of the players. </li><li>Any time a developer receives a kudo, the player owning him or her gets a dividend proportional to the rank of the kudo giver. </li><li>If a player possesses all developers of a project, they &quot;own&quot; that project. </li><li>Each turn, each player gets to &quot;use&quot; a random project picked from the set of all projects owned by a player, and must pay a fee proportional to the review score and number of users of that project. If the player doesn't have enough moohlah to pay up, one his or her developer is picked at random and sold at market value until the player becomes solvent again. If the player ends up without moohlah or hackers, he or she goes under.</li></ul> Yanick 2008-08-05T00:55:58+00:00 journal Object::InsideOut Cheatsheet http://use.perl.org/~Yanick/journal/36961?from=rss <p>Everybody is raving about <a href="http://search.cpan.org/~stevan/Moose/">Moose</a> these days, but I must say that I still prefer <a href="http://search.cpan.org/~jdhedden/Object-InsideOut">Object::InsideOut</a>. One of the things I love about OIO is its extensive documentation (70 glorious pages worth of pod!). One of things that I find daunting about it is, well, finding back the attribute I'm looking for as I thumb through those seventy-something blasted pages. </p><p>So I made myself a <a href="http://babyl.dyndns.org/perl/oio/oio-cheatsheet.pdf">cheatsheet</a>. It's not complete yet, but it's already containing what most mortals would use on a daily basis.</p><p>(btw, I've used <a href="http://www.scribus.net/">Scribus</a> to generate the 3-fold. Although I really, really want to like that software, I must say that it makes me miss Quark XPress real bad. If anyone has any suggestion for an alternative Desktop Publishing tool, please feel free to let me know.)</p> Yanick 2008-07-20T01:31:14+00:00 journal Bart on Git http://use.perl.org/~Yanick/journal/36922?from=rss <p> <a href="http://www.jukie.net/~bart/blog">Bart Trojanowki</a> gave a Git presentation to the Ottawa Ruby Group earlier this month (I attended as a deep undercover Perl mole). The slides and the podcast are now available at <a href="http://excess.org/article/2008/07/ogre-git-tutorial">http://excess.org/article/2008/07/ogre-git-tutorial</a>.</p><p>Very good presentation, meant as an introduction to the beast, but containing enough little nudgets to have anyone learn something from it.</p> Yanick 2008-07-16T02:13:07+00:00 journal Bring the blog back hooome http://use.perl.org/~Yanick/journal/36896?from=rss <p>Just to say that my main blog is going to be <a href="http://babyl.dyndns.org/techblog">here</a> (although I&apos;m probably going to echo my posts at use.perl.org for a while still). </p><p>I love the soapbox that use.perl.org provides but the site&apos;s blogging interface is, shall we say, a tad archaic and on the painful side. I can live with the html format of entries, but many times I&apos;ve longed for something a little bit more code snippet-friendly. So, when <a href="http://perlsphere.net/">Perlsphere</a> appeared at the horizon, the temptation to repatriate my blog on my own server became just too great to ignore...</p><p>Of course, considering that it&apos;s a blog about Perl blabbering, using some PHP blog engine would have not felt quite right. So I decided to experiment with <a href="http://search.cpan.org/~jrockway/Angerwhale">Angerwhale</a>. It&apos;s a pretty nifty engine, but it has a few rough edges. In fact, I already began to hack and patch at it... expect some entries about it sometimes soon.<nobr> <wbr></nobr>:-)</p> Yanick 2008-07-11T03:31:53+00:00 journal Test::Class + Test::Group http://use.perl.org/~Yanick/journal/36734?from=rss <p> I've been playing with <a href="http://search.cpan.org/~adie/Test-Class/">Test::Class</a> lately and, I must say, it's a heck of a nice module. Only thing that I wish it had is the possibility to report each test as a single pass/failure, no matter the number of assertions done in the function. Just like <a href="http://search.cpan.org/~domq/Test-Group">Test::Group</a> does.</p><p>Hmmm... But wait a second. Could it be possible to somehow stuff the caramel-like sweetness of Test::Group in the smooth chocolatey wrapping of Test::Class? Turns out that yes, it's perfectly possible! And even more, without even having to muck with the guts of either modules:</p><blockquote><div><p> <tt>package Some::TestSuite;<br> <br>use base qw/ Test::Class<nobr> <wbr></nobr>/;<br>use Test::Group;<br>use Test::More;<br> <br>sub Test<nobr> <wbr></nobr>:ATTR(CODE,RAWDATA) {<br>&nbsp; &nbsp;my ( $pkg, $funct, $code ) = @_;<br> <br>&nbsp; &nbsp;no warnings;&nbsp; # black magic starts here<br> <br>&nbsp; &nbsp;my $func_name = *{$funct}{NAME};<br>&nbsp; &nbsp;my $fullname = $pkg.'::'.$func_name;<br> <br>&nbsp; &nbsp;*{$funct} = sub {<br>&nbsp; &nbsp; &nbsp; &nbsp;print "begin test [", scalar localtime, "]\n";<br>&nbsp; &nbsp; &nbsp; &nbsp;Test::Group::test( $fullname =&gt; \&amp;{$code} );<br>&nbsp; &nbsp; &nbsp; &nbsp;print "end test [", scalar localtime, "]\n";<br>&nbsp; &nbsp;};<br> <br>&nbsp; &nbsp;Test::Class::Test( @_ );<br>}<br> <br>sub aTest : Test {<br>&nbsp; &nbsp; ok 1, 'eins';<br>&nbsp; &nbsp; ok 1, 'zwei';<br>&nbsp; &nbsp; ok 1, 'drei';<br>}<br> <br>sub otherTest : Test {<br>&nbsp; &nbsp; ok 1, 'un';<br>&nbsp; &nbsp; ok 0, 'deux';<br>&nbsp; &nbsp; ok 1, 'trois';<br>}<br> <br>Some::TestSuite-&gt;runtests;</tt></p></div> </blockquote><p>Which gives</p><blockquote><div><p> <tt>$ perl test.t<br>1..2<br>begin test [Thu Jun 19 22:17:16 2008]<br>ok 1 - Some::TestSuite::aTest<br>end test [Thu Jun 19 22:17:16 2008]<br>begin test [Thu Jun 19 22:17:16 2008]<br>#&nbsp; &nbsp;Failed test 'deux'<br>#&nbsp; &nbsp;in a.t at line 32.<br>not ok 2 - Some::TestSuite::otherTest<br>#&nbsp; &nbsp;Failed test 'Some::TestSuite::otherTest'<br>#&nbsp; &nbsp;at a.t line 17.<br>#&nbsp; &nbsp;(in Some::TestSuite-&gt;otherTest)<br>end test [Thu Jun 19 22:17:16 2008]<br># Looks like you failed 1 test of 2.</tt></p></div> </blockquote><p>This method, though, has two modest caveats:</p><ol> <li>A failed assertion will be given with the correct line, but the test itself will be reported as being located inside the Test() function.</li><li>Test fixtures have to be declared as having 1 test (i.e., it has to be <i>sub mySetup<nobr> <wbr></nobr>:Test(setup =&gt; 1) {<nobr> <wbr></nobr>.. })</i></li></ol> Yanick 2008-06-20T01:50:04+00:00 journal Why I am passionate about Perl http://use.perl.org/~Yanick/journal/36384?from=rss <p> <b>The person who introduced me to Perl showed me that</b><nobr> <wbr></nobr>... well, in my case it's kinda of a spurious question, considering that no-one really properly introduced me to the language. At the time, I just happened to look around for a good scripting language to learn and saw that Perl was one of the languages used by some members of my team. I bought the Camel book, dived in and... the rest is pretty much history.</p><p> <b>I first starting using Perl to </b> do small shell stuff. If I recall correctly, the first script I touched was a load balancer that was monitoring a unix corral and launching queued jobs on the less busy machines. Then I began to use it to diddle text files (change 'class Foo' to 'class Bar' in my source code, figure out how many functions are in each file, etc.). And then came the <a href="http://www.tipjar.com/games/solitaire/wheels.html">Solitaire 500</a>. My entry to the contest shamefully crashed and burn at the starting line, but I still managed to squeeze a t-shirt and a love of the language out of the experience. To this day, I still have both (although one is pretty much due for replacement).</p><p> <b>I kept using Perl because</b> it is so much damn fun. Most other languages are like station wagon cars. They get you from A to B, but they are not much to write home about. But Perl... Perl is like James Bond's car. Beside the driving wheel, you have a red button here to activate the flamethrowers. Below the glove compartment -- yes, you see right -- there's a lever that engages the retro-propellers. And it doesn't end there: if one was to ever get bored with all those nifty toys, Q still comes up regularly with new features.</p><p> <b> I can't stop thinking about Perl </b> for the same reason a rock star can't stop thinking about his Fender Stratocaster XII. </p><p> <b>I'm still using Perl because</b> I have yet to find another language that is so delightfully idiosyncratic and yet so practical. Or that has such a striving community. Or that has anything remotely comparable to that magnificent temple dedicated to Aergia that we call CPAN.</p><p> <b>I get other people to use Perl by</b> asking them what task they want to achieve, and doing it before their eyes in a handful of lines. Once I have thus acquired their awestruck attention, I reel them in for my weekly Perl Lunch'n'Learns where the true corruption can begin. </p><p> <b> I also program in </b> TCL <b> and </b>Javascript<b>, but I like Perl better since </b> it doesn't make me want to drive red-hot tetanus-laden nails through my prosencephalon. Javascript is not that bad, mind you -- I actually like it. But nothing, <i>nothing</i>, can shear such deep gouges in one's psyche like badly written TCL can. And this is coming from someone who known Intercal, brainf*ck and VisualBasic... </p> Yanick 2008-05-11T16:03:22+00:00 journal CPAN/Ohloh mashup http://use.perl.org/~Yanick/journal/36234?from=rss <p> Now that I've registered my Perl modules on <a href="http://www.ohloh.net/">Ohloh</a>, I thought it'd be fun to make things bilateral and have one of the <a href="http://www.ohloh.net/projects/test-pod-snippets/widgets">Ohloh widgets</a> displayed on the modules' CPAN page. So I mustered my <a href="http://www.greasespot.net/">Grease</a>-Fu, and hacked <a href="http://userscripts.org/scripts/show/25525">a little something</a>. </p><p> With that little script installed, if a module dist is registered on Ohloh [*], its widget will appear on the right side of the CPAN page right below the gravatar picture. </p><p> For sample modules, have a gander at <a href="http://search.cpan.org/~yanick/Test-Pod-Snippets-0.02/"> Test::Pod::Snippet</a> or <a href="http://search.cpan.org/~yanick/XML-XPathScript">XML::XPathScript</a>. </p><p> <b>[*]</b> The project must also be configured to have a <a href="http://www.ohloh.net/announcements/human_project_urls">name url</a> corresponding to module's name in lowercase and with all '::' substitued by '-' (e.g., 'Test::Pod::Snippets' =&gt; 'test-pod-snippets'). </p> Yanick 2008-04-23T23:50:53+00:00 journal per(l)version http://use.perl.org/~Yanick/journal/35940?from=rss <p> Updating the version number is all the files of a module distribution is a pain in the behind. It's repetitive, boring and ridiculously prone to errors -- in short, a task fit for a script, not for humans. So I decided to hack myself a little something, for the time being called <i>perversion</i>, to take care of it. </p><p> The idea is pretty straight-forward. In the root directory of my distribution, I have a config file named <i>perversionrc</i> that contains Perl code that return an hash of all files where the the module version is given, and regular expressions to capture the said version. For example, here's the <i>perversionrc</i> of WWW::Ohloh::API:</p><blockquote><div><p> <tt>use File::Find::Rule;<br> <br>my %file;<br> <br>$file{README} = qr/WWW-Ohloh-API version (\S+)/;<br> <br>for my $m ( File::Find::Rule-&gt;file-&gt;name( '*.pm' )-&gt;in( 'lib' ) ) {<br>&nbsp; &nbsp;$file{$m} = [ qr/\$VERSION\s*=\s*'(.*?)';/,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;qr/This document describes \S+ version (\S*)/ ];<br>}<br> <br>%file;</tt></p></div> </blockquote><p> Once that file is present, <i>perversion</i> is ready to rock. You want to verify that the version number is consistent in all given files?</p><blockquote><div><p> <tt>$ perversion<br>distribution version is set to 0.0.9<br>lib/WWW/Ohloh/API/Enlistment.pm:12: 0.0.6<br>!!! does not match distribution version (0.0.9) !!!<br>lib/WWW/Ohloh/API/Repository.pm:10: 0.0.6<br>!!! does not match distribution version (0.0.9) !!!<br>lib/WWW/Ohloh/API/ContributorLanguageFact.pm:10: 0.0.6<br>!!! does not match distribution version (0.0.9) !!!<br>lib/WWW/Ohloh/API/ContributorFact.pm:10: 0.0.6<br>!!! does not match distribution version (0.0.9) !!!<br>lib/WWW/Ohloh/API/ContributorFact.pm:241: 0.0.6<br>!!! does not match distribution version (0.0.9) !!!</tt></p></div> </blockquote><p>Want to set the version to a specific value?</p><blockquote><div><p> <tt>$ perversion -set 1.2.3<br>changing all versions to 1.2.3..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Language.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/ActivityFacts.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Account.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Kudos.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Project.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Enlistment.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/KudoScore.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Factoid.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Repository.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Projects.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/ContributorLanguageFact.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Languages.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/ActivityFact.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/ContributorFact.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Analysis.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating lib/WWW/Ohloh/API/Kudo.pm..<br>&nbsp; &nbsp; &nbsp; &nbsp; updating README..<br>done</tt></p></div> </blockquote><p>Don't want to go through the mental challenge of computing the next version yourself? No problem!</p><blockquote><div><p> <tt>$ perversion -inc revision<br>distribution version is set to 1.2.3<br>new distribution version is 1.2.4<br> <br>$ perversion -inc minor<br>distribution version is set to 1.2.4<br>new distribution version is 1.3.0<br> <br>$ perversion -inc major<br>distribution version is set to 1.3.0<br>new distribution version is 2.0.0<br> <br>$ perversion -inc alpha<br>distribution version is set to 2.0.0<br>new distribution version is 2.0_1</tt></p></div> </blockquote><p> The script is still raw and in need of polishing, but for those interested, it's available from its very own <a href="http://babyl.dyndns.org/git/?p=perversion.git"> git repository</a>. </p> Yanick 2008-03-20T02:13:22+00:00 journal XPathScript slides http://use.perl.org/~Yanick/journal/35815?from=rss <p>An introduction to <a href="http://search.cpan.org/~yanick/XML-XPathScript/">XPathScript</a> that I gave at this month's Ottawa Mongers Meeting can be found <a href="http://babyl.dyndns.org/perl/xpathscript/slides/">here</a>. </p><p>It probably reads a wee bit cryptic without my running commentaries, but some might still enjoy it.<nobr> <wbr></nobr>:-) </p> Yanick 2008-03-02T03:43:29+00:00 journal Thinking about taking over NetPacket http://use.perl.org/~Yanick/journal/35641?from=rss <p> At $work, an application that I wrote (<i>remora</i>, a companion application to <a href="http://www.wireshark.org/">Wireshark</a>) is extensively using <a href="http://search.cpan.org/~atrak/NetPacket-0.04/">NetPacket</a>. NetPacket is very handy but, alas, has <a href="http://rt.cpan.org/Ticket/Display.html?id=7010">some</a> <a href="http://rt.cpan.org/Ticket/Display.html?id=18941">bugs</a>, and seem to be orphaned (the latest update is from 2003). I've tried to poke the maintainers, but Stephanie Wehner's email is no longer working, and Tim Potter didn't reply yet (although, to be fair, I only began to poke last week). </p><p> Bottom line, I'm playing with the idea of taking over the module so that I can churn a new version with the bug fixes. So if anyone out there is in contact with Stephanie or Tim, can you let them know a madman is nefariously organizing a coup? Thanks.<nobr> <wbr></nobr>:-) </p> Yanick 2008-02-12T17:24:22+00:00 journal Git's the nightclub, Perltidy's the bouncer http://use.perl.org/~Yanick/journal/35626?from=rss <p> I finally wrapped my CVS-encrusted mind around Git's hooks. Huzzah! The biggest hurdle, really, was realizing that there is no spoon. </p><p> Anyway, as I'm an unsalvageable slob who always forget to run perltidy before committing changes, I've written a <code>pre-commit</code> hook that makes sure that all Perl files to be committed are all clean, neat and tidy (and aborts the commit and chides me if they are not):</p><blockquote><div><p> <tt>#!/usr/bin/perl<br> <br>use Perl6::Slurp;<br> <br>my $status = slurp '-|', 'git-status';<br> <br># only want what is going to be commited<br>$status =~ s/Changed but not updated.*$//s;<br> <br>my @dirty =<br>&nbsp; grep { !file_is_tidy($_) }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# not tidy<br>&nbsp; grep {<nobr> <wbr></nobr>/\.(pl|pod|pm|t)$/ }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # perl file<br>&nbsp; map&nbsp; {<nobr> <wbr></nobr>/(?:modified|new file):\s+(\S+)/ }&nbsp; &nbsp; # to be commited<br>&nbsp; split "\n", $status;<br> <br>exit 0 unless @dirty;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Alles gut<br> <br>warn "following files are not tidy, aborting commit\n",<br>&nbsp; &nbsp; &nbsp;map "\t$_\n" =&gt; @dirty;<br> <br>exit 1;<br> <br>### utility functions ###############################################<br> <br>sub file_is_tidy {<br>&nbsp; &nbsp; my $file = shift;<br> <br>&nbsp; &nbsp; my $original = slurp $file;<br>&nbsp; &nbsp; my $tidied = slurp '-|', 'perltidy', $file, '-st';<br> <br>&nbsp; &nbsp; return $original eq $tidied;<br>}</tt></p></div> </blockquote> Yanick 2008-02-09T22:18:41+00:00 journal Greasemonkeying dependencies http://use.perl.org/~Yanick/journal/35507?from=rss <p>Escalation wars... you just have to love'em.</p><p>First, David came up with the &#252;ber-cool <a href="http://cpandeps.cantrell.org.uk/"> CPAN deps</a> page.</p><p>Then <a href="http://use.perl.org/~AndyArmstrong/journal/">Andy</a> comes up with a <a href="http://use.perl.org/article.pl?sid=07/12/15/1931244">nifty Greasemonkey script </a> to add it to the CPAN distributions main pages. </p><p>Then I add a small patch to the script to retrieve some information from the Deps page.</p><p>Then David creates an xml interface to CPAN deps, opening the door wide open for Web 2.0 goodiness.</p><p>Then (and this is where we are right now) I hack together a new <a href="http://userscripts.org/scripts/show/21779">CPAN_Dependencies</a> monkeyscript to take advantage of said xml interface.</p><p>This, of course, is nowhere near the end of the story. My new script only scratches the surface of what can be done with the information contained in the xml. As soon as I have some tuits, I'll probably add a way to toggle between showing only the first-level dependencies and all dependencies, and have dependencies color-coded by degree of b0rkage, and whatever bell or whistle I can think of in the meantime.</p> Yanick 2008-01-29T01:28:11+00:00 journal Redux http://use.perl.org/~Yanick/journal/35000?from=rss <p> Lately, I've been having fun with <a href="https://addons.mozilla.org/en-US/firefox/addon/748">GreaseMonkey</a>. Net result: I've re-implemented my Perl-themed friends/foes icons (originally <a href="http://use.perl.org/~Yanick/journal/30746">done</a> using <a href="http://userstyles.org/stylish/">Stylish</a>) and hacked RT to provide sorting of bugs by severity (I got the idea for that one from <a href="http://use.perl.org/~schwern/journal/34967">Schwern</a>'s journal). Both monkey scripts are available on <a href="http://userscripts.org/users/38422/scripts">userscript.org</a>. </p><p>Also, a new version of <a href="http://cpanratings.perl.org/dist/Pod-Manual">Pod::Manual</a> is out. The code to generate my unexpectedly wildly popular ad-hoc <a href="http://use.perl.org/~Yanick/journal/33028">Catalyst manual</a> was already included in the previous distributions, and in this one I added a similar manual for <a href="http://search.cpan.org/~jsiracusa/Rose-DB-Object/">Rose::DB::Object</a>. The order in which the modules are given is a little rough and need improvement, but it's a start. For those who care more about the end than the means, the pdf of both manuals are available <a href="http://babyl.dyndns.org/perl/pod-manual">here</a> </p><p>. </p> Yanick 2007-11-29T01:23:10+00:00 journal No-one expected the Technorati inquisition http://use.perl.org/~Yanick/journal/33947?from=rss <p> <b>Slightly amusing trivia:</b> before the hoola-baloo of the last few days, I was persuaded that it was the techno<i>c</i>rati, and that it was secret organization of nefarious hackers -- an amalgam of the <a href="http://en.wikipedia.org/wiki/Illuminati">Illuminati</a> and WhiteWolf's <a href="http://en.wikipedia.org/wiki/Technocracy_(Mage:_The_Ascension)">Technocracy</a>. </p><p>Anyway, here goes: <a href="http://technorati.com/claim/x2kvkhe4q">Technorati Profile</a>.</p> Yanick 2007-08-01T12:21:59+00:00 journal Trying to define badness: Shakesphackers http://use.perl.org/~Yanick/journal/33858?from=rss <p> <b>Shakesphacker</b>: (<i>n.</i>) a programer who, at the instar of Shakespeare's infamous chimps, randomly bang on the keyboard until the laws of probability make him generate a working line of code.</p><p> I came up with that term Friday to try to put a label on a coding philosophy I observed. I'm not entierely satisfied by it though -- it sounds way too sophisticated for the kind of feeling it try to convey. "Foo flinger" could be more adequate. </p><p>In all cases, shakesphackers can be easily identified by their exuberant love of <i>eval</i>s -- they firmly believe that, just like violence, if it doesn't solve your problems, it's because your not using enough of it. </p> Yanick 2007-07-22T16:10:29+00:00 journal Pod::Manual http://use.perl.org/~Yanick/journal/33807?from=rss <p>A while ago, <a href="http://use.perl.org/~Yanick/journal/33028">I hacked together a way to gather many pod files into a single pdf file</a>. Well, finally I got around cleaning up the code and released it as <a href="http://search.cpan.org/~yanick/Pod-Manual/">Pod::Manual</a>.</p><p> It's still very muchly alpha quality, but the basics seem to work. For example, the following works (at least on my machine)[<a href="%23footnote">*]:</a> </p><blockquote><div><p> <tt>use Pod::Manual;<br> <br>my $manual = Pod::Manual-&gt;new({ title =&gt; 'Catalyst' });<br> <br>$manual-&gt;add_chapter( $_ ) for qw/<br>&nbsp; &nbsp; Catalyst::Manual::About<br>&nbsp; &nbsp; Catalyst::Manual::Actions<br>&nbsp; &nbsp; Catalyst::Manual::Cookbook<br>&nbsp; &nbsp; Catalyst::Manual::DevelopmentProcess<br>&nbsp; &nbsp; Catalyst::Manual::Internals<br>&nbsp; &nbsp; Catalyst::Manual::Intro<br>&nbsp; &nbsp; Catalyst::Manual::Plugins<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Intro<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::CatalystBasics<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::BasicCRUD<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Authentication<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Authorization<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Debugging<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Testing<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::AdvancedCRUD<br>&nbsp; &nbsp; Catalyst::Manual::Tutorial::Appendices<br>&nbsp; &nbsp; Catalyst::Manual::WritingPlugins<br>/;<br> <br>$manual-&gt;save_as_pdf( 'catalyst_manual.pdf' );</tt></p></div> </blockquote><p>At this stage of the game, bug reports and feature requests would be very welcome. As well as suggestions for other example manuals.</p><p>[*] caveat: for the moment you need <code>TeTeX</code> installed to generate pdf documents. One of the items on my todo list is to allow for other means to generate the pdf (<code>jadetex</code>, <code>FOP</code>, etc)</p> Yanick 2007-07-15T01:27:00+00:00 journal push @ISA, 'Married::Man' http://use.perl.org/~Yanick/journal/33619?from=rss <p>On Saturday, June the 23rd, me and my lovely lady joined APIs before friends, families and the Great Whitely-Bearded Hacker in the Sky (He was even kind enough to schedule some wicked light effects for the event). </p><p> Funnily enough, both the bride and the groom were wearing pearls for the occasion (in my case, it was an heirloom tie-pin given by the mother-in-law). As unforgivingly geeky as it is, I must say I got a secret kick out of that. </p> Yanick 2007-06-27T21:04:00+00:00 journal Catalyst's manual http://use.perl.org/~Yanick/journal/33028?from=rss <p>Don't get me wrong, I love perldoc. But for documentation that span several manpages, I often catch myself dreaming of tables of content, indexes, real dead-tree margins on which to annotate stuff. I'm funny that way.</p><p>So I went back to the script that I wrote to create the <a href="http://use.perl.org/~Yanick/journal/30715">XPathScript manual</a> and tinkered a bit with it. I then used that newly-concocted black magick (which basically convert and agglomerate pods into a docbook, which is then LaTeXified and subsequently pdfed) to turn the <a href="http://search.cpan.org/~jrockway/Catalyst-Manual-5.700501/">Catalyst manual</a> into a cute little <a href="http://babyl.dyndns.org/misc/catalyst_manual.pdf">pdf</a>. Me likes. I think I'll tidy up the aforementioned script and publish it as Pod::Manual or something of the kin as soon as time (ah!) allows.</p><p>(and yeah, I'm in the process of getting my feet wet with Catalyst. Last week I was hopelessly Not Getting It, but sometime during last week-end, an angel came to me and bapped me over the head with its trumpet. Epiphany! I grok it, now! Even better: I think I'm digging it too!)</p> Yanick 2007-04-19T02:41:58+00:00 journal Meeting Availability Dialect http://use.perl.org/~Yanick/journal/32641?from=rss <p><b>Background</b></p><p>Organizing the March meeting of <a href="ottawa.pm.org">Ottawa.pm</a>, I came across the problem that setting a date is pretty much like playing Battleship. If a specific date is proposed, people tend respond with boolean answers (can/can't come on that day), which is perfect to assess the punctual value of the attendency function, but quite lousy to determine its monthly optimum.</p><p>So, taking the premise that there's no simple problem that can't be solved by an overcomplex solution, I thought about a way we could all signal our availabilities for a certain month in a simple, standard and easy to parse way (for I have evil plans to hack a script to help me do the scheduling). A few bus commutes later, MADness was born.</p><p><b>Meeting Availability Dialect</b></p><p>A MAD signature line has the following syntax:</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <i>month</i> : <i>availability</i></p><p>The month is simply the name of the month. Availability is defined by a sequence of tokens that add or remove available days, depending if they are modified by a plus or minus sign.</p><p>E.g.:</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; April : WD + Sat - Wed - Day(13)</p><p>which means any work day, plus Satudays, but not Wednesdays or the 13th of the month.</p><p>The base token are:</p><p>Mon<br>Tue<br>Wed<br>Thu<br>Fri<br>Sat<br>Sun<br>AD - Any day<br>WE - Week-end (same as 'Sat + Sun')<br>WD - Week days (same as 'Mon + Tue + Wed + Thu + Fri')</p><p>For a specific date, use Day(X), where X is the date. For example, 'WD - Day(14)' means all week days, except on the 14th (one can surmise that was for February).</p><p>To target a specific week, append '(X)' to the token, where X is the week in question. Several weeks can be given, separated by commas or a range operator '..'. For example, 'Tue - Tue(2)' is equivalent to 'Tue(1,3..4)' and means the first, third or fourth Tuesday of the month.</p><p>Availability is resolved from left to right, which means that, for example,</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; April : AD - WE + Sun(1)</p><p>means any day, except week-ends, although the first Sunday is okay. Note that<br>this is equivalent to</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; April: WD + Sun(1)</p><p>MAD doesn't consider whitespaces as significant. The full availability, however, must be represented on a single line.</p> Yanick 2007-03-10T18:00:13+00:00 journal $tea="Earl Grey";print $tea http://use.perl.org/~Yanick/journal/32417?from=rss <p>Don't go and gnaw off your fingers just yet. Judging from this demonstration of the <a href="http://www.youtube.com/watch?v=KyLqUf4cdwc">bleeding edge of speech recognition technology</a>, we will need our ten stubby friends to bang on keyboards for a little while still....</p> Yanick 2007-02-16T03:09:06+00:00 journal XML::XPathScript 1.47 is out http://use.perl.org/~Yanick/journal/32217?from=rss <p>It is with great relish that I announce that XML::XPathScript v1.47 is on its way to a CPAN mirror near you.</p><p>[ ED: Do'h! The test that was supposed to gracefully skip if B::XPath isn't installed bombs instead. (blame it on my naive assumption that 'eval { use B::XPath; 1 }' would work). I'll do a s/use/require/ on that test and release 1.48 tonight. ]</p><p>What is new in this release:</p><p>* template tag attributes can now be functions as well as strings.</p><p> &nbsp; &nbsp; &nbsp; &nbsp; For example,</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $template-&gt;set( 'foo' =&gt; { testcode =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my( $n, $t ) = @_;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $name = $n-&gt;findvalue( 'name()' );<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $t-&gt;set({ pre =&gt; transfurbicate( $name ) });<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return $DO_SELF_AND_CHILDREN;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } );</p><p> &nbsp; &nbsp; &nbsp; &nbsp; can now be written</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $template-&gt;set( 'foo' =&gt; { pre =&gt; sub {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my( $n, $t ) = @_;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $name = $n-&gt;findvalue( 'name()' );<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return transfurbicate( $name );<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } );</p><p>* The 'content' template attribute, which associates template elements to<br>mini-stylesheets.</p><p> &nbsp; &nbsp; &nbsp; &nbsp; E.g., the code</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $template-&gt;set( 'foo' =&gt; {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pre =&gt; '&lt;newFoo foo_myattr="{@myattr}" &gt;',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; post =&gt; '&lt;/newFoo&gt;',<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; action =&gt; 'bar', # only process 'bar' node children<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } );<br> &nbsp; &nbsp; &nbsp; &nbsp; %&gt;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; can now be written</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $template-&gt;set( 'foo' =&gt; { content =&gt; &lt;&lt;'END_CONTENT' } );<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;newFoo foo_myattr="{@myattr}" &gt; &lt;%# look Ma, we interpolate! %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;%~ bar %&gt; &lt;%# only process bar children %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/newFoo&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; END_CONTENT<br> &nbsp; &nbsp; &nbsp; &nbsp; %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%# process all foo's %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%~<nobr> <wbr></nobr>//foo %&gt;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; Or, to be more easy on the eye, we can use the short-hand version:</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%@ foo<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;newFoo foo_myattr="{@myattr}" &gt; &lt;%# look Ma, we interpolate! %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;%~ bar %&gt; &lt;%# only proces bar children %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;/newFoo&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%# process all foo's %&gt;<br> &nbsp; &nbsp; &nbsp; &nbsp; &lt;%~<nobr> <wbr></nobr>//foo %&gt;</p><p>* B::XPath now a supported DOM tree. Bored with transforming XML documents?<br>How about transforming Perl Optrees?<nobr> <wbr></nobr>:-)</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; use B::XPath;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; use XML::XPathScript;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sub guinea_pig {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $x = shift;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print "oink oink " x $x;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $xps = XML::XPathScript-&gt;new;</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $xps-&gt;set_dom( B::XPath-&gt;fetch_root( \&amp;guinea_pig ) );<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $xps-&gt;set_stylesheet( '&lt;%~<nobr> <wbr></nobr>//print %&gt;' );</p><p> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print $xps-&gt;transform;</p> Yanick 2007-01-20T23:46:12+00:00 journal Resurrecting Ottawa.pm http://use.perl.org/~Yanick/journal/32125?from=rss <p>One of my resolutions for the new year is to try and see if I can stir Ottawa.pm back to life (it kinda went under two year-ish ago). I've already sent a humble request to the Power that Is at pm.org to get the keys to the ottawa.pm.org website and mailing list. But still remains the most daunting task: gather minions. I already spotted 11 Perl programmers on meetup.com that would probably be interested. And I should also be visiting the local LUG, always a fertile ground for young llamas.... </p><p> Anyway. No need to say, if you are in the vicinity and want to join the fray, please feel free to frantically wave in my direction. If not, well, wish me luck.<nobr> <wbr></nobr>:-)</p> Yanick 2007-01-12T03:26:20+00:00 journal