<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Lyle&apos;s Perl Blog</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/" />
    <link rel="self" type="application/atom+xml" href="http://perl.bristolbath.org/blog/lyle/atom.xml" />
    <id>tag:perl.bristolbath.org,2008-12-23:/blog/lyle//1</id>
    <updated>2010-06-10T04:16:34Z</updated>
    <subtitle>Perl things I&apos;m working on...</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.23-en</generator>

<entry>
    <title>Finishing off the spring cleaning</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2010/06/finishing-off-the-spring-cleaning.html" />
    <id>tag:perl.bristolbath.org,2010:/blog/lyle//1.21</id>

    <published>2010-06-10T03:00:23Z</published>
    <updated>2010-06-10T04:16:34Z</updated>

    <summary>Before I start off on some new Perl posts, I thought I&apos;d write about some of the useful things I came across when doing a spring clean of my disks. I decided it was about time to clean out all...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="aceftp" label="AceFTP" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="aescrypt" label="AESCrypt" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="bookmarks" label="Bookmarks" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="firefox" label="FireFox" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="hmailserver" label="hMailServer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="iis7" label="IIS 7" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="smtp" label="SMTP" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="synctoy" label="SyncToy" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Before I start off on some new Perl posts, I thought I'd write about some of the useful things I came across when doing a spring clean of my disks. I decided it was about time to clean out all my old disks, backups, folders, etc, into a nice ordered filing system. I ended up with 2 root folders, one for work and another for personal stuff. At the same time I upgraded my PCs and laptop to be quad core and use Windows 7.<br /><br />Firstly a warning, there are some very well made counterfeit copies of Windows 7, hollograms and all. Unless you have a genuine copy of compare them side by side, it's easy to buy a fake. Unfortunately I did :( Here is my <a href="http://social.microsoft.com/Forums/en/genuinewindows7/thread/bf1f91aa-38f4-42ad-b29e-10d3f1d1e079">post to Microsoft</a> about it.<br /><br />Some of my personal files I wanted to keep private, I searched for open source options and ended up using <a href="http://www.aescrypt.com/">AESCrypt</a>. There was another interesting one that created an encrypted drive, but for now I'm happy to put files in a zip and encrypt that file.<br />]]>
        <![CDATA[I also cleared out and organised my old bookmarks, a great little 
extension to help with this is <a href="http://www.andyhalford.com/checkplaces/">CheckPlaces</a> by Andy Halford. It quickly 
checks your bookmarks for errors, 404's, etc.<br />
<br />
I develop on Windows/IIS then test on Linux/Apache. I've always found 
doing it this way round leads to less problems. I was able to 
<a href="http://www.revindex.com/Articles/tabid/65/EntryID/34/Default.aspx">export/import my IIS sites</a> with simple commands.<br />
Although this left me to re-create the application pools. Oddly it 
included all the handler mappings, but did not populate the ISAPI and 
CGI Restrictions accordingly.<br />
<br />
IIS 7 on Windows 7 doesn't include an SMTP server, I settled on <a href="http://www.hmailserver.com/">
hMailServer</a> I'd used it before and had no problems.<br />
<br />
Another issue I've had is that my web designer always saves his locally 
and not to the server (despite repeated instructions to do so, yes Phil,
 I'm talking about you! :P ). When he does save things to the server 
they often get out of sync with the local copies he works on. This leads
 to issues as you can probably imagine.<br />
<br />
The solution I chose is <a href="http://www.microsoft.com/downloads/details.aspx?familyid=c26efa36-98e0-4ee9-a7c5-98d0592d8c52&amp;displaylang=en">SyncToy</a>. Now he can save locally, and the files 
will automatically sync with the server at the end of the day (that is 
if he manages to save them in the right place, lol). This also acts as a
 useful backup.<br />
<br />
I've switched to <a href="http://software.visicommedia.com/en/products/aceftpfreeware/">AceFTP freeware</a> so we can easily use synctoy to share the 
.ftp files with FTP details for all the sites we work on<br /><br /><br />Lyle<br /><br /> ]]>
    </content>
</entry>

<entry>
    <title>First Perl 6 experiences part 2</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/04/first-perl-6-experiences-part-2.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.20</id>

    <published>2009-04-09T13:04:45Z</published>
    <updated>2009-04-09T15:20:29Z</updated>

    <summary>First Perl 6 experiences part 2When I first looked at this Sunday night I promised myself I&apos;d spend no more than an hour or two on it. Well that went right out of the window :/My initial aim was to...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="iis" label="iis" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="parrot" label="parrot" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl6" label="perl 6" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rakudo" label="rakudo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vista" label="vista" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">First Perl 6 experiences part 2</font><br /><br />When I first looked at this Sunday night I promised myself I'd spend no more than an hour or two on it. Well that went right out of the window :/<br /><br />My initial aim was to get it working on Vista and run as CGI on IIS. This didn't work. I've spent the last 3 days playing about with it and testing out a load of things to find out why. Eventually with the help of the good people on IRC #perl6 and #parrot we found the problem and came up with a fix. Here are some of the details...<br /><br />Following on from my last post, the people of the perl6-compiler@perl.org mailing list pointed me to a Rakudo build fix so I was able to build perl.exe by running mingw32-make. This has now been patched into Rakudo on github so if you are following this you shouldn't have the issue I had.<br /><br />Playing with Rakudo on the command prompt I made my first hello world script 'saved as hello.p6':-<br /><br />#!c:/temp/rakudo/perl6.exe<br />say( 'hello' );<br /><br />And ran it with 'perl6 hello.p6'.<br /><br />Following that I prepared a version for CGI that included the content-type header:-<br /><br />#!c:/temp/rakudo/perl6.exe<br />say( "Content-Type: text/html\r\n\r" ); # say adds the last \n<br />say( 'hello' );<br /><br />I checked this on the command prompt to make sure it was outputting properly and it was. Now to setup with IIS.<br />]]>
        <![CDATA[<font style="font-size: 1.25em;">Setting up Rakudo with IIS<br /></font><br />Open
up IIS7 services manager. Then select the website from the left panel
(for my it's under COMPNAME-&gt;Sites-&gt;Default Website). In the
center panel there is a link for 'handler mappings', double click. <br />&nbsp; Top right click on 'Add script map' and fill in:-<br />Request Path: *.p6<br />Executable: C:\temp\rakudo\perl6.exe "%s" %s<br />Name: Rakudo<br /><br />When I clicked OK a message popped up asking "Do you want to allow this ISAPI extention?" I clicked Yes.<br /><br />Now
we *should* be able to run Rakudo cgi scripts through IIS. But copying
my test script to c:\inetput\wwwroot\cgi-bin and trying to run through
the browser localhost/cgi-bin/hello.p6 gave me a 502 error. At this
point I tried a lot of different scripts such as:-<br /><br />#!c:/temp/rakudo/perl6.exe<br />$*ERR = open("C:/inetpub/wwwroot/cgi-bin/err.txt", :w);<br />my $crlf = "\x[0D]\x[0A]";<br />$*OUT.say( "Content-Type: text/html$crlf$crlf" );<br />$*OUT.say( 'hello it works' );<br />$*ERR.say( 'got to end' );<br /><br />Which
still gave me the error, but when I check err.txt it was having 'got to
end' written to it, so the script was actually running... To convince
myself I wasn't going mad I installed Apache and tested through that as
well:-<br /><br /><font style="font-size: 1.25em;">Setting up Rakudo with Apache</font><br /><br />I
know they are working on a mod_perl6, but right now I just want it to
work through cgi. I installed Apache 2.2 on port 8080 and updated my
httpd.conf with the line:-<br /><br />AddHandler cgi-script .cgi .pl .pl6 .p6<br /><br />I
also updated my htdocs and cgi-bin folders to be at c:\htdocs and
c:\htdocs\cgi-bin. I restarted Apache, put my hello.p6 script in
c:\htdocs\cgi-bin and ran it through the browser
http://localhost:8080/cgi-bin/hello.p6. Bingo! That worked as expected.
So at least I'm not going crazy, the hello.p6 test script is working,
so why isn't IIS displaying it's output?<br /><br /><font style="font-size: 1.25em;">Installing November</font><br /><br />At this point I was thinking maybe it was worth trying a more detailed cgi script to see what happened. I grabbed a copy of <a href="http://github.com/viklund/november/tree/master">november from github</a>.
It didn't look like anyone had tried installing november on Vista, so I
joined the november-wiki@googlegroups.com mailling list and kept them
updated as to my progress. I ended up submitting 4 patches and 1 new
script to get it running on Vista command prompt. But still IIS and
Apache weren't working :(<br /><br /><font style="font-size: 1.25em;">IRC #perl6</font><br /><br />I
was going round in circles and not getting any further. I contacted the
ActiveState mailing list thinking Jan might be able to shed some light,
but unfortunately he was away for the week. Seemed a cautious pestering
of the people on the #perl6 IRC channel was in order.<br /><br />I said hi
and spoke to PerlJam, Moritz_, jnthn and Masak. I felt a bit more
compfortable when Moritz_ said "Lyle: ah, that was you... does Rakudo
build on vista without modifications now?". TimToady was on there as
well, but I'll have to build up a bit of courage before I speak to
him...<br /><br />I told them the things I'd tried and they suggested trying some more. Nothing worked. One error that kept coming out was "<i>src\io\api.c:233: failed assertion 'pmc'</i>".
jnthn suggested writing a parrot PIR hello world cgi script and seeing
if that failed as well. Then we'd know if it was a Rakudo or Parrot
issue. (looking back at the IRC logs jnthn had an incling it was
something to do with IO and STDIN which proved almost spot on in the
end).<br /><br />I managed to get november working on Apache when I finally
realized it wasn't picking up the libraries. Still no further with IIS.
Masak also suggested writing a PIR hello world script...<br /><br /><font style="font-size: 1.25em;">Parrot PIR hello world script</font><br /><br />I searched online and found a deceptively simple script (saved as hi.pir):-<br /><br />.sub main :main<br />&nbsp;&nbsp;&nbsp; print "Hello world!\n"<br />.end<br /><br />I updated it for CGI:-<br /><br />#!c:/temp/rakudo/parrot/parrot.exe<br />.sub main :main<br />&nbsp;&nbsp;&nbsp; print "Content-Type: text/html\r\n\r\n"<br />&nbsp;&nbsp;&nbsp; print "Hello world!\n"<br />.end<br /><br />Setting
up Apache and IIS for parrot in exactly the same way I did for Rakudo
except for .pir files and the c:/temp/rakudo/parrot/parrot.exe
executable. I found similarly this worked for Apache and not IIS. This
told me it was definitly a parrot issue. Time for more help...<br /><br /><font style="font-size: 1.25em;">IRC #parrot</font><br />
<br />I joined this channel and updated them as to the problem and the
things I'd tried. They suggested trying a few more things. I ended up
with a PIR script that tried to write out to a file but kept failing
with "<i>src\io\api.c:455: failed assertion 'pmc'</i>". I tried getting IIS to run parrot with trace enabled -t1 but that just changed the error slightly "<i>src\io\api.c:603: failed assertion 'pmc'</i>".
I also tried a few hacky things to try and get the parrot output but
they didn't work. Infinoid offered his assistance, and guided me
through using MinGW's gdb program to attach to the running parrot
process and add a breakpoint. This was all well above my head by
Infinoid was very patient and told me exactly what i needed to do.<br /><br />The basic process was:-<br /><ol><li>Update hi.pir with a sleep 30 command near the top</li><li>Run through IIS</li><li>As it hangs use Task manager to grab the PID</li><li>Run gdb parrot.exe &lt;PID&gt;</li><li>Type "break Parrot_io_putps" from within gdb</li><li>Type "cont" until we got to a break point that had the null value we were looking for</li><li>Then type "bt" to dump some info about it<br /></li></ol><br />As
soon as this was done Infinoid saw what the problem was in win32.c.
Parrot was trying to open STDIN and failing. When IIS invokes a CGI
script it doesn't allow STDIN unless there is POST data. Infinoid wrote
a patch and I even got to edit a little bit of C code myself :)<br /><br /><font style="font-size: 1.25em;">Success!</font><br /><br />After
much torment parrot worked on IIS through cgi. I was able to rebuild
Rakudo (had to do a 'mingw32-make clean', then 'mingw32-make') and get
Perl 6 working as well. Much happiness :)<br /><br />I couldn't help but
feel like I'd made a different (albeit very small). The problem in
parrot meant none of the parrot based languages were working on IIS
through CGI, not just Perl 6. Now it's all sorted. Thanks again to
everyone.<br /><br /><br />Lyle]]>
    </content>
</entry>

<entry>
    <title>First Perl 6 experiences</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/04/first-perl-6-experiences.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.19</id>

    <published>2009-04-05T23:38:47Z</published>
    <updated>2009-04-09T13:04:37Z</updated>

    <summary>First Perl 6 experiencesOk. I&apos;ve been telling myself I can look at Perl 6 after I&apos;ve finished my big project... But I just can&apos;t wait. I&apos;m going to have a go at installing it on my Vista 32 laptop, and...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="perl6" label="perl 6" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="rakudo" label="Rakudo" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">First Perl 6 experiences</font><br /><br /><br />Ok. I've been telling myself I can look at Perl 6 after I've finished my big project... But I just can't wait. I'm going to have a go at installing it on my Vista 32 laptop, and getting it working through CGI with IIS7.<br /><br /><font style="font-size: 1.25em;">Getting Rakudo</font><br /><br />The <a href="http://rakudo.org/how-to-get-rakudo">Rakudo site</a> has an easy looking guide.<br /><br />I'm still very new to git, so rather than faf about trying to remember how to use it, I'm just going to download the tarball from:-<br /><a href="http://github.com/rakudo/rakudo/tree/master">http://github.com/rakudo/rakudo/tree/master</a><br /><br />Unzipped it to c:\temp and renamed the long rakudo-rakudo-xxxxxxxxx folder to just 'rakudo'.<br /><br /><blockquote>cd c:\temp\rakudo<br />perl Configure.pl --gen-parrot<br /></blockquote><br />Error: <br /><i>Generating Parrot ...<br />C:\Perl\bin\perl.exe build/gen_parrot.pl<br /><br />The system cannot find the path specified.<br />Checking out Parrot r37869 via svn...<br />'svn' is not recognized as an internal or external command,<br />operable program or batch file.</i><br /> ]]>
        <![CDATA[Oops. I need to have subversion installed so that it can grab the parrot sources. I remember starting a <a href="http://perl.bristolbath.org/index.cgi?Perl6RoadmapToHelpingWithDevelopment">Perl 6 guide</a> last year that gave instructions on how to get subversion and svk setup.<br /><br />After skipping through, I downloaded:-<br />svn-win32-1.6.0.zip<br />svn-win32-1.6.0_dev.zip<br />svn-win32-1.6.0_pl.zip<br />from:-<br /><a href="http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=8100">http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=8100</a><br /><br />Then
extracted them to c:\temp\svn. I don't think I need to set this up with
Apache to get this working. So for now I'll just update my path to
point to the svn binary folder:-<br /><br /><blockquote>set PATH=%PATH%;c:\temp\svn\svn-win32-1.6.0\bin<br /></blockquote><br />Now retry the Rakudo build:-<br /><br /><blockquote>cd c:\temp\rakudo<br />perl Configure.pl --gen-parrot<br /></blockquote><br />Ok. Got a lot further this time but still failed. Useful parts of the output:-<br /><br /><i>Since you're running this program, you obviously have Perl 5--I'll be pulling<br />some defaults from its configuration.<br /><br />...blah...<br /><br />inter::progs -&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Determine what C compiler and linker to use...Compilation failed with 'cl'<br /></i><br />So
it's getting default from Perl 5. As I'm running ActivePerl which comes
pre-compiled and without a compiler, this is the problem. ActivePerl is
built with MSVC++. I can see 3 options:-<br /><br />1) Installing MSVC++<br />2) Install Strawberry Perl that comes with a compiler<br />3) Install a separate compiler and get the parrot install to use this instead of MSVC++<br /><br />Hmm.
I do have a copy of MSVC++, but it takes ages to install and I don't
fancy waiting for it. Installing Strawberry Perl would be easy, but it
might effect my current ActivePerl and scripts I run on this system.
I'll try option 3.<br /><br />Googling ActivePerl MinGW seems that these two work well together and have done since 2005. I'll try just installing <a href="http://www.mingw.org/wiki/MinGW">MinGW</a> and see if that's enough.<br /><br />I downloaded the <a href="http://sourceforge.net/project/showfiles.php?group_id=2435">Automated MinGW Installer</a> and ran it selecting a full install to c:\MinGW.<br /><br />Add this to the path and retry the Rakudo install:-<br /><br /><blockquote>set PATH=%PATH%;c:\MinGW\bin<br /><br />cd c:\temp\rakudo<br />perl Configure.pl --gen-parrot<br /></blockquote><br />That seems to have been enough. Parrot it now building.<br /><br />Righty then. Looks like it all went ok. Finishing with the message:-<br /><br /><i>You can now use 'mingw32-make' to build Rakudo Perl.<br />After that, you can use 'mingw32-make test' to run some local tests,<br />or 'mingw32-make spectest' to check out (via svn) a copy of the Perl 6<br />official test suite and run its tests.</i><br /><br />But running mingw32-make is giving me the error:-<br /><br /><i>makefile:332: *** commands commence before first target.&nbsp; Stop.</i><br /><br />Checking the makefile, line 332 is:-<br /><i>perlcritic -1 --profile tools\util\perlcritic.conf $(CRITIC_FILES)</i><br /><br />If
I type perlcritic in the command shell then I get a command not
recognised error. So I'm guessing perlcritic is a requirement that you
need to install before trying to build Rakudo.<br /><br />ppm install Perl-Critic<br /><br />Hmmm. Still getting the same make error, even with a working perlcritic command...<br /><br />I'm
no Makefile expert, I can't see what's wrong. I've subscribed to the
perl6-compiler@perl.org mailing list to see if they can help :/<br /><br /><b>Update:</b>&nbsp; The guys on the mailing list got back to me with a solution the same night :) They've also updated the master tree with the fix, so anyone reading this should find it works first try.<br />&nbsp;I'll do another blog post when I've had a bit more of a play...<br /><br /><br />Lyle<br />]]>
    </content>
</entry>

<entry>
    <title>Perl patching experiences part 2</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/03/perl-patching-experiences-part-2.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.18</id>

    <published>2009-03-02T03:40:05Z</published>
    <updated>2009-03-02T03:50:26Z</updated>

    <summary>Perl patching experiences part 2Success with patching Email::Stuff! I saw that it was a part of the Perl Email Project. I got in touch with them about the Email::Stuff bug on their mailing list then followed up on IRC (irc.perl.org...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="email" label="email" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Perl patching experiences part 2</font><br /><br />Success with patching Email::Stuff! I saw that it was a part of the <a href="http://emailproject.perl.org/">Perl Email Project</a>. I got in touch with them about the <a href="http://www.mail-archive.com/pep%40perl.org/msg00347.html">Email::Stuff bug</a> on their mailing list then followed up on IRC (irc.perl.org #email).<br />&nbsp; Ricardo SIGNES was good enough to help me investigate if this was an issue with Email::Stuff or one of the underlying Email::modules. He confirmed this was a stuff issue, and also pointed out a couple of <a href="http://www.mail-archive.com/pep%40perl.org/msg00349.html">other bugs</a>.<br />&nbsp; I offered to supply patches to fix all these bugs. RJBS pulled Email::Stuff into github and gave me a fork to work on (which for me also meant getting a github account and learning the basics of git). A few hours later I had a fully working fork fixing the header loss issue, unused clone issue, and also multipart/alternative issue. I went further to write unit tests to check that these were working properly and ensure they continued to do so in the future. I also updated the docs a little, although I should probably have documented the new conforming functionality a bit more.<br />&nbsp; With the minor patch I submitted to Params::Util getting applied but giving me no mention in the changelog. This time I was very chuffed to see my name appear in the credits :)<br /><br />Patched <a href="http://search.cpan.org/dist/Email-Stuff/">Email::Stuff</a> 2.07 now on <a href="http://www.cpan.org/">cpan</a> ;)<br /><br />Clone issue fixed, <a href="http://rt.cpan.org/Public/Bug/Display.html?id=27320">RT BUG</a> fixed and other problems Ricardo found all fixed.<br /><br /><br />Lyle<br /><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Perl patching experiences part 1</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/02/perl-patching-experiences-part-1.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.17</id>

    <published>2009-02-25T01:28:06Z</published>
    <updated>2009-02-25T01:33:19Z</updated>

    <summary>Perl patching experiences part 1 Recently I looked at submitting code fixes and posted a quick guide. Since that post I managed to find and fix a bug in Params::Util, submitting the appropriate patch. Adam Kennedy (the maintainer of the...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="bug" label="bug" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="patch" label="patch" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tests" label="tests" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Perl patching experiences part 1</font><br />
<br />Recently I looked at submitting code fixes and posted a quick guide. Since that post I managed to find and fix a bug in Params::Util, submitting the appropriate patch. Adam Kennedy (the maintainer of the module) took it further to write the appropriate unit tests to make sure the problem never came about again.<br /><br />This has made me realize that patches can be more than just code and typo fixes. An ideal patch would include code fix, unit tests for the problem and possibly documentation updates. It could even be code replacement, or alternative versions.<br />]]>
        <![CDATA[I created a patch for Data::FormValidator that provided some Pure Perl
alternatives if XS based modules are not available on a system (yet to
be implemented). You could in turn submit faster XS alternatives to
Pure Perl code.<br /><br />My latest plugin for CGI::Application is an
email module which currently isn't much more than a wrapper around
Email::Stuff. When choosing it 2 things put me off. One was the
promblem with Pure Perl Params::Util which is now fixed. The other was
that is uses Clone which is an XS only module. Upon further inspection,
Clone is loaded, but ever actually used. I guess this was a feature
Adam was planning but didn't implement. I asked him about it and he
said it wouldn't be an issue to remove Clone.<br /><br />It's been a couple
of weeks and the Email::Stuff on CPAN still declares Clone as a
dependency. So my CGI::Application::Plugin::Email module currently
looks like it doesn't have a Pure Perl option (which is the aim for all
of my CGI::Application modules).<br /><br />I know Adam runs a lot of
projects and is very busy. Given his very fast responce to fixing
Params::Util when I submitted a patch. My current thinking is that I
can give him a worthwhile update to Email::Stuff (more than just a
removal of "use Clone;") then it'll be worth updating the CPAN version.<br /><br />Taking a look at the RT, there is <a href="http://rt.cpan.org/Public/Bug/Display.html?id=27320">a bug</a> that has been in there for over a year. I'm hoping if I fix this then I'll be able to also fit in the Clone removal.<br /><br />Results to follow ;)<br /><br /><br />Lyle ]]>
    </content>
</entry>

<entry>
    <title>Writing a CPAN Task</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/02/writing-a-cpan-task.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.16</id>

    <published>2009-02-08T21:30:59Z</published>
    <updated>2009-02-08T21:33:26Z</updated>

    <summary>Writing a CPAN TaskLast week I was looking into CPAN Bundles and created my first Bundle for the PerlCertifiedHosting project. As a follow up this week I&apos;ll create a Task, which is the successor to Bundle.After listing a load of...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="bundle" label="Bundle" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="task" label="Task" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Writing a CPAN Task<br /><br />Last week I was looking into CPAN Bundles and created my first Bundle for the PerlCertifiedHosting project. As a follow up this week I'll create a Task, which is the successor to Bundle.<br /><br />After listing a load of CGI::Application modules in my Bundle::CertHost it seems it would make a lot of sense if CGI::Application had it's own Bundle or Task that I could just link to.<br /><br /><a href="http://search.cpan.org/dist/Task/lib/Task.pm">http://search.cpan.org/dist/Task/lib/Task.pm</a><br /> ]]>
        <![CDATA[A Task is very straight forward. Nothing special about it really as it uses the same Makefile.PL system as normal modules.<br />
<br />
First Draft<br />
<br />
### In Makefile.PL<br />
use inc::Module::Install;<br />
<br />
name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'Task-CGI-Application';<br />
abstract&nbsp;&nbsp;&nbsp;&nbsp; 'Install the most common CGI::Application modules';<br />
author&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'Lyle Hopkins &lt;cosmicnet@cpan.org&gt;';<br />
version_from 'lib/Task/CGI/Application.pm';<br />
license&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'perl';<br />
<br />
# All the things we need for CGI::Application<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'CGI::Simple' =&gt; 0;<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'FCGI' =&gt; 0;<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'CGI::Fast' =&gt; 0;<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'CGI::Application' =&gt; 0;<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'CGI::Application::Plugin::ActionDispatch' =&gt; 0;<br />
...lots more...<br />
requires&nbsp;&nbsp;&nbsp;&nbsp; 'Titanium' =&gt; 0;<br />
<br />
WriteAll;<br />
<br />
<br />
### In lib/Task/CGI/Application.pm<br />
package Task::CGI::Application;<br />
<br />
use strict;<br />
use vars qw( $VERSION );<br />
BEGIN {<br />
&nbsp;&nbsp;&nbsp; $VERSION = '0.01';<br />
}#BEGIN<br />
<br />
<br />
1;<br />
<br />
That was pretty easy. This is the first time I've used Module::Install
so I had to grab that module first "ppm install Module::Install". Also
I had to update the MANIFEST to include the Module::Install files that
are put in the inc/ folder.<br />
<br />
### In MANIFEST<br />
Changes<br />
Makefile.PL<br />
MANIFEST<br />
README<br />
t/Task-CGI-Application.t<br />
lib/Task/CGI/Application.pm<br />
inc/Module/Install.pm<br />
inc/Module/Install/Base.pm<br />
inc/Module/Install/Can.pm<br />
inc/Module/Install/Fetch.pm<br />
inc/Module/Install/Makefile.pm<br />
inc/Module/Install/Metadata.pm<br />
inc/Module/Install/Win32.pm<br />
inc/Module/Install/WriteAll.pm<br />
<br />
<br />
nmake dist<br />
perl \UnixUtils\tarfixer.pl -i.bak Task-CGI-Application-0.01.tar.gz<br />
<br />
Ready to go up to CPAN. That was easy :)<br />
<br />
<br />
Lyle<br /><br />
]]>
    </content>
</entry>

<entry>
    <title>Writing a CPAN Bundle</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/writing-a-cpan-bundle.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.15</id>

    <published>2009-01-31T04:15:49Z</published>
    <updated>2009-01-31T04:16:44Z</updated>

    <summary><![CDATA[Writing a CPAN BundleI decided to take an hour out from my big project today to make my first CPAN Bundle for the PerlCertifiedHosting Project. Last year I posted to B&amp;BPM asking how this was done as when I looked...]]></summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="bundle" label="Bundle" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Writing a CPAN Bundle</font><br /><br />I decided to take an hour out from my big project today to make my first CPAN Bundle for the PerlCertifiedHosting Project. Last year I posted to B&amp;BPM asking how this was done as when I looked at bundles on CPAN I couldn't see anything special. David Cantrell was good enough to respond, pointing me to:-<br />http://search.cpan.org/dist/CPAN/lib/CPAN.pm#Bundles<br />Which explains it. I was looking for some special code or something, when after all it's just a list of modules in the contents section.<br /><br />First draft:-<br /> ]]>
        <![CDATA[package Bundle::CertHost;<br />
<br />
$VERSION = "0.01";<br />
<br />
1;<br />
<br />
__END__<br />
<br />
=head1 NAME<br />
<br />
Bundle::CertHost - A bundle to install PerlCertifiedHosting.com module requirements<br />
<br />
=head1 SYNOPSIS<br />
<br />
Linux:-<br />
&nbsp;perl -MCPAN -e 'install Bundle::CertHost'<br />
<br />
Windows:-<br />
&nbsp;ppm install Bundle-CertHost<br />
<br />
=head1 CONTENTS<br />
<br />
Bundle::DBI - Start DB section<br />
<br />
DBD::mysql<br />
<br />
... to many to list in the blog post<br />
<br />
=head1 DESCRIPTION<br />
<br />
This bundle provides the CPAN module requirements for PerlCertifiedHosting.com.<br />
<br />
=head1 AUTHOR<br />
<br />
Lyle Hopkins E&lt;lt&gt;webmaster@cosmicperl.com&gt;<br />
<br />
=cut <br />
<br />
The list is already very long. While wondering how to make this bundle
easier to maintain I came across Bundle::Math, which is a Bundle that
only lists other Bundles in it's namespace. This seems an excellent way
of breaking up the modules into groups. Although I'll save this for
next time.<br />
<br />
Next steps will be making a TASK:: version and splitting up
Bundle::PerlCert into groups. Also I'll need to make a script (or
collection of scripts) to automate this process.<br />
<br />
<br />
Lyle<br />
]]>
    </content>
</entry>

<entry>
    <title>How to submit Perl patches?</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/how-to-submit-perl-patches.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.14</id>

    <published>2009-01-24T19:36:33Z</published>
    <updated>2009-01-30T17:14:40Z</updated>

    <summary>How to submit Perl patches?It&apos;s about time I learnt to submit proper patches. In the past I&apos;ve just emailed module authors spelling mistakes and code fixes. This isn&apos;t good for the authors as then they have to scan through and...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="cgikwiki" label="CGI::Kwiki" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="diff" label="diff" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="patch" label="patch" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">How to submit Perl patches?<br /></font><br /><br />It's about time I learnt to submit proper patches. In the past I've just emailed module authors spelling mistakes and code fixes. This isn't good for the authors as then they have to scan through and manually edit the modules themselves. Thus making it more time consuming for them, and less likely for them to apply your fix. The proper way to do with is by supplying a diff which can be patched into the module. I've been sending lots of typo fixes to Mark Stosberg recently as I've been reading up on CGI::Application. I've promised him the next ones I send will be proper patches. Although as it turns out, my first patch wont be for CGI::App typos.<br /><br />This post is a continuation of my last post, which you'll need to follow for the example to work.<br /><br />Let's go through the process for the bug I found in the CGI::Kwiki test suite when ran under Windows.<br /><br />First let look at the current test file (C:\temp\CGI-Kwiki-0.18\t\test.t):-<br /><br /> ]]>
        <![CDATA[<br /><i>use lib 'inc';<br />use Test::More;<br />use Cwd;<br />use File::Path;<br /><br />plan(tests =&gt; 9);<br /><br />my $cwd = cwd;<br />rmtree('t/kwiki');<br />ok(mkdir 't/kwiki', 0777);<br />ok(chdir 't/kwiki');<br />ok(system("PERL5LIB=../../blib/lib;../../blib/script/kwiki-install") == 0);<br />ok(-f 'config.yaml');<br />ok(-d 'database');<br />ok(-f 'database/HomePage');<br />ok(-f 'database/KwikiFormattingRules');<br />ok(-f 'database/KwikiHelpIndex');<br />ok(chdir $cwd);<br /></i><br /><br />I can see the problem starts on line 12 with the call to system.<br /><i>ok(system("PERL5LIB=../../blib/lib;../../blib/script/kwiki-install") == 0);</i><br /><br />On Windows it's done a little differently. First I'll make a backup of the current test.t file called test.t.bak.<br />Now I'm changing that line to:-<br /><i>if ( ( $^O eq 'MSWin32' ) || defined( $ENV{'OS'} ) ) {<br />&nbsp;&nbsp;&nbsp; ok(system("SET PERL5LIB=../../blib/lib") == 0 &amp;&amp; system('..\..\blib\script\kwiki-install') == 0);<br />}#if<br />else {<br />&nbsp;&nbsp;&nbsp; ok(system("PERL5LIB=../../blib/lib;../../blib/script/kwiki-install") == 0);<br />}#else<br /></i><br />On
Linux that single call to system has set the PERL5LIB environment
variable and then executed the kwiki-install script. For windows I've
had to break it up into 2 system calls, use SET for the environment
variable and fixed the Windows file path \'s, hence ' and not "
otherwise I'd have to use \\. Internally Perl with convert / to \ when
on Windows, but when you are talking to the OS directing with system
you need to use \.<br /><br />I've ran "nmake test" to see that this is working and it is. Brill :)<br /><br />So now I have the new working test.t file and the old test.t.bak file.<br /><br /><br /><font style="font-size: 1.25em;">Time for diff</font><br /><br />Luckily diff and patch come as a part of UnxUtils that I described how to download and setup in my previous post.<br /><br />First
I need to change the file names, as I don't want my patch to be for
test.t.bak, but for the original test.t. So I've renamed test.t (that
has my working code) to test.new and test.t.bak back to test.t. (I had
to name my new file test.t earlier in order for "nmake test" to work).<br /><br />Next I open a command prompt and navigate to the C:\temp\CGI-Kwiki-0.18\t folder.<br />Now I run the diff program with the -u option for "Unified format", this is the diff format that most patch programs want.<br /><br /><i>diff -u test.t test.t.new<br /></i><br />It gives me the output:-<br /><br /><i>--- test.t&nbsp;&nbsp; &nbsp;Sat Jan 24 16:45:54 2009<br />+++ test.t.new&nbsp;&nbsp; &nbsp;Sat Jan 24 17:06:14 2009<br />@@ -9,7 +9,12 @@<br />&nbsp;rmtree('t/kwiki');<br />&nbsp;ok(mkdir 't/kwiki', 0777);<br />&nbsp;ok(chdir 't/kwiki');<br />-ok(system("PERL5LIB=../../blib/lib;../../blib/script/kwiki-install") == 0);<br />+if ( ( $^O eq 'MSWin32' ) || defined( $ENV{'OS'} ) ) {<br />+&nbsp;&nbsp;&nbsp; ok(system("SET PERL5LIB=../../blib/lib") == 0 &amp;&amp; system('..\..\blib\script\kwiki-install') == 0);<br />+}#if<br />+else {<br />+&nbsp;&nbsp;&nbsp; ok(system("PERL5LIB=../../blib/lib;../../blib/script/kwiki-install") == 0);<br />+}#else<br />&nbsp;ok(-f 'config.yaml');<br />&nbsp;ok(-d 'database');<br />&nbsp;ok(-f 'database/HomePage');<br /></i><br />You
can see the line numbers and the - before the line that is removed, and
the + before the lines that need to be added. Before and after there
are 3 lines of matching text. These are used so the patch program can
still apply the diff if the line numbers don't match up.<br /><br />The output looks good to me, so I'm going to run the command again and save the output to a file called test.patch:-<br /><br /><i>diff -u test.t test.t.ew &gt; test.patch<br /></i><br />Almost
there. Now that I have my diff that explains how to apply my patch to
test.t I need to test that it actually does it's job properly.<br /><br /><br /><font style="font-size: 1.25em;">Time for patch<br /></font><br />Patch
is the program that'll apply the diff. I'm going to use it now to check
that my patch file works properly. I'll be using the -b option so that
the original file is backed up before it's patched.<br /><i><br />patch -b test.t test.patch<br /><br /></i>Seems
to have worked. The backup file is named test.t.orig, checking test.t I
can see the patch has been applied correctly. If I wanted to remove the
patch I can by running the command above with the -R option instead of
-b. Or of course I could just restore the test.t.orig file.<br /><br />Right, final test.<br /><br /><i>cd \temp\CGI-Kwiki-0.18<br />nmake test<br /></i><br />Brilliant!
So I've found a bug, fixed it, created the patch, and tested the patch
out. Now I just need to get the patch to the module author and hope he
applies it...<br /><br />DOH! Just check the RT (Request Tracker) for Kwiki, it appears someone posted this as a critical bug 4 years ago! Yikes!:-<br />http://rt.cpan.org/Public/Dist/Display.html?Name=CGI-Kwiki<br />http://rt.cpan.org/Public/Bug/Display.html?id=2550<br /><br />Aghh well. They didn't seem to provide a patch then, maybe if I submit a new bug with my patch it'll get used.<br /><br /><br />Lyle<br />]]>
    </content>
</entry>

<entry>
    <title>Building perl modules from source on windows</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/building-perl-modules-from-source-on-windows.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.13</id>

    <published>2009-01-24T06:25:19Z</published>
    <updated>2009-01-24T06:30:13Z</updated>

    <summary>Building perl modules from source on windowsThis guide is to cover building and installing Pure Perl modules on Windows for use with ActivePerl. It doesn&apos;t cover XS Perl modules that use C libraries. I&apos;ll leave that for another post :)You&apos;ll...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="kwiki" label="Kwiki" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nmake" label="nmake" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="source" label="source" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Building perl modules from source on windows</font><br /><br /><br />This guide is to cover building and installing Pure Perl modules on Windows for use with ActivePerl. It doesn't cover XS Perl modules that use C libraries. I'll leave that for another post :)<br /><br />You'll want UnxUtils from sourceforge and nmake from Microsoft. If you haven't already installed these, follow these steps:-<br /> ]]>
        <![CDATA[1. Download <a href="http://sourceforge.net/projects/unxutils">UnxUtils.zip</a><br />
<br />
2. Unzip to a temp folder, for some reason the folder you want is in
temp\usr\local\wbin. Move this wbin folder into your c:\ root to make
c:\wbin, then rename to something sensible like c:\UnixUtils. (yes I
added the 'i').<br />
<br />
3. Update your path environment variable to include this folder on the
end. In Vista32 in go Start-&gt;(Right click
on)Computer-&gt;Properties-&gt;Advanced System Settings, then click the
Advanced tab at the top of the window, then the Environment Variables
button near the bottom. Finally under 'System Variables' scroll&nbsp; to
find Path, select then click the edit button. Scroll to the end of the
list and add ";c:\UnixUtils". Click Ok and Ok again. You may need to
reboot for this to take full effect.<br />
<br />
4. Now you need to grab <a href="http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe">nmake</a> from Microsoft.<br />
(this link is subject to change, you may need to search their site).
Move the downloaded nmake15.exe file to c:\windows, then run it. It'll
extract the nmake.exe executable.<br />
<br />
<br />
Now we've got everything we need to build and install the Perl module sources.<br />
<br />
From my last post I'll use CGI::Kwiki as an example.<br />
<br />
Grab the <a href="http://search.cpan.org/CPAN/authors/id/I/IN/INGY/CGI-Kwiki-0.18.tar.gz">CGI::Kwiki sources</a> from CPAN, extract them to a temp folder, such as c:\temp. (If you find you can't extract this, get hold of <a href="http://www.rarlab.com/">WinRAR</a>)<br />
<br />
Open a command prompt, navigate to the temp Kwiki folder you extracted eariler ("cd \temp").<br />
Now run Makefile.PL to create the makefile ("perl Makefile.PL").<br />
Now run "nmake" to build it, then "nmake test" to run the modules test suite.<br />
<br />
Hmm... Seems CGI::Kwiki 0.18 fails on some tests. That'll be why ActiveState don't have it as a ppm.<br />
Looking closer at the tests it's failing because the test is trying to set a Linux style environment variable.<br />
<br />
I think all that's needed is the test to be updated to check if the OS
is windows, and set the environment variable Windows style.<br />
<br />
I'm going to run "nmake install" to install this module as it does look
like it's actually working, the problem is with the tests.<br />
<br />
Although I would like to fix this problem so that Kwiki gets
automatically built into a ppm by ActiveState. Which brings me onto my
next blog post...<br />
<br />
<br />
Lyle<br />
]]>
    </content>
</entry>

<entry>
    <title>Taking a look at Kwiki</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/taking-a-look-at-kwiki.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.12</id>

    <published>2009-01-23T21:55:24Z</published>
    <updated>2009-01-24T19:43:20Z</updated>

    <summary>Taking a look at KwikiA few months ago I was looking at Perl Wikis. I had a terrible experience trying to get SocialText installed on CentOS and ended up using TWiki for 3 sites.I was impressed by TWiki, but there...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="kwiki" label="Kwiki" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="twiki" label="TWiki" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="wiki" label="wiki" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Taking a look at Kwiki</font><br /><br />A few months ago I was looking at Perl Wikis. I had a terrible experience trying to get <a href="http://www.socialtext.net/open/index.cgi?redhat_rhel5_installs">SocialText installed on CentOS</a> and ended up using TWiki for 3 sites.<br /><br />I was impressed by TWiki, but there are a few things that nag me about it. I don't like having to setup redirects from a would be index.html to /twiki/bin/view/Main/WebHome. My designer has been moaning at me that getting the designs he wants into it is hard. For smaller Wiki's, it does seem a bit like overkill. So what about the other end of the Perl Wiki scale?<br /><br />I've recently been looking at redesigning a site that uses Kwiki. So let's take a closer look.<br /><br /><font style="font-size: 1.25em;">Kwiki - "A Quickie Wiki that's not too Tricky"<br /></font><br />Well at the moment the <a href="http://www.kwiki.org/">Kwiki site</a> seems to be down most the time. Not quite sure what's happening there.<br />Luckily you can get it on cpan:-<br />http://search.cpan.org/dist/CGI-Kwiki<br />(Make sure you get the old CGI::Kwiki from cpan, and not the new Kwiki distro. You should only download Kwiki from the Kwiki.org site)<br /><br />I had a quick look on ppm and CGI::Kwiki wasn't there. Having a quick look at CPAN testers I got the feeling it was a problem with the tests rather than Kwiki itself. Which leads me onto my next 2 posts...<br /><br /><br />Lyle<br /><br />]]>
        
    </content>
</entry>

<entry>
    <title>Useful firefox search hack</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/useful-firefox-search-hack.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.11</id>

    <published>2009-01-16T15:09:54Z</published>
    <updated>2009-01-16T15:16:29Z</updated>

    <summary>Useful Firefox search hackI read of a really useful Firefox hack the other day which I&apos;ve been using an awful lot since. It&apos;s saved me a lot of time, but I can&apos;t for the life of me remember where I...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="cpan" label="cpan" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="firefox" label="firefox" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Useful Firefox search hack<br /><br />I read of a really useful Firefox hack the other day which I've been <br />using an awful lot since. It's saved me a lot of time, but I can't for <br />the life of me remember where I read about it... I'm sure it was a book <br />review or something?&nbsp; :-\ <br /><br />Anyway, in Firefox do:-<br />Bookmarks-&gt;Organise Bookmarks<br />Then click on 'Bookmarks Menu', right click on the right pane and select <br />'New Bookmark'.<br /><br />Call it 'CPAN search', put the location as <br />'http://search.cpan.org/search?query=%s&amp;mode=all' and most importantly <br />set the keyword to 'cpan' (This is why we're adding through Organise <br />Bookmarks rather than just add bookmark).<br /><br />Now you can easily search cpan. Just type 'cpan MODULE' in the address bar.<br /><br />You can of course use this same hack for any number of sites that have <br />the search term in the query string.<br /><br /><br />Lyle<br /><br />]]>
        
    </content>
</entry>

<entry>
    <title>Making .po and .mo files</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/making-po-and-mo-files.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.10</id>

    <published>2009-01-16T14:37:06Z</published>
    <updated>2009-01-16T19:58:52Z</updated>

    <summary>Using CGI::Application::Plugin::I18NMaking .po and .mo files.Now the the module is released to CPAN I&apos;ve added a i18n guide on how to make .po and .mo files. Here is a cut down version for my blog:- Creating .po and .mo files...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="gettext" label="gettext" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="i18n" label="i18n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="internationalization" label="internationalization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="l10n" label="l10n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="loc" label="loc" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="localization" label="localization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="localtext" label="localtext" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="maketext" label="maketext" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mo" label="mo" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="po" label="po" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Using CGI::Application::Plugin::I18N<b><br /><br /></b><font style="font-size: 1.25em;">Making .po and .mo files.<br /></font><br /><br />Now the the module is released to CPAN I've added a <a href="http://search.cpan.org/%7Ecosmicnet/CGI-Application-Plugin-I18N/lib/CGI/Application/Plugin/I18N/Guide.pod">i18n guide</a> on how to make .po and .mo files. Here is a cut down version for my blog:-<br /><br />

<p><font style="font-size: 1.25em;">Creating .po and .mo files</font></p>

<p>The .po files are the editable language packs.
The .mo files are compiled versions that are a bit faster to use.</p>

<p>I've found a good little app for creating .po and .mo files:- <a href="http://www.poedit.org/" class="podlinkurl">http://www.poedit.org</a> It's cross platform and gives you a nice GUI to work from.
Of course you can always edit the .po files direct and generate the .mo files yourself.</p>]]>
        <![CDATA[<p><font style="font-size: 1.25em;">Getting the sample files</font></p>

<p>CGI::Application::Plugin::I18N includes some sample files you can
use to test out your .po and .mo files. For this blog post I'll try and
make things a bit more general.</p>

<p><font style="font-size: 1.25em;">Using Poedit</font></p>

<p>Download and install Poedit.
When you open for the first time it'll ask for your name and email,
don't worry this is just for stamping the .po files with your details.</p>

<p>Click the <i>File</i> menu,
then <i>Preferences</i> and select the <i>Parsers</i> tab.
You'll see that there is a Perl parser,
select this and then click the <i>Edit</i> button.</p>

<p>You'll see that the list of file extensions only has <i>*.pl</i>,
extend this so that is contains <i>*.pl;*.pm;*.cgi</i> and any other extensions you use for your applications Perl files.
Click <i>OK</i> and <i>OK</i> again.</p>

<p>Now we are ready to create our first catalog.
Click <i>File-&gt;New catalog</i>.
The
details I entered:- Project name: Demo Team: po testers Team email:
not@now.com Language: English Country: United States Charset: UTF-8
Source code charset: UTF-8</p>

<p>Then select the <i>Paths</i> tab,
click the little square graphic for <i>new item</i> then input the path to your script files,
I've done /tmp/potest</p>

<p>Then select the <i>Keywords</i> tab and add <i>localtext</i> the
same way you added the path. If you aren't using my I18N module, then
you'd input the name of the function or method that generals the local
text, such as maketext, gettext, loc, etc.</p>

<p>Click <i>OK</i> to finish,
a dialog will ask you where to save your .po file.
I selected /tmp/potest/I18N/en-us.po.</p>

<p>At this point Poedit will search in the paths you selected for files
that contain the keyword you input. For me it'll be searching for .pl,
.cgi and .pm files and looking for localtext. It'll extract all the
text it finds, and provide a list of strings that need translating.
You should get a window titled <i>Update summary</i> appear with a list of all the strings.
Click <i>OK</i>.<br />
(If it doesn't find any you'll get an error)</p>

<p>If you change any of your files to include new localized strings then all
you need do is click on the globe icon at the top and it'd parse the
files again for new strings.</p>

<p>Enter in your translations.
Now click the save icon.
The .mo compiled version of this file is generated automatically on each save.</p><p><br /></p>Lyle


]]>
    </content>
</entry>

<entry>
    <title>Packaging CPAN modules from Windows in Linux Style</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/packaging-cpan-modules-from-windows-in-linux-style.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.9</id>

    <published>2009-01-08T02:24:25Z</published>
    <updated>2009-01-08T02:34:06Z</updated>

    <summary>Packaging CPAN modules from Windows in Linux StyleYou&apos;re a CPAN author, but against the trend you develop on Windows rather than Linux.This is fine, helps a lot with your modules cross platform compatibility, but when you come to package your...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="cpan" label="CPAN" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dist" label="dist" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="distribution" label="distribution" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gzip" label="gzip" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="linux" label="Linux" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="make" label="make" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="nmake" label="nmake" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="tar" label="tar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="windows" label="Windows" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Packaging CPAN modules from Windows in Linux Style<br /><br /><br />You're a CPAN author, but against the trend you develop on Windows rather than Linux.<br />This is fine, helps a lot with your modules cross platform compatibility, but when you come to package your modules for CPAN you hit a snag. Windows doesn't have tar or gzip, or even make... You can get nmake as a download from Microsoft, you could use .zip rather than .tar.gz, but this isn't going to make the Linux buffs very happy.<br /><br />The solution is pretty simple, luckily there is a package called UnxUtils (yes no i in Unx) available on sourceforge. This has Win32 ports of gzip, tar and make. Although you'll still need nmake from Microsoft as you'll find make won't read windows paths properly.<br /><br />Here is a quick step by step:-<br /><br />]]>
        <![CDATA[1. Create your module, I suggest starting with <a href="http://search.cpan.org/dist/Module-Starter/bin/module-starter">Module::Starter</a> rather than h2xs as it gives you a better starting point.<br /><br />2. Download <a href="http://sourceforge.net/projects/unxutils">UnxUtils.zip</a><br /><br />3.
Unzip to a temp folder, for some reason the folder you want is in
temp\usr\local\wbin. Move this wbin folder into your c:\ root to make
c:\wbin, then rename to something sensible like c:\UnixUtils. (yes I
added the i).<br /><br />4. Update your path environment variable to
include this folder on the end. In Vista32 in go Start-&gt;(Right click
on)Computer-&gt;Properties-&gt;Advanced System Settings, then click the
Advanced tab at the top of the window, then the Environment Variables
button near the bottom. Finally under 'System Variables' scroll&nbsp; to
find Path, select then click the edit button. Scroll to the end of the
list and add ";c:\UnixUtils". Click Ok and Ok again. You may need to
reboot for this to take full effect.<br /><br />5. Now you need to grab <a href="http://download.microsoft.com/download/vc15/patch/1.52/w95/en-us/nmake15.exe">nmake</a> from Microsoft.<br />(this
link is subject to change, you may need to search their site). Move the
downloaded nmake15.exe file to c:\windows, then run it. It'll extract
the nmake.exe executable.<br /><br />6. You are ready to build your
distribution :) Open a command prompt and navigate to your modules
folder that you created in step 1. Run:-<br />perl Makefile.pl<br />nmake test<br />nmake dist<br /><br />7.
It's important to note, that although at this point you'll have what
seems to be a perfectly acceptable .tar.gz file for your module. If you
upload this module to PAUSE you'll get an error because it contains
world writeable files and folders. This is because tar perceives
windows files permissions as being equivalent to open Linux file
permissions. <br /><br />When I first hit this snag I thought I was going
to have to write a script to fix it, but luckily someone else has
already done it :) Visit the <a href="http://perlmonks.org/index.pl?node_id=731935">PerlMonks node 731935</a> and save the code to c:\UnixUtils as tarfixer.pl (use the <a href="http://perlmonks.org/index.pl?displaytype=displaycode;node_id=731935">Download</a> code link at the bottom, don't just copy and paste).<br /><br />8. Now you can fix your distribution with perl c:\UnixUtils\tarfixer.pl -i.bak Module-Name.tar.gz<br />Hopefully bart will be good enough to upload this script to CPAN and create a nice tarfixer.bat file for us.<br /><br /><br />Voilà! A nice Linuxy .tar.gz Perl module built on Windows.<br /><br /><br />Lyle<br />]]>
    </content>
</entry>

<entry>
    <title>Giving CGI::Application internationalization (I18N) part4</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2009/01/giving-cgiapplication-internationalization-i18n-part4.html" />
    <id>tag:perl.bristolbath.org,2009:/blog/lyle//1.8</id>

    <published>2009-01-07T00:28:08Z</published>
    <updated>2009-01-07T00:30:20Z</updated>

    <summary>Giving CGI::Application internationalization (I18N)Part 4After a bit of debugging I finally have the first release of the module ready. All the methods are documented, I&apos;ve done some manual testing but I still need to bulk out all of the automated...</summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="cgi" label="cgi" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cgiapplication" label="CGI::Application" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cgiapp" label="cgiapp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="findbin" label="FindBin" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="i18n" label="i18n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="internationalization" label="internationalization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="l10n" label="l10n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="localization" label="localization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[Giving CGI::Application internationalization (I18N)<br /><br />Part 4<br /><br /><br />After a bit of debugging I finally have the first release of the module ready. All the methods are documented, I've done some manual testing but I still need to bulk out all of the automated tests. I also need to writing documenation on how to create the .po and .mo files to use with this, but I've come across a very useful cross platform app called <a href="http://www.poedit.net/">Poedit</a> which makes it a lot easier.<br /><br />I'm probably over eager to upload this to CPAN, as it's only version 0.01 but I'm keen to get it up.<br /><br />With a bit of luck I'll have it uploaded tonight. It's also given me some good material for my next post "Packaging CPAN modules from Windows in Linux Style", as I'm having to do this and I've seen this come up in forums from time to time.<br /><br /><br />Module code below:-<br /><br />&nbsp;]]>
        <![CDATA[package CGI::Application::Plugin::I18N;<br />
<br />
<br />
=head1 NAME<br />
<br />
CGI::Application::Plugin::I18N - I18N and L10N methods for CGI::App<br />
<br />
=head1 SYNOPSIS<br />
<br />
&nbsp;&nbsp;&nbsp; use CGI::Application::Plugin::I18N;<br />
<br />
Within your setup, cgiapp_init, cgiapp_prerun or specific runmode routine add<br />
the line<br />
<br />
&nbsp;&nbsp;&nbsp; $self-&gt;i18n_config();<br />
<br />
Or<br />
<br />
&nbsp;&nbsp;&nbsp; $self-&gt;i18n_config( %options );<br />
<br />
%options are the same as for Locale::Maketext::Simple. If none are passed the<br />
following default are used:-<br />
<br />
&nbsp;&nbsp;&nbsp; %DEFAULT_OPTIONS = (<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Path&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; "$RealBin/I18N",<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Style&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'gettext',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Export&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; '_maketext',<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Decode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 1,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Encoding&nbsp;&nbsp;&nbsp; =&gt; 'locale',<br />
&nbsp;&nbsp;&nbsp; );<br />
<br />
$RealBin being the folder from which the executed cgi script is running.<br />
B&lt;Note that Export must remain as _maketext for this module to function<br />
properly!&gt;<br />
<br />
For instance if you wanted to use maketext style markup in your lexicons you<br />
would use the line:-<br />
<br />
&nbsp;&nbsp;&nbsp; $self-&gt;i18n_config( Style =&gt; 'maketext' );<br />
<br />
Then use the I&lt;localtext&gt; method to localize text:-<br />
<br />
&nbsp;&nbsp;&nbsp; print $self-&gt;localtext( 'Hello World!' );<br />
<br />
=head1 DESCRIPTION<br />
<br />
This module is a wrapper around C&lt;Locale::Maketext::Simple&gt; by Audrey Tang.<br />
It extends the C&lt;CGI::Application&gt; object with variour methods to control the<br />
localization of text. A L&lt;/FAQ&gt; is provided with the aim to fill in the gaps.<br />
<br />
=head1 Methods<br />
<br />
=head2 i18n_config<br />
<br />
Runs the initial configuration of C&lt;Locale::Maketext::Simple&gt; and runs it's<br />
import within your calling objects namespace (Your CGI::App class)<br />
<br />
=head2 localtext_langs<br />
<br />
Sets the current language for localtext output. Usage:-<br />
<br />
&nbsp;&nbsp;&nbsp; $self-&gt;localtext_langs( LIST );<br />
<br />
LIST must consist of valid language tags as defined in RFC3066. See<br />
C&lt;I18N::LangTags&gt; for more details.<br />
If LIST is ommited then the method will attempt to figure out the users locale<br />
using C&lt;I18N::LangTags::Detect&gt;.<br />
<br />
This method will also return the list of language tags as an array reference.<br />
<br />
&nbsp;&nbsp;&nbsp; my $langtags = $self-&gt;localtext_langs( LIST );<br />
&nbsp;&nbsp;&nbsp; print @$langtags;<br />
<br />
=head2 localtext_lang<br />
<br />
This method returns the currently selected language. This is the tag that was<br />
actually available for use, after searching through the localtext_langs list.<br />
This is the name of the module used in your MyAPP::I18N::XXX namespace (where<br />
XXX is the name of the lexicon used)<br />
<br />
&nbsp;&nbsp;&nbsp; my $lexicon = $self-&gt;localtext_lang;<br />
<br />
=head2 localtext_lang_tag<br />
<br />
This method returns the RFC3066 language tag for the currently selected<br />
language. This differs from the above method which would most likely return<br />
I&lt;en_us&gt; for American English, whereas this method would return I&lt;en-us&gt;.<br />
<br />
&nbsp;&nbsp;&nbsp; my $langtag = $self-&gt;localtext_lang_tag;<br />
<br />
=head2 localtext<br />
<br />
This is the method that actually does the work.<br />
<br />
&nbsp;&nbsp;&nbsp; print $self-&gt;localtext( 'Hello World!' );<br />
<br />
=head1 FAQ<br />
<br />
=head2 How does it all work?<br />
<br />
I kept a blog on how I put this module together and all the material I looked<br />
through in order to understand internationalization.<br />
L&lt;http://perl.bristolbath.org/blog/lyle/2008/12/giving-cgiapplication-internationalization-i18n.html&gt;<br />
<br />
=head2 What is a Lexicon?<br />
<br />
Think of it as a kind of hash. Where the text you use (usually english) has a<br />
corrosponding value in the local language. So the 'Hello world' under a German<br />
lexicon would have the value 'Hallo welt'.<br />
<br />
=head1 Thanks to:-<br />
<br />
C&lt;Catalyst::Plugin::I18N&gt; - The module this one was heavily based on<br />
<br />
C&lt;Locale::Maketext::Simple&gt; - Making it possible<br />
<br />
C&lt;Locate::Maketext&gt; - Doing all the hard work<br />
<br />
C&lt;CGI::Application&gt; - Providing the framework<br />
<br />
And all others I haven't yet mentioned.<br />
<br />
=cut<br />
<br />
<br />
<br />
use strict;<br />
use warnings;<br />
use Carp;<br />
<br />
use FindBin qw($RealBin);<br />
<br />
use I18N::LangTags ();<br />
use I18N::LangTags::Detect;<br />
<br />
require Locale::Maketext::Simple;<br />
<br />
use vars qw ( $VERSION @ISA @EXPORT @EXPORT_OK $RealBin %DEFAULT_OPTIONS );<br />
<br />
require Exporter;<br />
@ISA = qw(Exporter);<br />
<br />
@EXPORT = qw (<br />
&nbsp;&nbsp;&nbsp; i18n_config<br />
&nbsp;&nbsp;&nbsp; localtext_langs<br />
&nbsp;&nbsp;&nbsp; localtext_lang<br />
&nbsp;&nbsp;&nbsp; localtext_lang_tag<br />
&nbsp;&nbsp;&nbsp; localtext<br />
);<br />
<br />
@EXPORT_OK = qw(<br />
&nbsp;&nbsp;&nbsp; i18n_config<br />
);<br />
<br />
$VERSION = '0.01';<br />
<br />
%DEFAULT_OPTIONS = (<br />
&nbsp;&nbsp;&nbsp; Path&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; "$RealBin/I18N",<br />
&nbsp;&nbsp;&nbsp; Style&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 'gettext',<br />
&nbsp;&nbsp;&nbsp; Export&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; '_maketext',<br />
&nbsp;&nbsp;&nbsp; Decode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =&gt; 1,<br />
&nbsp;&nbsp;&nbsp; Encoding&nbsp;&nbsp;&nbsp; =&gt; 'locale',<br />
);<br />
<br />
<br />
sub i18n_config {<br />
<br />
&nbsp;&nbsp;&nbsp; my $self = shift;<br />
&nbsp;&nbsp;&nbsp; my $class = ref $self || $self;<br />
&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp; local %DEFAULT_OPTIONS = %DEFAULT_OPTIONS;<br />
&nbsp;&nbsp;&nbsp; if ( @_ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my %newoptions = @_;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my @valid_options = ("Class","Style","Export","Subclass","Decode","Encoding","Path");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach my $key (keys %newoptions) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unless (grep (/^$key$/, @valid_options)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; croak( "Invalid option: $key" );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }#unless<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }#foreach<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %DEFAULT_OPTIONS = (%DEFAULT_OPTIONS, %newoptions);<br />
&nbsp;&nbsp;&nbsp; }#if<br />
<br />
&nbsp;&nbsp;&nbsp; my $evalcode = qq~<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; package $class;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Locale::Maketext::Simple-&gt;import( \%CGI\::Application\::Plugin\::I18N\::DEFAULT_OPTIONS );<br />
&nbsp;&nbsp;&nbsp; ~;<br />
&nbsp;&nbsp;&nbsp; eval $evalcode;<br />
<br />
&nbsp;&nbsp;&nbsp; if ( $@ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; croak( qq~Couldn't initialize i18n, error "$@", code "$evalcode"~ );<br />
&nbsp;&nbsp;&nbsp; }#if<br />
&nbsp;&nbsp;&nbsp; <br />
}#sub<br />
<br />
<br />
sub localtext_langs {<br />
&nbsp;&nbsp;&nbsp; my $self = shift;<br />
&nbsp;&nbsp;&nbsp; my @langs = @_;<br />
&nbsp;&nbsp;&nbsp; if (@langs) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $self-&gt;{__I18N_LANGS} = \@langs;<br />
&nbsp;&nbsp;&nbsp; }#if<br />
&nbsp;&nbsp;&nbsp; else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ### Get CGI query object<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my $q = $self-&gt;query();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $self-&gt;{__I18N_LANGS} = [<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::implicate_supers(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::Detect-&gt;http_accept_langs(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $q-&gt;http('Accept-Language')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'i-default'<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] unless $self-&gt;{__I18N_LANGS};<br />
&nbsp;&nbsp;&nbsp; }#else<br />
&nbsp;&nbsp;&nbsp; no strict 'refs';<br />
&nbsp;&nbsp;&nbsp; &amp;{ ref($self) . '::_maketext_lang' }( @{ $self-&gt;{__I18N_LANGS} } );<br />
&nbsp;&nbsp;&nbsp; return $self-&gt;{__I18N_LANGS};<br />
}#sub<br />
<br />
<br />
sub localtext_lang {<br />
&nbsp;&nbsp;&nbsp; my $self = shift;<br />
&nbsp;&nbsp;&nbsp; my $class = ref $self || $self;<br />
<br />
&nbsp;&nbsp;&nbsp; my $lang = ref "$class\::I18N"-&gt;get_handle( @{ $self-&gt;localtext_langs } );<br />
&nbsp;&nbsp;&nbsp; $lang =~ s/.*:://;<br />
<br />
&nbsp;&nbsp;&nbsp; return $lang;<br />
}#sub<br />
<br />
<br />
sub localtext_lang_tag {<br />
&nbsp;&nbsp;&nbsp; my $self = shift;<br />
&nbsp;&nbsp;&nbsp; my $class = ref $self || $self;<br />
<br />
&nbsp;&nbsp;&nbsp; return "$class\::I18N"-&gt;get_handle( @{ $self-&gt;localtext_langs } )-&gt;language_tag;<br />
}#sub<br />
<br />
<br />
sub localtext {<br />
&nbsp;&nbsp;&nbsp; my $self = shift;<br />
&nbsp;&nbsp;&nbsp; $self-&gt;localtext_langs unless $self-&gt;{__I18N_LANGS};<br />
&nbsp;&nbsp;&nbsp; no strict 'refs';<br />
&nbsp;&nbsp;&nbsp; return &amp;{ ref($self) . '::_maketext' }( $_[0], @{ $_[1] } ) if ( ref $_[1] eq 'ARRAY' );<br />
&nbsp;&nbsp;&nbsp; return &amp;{ ref($self) . '::_maketext' }(@_);<br />
}#sub<br />
<br />
<br />
<br />
1;<br />
]]>
    </content>
</entry>

<entry>
    <title>Giving CGI::Application internationalization (I18N) part3</title>
    <link rel="alternate" type="text/html" href="http://perl.bristolbath.org/blog/lyle/2008/12/giving-cgiapplication-internationalization-i18n-part3.html" />
    <id>tag:perl.bristolbath.org,2008:/blog/lyle//1.7</id>

    <published>2008-12-30T23:43:40Z</published>
    <updated>2008-12-30T23:46:37Z</updated>

    <summary><![CDATA[Giving CGI::Application internationalization (I18N)Part 3Lets look at the remaining functions of Catalyst::Plugin::I18N and what they are doing.sub languages {&nbsp;&nbsp;&nbsp; my ( $c, $languages ) = @_; ### Getting the catalyst object and languages to set to it.&nbsp;&nbsp;&nbsp; if ($languages) {...]]></summary>
    <author>
        <name>Lyle</name>
        
    </author>
    
    <category term="cgi" label="cgi" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cgiapplication" label="CGI::Application" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="cgiapp" label="cgiapp" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="findbin" label="FindBin" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="i18n" label="i18n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="internationalization" label="internationalization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="l10n" label="l10n" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="localization" label="localization" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="Perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://perl.bristolbath.org/blog/lyle/">
        <![CDATA[<font style="font-size: 1.25em;">Giving CGI::Application internationalization (I18N)</font><br /><br />Part 3<br /><br /><br />Lets look at the remaining functions of Catalyst::Plugin::I18N and what they are doing.<br /><br /><br /><i>sub languages {<br />&nbsp;&nbsp;&nbsp; my ( $c, $languages ) = @_; ### Getting the catalyst object and languages to set to it.<br />&nbsp;&nbsp;&nbsp; if ($languages) { $c-&gt;{languages} = $languages } ### Setting the objects languages property if languages passed in<br />&nbsp;&nbsp;&nbsp; else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $c-&gt;{languages} ||= [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::implicate_supers(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::Detect-&gt;http_accept_langs(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $c-&gt;request-&gt;header('Accept-Language')<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'i-default'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ];<br />&nbsp;&nbsp;&nbsp; } ### Otherwise detects users language tags using I18N::LangTags::Detect and make sure all superordinates are included using I18N::LangTags::implicate_supers (if the objects languages property is empty)<br />&nbsp;&nbsp;&nbsp; no strict 'refs';<br />&nbsp;&nbsp;&nbsp; &amp;{ ref($c) . '::_loc_lang' }( @{ $c-&gt;{languages} } ); ### Call Locale::Maketext::Simple's loc_lang function from the calling objects namespace setting the languages<br />&nbsp;&nbsp;&nbsp; return $c-&gt;{languages};<br />}<br /></i>]]>
        <![CDATA[<i>sub language {<br />&nbsp;&nbsp;&nbsp; my $c = shift;<br />&nbsp;&nbsp;&nbsp; my $class = ref $c || $c; ### Getting the objects package name<br /><br />&nbsp;&nbsp;&nbsp;
my $lang = ref "$class\::I18N"-&gt;get_handle( @{ $c-&gt;languages } );
### Bipassing Locale::Maketext::Simple and calling Locale::Maketext's
get_handle routine directly, returning a language handle object.<br />&nbsp;&nbsp;&nbsp; $lang =~ s/.*:://; ### Which is then stripped to give you the name of the lexicon that is actually being used.<br /><br />&nbsp;&nbsp;&nbsp; return $lang;<br />}<br /><br />sub language_tag {<br />&nbsp;&nbsp;&nbsp; my $c = shift;<br />&nbsp;&nbsp;&nbsp; my $class = ref $c || $c;<br /><br />&nbsp;&nbsp;&nbsp;
return "$class\::I18N"-&gt;get_handle( @{ $c-&gt;languages }
)-&gt;language_tag; ### Similar to above, but returning the language
tag name as opposed to the <br />}<br /></i><br /><br />At first these two
functions appeared to be needlessly creating a new language handle to
get the required info. I thought Locale::Maketext::Simple must already
have a language handle it's using, why not just access that. But when I
looked deeper at the Locale::Maketext::Simple code, it seemed that
handle wouldn't be easy to access at all, if even possible...<br /><br /><br /><i>*loc = \&amp;localize; ### Make the glob of loc a reference to the subroutine localize<br /><br />sub localize {<br />&nbsp;&nbsp;&nbsp; my $c = shift; ### Get catalyst object<br />&nbsp;&nbsp;&nbsp; $c-&gt;languages; ### Sets the language on each call??? Seems a bit much...<br />&nbsp;&nbsp;&nbsp; no strict 'refs';<br />&nbsp;&nbsp;&nbsp; return &amp;{ ref($c) . '::_loc' }( $_[0], @{ $_[1] } )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
if ( ref $_[1] eq 'ARRAY' ); ### Returns the output of the _loc routine
(Locale::Maketext::Simple version of maketext), automatically
dereferences array references passed as the second arguement<br />&nbsp;&nbsp;&nbsp;
return &amp;{ ref($c) . '::_loc' }(@_); ### Returns the output of the
_loc routine (Locale::Maketext::Simple version of maketext)<br />}</i><br /><br /><br />Here
is the bit that actually displays the text. It links up the glob so
that loc can be used as well as localize (that's why they've renamed
Locale::Maketext::Simple's loc export to _loc).<br /><br />Again none of
these things are exported as they would need to be in CGI::App so I'm
assuming Catalyst does this by default. Here are my routines:-<br /><br /><br /><i>sub localtext_langs {<br />&nbsp;&nbsp;&nbsp; my ($self, $langs) = @_;<br />&nbsp;&nbsp;&nbsp; if ($langs){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $self-&gt;{__I18N_LANGS} = $langs;<br />&nbsp;&nbsp;&nbsp; }#if<br />&nbsp;&nbsp;&nbsp; else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ### Get CGI query object<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; my $q = $self-&gt;query();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $self-&gt;{__I18N_LANGS} = [<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::implicate_supers(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; I18N::LangTags::Detect-&gt;http_accept_langs(<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $q-&gt;http('Accept-Language')<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ),<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'i-default'<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ] unless $self-&gt;{__I18N_LANGS};<br />&nbsp;&nbsp;&nbsp; }#else<br />&nbsp;&nbsp;&nbsp; no strict 'refs';<br />&nbsp;&nbsp;&nbsp; &amp;{ ref($self) . '::_maketext_lang' }( @{ $self-&gt;{__I18N_LANGS} } );<br />&nbsp;&nbsp;&nbsp; return $self-&gt;{__I18N_LANGS};<br />}#sub<br /><br /><br />sub localtext_lang {<br />&nbsp;&nbsp;&nbsp; my $self = shift;<br />&nbsp;&nbsp;&nbsp; my $class = ref $self || $self;<br /><br />&nbsp;&nbsp;&nbsp; my $lang = ref "$class\::I18N"-&gt;get_handle( @{ $self-&gt;localtext_langs } );<br />&nbsp;&nbsp;&nbsp; $lang =~ s/.*:://;<br /><br />&nbsp;&nbsp;&nbsp; return $lang;<br />}#sub<br /><br /><br />sub localtext_lang_tag {<br />&nbsp;&nbsp;&nbsp; my $self = shift;<br />&nbsp;&nbsp;&nbsp; my $class = ref $self || $self;<br /><br />&nbsp;&nbsp;&nbsp; return "$class\::I18N"-&gt;get_handle( @{ $self-&gt;localtext_langs } )-&gt;localtext_lang_tag;<br />}#sub<br /><br /><br />sub localtext {<br />&nbsp;&nbsp;&nbsp; my $self = shift;<br />&nbsp;&nbsp;&nbsp; $self-&gt;localtext_langs unless $self-&gt;{__I18N_LANGS};<br />&nbsp;&nbsp;&nbsp; no strict 'refs';<br />&nbsp;&nbsp;&nbsp; return &amp;{ ref($self) . '::_maketext' }( $_[0], @{ $_[1] } ) if ( ref $_[1] eq 'ARRAY' );<br />&nbsp;&nbsp;&nbsp; return &amp;{ ref($self) . '::_maketext' }(@_);<br />}#sub<br /></i><br /><br />I'll export all these by default so the CGI::App object can have them as methods.<br /><br />Again I have to stress that all this is completely untested. My next post should have some tests, and most likely fixes...<br /><br /><br />Lyle ]]>
    </content>
</entry>

</feed>

