Graphical widgets in my text console? How perverse!

Things like this:


are now possible in Perl and Moose. Get from CPAN

Now some history...

Like most configuration systems the history is nearly the same. First you start out with global variables because no one really thought about it nor cared about future maintenance. So you end up with:


And then you realize that was a terrible idea because someone changed it to a value that had disastrous effects in production because any number of reasons, the value didn't have any consequences in your internal test environment, typo, etc.

Then you move on to config files, possibly Perl or hand made. Then to a standard format, ini or whatever. Then you realize how smart YAML and JSON are and settle with those.

But there still is a problem. What is an easy way for someone new to the application to setup up their own configuration? How about someone not intimately familiar with Perl? I decided that enough was enough and a real solution was required. I browsed and browsed for a solution that would allow me to use some sort of graphical interface in the terminal or possibly even X that I could piggy back off of and build an easy configuration management system. There was no complete solution that met the Adam's Standard of Software Excellence approval, so like most driven developers, I created (or in this case glued) my own using dialog (more precisely libdialog which dialog is built from), which uses ncurses for drawing.

The result: Hobocamp. Yes, it has a silly name, here's where it's from.

Now we needed a way to make config values adjustable. This is an example pulled from our home grown system at work. We have a type library and knobs which are a single item in the menu list. This ties directly into our configuration library (based on YAML) so altering a value here via the GUI results in the data being written back on save.

package Amethyst::BuildConf::Knob::UnixBinary;

use Moose;
use File::Spec;
use Amethyst::Types qw(UnixExecutableFile);

has 'conf_key_name' => (
    'isa'     => 'Str',
has 'name' => (
    'isa'     => 'Str',
has 'question' => (
    'isa'     => 'Str',
has 'value' => (
    'isa' => UnixExecutableFile,
    'is'  => 'rw',
has 'data' => (
    'isa'     => 'Str',
    'is'      => 'ro',
    'default' => '/tmp/a.out'
with qw(Amethyst::BuildConf::Roles::Knob Amethyst::BuildConf::Roles::UI::FileSelect);

The role defines what GUI widget is used.

A test would look something like this:

subtype UnixFilename,
    as Str,
    where { m/[\0|\/]/ },
    message { "$_ is not a valid Unix file name" };

And any invalid input catches that message and displays to the user as message box widget.

And now we have a robust solution that both developers and non-developers can easily use.


Shouldn't this fall under the Term or Curses namespace, i.e. Term::Hobocamp or Curses::Hobocamp?

Yeah, apparently top-level project name is becoming more common nowadays. Probably because that's the way it's done in Python and Ruby.

Cool module, BTW.

Leave a comment

About Adam Flott

user-pic I blog about Perl.