perlconsole

 view release on metacpan or  search on metacpan

lib/PerlConsole/Console.pm  view on Meta::CPAN

package PerlConsole::Console;

# This class implements all the stuff needed to communicate with 
# the console.
# Either for displaying message in the console (error and verbose stuff)
# or for launcing command, or even changing the console's context.

# dependencies
use strict;
use warnings;
use Term::ReadLine;
use PerlConsole::Preferences;
use PerlConsole::Commands;
use Module::Refresh;
use Lexical::Persistence;
use Getopt::Long;
use B::Keywords qw(@Functions);

# These are all the built-in keywords of Perl
my @perl_keywords = @B::Keywords::Functions;

##############################################################
# Constructor
##############################################################
sub new($@)
{
    my ($class, $version) = @_;

    # the console's data structure
    my $self = {
        version             => $version,
        prefs               => new PerlConsole::Preferences,
        terminal            => new Term::ReadLine("Perl Console"),
        lexical_environment => new Lexical::Persistence,
        rcfile              => $ENV{HOME}.'/.perlconsolerc',
        prompt              => "Perl> ",
        modules             => {},
        logs                => [],
        errors              => [],
    };
    bless ($self, $class);

    # set the readline history if a Gnu terminal
    if ($self->{'terminal'}->ReadLine eq "Term::ReadLine::Gnu") {
        $SIG{'INT'} = sub { $self->clean_exit(0) };
        $self->{'terminal'}->ReadHistory($ENV{HOME} . "/.perlconsole_history");
    }

    # init the completion list with Perl internals...
    $self->addCompletion([@perl_keywords]);

    # ... and with PerlConsole's ones 
    $self->addCompletion([$self->{'prefs'}->getPreferences]);
    foreach my $pref ($self->{'prefs'}->getPreferences) {
        $self->addCompletion($self->{'prefs'}->getValidValues($pref));
    }
    # FIXME : we'll have to rewrite the commands stuff in a better way
    $self->addCompletion([qw(:quit :set :help)]);
    # the console's ready!
    return $self;
}

# This is where we define all the options supported
# on the command-line
sub parse_options
{
    my ($self) = @_;
    GetOptions('rcfile=s' => \$self->{rcfile});
    
    # cleanup of the ~ shortcut for $ENV{HOME}
    my $home = $ENV{HOME};
    $self->{rcfile} =~ s/^~/${home}/;
}

# method for exiting properly and flushing the history
sub clean_exit($$)
{
    my ($self, $status) = @_;
    if ($self->{'terminal'}->ReadLine eq "Term::ReadLine::Gnu") {
        $self->{'terminal'}->WriteHistory($ENV{HOME} . "/.perlconsole_history");
    }
    exit $status;
}

##############################################################
# Terminal
##############################################################

sub addCompletion($$)
{
    my ($self, $ra_list) = @_;
    my $attribs = $self->{'terminal'}->Attribs;
    $attribs->{completion_entry_function} = $attribs->{list_completion_function};
    if (! defined $attribs->{completion_word}) {
        $attribs->{completion_word} = $ra_list;
    }
    else {
        foreach my $elem (@{$ra_list}) {
            push @{$attribs->{completion_word}}, $elem;
        }
    }
}

sub is_completion
{
    my ($self, $item) = @_;
    my $attribs = $self->{'terminal'}->Attribs;
    return grep /^${item}$/, @{$attribs->{completion_word}};
}

sub getInput
{
    my ($self) = @_;
    return $self->{'terminal'}->readline($self->{'prompt'});
}

lib/PerlConsole/Console.pm  view on Meta::CPAN


sub message
{
    my ($self, $string) = @_;
    if (! defined $string) {
        print "undef\n";
    }
    else {
        chomp $string;
        print "$string\n";
    }
}

# time 
sub getTime($)
{
    my ($self) = @_;
    my ($sec, $min, $hour, 
        $mday, $mon, $year, 
        $wday, $yday, $isdst) = localtime(time);
    $mon++;
    $year += 1900;
    $mon = sprintf("%02d", $mon);
    $mday = sprintf("%02d", $mday);
    return "$year-$mon-$mday $hour:$mon:$sec";
}

# push a log message on the top of the stack
sub addLog($$)
{
    my ($self, $log) = @_;
    push @{$self->{'logs'}}, "[".$self->getTime."] $log";
}

# get the last log message and remove it
sub getLog($)
{
    my ($self) = @_;
    my $log = $self->{'logs'}[$#{$self->{'logs'}}];
    pop @{$self->{'logs'}};
    return $log;
}

# Return the list of all unread log message and empty it
sub getLogs
{
    my ($self) = @_;
    my $logs = $self->{'logs'};
    $self->{'logs'} = [];
    return $logs;
}

##############################################################
# Preferences
##############################################################

# accessors for the encapsulated preference object
sub setPreference($$$)
{
    my ($self, $pref, $value) = @_;
    my $prefs = $self->{'prefs'};
    $self->addLog("setPreference: $pref = $value");
    return $prefs->set($pref, $value);
}

sub getPreference($$)
{
    my ($self, $pref) = @_;
    my $prefs = $self->{'prefs'};
    my $val = $prefs->get($pref);
    return $val;
}

# set the output and take care to load the appropriate module
# for the output
sub setOutput($$)
{
    my ($self, $output) = @_;
    my $rh_output_modules = {
        'yaml'   => 'YAML',
        'dumper' => 'Data::Dumper',
        'dump'   => 'Data::Dump',
        'dds'    => 'Data::Dump::Streamer',
    };
    
    if (exists $rh_output_modules->{$output}) {
        my $module = $rh_output_modules->{$output};
        unless ($self->load($module)) {
            $self->error("Unable to load module \"$module\", ".
                "cannot use output mode \"$output\"");
            return 0;
        }
    }
    
    unless ($self->setPreference("output", $output)) {
        $self->error("unable to set preference output to \"$output\"");
        return 0;
    }

    return 1;
}

# this interprets a string, it calls the appropriate internal 
# function to deal with the provided string
sub interpret($$)
{
    my ($self, $code) = @_;

    # cleanup a bit the input string
    chomp $code;
    return unless length $code;

    # look for the exit command.
    $self->clean_exit(0) if $code =~ /(:quit|exit)/i;

    # look for console's internal language
    return if $self->command($code);

    # look for a module to import
    return if $self->useModule($code);

    # Refresh the loaded modules in @INC that have changed
    Module::Refresh->refresh;

    # looks like it's time to evaluates some code ;)
    $self->print_result($self->evaluate($code));
    print "\n";
    
    # look for something to save in the completion list
    $self->learn($code);



( run in 0.636 second using v1.01-cache-2.11-cpan-98e64b0badf )