FunctionalPerl
view release on metacpan or search on metacpan
lib/FP/Repl/Repl.pm view on Meta::CPAN
# (no sorting necessary)
return $term->completion_matches($text,
$attribs->{list_completion_function})
} else {
# restore defaults.
$attribs->{completion_append_character} = " ";
return ()
}
}
}
our $clear_history = do {
my $did = 0;
sub {
my ($term) = @_;
# Term::ReadLine::Perl does not have clear_history, so, wrap
# it. ->can doesn't work either (lazy loading?), so:
eval {
$term->clear_history;
1
} || do {
warn $@ . "install Term::ReadLine::Gnu if you can" unless $did++;
}
}
};
our ($maybe_input, $maybe_output); # dynamic parametrization of
# filehandles
our $repl_level; # maybe number of repl layers above
our $args; # see '$FP::Repl::Repl::args' in help text
our $argsn; # see '$FP::Repl::Repl::argsn' in help text
# TODO: split this monstrosity into pieces.
sub run {
my ($self, $maybe_skip) = @_;
my $skip = $maybe_skip // 0;
my $stack = FP::Repl::StackPlus->get($skip + 1);
local $repl_level = ($repl_level // -1) + 1;
my $frameno = 0;
my $get_package = sub {
# (What is $$self[Maybe_package] for? Can set the maybe_prompt
# independently. Security feature or just overengineering?
# Ok, remember the ":p" setting; but why not use a lexical
# within `run`? Ok how long-lived are the repl objects, same
# duration? Then hm is the only reason for the object to be
# able to set up things explicitely first? Thus is it ok after
# all?)
my $r = $$self[Maybe_package] || $stack->package($frameno);
$r
};
my $oldsigint = $SIG{INT};
eval {
local $SIG{__DIE__};
# It seems this is the only way to make signal handlers work in
# both perl 5.6 and 5.8:
sigaction SIGINT,
POSIX::SigAction->new(__PACKAGE__ . '::__signalhandler')
or die "Error setting SIGINT handler: $!\n";
1
} || do {
if ($^O eq 'MSWin32') {
# XX will that work?
$SIG{INT} = \&__signalhandler;
} else {
warn "could not set up signal handler: $@ ";
}
};
{
local $SIG{__DIE__};
require Term::ReadLine;
}
# only start one readline instance, do not nest (doing otherwise
# seems to lead to segfaults). okay?.
local our $term = $term || Term::ReadLine->new('Repl');
# This means that the history from nested repls will also show up
# in the history of the parent repl. Not saved, but within the
# readline instance. (Correct?)
# XX: idea: add nesting level to history filename?
my $attribs = $term->Attribs;
my ($INPUT, $OUTPUT, $ERROR) = do {
my $tty = lazy {maybe_tty};
my $in = $self->maybe_input // $maybe_input // force($tty) // $term->IN
// *STDIN;
my $out = $self->maybe_output // $maybe_output // force($tty)
// $term->OUT // *STDOUT;
$term->newTTY($in, $out);
($in, $out, $out)
};
# carry over input/output to subshells:
local $maybe_input = $INPUT;
local $maybe_output = $OUTPUT;
my $printerror_frameno = sub {
my $max = $stack->max_frameno;
print $ERROR "frame number must be between 0..$max",
(@_ ? ", got @_" : ()), "\n";
};
my ($view_with_port, $view_string) = $self->viewers($OUTPUT, $ERROR);
{
my @history;
local $current_history = \@history;
lib/FP/Repl/Repl.pm view on Meta::CPAN
(defined blessed $error)
&& $error->can("plain")
?
# error in plaintext; XX:
# change to better
# thought-out protocol?
$error->plain
: show($error)
);
chomp $err;
$err . "\n"
; # no prefix? no safe way to differentiate.
} else {
if (my $varname
= $$self[Maybe_keepResultIn])
{
$varname
= &$get_package() . "::$varname"
unless $varname =~ /::/;
no strict 'refs';
$$varname
= $self->mode_context eq "1"
? $$results[0]
: $results;
}
&$format_vals(@$results)
}
}
);
$maybe_kept_results = $results
if $$self[DoKeepResultsInVARX];
};
&$evaluator();
} elsif ($$self[DoRepeatWhenEmpty]) {
&$evaluator();
} else {
next;
}
if (length $input
and ((!defined $history[-1]) or $history[-1] ne $input))
{
# XX this is, now that entries are written to disk
# immediately, only used for nested repls (see
# todo above)
push @history, $input;
chomp $input;
$term->addhistory($input);
#splice @history,0,@history-$$self[MaxHistLen] = ();
if ($$self[MaxHistLen] >= 0) { # <-prevent endless loop
shift @history while @history > $$self[MaxHistLen];
}
}
}
}
print $OUTPUT "\n";
$SIG{INT} = defined($oldsigint) ? $oldsigint : "DEFAULT";
# (Is there no other return path from sub run? should I use
# DESTROY objects for this? -> nope, no returns, but if
# exceptions not trapped it would fail)
}
# restore previous history, if any
if ($current_history) {
$clear_history->($term);
for (@$current_history) {
chomp;
$term->addhistory($_);
}
}
}
end Chj::Class::Array;
# for backwards compatibility:
*set_maxhistlen = *set_maxHistLen{CODE};
*set_docatchint = *set_doCatchINT{CODE};
*set_dorepeatwhenempty = *set_doRepeatWhenEmpty{CODE};
*set_maybe_keepresultin = *set_maybe_keepResultIn{CODE};
( run in 1.449 second using v1.01-cache-2.11-cpan-71847e10f99 )