AndyArmstrong's Journal AndyArmstrong'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:13:19+00:00 pudge Technology hourly 1 1970-01-01T00:00+00:00 AndyArmstrong's Journal Safari 4 likes clicking <p>Installing Safari 4 had a pretty strange effect for me: Lights in the house switched on and off at random.</p><p>It turns out that Safari likes to visit your favourite pages periodically to update its Top Sites browser. Which is fine unless some of the lights in your house are controlled by a web interface which uses GET for the light switch buttons.</p><p>Since it's private to the house network I hadn't bothered to password protect it. I assume Safari would have left it alone if I had. On a hunch I fixed the problem by switching the lighting control page to https - and it seems to have worked.</p><p>I can't help wondering 1) how many intranets it's attacked already and 2) does it know to refrain from clicking on sites that use cookie based auth (RT?) and if so, how?</p> AndyArmstrong 2009-07-02T10:24:32+00:00 apple Test::Harness on Github <p>For the last few years Test::Harness has lived in subversion. Over the last couple of weeks I've been moving my modules to Github and yesterday I moved Test::Harness. You can find it here:</p><p> <a href=""></a> </p><p>As an aside, I assume everyone who hasn't been bitten by the git bug is getting sick of hearing about projects moving to Github. To you I say this: two weeks ago I was that sceptic - but git really is that good.</p> AndyArmstrong 2009-06-17T13:03:32+00:00 newsnews Oslo QA Hackathon Report <p>Last week I was in Oslo for the Perl QA hackathon and then the GoOpen conference. My objective for the hackathon was to bring parallel testing to the Perl core. Test::Harness already supports parallel testing but has a simpleminded idea of scheduling. To successfully run Perl's own tests in parallel it needs to handle scheduling rules. Some core tests that shouldn't be run while others from the same group are running because they do things like using the same temporary file.</p><p>Although this work is for Perl core it will eventually benefit all users of Test::Harness who'd like parallel testing with scheduling rules.</p><p>Well, I didn't get it done. Tux wrote a simple set of rules and theoretically after that it was a Simple Matter of Programming - but it's programming that hasn't happened yet...</p><p>I decided that it wasn't a good use of my time to withdraw into my programming shell given the unprecedented opportunity to work with other Perl QA folk on issues such as the future direction of the TAP protocol. For once the circumstances dictated that talk was more valuable than action and I can program any time<nobr> <wbr></nobr>:)</p><p>So I spent most of my time in the TAP room contributing to the debate about how we integrate structured diagnostics and nested TAP without causing too much backwards compatibility breakage. We <i>nearly</i> reached consensus too; decisions were reached on most of the major areas. Over on the <a href="">TAP-L mailing list</a> there's still a debate on the precise form that nested TAP should take but we're much closer to agreement and a clear route forward than we were.</p><p>For me, the hackathon was about more than specific tasks. It was a chance for a group of people who normally communicate on email and IRC to meet face to face. It turns out that even when we're not talking about Perl we can sustain an interesting conversation. Who knew?</p><p>I'm working on the implementation of the parallel testing scheduling rules now, feeling optimistic about the future of TAP and happy to have had the chance to spend time with such a great bunch of comrades.</p><p>I'd like to thank my sponsors for the trip, <a href=""></a>, hackathon hosts <a href="">Linpro</a>, brilliant organiser Salve Nilsen and all the local crew who made us so welcome.</p><p>Here's a list of others' reports:</p><ul> <li> <a href="">My Oslo QA Hackathon Wrapup | brian d foy</a> </li><li> <a href="">The Oslo Consensus | Alias</a> </li><li> <a href="">Oslo Hackathon 2008 -- wrap-up writeup | dagolden</a> </li><li> <a href="">random notes after the qa hackathon | rjbs</a> </li><li> <a href="">Oslo Perl QA Hackathon Letdown | Ovid</a> </li><li> <a href="">Oslo QA Hackathon | domm</a> </li><li> <a href="">Oslo QA Workshop and Smolder | mpeters</a> </li><li> <a href="">Travelling home from Oslo QA hackathon | jonasbn</a> </li><li> <a href="">Oslo Perl QA Hackathon, Day 2 | Ovid</a> </li><li> <a href="">oslo qa hackathon day 2 | rjbs</a> </li><li> <a href="">Oslo QA Hackathon, Saturday | brian d foy</a> </li><li> <a href="">My Oslo QA Hackaton - Day 2 (in progress...) | cosimo</a> </li><li> <a href="">Oslo QA Hackathon 2008, day #3 (sunday) | jonasbn</a> </li><li> <a href="">Oslo QA Hackathon 2008, day #2 (saturday) | jonasbn</a> </li><li> <a href="">Oslo - Day 1 - HTTP transport for CPAN::Testers | dagolden</a> </li><li> <a href="">oslo qa hackathon day 1 | rjbs</a> </li><li> <a href="">My Oslo QA Hackaton - Day 1 | cosimo</a> </li><li> <a href="">Oslo: TAP Diagnostics | Ovid</a> </li><li> <a href="">Oslo QA Hackathon 2008, day #1 (friday) | jonasbn</a> </li><li> <a href="">Oslo QA Hackathon, Wednesday and Thursday | brian d foy</a> </li><li> <a href="">Oslo Perl QA Hackathon | Ovid</a> </li><li> <a href="">Oslo QA Hackathon, the plane trip | brian d foy</a> </li></ul> AndyArmstrong 2008-04-15T15:32:29+00:00 events Perl debugger: stop at a specific test number <p>I like data driven tests. The general pattern is a big array of test cases and some driver code at the bottom that loops over the cases applying the same assertions to each of them.</p><p>That's all well and good until you want to use the Perl debugger to step through test #1967 of 2673. There's no good place to set a break point because the driver loop will execute many times before it hits the test you want to single step through. You can fake it like this:</p><blockquote><div><p> <tt>if (Test::Builder-&gt;new-&gt;current_test &gt;= 85) {<br>&nbsp; &nbsp; $DB::single = 1;<br>}</tt></p></div> </blockquote><p>Setting <code>$DB::single</code> to a true value makes the debugger break at the following line. It'd be much nicer though to be able to set a magic breakpoint in the debugger that'd stop at test #1967. Add the following code to your ~/.perldb and that's exactly what you'll be able to do.</p><blockquote><div><p> <tt>my @opts = qw( windowSize=30 );<br> <br>if ( $] &gt;= 5.010000 ) {<br>&nbsp; &nbsp; push @opts, "HistFile='" . glob( '~/.perldb_history' ) . "'";<br>}<br> <br>parse_options( $_ ) for @opts;<br> <br>@DB::testbreak = ();<br> <br># Monkeypatch cmd_b (set breakpoint)<br>my $cmd_b = \&amp;DB::cmd_b;<br>*DB::cmd_b = sub {<br>&nbsp; &nbsp; my ( $cmd, $line, $dbline ) = @_;<br>&nbsp; &nbsp; if ( $line =~<nobr> <wbr></nobr>/\s*#\s*(\d+(?:\s*,\s*\d+)*)$/ ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; my %seen;<br>&nbsp; &nbsp; &nbsp; &nbsp; @DB::testbreak = grep { !$seen{$_}++ }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sort { $a &lt;=&gt; $b } ( split(<nobr> <wbr></nobr>/\s*,\s*/, $1 ), @DB::testbreak );<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; else {<br>&nbsp; &nbsp; &nbsp; &nbsp; $cmd_b-&gt;( @_ );<br>&nbsp; &nbsp; }<br>};<br> <br>sub afterinit {<br>&nbsp; &nbsp; $trace |= 4;&nbsp; &nbsp; # Enable watchfunction<br>}<br> <br>sub watchfunction {<br>&nbsp; &nbsp; if ( @DB::testbreak &amp;&amp; exists $INC{'Test/'} ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $next = Test::Builder-&gt;new-&gt;current_test + 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; if ( $next &gt;= $DB::testbreak[0] ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; shift @DB::testbreak<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while @DB::testbreak &amp;&amp; $next &gt;= $DB::testbreak[0];<br> <br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my $depth = 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; while ( 1 ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; my ( $package, $file, $line ) = caller $depth;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last unless defined $package;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last unless $package =~<nobr> <wbr></nobr>/^Test::/;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $depth++;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $DB::stack[ -$depth ] = 1;<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br> <br>&nbsp; &nbsp; return;<br>}</tt></p></div> </blockquote><p>It modifies the debugger's 'b' (breakpoint) command so that you can type:</p><blockquote><div><p> <tt>&nbsp; DB&lt;1&gt; b #1967<br>&nbsp; DB&lt;1&gt; c</tt></p></div> </blockquote><p>That'll run the tests until immediately after test #1966 and then stop, ready for the setup to the test you're interested in. Regular breakpoints still work as normal.</p><p>It's a little rough and ready. It decides which scope to stop in by unwinding the call stack skipping past any packages that are called <i>Test::*</i> - if your package naming doesn't work like that you'll have to hack it about a bit.</p><p>If you have any improvements please let me know.</p> AndyArmstrong 2008-02-28T19:48:12+00:00 tools 64 bit Fedora Core shell account? <p>I'm currently attempting to resolve a problem that the Red Hat folks are having with <a href="">IPC::ShareLite</a> on 64 bit Fedora Core with Perl 5.10. It's quite important; in fact it's critical to getting 5.10 on FC.</p><p>Unfortunately I don't own a 64 bit box. It seems (thanks <a href="">Nicholas</a>) that it might be possible to reproduce the problem using a Perl built with 64 bit ints on a non-64 bit platform - but I've had no luck in that direction yet and, in any case, I'd like to test on a 64 bit machine just to be sure.</p><p>Is there anyone out there in Perl land who could provide me with a temporary shell account on a 64 bit Fedora Core machine? That'd have to be someone who didn't mind me burning enough CPU cycles to build Perl 5.10 from source.</p><p>If you can help with getting 5.10 into Fedora by providing access to a suitable box please drop me a line and earn the eternal gratitude of, well, everyone really.</p><p>Thanks.</p> AndyArmstrong 2008-02-23T18:38:59+00:00 linux It feels good to get rid of those four lines <p>This has bothered me <i>far</i> more than it should. I quite often end up writing test code that looks like this:</p><blockquote><div><p> <tt>{<br>&nbsp; &nbsp; my @log = ();<br> <br>&nbsp; &nbsp; no warnings 'redefine';<br>&nbsp; &nbsp; *Some::Package::some_func = sub { push @log, [@_] };<br> <br>&nbsp; &nbsp; sub get_log {<br>&nbsp; &nbsp; &nbsp; &nbsp; my @old_log = @log;<br>&nbsp; &nbsp; &nbsp; &nbsp; @log = ();<br>&nbsp; &nbsp; &nbsp; &nbsp; return @old_log;<br>&nbsp; &nbsp; }<br>}<br> <br># Then some tests that call subroutines that end up calling some_func.</tt></p></div> </blockquote><p>The idea is to <a href="">monkeypatch</a> (Perl word of the week) the module I'm testing so I can make sure it calls <code>some_func</code> with the right arguments. For example with <a href="">TextMate::JumpTo</a> I wanted to test that it was going to invoke<nobr> <wbr></nobr><code>/usr/bin/open</code> with the correct args - without actually going through with it and opening something. I didn't want the tests to spew a bunch of random windows into the user's text editor.</p><p>None of that is what bothers me. What I find troubling is that <code>get_log</code> is five lines of code just to read and reset the contents of a list. That's really quite upsetting, right?</p><p>Today I decided I could endure it no longer (I may be being a little theatrical here) so I spent some time thinking about it. Ideally I'd like to do away with the temporary variable altogether but I can't see a way to do that. Instead I've settled for this:</p><blockquote><div><p> <tt>&nbsp; &nbsp; sub get_log { ( my @got, @log ) = @log }</tt></p></div> </blockquote><p>It's not especially pretty but it's <i>better</i>. That temporary still bugs me though...</p><p> <small> <a href="">Ads by Boggle</a> </small> <br> <b>Obsessive? Compulsive? Need Help?</b> <br> No expensive therapy! No painful brain surgery! You can help yourself. Just step away from the keyboard, take a walk, smell the fresh air. YOU ARE FREE!</p> AndyArmstrong 2008-01-19T22:19:00+00:00 journal Integrating TextMate with the Perl debugger <p>I've been stepping through a lot of code in the Perl debugger recently. The debugger has a bit of a forbidding reputation but it's not too bad once your muscle memory has got the essential commands down.</p><p>Once thing that would really help me though would be to have my text editor (<a href="">TextMate</a>) track the current debugger file and line. Then, when I wanted to see the code around the current location, I could just flip to my editor instead of hunting around with the debugger's code viewing commands.</p><p>TextMate registers a handler for the txmt:// URL scheme that can be used to send it to a particular file, line and column (you can read more about that <a href="">here</a>).</p><p>Mac OS has<nobr> <wbr></nobr><i>/usr/bin/open</i> which allows an arbitrary URL (or file or application) to be opened from the command line.</p><p>The Perl debugger recognises a function <i>watchfunction</i>, defined in <i>~/.perldb</i> and calls it for every line it executes.</p><p>Throwing all those ingredients together gives us <a href="">TextMate::JumpTo</a> - a module to remotely control TextMate's current location - and this <i>~/.perldb</i> file which tells the debugger to sync its position with TextMate:</p><blockquote><div><p> <tt>use TextMate::JumpTo qw(jumpto);<br> <br>sub afterinit {<br>&nbsp; &nbsp; $trace |= 4;&nbsp; &nbsp; # Enable watchfunction<br> <br>&nbsp; &nbsp; # Needed to work out where filenames are relative to<br>&nbsp; &nbsp; chomp( $base_dir = `pwd` );<br>}<br> <br>sub watchfunction {<br>&nbsp; &nbsp; my ( $package, $file, $line ) = @_;<br>&nbsp; &nbsp; local $trace = 0;<br>&nbsp; &nbsp; if ( $file =~<nobr> <wbr></nobr>/^\(eval\s+\d+\)\[(.+?):(\d+)\]/ ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; $file = $1;<br>&nbsp; &nbsp; &nbsp; &nbsp; $line += $2 - 1;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; $file = File::Spec-&gt;rel2abs( $file, $base_dir );<br>&nbsp; &nbsp; jumpto( file =&gt; $file, line =&gt; $line, bg =&gt; 1 )<br>&nbsp; &nbsp; &nbsp; if substr( $file, 0, length( $base_dir ) ) eq $base_dir;<br>}</tt></p></div> </blockquote><p>Now I just debug normally and any time I want to see the code around the current line I switch to the editor and there it is. It's not quite full editor integration but it immediately makes my life a lot easier.</p> AndyArmstrong 2008-01-19T15:49:30+00:00 tools Devel::DTrace <p>Since installing Mac OS 10.5 I've been falling in love with <a href="">dtrace</a>. I'd like to have dtrace instrumentation built into Perl as standard. Last night I started playing around with Alan Burlison's <a href="">experimental dtrace patch</a> and in particular with Richard Dawe's <a href="">modified version of Alan's patch</a>.</p><p>I made some progress and got the patch to apply cleanly against bleadperl and made a couple of changes (simplifications actually) to correspond with how dtrace itself has evolved.</p><p>This morning it occurred to me that I might be able to add the dtrace probes to a <a href="">replacement runops loop</a> instead of making it a compile time option for Perl itself. As a result I've just released <a href="">Devel::DTrace</a>.</p><p>Having launched a Perl process like this</p><blockquote><div><p> <tt>perl -MDevel::DTrace</tt></p></div> </blockquote><p>you can attach to it with dtrace and watch the subroutine calls go by.</p><p>For the next release of Devel::DTrace I plan to have it build a custom probe-enabled interpreter, dtperl (which is <a href="">quite simple</a>) which will be <i>nearly</i> as good as having probes hard wired into Perl.</p><p>I'd still like to get dtrace into core but doing so depends on minimising the performance hit that's incurred. At the moment the probe code works out the subroutine name, file and line number for every entry and exit even if the probe is disabled. The recommended solution (as per Alan's article linked above) is to move that decode logic out of Perl and into dtrace - but that's not trivial because the code has to do different things depending on how Perl is built.</p><p>In the mean time if you have a system that supports dtrace please give Devel::DTrace a try.</p> AndyArmstrong 2008-01-06T16:42:49+00:00 tools Add your Perl to Ohloh <p> <a href="">Ohloh</a> tracks open source projects that have public version control repositories. Currently more than 10,000 projects are listed of which more than 2,000 use Perl. They've scanned nearly 59,000,000 lines of Perl.</p><p>Ironically if it were not for the CPAN (surely one of the world's most valuable collections of free software) Perl would, I believe, be even better represented. As <a href=";percent=&amp;l0=cncpp&amp;l1=java&amp;l2=perl&amp;l3=php&amp;l4=python&amp;l0_0=ruby&amp;l0_1=-1&amp;commit=Update">this graph</a> shows Perl doesn't feature particularly strongly in Ohloh's commit stats. Projects written in languages that don't have the benefit of a dedicated archive like CPAN tend to be hosted on Sourceforge or Google Code which automatically gets them a public repository that Ohloh can scan. CPAN modules tend to live between the author's computer and the CPAN and remain largely invisible to the wider community.</p><p>If you're a CPAN author whose modules are not listed on Ohloh consider adding them. If your code is in a public repository list that too. Let's get a more accurate picture of how much code the CPAN represents.</p><p>Sceptics will note that Ohloh's LoC (Lines of Code) and comment ratio metrics are flawed, tending to favour verbose languages and (I think) ignoring embedded POD. My impression is that the Ohloh team are actively working to improve their metrics. If Perl is well represented they will have a greater incentive to get the metrics right for Perl.</p><p>Show the rest of the free software world just how much high quality code we're cranking out. Add your Perl project to Ohloh today.</p> AndyArmstrong 2007-12-30T14:31:21+00:00 useperl Why Perl 6 needs to be deemphasized and renamed: a response <p>Paul Cory would like to <a href="">rebrand Perl 6 into the shadows</a>. It's the kind of Stalinist revisionism favoured by corporations that realise that their "next big thing" has become an embarrassing albatross.</p><p>Here are his reasons:</p><blockquote><div><p>1) It emphasises the "inadequacies" of Perl 5.</p></div></blockquote><p>All languages have inadequacies, imperfections, miss-features, cruft. Perl 5 is no different. Fortunately, instead of brushing them under the rug, the Perl community is actively seeking to right those wrongs. A question: would you rather use a language that's maintained by people who are a) in denial about it's inadequacies or b) actively developing a new language based on recognised shortcomings? I hope that's a rhetorical question.</p><blockquote><div><p>2) It makes the development community look unorganized, at best. People comparing at the development pace of Python, Ruby and PHP to Perl 6 are likely to come to harsher conclusions about the community's focus, viability and competence, based on Perl 6's seven-year, and counting, gestation period.</p></div></blockquote><p>Those hypothetical people are wrong and I don't want to be part of a community that panders to their views. The Perl 5 Porters are doing a great job of continuously improving Perl 5. The Perl 6 team are laying the foundations for the next generation of Perl. Perl 5 and Perl 6 have a mutually beneficial relationship: features, tools and ideas are traded freely between the two groups. It's healthy, responsible and creative.</p><p>Python and Ruby have, to their credit, somewhat similar splits between far sighted strategic development and tactical improvements to the current language generation. PHP is a bizarre bazaar that does not provide a model other language communities should emulate.</p><blockquote><div><p>3) It creates uncertainty: what happens to Perl 5 when Perl 6 finally drops? How much new stuff will I have to learn? How will my existing code work, or not, if I upgrade? Why should I invest time in Perl 5 if Perl 6 is just around the corner, and will be far superior?</p></div></blockquote><p>Learning to deal with an uncertain future comes with the territory of computing. Continual improvement necessarily means that things will change.</p><p>Perl 6 is visible proof that we have vision. Perl 5 is visible proof that we can maintain an extremely high quality programming language. These facts combined should give observers confidence about the health of Perl. As a community we certainly need to work to allay fears and calibrate expectations. But let's not start by hiding one of our greatest assets, ok?</p><blockquote><div><p>4) It creates frustration inside the community. Perl 6 has been "coming soon" for 7.5 years now. It's hard to remain excited about something that long with no payoff.</p></div></blockquote><p>Welcome to the world of free software. Instead of waiting for Godot we can go and meet him half way; help him carry his load. Let's be explicit here: if Perl is part of your life or career and you're tired of waiting for Perl 6 <b>help make it happen.</b> </p><p>You don't have to contribute code to help. Learn more about Perl 6 so you can explain it to others. If you find it hard to learn make it easier for others: write an article that explains some of the important points, give talks, learn so you can teach.</p><blockquote><div><p>5) The story is confusing: Pugs? Haskell? Parrot? Two development tracks? I thought this was about Perl? Yes, I have an idea of what those things are, but most folks outside the community (and a fair few inside, I'd wager) don't know, don't care, and shouldn't have to.</p></div></blockquote><p>If the story is confusing we need to tell it more clearly. That doesn't justify changing the underlying technical narrative.</p><p>In a commodified world criticism and spending discretion are the consumer's only levers. We crave influence over the things we consume. In the absence of direct influence over a product's design we use criticism as a proxy for control. We hope that they'll make the next version better as a result.</p><p>Criticism is still valid in the free software world but it's importance is de-emphasised. You can criticise or you can help. In fact you can criticise <i>and</i> help.</p><p>It's important that Perl 6 is not immune from scrutiny but if you're frustrated that it's taking a while then volunteer. The Perl 6 team is small at the moment; small enough that a few well placed contributions can make a real difference. Let's not default to bitching about it when we have the opportunity of contributing to its success.</p> AndyArmstrong 2007-12-28T12:31:49+00:00 perl6 HTTP::Proxy::GreaseMonkey <p>Yesterday I posted a <a href="">GreaseMonkey script to add a CPAN Dependencies link to</a>.</p><p>The only problem with that is that FireFox is not my main browser. I tend to use FireFox for web development (FireBug++) and Safari for general surfing. Theoretically you can use GreaseMonkey scripts in Safari using <a href="">CreamMonkey</a> - but I couldn't get that to play nicely with Leopard.</p><p>So I've released <a href="">HTTP::Proxy::GreaseMonkey</a> which builds on BooK's excellent <a href="">HTTP::Proxy</a> to provide a local proxy that functions like GreaseMonkey.</p><p>Version 0.01 of HTTP::Proxy::GreaseMonkey has no support for the GM_* utility functions that the real GreaseMonkey provides - but it works well enough to support my CPAN dependencies user script and probably quite a few other GM scripts. Suggestions are welcome. Suggestions with patches even more so.</p> AndyArmstrong 2007-12-16T19:11:29+00:00 tools CPANdeps + Greasemonkey <p>I've just written a quick and dirty Greasemonkey script that adds a link to David Cantrell's excellent <a href="">CPAN dependencies</a> to any CPAN distribution's page on</p><blockquote><div><p><nobr> <wbr></nobr><tt>// ==UserScript==<br>// @name&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CPAN Search<br>// @namespace&nbsp; &nbsp; &nbsp;<br>// @description&nbsp; &nbsp; Add links to CPAN<br>// @include&nbsp; &nbsp; &nbsp; &nbsp;<br>// ==/UserScript==<br> <br>var new_links = {<br>&nbsp; &nbsp; 'CPAN Dependencies': function(url, name) {<br>&nbsp; &nbsp; &nbsp; &nbsp; return ''<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + escape(make_module_name(name));<br>&nbsp; &nbsp; }<br>};<br> <br>function canonical_url() {<br>&nbsp; &nbsp; var permalink = document.getElementById('permalink');<br>&nbsp; &nbsp; if (permalink) {<br>&nbsp; &nbsp; &nbsp; &nbsp; return permalink.firstChild.href;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; return '';<br>}<br> <br>function trim_url(url) {<br>&nbsp; &nbsp; return url.replace(/^http:\/\/[^\/]+\/[^\/]+\//, '').replace(/\/$/, '');<br>}<br> <br>function make_module_name(dist_name) {<br>&nbsp; &nbsp; return dist_name.replace(/-/, '::');<br>}<br> <br>function add_links(nd) {<br>&nbsp; &nbsp; var end = nd.lastChild;<br>&nbsp; &nbsp; nd.removeChild(end);<br>&nbsp; &nbsp; var dist_url&nbsp; = canonical_url();<br>&nbsp; &nbsp; var dist_name = trim_url(dist_url);<br>&nbsp; &nbsp;<nobr> <wbr></nobr>// console.log(dist_name + ' ' + dist_url);<br>&nbsp; &nbsp; var keys = [];<br>&nbsp; &nbsp; for (var k in new_links) {<br>&nbsp; &nbsp; &nbsp; &nbsp; keys.push(k);<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; keys = keys.sort();<br>&nbsp; &nbsp; for (var l = 0; l &lt; keys.length; l++) {<br>&nbsp; &nbsp; &nbsp; &nbsp; nd.appendChild(document.createTextNode(" ]\n[ "));<br>&nbsp; &nbsp; &nbsp; &nbsp; var name = keys[l];<br>&nbsp; &nbsp; &nbsp; &nbsp; var link = document.createElement('A');<br>&nbsp; &nbsp; &nbsp; &nbsp; link.href = new_links[name](dist_url, dist_name);<br>&nbsp; &nbsp; &nbsp; &nbsp; link.innerHTML = name;<br>&nbsp; &nbsp; &nbsp; &nbsp; nd.appendChild(link);<br>&nbsp; &nbsp; &nbsp; &nbsp;<nobr> <wbr></nobr>// console.log(name + " " + link);<br> <br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; nd.appendChild(end);<br>}<br> <br>var rows = document.getElementsByTagName('tr');<br>if (rows) {<br>&nbsp; &nbsp; for (var r = 0; r &lt; rows.length; r++) {<br>&nbsp; &nbsp; &nbsp; &nbsp; var cells = rows[r].getElementsByTagName('td');<br>&nbsp; &nbsp; &nbsp; &nbsp; if (cells.length == 2 &amp;&amp; cells[0].innerHTML == 'Links') {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; add_links(cells[1].firstChild);<br>&nbsp; &nbsp; &nbsp; &nbsp; }<br>&nbsp; &nbsp; }<br>}</tt></p></div> </blockquote><p>I'm sure the DOM walking can be improved - but it works. To add other links add them to the new_links hash. Each entry is the anchor text for the link and a function that returns the URL to link to.</p> AndyArmstrong 2007-12-15T18:52:40+00:00 cpan Test::Harness 3.00 <p>We've just released <a href="">Test::Harness 3.00</a>. It's a complete rewrite of Test::Harness with a more modular architecture that should make it easier to write custom testing tools.</p><p>In no particular order here are some of the things that have changed:</p><ul> <li>Support for TAP version 13</li><li>Cleaner API</li><li>Closer integration with CPAN::Reporter</li><li>Parallel test runs</li><li>Improved output formatting</li><li>Machine readable YAML diagnostics</li><li>Better detection of TAP syntax errors</li></ul><p>And in alphabetical order some of the people who made it happen:</p><ul> <li>Sebastien Aperghis-Tramoni</li><li>Leif Eriksen</li><li>Shlomi Fish</li><li>David Golden</li><li>Jim Keenan</li><li>Andy Lester</li><li>Michael Peters</li><li>Curtis Ovid Poe</li><li>Michael Schwern</li><li>Gabor Szabo</li><li>Eric Wilhelm</li></ul><p>Thanks!</p><p>Development on Test::Harness continues. There are a number of proposals on the <a href="">Test Anything Wiki</a> and at least some of them will make it into future releases. If you'd like to follow progress more closely - or offer some help - you'll find the Test::Harness developers on the <a href="">TAPX-DEV mailing list</a> or on #toolchain on IRC.</p> AndyArmstrong 2007-11-06T13:49:27+00:00 modules Leopard's tar is broken <p>I've just upgraded my MBP to Leopard. Apple's version of <code>tar</code> has the annoying habit of generating extra files to represent Mac specific attributes. That's particularly annoying for CPAN authors because they tend to break your test suite and you can't easily see them without unpacking the archive on a non-Mac system. Grrr.</p><p>It used to be possible to disable this behaviour by setting the env var <code>COPY_EXTENDED_ATTRIBUTES_DISABLE</code> to some true value - but this seems to have stopped working in Leopard. As a result I've just released a broken version of <a href="">Captcha::reCAPTCHA</a>. Double Grrr.</p><p> <code>strings<nobr> <wbr></nobr>/usr/bin/tar</code> fails to reveal anything promising,<nobr> <wbr></nobr><code>/usr/bin/gnutar</code> is just a hard link to<nobr> <wbr></nobr><code>/usr/bin/tar</code> and I can't get the MacPorts <code>gnutar</code> to build so for now I've restored a copy of Tiger's <code>tar</code> from a backup and dumped it in <code>~/bin</code> (which I have on my path). Phew.</p><p>Watch out Mac-based module authors - it's hard to detect that you have a broken archive without testing it on a non-Mac machine.</p> AndyArmstrong 2007-11-01T22:06:43+00:00 tools Testing on VMS <p>As <a href="">previously reported</a> progress on Test::Harness 3.00 ran aground temporarily while we worked out how to run our test suite on VMS. We're back on track now, running our smoke tests automatically on a VMS TestDrive account.</p><p>With help from Craig Berry and Michael Lemke I've put together a page on the <a href="">Perl-QA Wiki</a> that describes the process:</p><p> <a href=""></a> </p><p>It includes a link to the <a href="">script</a> we use to remotely execute our test suite. If I've missed anything important or made any errors please feel free to dive in and fix them.</p> AndyArmstrong 2007-11-01T20:30:19+00:00 tools Perl Flavoured Google <p>For the last few months I've been using a couple of Perl specific <a href="">Google Co-op</a> searches.</p><p>The <a href="">Perl search</a> pulls results from 72 assorted Perl related sites including CPAN and It tends to work for those questions that you're not even sure where to ask.</p><p>Perhaps more useful is the <a href="">CPAN search</a> which I find often outperforms In particular it finds 'one word' module names like <a href=";q=CGI&amp;sa=Search&amp;;adkw=AELymgUV-CkDmPbn1D16f3gxQ1wj18E7_AuU4A6pntgqnSZe363MGD0zAABAS3RM_IeTTNm9pX189GQPCZcUmvDmYoxB13faqXF7aevqURUfLpdF5SOEUxJLAwr0u_zSqjy5Bc3dAVe-&amp;hl=en&amp;client=pub-9129330694879301&amp;channel=3534674786">CGI</a> or <a href=";q=FCGI&amp;sa=Search&amp;;adkw=AELymgVKxHKFjRjXhafuJp6ayIVeeeryu0ULwVQTtBKxLBVO8O5BqUp8oJw3scWrgpi2giFmQqkbSX3VHt1Yg4vu4OKnhc1vHCTgeU2oO2timEFLWnLQBKdaopUFPOBq89jUzhTSQv8j&amp;hl=en&amp;client=pub-9129330694879301&amp;channel=3534674786">FCGI</a> both of which currently overlooks.</p><p>If you have any suggestions for sites I've missed or other improvements give me a shout.</p> AndyArmstrong 2007-10-22T12:58:04+00:00 links The Future of Test::Harness::Straps <p>One of the implications of the work on <a href="">Test::Harness 3.0</a> is that <a href="">Test::Harness::Straps</a> will no longer exist as part of Test::Harness.</p><p>For new applications you are encouraged to use TAP::Harness / TAP::Parser. The awkwardness of Straps was one of the reasons to embark on a rewrite of Test::Harness and the new code should make it far easier to write ad-hoc testing applications.</p><p>That leaves the question of what should happen to Straps. As Schwern <a href="">points out</a> it will still work once you have installed Test::Harness 3.0 - but it would be orphaned: installed but unmaintained with no updates available.</p><p>The solution might be to make an independent release of Test::Harness::Straps. There's a slight danger then that people would continue to use it for new code but the documentation would carry warnings about the inadvisability of that - and ultimately if someone finds it useful, why not?</p><p>Let me know what you think.</p> AndyArmstrong 2007-10-16T17:06:09+00:00 tools The Faces of CPAN <p>Now that some of us have <a href="">added our Gravatars to CPAN</a> I thought it'd be fun (and perhaps a little scary) to collect all the available mugshots in one place.</p><p> <a href="">The Faces of CPAN</a> </p><p>We're disappointingly white and male - but who knew how damn fine we'd look as a group? Somebody should organise a naked calendar photo shoot next. People would pay lots of money not to see that.</p> AndyArmstrong 2007-10-14T16:08:04+00:00 cpan Strawberry Perl <p> <a href="">David Golden</a> recently alerted me to his <a href="">Strawberry Perl</a> distribution for Win32. It bundles GCC, dmake and a slew of useful modules and for my money provides a better out of the box experience than ActiveState. The default for installing modules is cpan rather than ppd and the bundled GCC means that XS modules build just fine. It also bundles David's excellent <a href="">CPAN::Reporter</a> which means you'll be giving module authors helpful Win32 feedback every time you install.</p><p>It's currently alpha but I found it completely stable. It manages to work pretty much like Perl on other platforms without having to pretend that Windows <i>is</i> another platform (&#224; la Cygwin).</p><p>Highly recommended, thanks David.</p> AndyArmstrong 2007-10-13T15:12:27+00:00 windows CPAN v DTD (spoiler: CPAN loses) <p>I need to parse a DTD. Specifically I need to parse this DTD:</p><p> <a href=""></a> </p><p>It's quite a well known one. Certainly there'll be a module on CPAN that can parse it. Let's have a look.</p><p> <b> <a href="">XML::DTD</a> </b> </p><p>Looks promising, comprehensive. Unfortunately it fails with an error which is eventually tracked to a misspelled method name. So much for test coverage. Fix that and it throws a bunch of warnings that cause a rapid loss of confidence. No matter, let's try...</p><p> <b> <a href="">XML::DTDParser</a> </b> </p><p>It's a "quick and dirty DTD parser". Hmm. "I'm too lazy to document the structure". Nice.</p><blockquote><div><p>"Since version 1.6 this module supports my "extensions" to DTDs. If the DTD contains a comment in form"</p></div></blockquote><p>Maybe I'll come back to XML::DTDParser...</p><p> <b> <a href="">SGML::DTDParse</a> </b> </p><p>SGML? That's got to be good, right? SGML is the daddy. Every fule no that. Unfortunately it doesn't really seem to have much of a Perl interface. It's all about translating DTDs to XML. I <i>might</i> be able to use that. I'm getting desperate.</p><p>I'll take a quick look at the test suite for a confidence boost. Here's one:</p><blockquote><div><p> <tt>&nbsp; &nbsp; # Before `make install' is performed this script should be runnable with<br>&nbsp; &nbsp; # `make test'. After `make install' it should work as `perl SGML-DTDParse.t'<br> <br>&nbsp; &nbsp; #########################<br> <br>&nbsp; &nbsp; # change 'tests =&gt; 1' to 'tests =&gt; last_test_to_print';<br> <br>&nbsp; &nbsp; use Test::More tests =&gt; 1;<br>&nbsp; &nbsp; BEGIN { use_ok('SGML::DTDParse') };<br> <br>&nbsp; &nbsp; #########################<br> <br>&nbsp; &nbsp; # Insert your test code below, the Test::More module is use()ed here so read<br>&nbsp; &nbsp; # its man page ( perldoc Test::More ) for help writing this test script.</tt></p></div> </blockquote><p>The other test is pretty similar. I'm not that confident now.</p><p> <b> <a href="">XML::ParseDTD</a> </b> </p><p>Running out of options. Let's look at XML::ParseDTD. From the documentation it appears to rock. The test results say "2 PASS, 2 FAIL". 50/50. So at least it's <i>got</i> some tests, right? Damn right! Here they are in their entirety:</p><blockquote><div><p> <tt>&nbsp; &nbsp; #!/usr/bin/env perl -w<br> <br>&nbsp; &nbsp; use strict;<br>&nbsp; &nbsp; use Test::Simple tests =&gt; 2;<br>&nbsp; &nbsp; use XML::ParseDTD;<br> <br>&nbsp; &nbsp; my $dtd = new XML::ParseDTD('');&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;# create an object<br>&nbsp; &nbsp; ok( defined $dtd, 'new() returned something' );&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # check that we got something<br>&nbsp; &nbsp; ok( $dtd-&gt;isa('XML::ParseDTD'), 'it\'s the right class' );&nbsp; &nbsp; &nbsp;# and it's the right class</tt></p></div> </blockquote><p>I'm momentarily impressed that it managed to score two failures with that. I'm about to find out how.</p><p>Never mind, the DTD URI in the test looks a lot like the DTD I need to parse. I'm getting close. I can feel it.</p><p>Unfortunately it has a dependency on Cache::SharedMemoryCache (why?) which in turn depends on IPC::ShareLite - which doesn't install on my PowerBook. So now I need to fix / avoid IPC::ShareLite.</p><p>See kids: the great thing about CPAN is how much time it saves!</p> AndyArmstrong 2007-06-01T16:34:54+00:00 journal Stop saying "type safe" <p>I want to stop C, C++ and Java people referring to their languages as 'type safe'. They're not 'type safe' - they're type constrained. </p><p>C has static types for two completely distinct reasons: </p><ol> <li> a partial attempt at Pascal / ADA style type bondage </li><li> as an efficiency - so the compiler need not generate code to handle dynamic types at runtime </li></ol><p>In practice it's really hard to graft dynamic types onto a statically typed language. In fact once you've implemented dynamic types you've done so much work that you might as well implement the rest of the dynamic language. And if you're going to do that you might as well just use a dynamic language in the first place. The debatable virtue of type bondage is used to mask the fact that C-like languages can't get all funky and dynamic - even if they want to. </p><p>Type bondage sounds good on paper - "if we constrain this value really tightly at compile time we'll catch all sorts of runtime problems". That certainly sounds like it'd be a good thing. </p><p>Unfortunately it mitigates against a better thing: being able to write <b>correct code that remains correct even when asked to process kinds of things that doesn't know about</b>. </p><p> <b>Dynamic typing? Don't need it!</b> </p><p>You'll sometimes read something like <i>dynamic typing offers no advantage in a properly designed program</i>. The implication being that dynamic typing is for sloppy thinkers who can't plan ahead. That may be true. The problem is that at the limit we're all "sloppy thinkers who can't plan ahead". </p><p>The design of C does, in fact, acknowledge the need for dynamic typing. The <i>sort()</i> standard function achieves type-agnosticism by allowing the programmer to pass in </p><ul> <li> the address of the things being sorted </li><li> the number of things to being sorted </li><li> the size of the things being sorted </li><li> a function to compare the things being sorted </li></ul><p>Whoever implemented <i>sort</i> understood that you'd want to able to sort just about anything. So, fortunately, they decided to make it type-unsafe, type-dangerous, type-scary. Its interface is necessary clunky - because C doesn't do dynamic types - but at least you can use it to sort your own data types. </p><p>We're invited to believe that <i>sort</i> is a special case, that in general you won't be needing that kind of flexibility. The necessity of type-inflexibility is spun as the virtue of type-safety. Safety is good! How can you oppose safety? Think of the children! </p> AndyArmstrong 2007-05-20T12:35:48+00:00 journal Perl QA wiki moved <p>The current Perl QA wiki has been attracting a lot of spam recently - and we seem to have lost contact with Tyler MacDonald who as far as I know is the only person with admin access to it.</p><p>So I've moved all the content to <a href=""></a> and set it up so that only registered users may edit. It's a shame to have to restrict access in that way; certainly we'll get fewer drive-by contributions as a result. On balance it's better than the message that a spam-riddled quality (quality!) wiki sends I think.</p><p>Please update bookmarks / links accordingly.</p> AndyArmstrong 2007-05-05T13:57:36+00:00 newsnews Wiki Widgets <p>(warning: this item may contain traces of PHP)</p><p>A classic case of <a href="">yak shaving</a>: too much work on anyway, decided to take a break by turning our local <a href="">community site</a> into a wiki. Then I thought it'd be nice to embed a Google map showing a few local landmarks. Must be possible, right? Well it probably <i>has</i> been done already but it seemed pretty simple (and an interesting diversion) to write a MediaWiki extension to allow maps to be embedded.</p><p>So then you need to let users add points to the map - so the map needs button that spits out a chunk of markup that can be used to add a point. So I wrote some Javascript to do that.</p><p>Of course one extension is never enough (just say no kids). I was writing a load of code that'd be useful in other extensions anyway. What about a framework for extensions? Yup, the dreaded 'f' word. Oh well.</p><p>Anyway, to cut a long story short: <a href="">Wiki Widgets</a>.</p><p>One of the things I wanted to do (you know, once it became a project rather than a displacement activity) was to make widgets that, from the user's point of view, are discoverable. It's all very well installing an extension but if users can't find out about it they won't use it. Wiki Widgets has a pretty simple take on discoverability: make a blank page and add the markup:</p><blockquote><div><p> <code>&lt;widget<nobr> <wbr></nobr>/&gt;</code></p></div> </blockquote><p>to it. When you save or preview the page you'll get a list of all the installed Wiki Widgets. For each Widget there's a link that takes you directly to a (wiki) page that explains how to use it. From there you should be able to select the widget you want. Wherever possible I plan to make the individual Widgets support additional discoverability. For example if you add an empty Google Gadget Widget like this:</p><blockquote><div><p> <code>&lt;widget type="googlegadget"<nobr> <wbr></nobr>/&gt;</code></p></div> </blockquote><p>you should get a user interface that makes it easy to add the gadget you want and set up its parameters.</p><p>Anyway, back to the day job now.</p> AndyArmstrong 2007-04-13T19:35:14+00:00 journal Dependency Frenzy <p>Wow. I'm just installing <a href="">Plagger</a> on a couple of boxes. One of them is my regular laptop and it already has quite a lot of CPAN installed. Even so Plagger has what look like <i>hundreds</i> of unsatisfied dependencies.</p><p>I'm sure it's all going to be worth it - although all I want to do is merge a handful of RSS feeds. Right now it feels <i>slightly</i> like overkill for that task<nobr> <wbr></nobr>:)</p> AndyArmstrong 2007-03-27T19:18:28+00:00 journal Shortest FizzBuzz <p>I wish I'd never started this FizzBuzz thing now. Anyway, FizzBuzz/Perl in 60 bytes:</p><blockquote><div><p> <tt>print$_%3*$_%5?$_:($_%3?Bu:$_%5?Fi:FizzBu).zz,"\n"for 1..100</tt></p></div> </blockquote><p>Can it be bettered?</p> AndyArmstrong 2007-03-23T16:15:40+00:00 journal New site for TAP (Test Anything Protocol) <p>As you may know Perl's test result protocol is officially known as TAP - the Test Anything Protocol. Over on the <a href="">perl-qa mailing list</a> a <a href="">discussion</a> has been raging about the future of TAP. One of the points that came up was that TAP is no longer Perl specific. That means that a Perl mailing list is no longer the best place to discuss it. So that there's a language-neutral hangout for TAP fans I've created <a href="">tap-l</a> - a mailing list dedicated to TAP.</p><p>Most of the current TAP documentation lives on the <a href="">Perl QA</a> wiki. Again, not the best place if we want to persuade people that TAP is language neutral. So there's also a new TAP specific wiki:</p><p> <a href=""></a> </p> AndyArmstrong 2007-03-19T03:17:55+00:00 news FizzBuzz in 6502 assembler <p> <a href="">FizzBuzz</a> is an extremely basic competence test for programmers. So I thought I'd write a version extremely in BASIC. Here it is in BBC Basic's embedded 6502 assembler.</p><p>What's that got to do with Perl? Well I used my <a href="">6502 emulator written in Perl</a> to develop it on.</p><blockquote><div><p> <tt>&nbsp; &nbsp;10 REM FizzBuzz in 6502 assembler<br>&nbsp; &nbsp;20 DIM code% 1000<br>&nbsp; &nbsp;30 OSWRCH = &amp;FFEE<br>&nbsp; &nbsp;40 OSNEWL = &amp;FFE7<br>&nbsp; &nbsp;50 work = &amp;70<br>&nbsp; &nbsp;60 DIM FizzM 4 : $FizzM = "zziF"<br>&nbsp; &nbsp;70 DIM BuzzM 4 : $BuzzM = "zzuB"<br>&nbsp; &nbsp;80 FOR pass% = 0 TO 3 STEP 3<br>&nbsp; &nbsp;90 P%=code%<br>&nbsp; 100 [opt pass%<br>&nbsp; 110<br>&nbsp; 120<nobr> <wbr></nobr>.FizzBuzz&nbsp; LDA #1<br>&nbsp; 130&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDX #3<br>&nbsp; 140&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDY #5<br>&nbsp; 150<nobr> <wbr></nobr>.FB1&nbsp; &nbsp; &nbsp; &nbsp;SEC<br>&nbsp; 160&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DEX<br>&nbsp; 170&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BNE FB2<br>&nbsp; 180&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR Fizz<br>&nbsp; 190&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDX #3<br>&nbsp; 200<nobr> <wbr></nobr>.FB2&nbsp; &nbsp; &nbsp; &nbsp;DEY<br>&nbsp; 210&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BNE FB3<br>&nbsp; 220&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR Buzz<br>&nbsp; 230&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDY #5<br>&nbsp; 240<nobr> <wbr></nobr>.FB3&nbsp; &nbsp; &nbsp; &nbsp;BCC FB4<br>&nbsp; 250&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR PrDecimal<br>&nbsp; 260<nobr> <wbr></nobr>.FB4&nbsp; &nbsp; &nbsp; &nbsp;PHA<br>&nbsp; 270&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR OSNEWL<br>&nbsp; 280&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PLA<br>&nbsp; 290&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CLC<br>&nbsp; 300&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ADC #1<br>&nbsp; 310&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMP #101<br>&nbsp; 320&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BCC FB1<br>&nbsp; 330&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RTS<br>&nbsp; 340<br>&nbsp; 350<nobr> <wbr></nobr>.Fizz&nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 360&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDX #3<br>&nbsp; 370<nobr> <wbr></nobr>.Fizz1&nbsp; &nbsp; &nbsp;LDA FizzM, X<br>&nbsp; 380&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR OSWRCH<br>&nbsp; 390&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DEX<br>&nbsp; 400&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BPL Fizz1<br>&nbsp; 410&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CLC<br>&nbsp; 420&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PLA<br>&nbsp; 430&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RTS<br>&nbsp; 440<br>&nbsp; 450<nobr> <wbr></nobr>.Buzz&nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 460&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDY #3<br>&nbsp; 470<nobr> <wbr></nobr>.Buzz1&nbsp; &nbsp; &nbsp;LDA BuzzM, Y<br>&nbsp; 480&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR OSWRCH<br>&nbsp; 490&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; DEY<br>&nbsp; 500&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BPL Buzz1<br>&nbsp; 510&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CLC<br>&nbsp; 520&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PLA<br>&nbsp; 530&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RTS<br>&nbsp; 540<br>&nbsp; 550<nobr> <wbr></nobr>.PrDecimal STA work<br>&nbsp; 560&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 570&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TXA<br>&nbsp; 580&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 590&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDA #0<br>&nbsp; 600&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 610<nobr> <wbr></nobr>.PrDec0&nbsp; &nbsp; LDX #8<br>&nbsp; 620&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDA #0<br>&nbsp; 630<nobr> <wbr></nobr>.PrDec1&nbsp; &nbsp; ASL work<br>&nbsp; 640&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ROL A<br>&nbsp; 650&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CMP #10<br>&nbsp; 660&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BCC PrDec2<br>&nbsp; 670&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SBC #10<br>&nbsp; 680&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; INC work<br>&nbsp; 690<nobr> <wbr></nobr>.PrDec2&nbsp; &nbsp; DEX<br>&nbsp; 700&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BNE PrDec1<br>&nbsp; 710&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CLC<br>&nbsp; 720&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ADC #ASC"0"<br>&nbsp; 730&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PHA<br>&nbsp; 740&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; LDX work<br>&nbsp; 750&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BNE PrDec0<br>&nbsp; 760<nobr> <wbr></nobr>.PrDec3&nbsp; &nbsp; PLA<br>&nbsp; 770&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; BEQ PrDec4<br>&nbsp; 780&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JSR OSWRCH<br>&nbsp; 790&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; JMP PrDec3<br>&nbsp; 800<nobr> <wbr></nobr>.PrDec4&nbsp; &nbsp; PLA<br>&nbsp; 810&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TAX<br>&nbsp; 820&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; PLA<br>&nbsp; 830&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RTS<br>&nbsp; 840 ]<br>&nbsp; 850 NEXT</tt></p></div> </blockquote> AndyArmstrong 2007-03-17T20:40:18+00:00 journal YAML support in TAP <p>I've been working this week to add support <a href="">YAML-based diagnostic syntax</a> to <a href="">TAP::Parser</a>. Those changes haven't made it to CPAN yet but we'll probably make a release in the next few days. In the mean time you can find the bleeding edge version in the <a href="">subversion repo</a>.</p><p>Now TAP producers can elect to add machine readable diagnostics to test failures like this:</p><blockquote><div><p> <tt>&nbsp; &nbsp; TAP version 13<br>&nbsp; &nbsp; plan 1..5<br>&nbsp; &nbsp; ok 1<br>&nbsp; &nbsp; ok 2<br>&nbsp; &nbsp; not ok 3<br>&nbsp; &nbsp; ---<br>&nbsp; &nbsp; severity: fail<br>&nbsp; &nbsp; message: "Array unsorted"<br>&nbsp; &nbsp; data:<br>&nbsp; &nbsp; &nbsp; got:<br>&nbsp; &nbsp; &nbsp; &nbsp; - 1<br>&nbsp; &nbsp; &nbsp; &nbsp; - 3<br>&nbsp; &nbsp; &nbsp; &nbsp; - 2<br>&nbsp; &nbsp; &nbsp; expected:<br>&nbsp; &nbsp; &nbsp; &nbsp; - 1<br>&nbsp; &nbsp; &nbsp; &nbsp; - 2<br>&nbsp; &nbsp; &nbsp; &nbsp; - 3<br>&nbsp; &nbsp;<nobr> <wbr></nobr>...<br>&nbsp; &nbsp; ok 4<br>&nbsp; &nbsp; ok 5</tt></p></div> </blockquote><p>The harness doesn't currently actually <i>do</i> anything with the diagnostic information but it does expose an interface that allows display plugins to be written. With the right plugin the test harness becomes responsible for displaying the detail of what went wrong. Currently that's something test scripts must do themselves, calling diag() to display a description of the problem. Because diag() outputs to STDERR the diagnostics can get out of sync with the test results.</p><p>Look out for more progress on display plugins and a practical end-to-end example of a test that emits structured diagnostics sometime next week.</p> AndyArmstrong 2007-03-17T19:28:17+00:00 modules Adam's little joke? <p>From Adam Kennedy's <a href="">YAML::Tiny</a>:</p><blockquote><div><p> <tt>&nbsp; &nbsp; if ( $string =~<nobr> <wbr></nobr>/^"((?:\\.|[^"])*)"$/ ) {<br>&nbsp; &nbsp; &nbsp; &nbsp; my $str = $1;<br>&nbsp; &nbsp; &nbsp; &nbsp; $str =~ s/\\"/"/g;<br>&nbsp; &nbsp; &nbsp; &nbsp; $str =~ s/\\([never\\fartz]|x([0-9a-fA-F]{2}))/(length($1)&gt;1)?pack("H2",$2):$UNESCAPES{<nobr>$<wbr></nobr> 1}/gex;<br>&nbsp; &nbsp; &nbsp; &nbsp; return $str;<br>&nbsp; &nbsp; }</tt></p></div> </blockquote><p>What, never?<nobr> <wbr></nobr>:)</p> AndyArmstrong 2007-03-16T17:08:35+00:00 journal Anyone got 5.8.5 running on Windows? <p>This is a bit of a long shot. We have a test failure for TAP::Parser 0.51 on Windows:</p><p> <a href=""></a> </p><p>It's Perl 5.8.5 and to this (untutored) eye it looks as if it's not ActiveState's build. I've tried to build 5.8.5 here but can't get it to play nice with VC++ 8.0.</p><p>If anyone might happen to have 5.8.5 installed on a Windows box and could make test against both T::P 0.51 and a snapshot from the <a href="">SVN</a> and report back I'd be most grateful.</p><p>FWIW the tests all pass on Windows/5.8.8.</p> AndyArmstrong 2007-03-15T20:41:34+00:00 journal