working automatic prompting
[scpubgit/Object-Remote.git] / lib / Object / Remote / Role / Connector / PerlInterpreter.pm
1 package Object::Remote::Role::Connector::PerlInterpreter;
2
3 use IPC::Open2;
4 use IO::Handle;
5 use Object::Remote::ModuleSender;
6 use Object::Remote::Handle;
7 use Scalar::Util qw(blessed);
8 use Moo::Role;
9
10 with 'Object::Remote::Role::Connector';
11
12 has module_sender => (is => 'lazy');
13
14 sub _build_module_sender {
15   my ($hook) =
16     grep {blessed($_) && $_->isa('Object::Remote::ModuleLoader::Hook') }
17       @INC;
18   return $hook ? $hook->sender : Object::Remote::ModuleSender->new;
19 }
20
21 around connect => sub {
22   my ($orig, $self) = (shift, shift);
23   my $conn = $self->$orig(@_);
24   Object::Remote::Handle->new(
25     connection => $conn,
26     class => 'Object::Remote::ModuleLoader',
27     args => { module_sender => $self->module_sender }
28   )->disarm_free;
29   require Object::Remote::Prompt;
30   Object::Remote::Prompt::maybe_set_prompt_command_on($conn);
31   return $conn;
32 };
33
34 sub _perl_command { 'perl', '-' }
35
36 sub _start_perl {
37   my $self = shift;
38   my $pid = open2(
39     my $foreign_stdout,
40     my $foreign_stdin,
41     $self->_perl_command(@_),
42   ) or die "Failed to run perl at '$_[0]': $!";
43   return ($foreign_stdin, $foreign_stdout, $pid);
44 }
45
46 sub _open2_for {
47   my $self = shift;
48   my ($foreign_stdin, $foreign_stdout, $pid) = $self->_start_perl(@_);
49   $foreign_stdin->autoflush(1);
50   print $foreign_stdin 'BEGIN { $ENV{OBJECT_REMOTE_DEBUG} = 1 }'."\n"
51     if $ENV{OBJECT_REMOTE_DEBUG};
52   print $foreign_stdin $self->fatnode_text
53     or die "Failed to send fatpacked data to new node on '$_[0]': $!";
54   return ($foreign_stdin, $foreign_stdout, $pid);
55 }
56
57 sub fatnode_text {
58   my ($self) = @_;
59   require Object::Remote::FatNode;
60   my $text = '';
61   $text .= 'BEGIN { $ENV{OBJECT_REMOTE_DEBUG} = 1 }'."\n"
62     if $ENV{OBJECT_REMOTE_DEBUG};
63   $text .= <<'END';
64 $INC{'Object/Remote/FatNode.pm'} = __FILE__;
65 $Object::Remote::FatNode::DATA = <<'ENDFAT';
66 END
67   $text .= $Object::Remote::FatNode::DATA;
68   $text .= "ENDFAT\n";
69   $text .= <<'END';
70 eval $Object::Remote::FatNode::DATA;
71 END
72   $text .= "__END__\n";
73   return $text;
74 }
75
76 1;