Zoidberg Archives

The Triumphant Return of Zoidberg -- A Modular Perl Shell

After more than a year of hoping to be able to say this, here goes: Zoidberg is back!

What is Zoidberg you ask? Well its a Perl shell, of course. Think of the fun of it all:

mv($_ => lc($_)) for grep /[A-Z]/, <*>

If you use a reserved Perl word first or if you wrap code in a block it is interpreted as Perl, if not then its a shell command. Along with having most of the things you would expect from a shell, it features plenty of extra bells and whistles, like a multiline input system (when Term::ReadLine::Zoid, part of Bundle::Zoidberg, is installed) and automatic splitting of variables to arrays like @PATH which is just $ENV{PATH} split on :.

When used as your login shell, it can be used from inside other programs like vim.

:!cat % | {/^\S/}g | wc -

Further, it is easy to extend with the Zoidberg::Fish plugin system.

Read plenty more about it in a couple of rather old, but still relevant articles:

Zoidberg had developed a few warts over the years, which have been fixed. I also noticed a few things which needed immediate work, which has been done. There is plenty more to do, but Jaap was close to declaring it stable back in 2006, so it is very usable already.

Some of the TODOs include modernizing parts of the test suite and investigating the viability of using some standard modules, like Devel::REPL, Moose, and Getopt::Long to bring zoid into the world of Modern Perl.

It is a testament to the stability of Perl that after all these years without maintenance that it took so little work to get it going again. Please enjoy Zoidberg and let me know what you think of it, or of course of any problems you have.

To try it, you can simply install with:

cpanm Bundle::Zoidberg

and the repo is on GitHub, so fork away!

For some more info start at the zoiduser man page. Then run zoid to take it for a spin!

A Zoidberg Story

I just read Buddy Burden’s recent post A Random Story and it was fun to see that his reasons for adopting Data::Random was the same as my reason for adopting Zoidberg: failing tests. The difference was that his failing tests were his own and mine were in Zoidberg.

I was a few years into using Linux and I had really fallen in love with Perl, which was my first real programming language (after Maple, Mathematica, and LaTeX), but I had never really gotten the hang of Bash. Since Perl was used in scripting, and even things that looked like shell scripting, I wondered if there was a Perl shell. I looked and I saw a few Zoidberg and Psh stood out as being functional.

Now I can’t remember what it was, but Zoidberg was the one that kept my attention, there was probably something, but I can’t remember anymore. It had a problem though, a failing test on installation through CPAN. I could install it through apt though, so no problem, right?

A little while longer, I had gotten better at Perl and I decided to see if I could play the sleuth and find the problem. It was an interesting problem (documented at SO) wherein its GetOpt module fails parsing its prototypes. Matches were leaking across loop iterations, not getting reset. This minimal example shows the problem.

#!/usr/bin/perl

use strict;
use warnings;

my @a = qw/n a$ b@ c/;
my @b = @a;
my @c = @a;

print "Test A -- Doesn't work (c !-> 0)\n";
for (@a) {
  s/([\$\@\%])$//;
  my $arg = $1 || 0;
  print $_ . " -> " . $arg . "\n";
}

print "\nTest B -- Works\n";
for (@b) {
  my $arg;
  if (s/([\$\@\%])$//) {
    $arg = $1;
  }
  $arg ||= 0;
  print $_ . " -> " . $arg . "\n";
}

print "\nTest C -- Works, more clever\n";
for (@c) {
  my $arg = s/([\$\@\%])$// ? $1 : 0;
  print $_ . " -> " . $arg . "\n";
}

The strange thing is, that test A worked before 5.10, even though it apparently wasn’t supposed to (cjm confirmed that I wasn’t going crazy). I think this may have scared many people away, but to me it was a great challenge.

Much like Buddy I submitted a patch, and while the author, Jaap Karssenberg, was responsive, he had moved on. He offered that I could adopt it if I wanted, and has helped, finding his old notes and commenting on some of my fixes.

Turns out the failing test had masked something much more sinister, the shared data wasn’t getting installed to the proper location anymore (was it installing at all?). Anyway, Module::Build had progressed a long way since Zoidberg 0.96 had been released and offered the share_dir feature, which when combined with File::ShareDir, fixes the problem quite nicely.

These and a few other fixes are essentially complete, and I hope to submit Zoidberg 0.97 to PAUSE soon. There are plenty of modernizations planned and features (literally, I want to add say, state and given/when), but those will probably have to wait until the next release.

This brings me back to the beginning of the story to say, thanks to all the CPAN authors for writing the tests, they can help an intermediate programmer try to reach in and salvage an excellent piece of software for falling into obscurity before it should. I hope to live up to the example (remember that when you start to feel lazy Joel!).

And P.S. Buddy, thanks for reminding me about done_testing, I need to look around to see if I have fallen victim to that one (I’m sure I have!).

Auto(Split|Loader) in a modern Perl world

As a few of my previous posts have implied, I am attempting to reinvigorate the Zoidberg Perl shell. Much of the work of getting it back to a functional state has already been done at my GitHub repo. I have a bigger post coming on why this is cool and even another with some examples, but for now I have a question:

Is an AutoSplit/AutoLoader mechanism helpful on modern hardware? I mean Moose/MOP (and many other projects) are huge and doesn’t use it. In fact it seems that very few modules depend on it.

Now, I understand that AutoLoader has some cool uses for causing subs to spring into existance. In the context of Zoidberg, though, I only care about its use to defer loading infrequently used subs.

To test some things, I created a branch in which I naively removed these bits, and lo and behold, with only one missing my (see AutoLoader Considered Harmful), the tests all pass and a quick run seems fine.

So I fairly call the question: should I leave AutoLoader in, or pull it?

About Joel Berger

user-pic As I delve into the deeper Perl magic I like to share what I can.