Goo::ConfigFile - Parse and load .goo files. Based loosely on .ini files.


Goo documentation Contained in the Goo distribution.

Index


Code Index:

NAME

Top

Goo::ConfigFile - Parse and load .goo files. Based loosely on .ini files.

SYNOPSIS

Top

use Goo::ConfigFile;

DESCRIPTION

Top

All Things have a corresponding ".goo" file based on their file suffix. Perl modules, for example, have the configuration file "pm.goo", scripts "pl.goo", Javascript files "js.goo", log files "log.goo" and Goo configuration files "goo.goo".

All .goo files are stored in the user's home directory: ~/.goo/things/goo/.

A .goo configuration file includes a list of actions (e.g., E[X]it) and an action handler (e.g., Exiter.pm). For file-based Things (see Goo::FileThing) the configuration file includes a "location" field(s) where Things of this type can be found.

For database Things (see Goo::DatabaseThing) the configuration file includes a "table" field where Things of this type can be found.

Each action specified in .goo file contain an action letter in square brackets (e.g., [E]dit). This letter can be used directly on the command line to invoke the action handler on the Thing (e.g., goo -e Object.pm).

METHODS

Top

new

constructor

get_action_handler

return the action handler for a given command

has_locations

does it have any directory locations?

get_locations

return a list of all the directory locations found in the config file

parse

slurp in a .goo config file and parse it

write_to_file

very simplistic writer for single key value additions

get_program

return the program that handles an action

get_commands

return all the commands for this config file

has_table

does it have a database "table"?

AUTHOR

Top

Nigel Hamilton <nigel@trexy.com>

SEE ALSO

Top


Goo documentation Contained in the Goo distribution.

package Goo::ConfigFile;

###############################################################################
# Nigel Hamilton
#
# Copyright Nigel Hamilton 2005
# All Rights Reserved
#
# Author:       Nigel Hamilton
# Filename:     Goo::ConfigFile.pm
# Description:  Goo Config - parse .goo files. Based loosely on .ini files.
#               We want # comments and fields = values
#
# Date          Change
# -----------------------------------------------------------------------------
# 30/07/2005    Realised this was not going to be good enough
# 17/10/2005    Added method: getProgram
#
###############################################################################

use strict;

use File::Find;
use Goo::List;
use Goo::Object;
use Data::Dumper;
use Goo::Prompter;
use Goo::FileUtilities;
use base qw(Goo::Object);

my $GOO_ROOT = "$ENV{HOME}/.goo/things";


###############################################################################
#
# new - return a goo_config_file
#
###############################################################################

sub new {

    my ($class, $filename) = @_;

    # strip the path
    $filename =~ s/.*\///;

    my $this = $class->SUPER::new();

    unless ($filename =~ /\.goo$/) {
        die("Invalid Goo config file. $filename must end with .goo.");
    }

    my $full_path = $GOO_ROOT . '/goo/' . $filename;

    unless (-e $full_path) {
        Goo::Prompter::say("No Goo configuration file found for $full_path.");
        Goo::Prompter::say("To make a new type of Thing enter: goo -m $filename.");
        exit;
    }

    $this->parse($full_path);

    return $this;

}


###############################################################################
#
# get_action_handler - return the handler for this command
#
###############################################################################

sub get_action_handler {

    my ($this, $command) = @_;

    # return the action handler for this command
    return $this->{commands}->{$command};

}


###############################################################################
#
# has_locations - does it have any
#
###############################################################################

sub has_locations {

    my ($this) = @_;

    # return the locations for this Thing!
    return ref($this->{locations}) eq "ARRAY";

}


###############################################################################
#
# get_locations - return a list of all the locations of the config file
#
###############################################################################

sub get_locations {

    my ($this) = @_;

    # return the locations for this Thing!
    return @{ $this->{locations} }
        if ($this->has_locations());

    # other return nothing
    return undef;

}


###############################################################################
#
# parse - slurp in a file and parse it
#
###############################################################################

sub parse {

    my $this      = shift;    # ARG1: get object reference
    my $full_path = shift;    # ARG2: get full path to *.goo cfg file

    my @locations;

    my $location_finder = sub {    # define anonymous sub
                                   # for File::Find
        my $subdir = $File::Find::name;    # memoize current file
        push @locations, $subdir if (-d $subdir);    # add if directory

    };

    # parse the config file line by line
    for my $line (Goo::FileUtilities::get_file_as_lines($full_path)) {
        next
            if ($line =~ /^\s*\#/ or                     # skip commented out or
                $line =~ /^\s*$/);                                    # empty lines

        # strip whitespace
        $line =~ s/\s*=\s*/=/;
        $line =~ s/^\s+//;
        $line =~ s/\s+$//;

        # split out key value pairs
        my ($field, $value) = split(/=/, $line);

        if ($field =~ /location/) {

            # field is a location entry
            $value = "$ENV{HOME}/.goo/$value"
                if ($value !~ /^\//);    # prepend ~/.goo if relative path
            $value = "$ENV{HOME}/.goo" if ($value eq '~');    # put in ~/.goo if "tilde" given
            &find($location_finder, $value);              # recursive directory finder

        } elsif ($field =~ /\[(.)\]/) {                   # field is a command
            my $letter = $1;                              # match the command letter

            if ($letter !~ /[A-Z\d]/) {
                die("Invalid command [$letter] in config file: $full_path. Commands must be uppercase."
                   );
            }

            # [E]dit = $this->{actions}->{E}->{command} = "[E]dit";
            $this->{actions}->{$letter}->{command} = $field;

            # [E]dit = $this->{actions}->{E}->{action}  = "ProgramEditor";
            $this->{actions}->{$letter}->{action} = $value;

            # remember the full command string too
            $this->{commands}->{$field} = $value;

        } else {
            $this->{$field} = $value;
        }
    }

    # make sure we only have unique locations
    if (scalar(@locations) > 0) {

        my @unique_list = Goo::List::get_unique(@locations);
        $this->{locations} = \@unique_list;

    }

}


###############################################################################
#
# write_to_file - very simple writer for single key value additions
#
###############################################################################

sub write_to_file {

    my ($filename, $key, $value) = @_;

    my $full_path = $GOO_ROOT . "/" . $filename;

    # get all the lines that don't match the key
    my @lines = grep { $_ !~ /^$key/ } Goo::FileUtilities::get_file_as_lines($full_path);

    # add the new value for the key
    push(@lines, "$key \t = \t $value \n");

    # save the file
    Goo::FileUtilities::write_lines_as_file($full_path, @lines);

}


###############################################################################
#
# get_program - return the program that handles an action
#
###############################################################################

sub get_program {

    my ($this, $letter) = @_;

    return $this->{actions}->{$letter}->{action};

}


###############################################################################
#
# get_commands - return all the commands for this config file
#
###############################################################################

sub get_commands {

    my ($this) = @_;

    return keys %{ $this->{commands} };

}


###############################################################################
#
# has_table - does it have a database "table"
#
###############################################################################

sub has_table {

    my ($this) = @_;

    # has a table field been defined for this Thing?
    return exists $this->{table};

}

1;



__END__