package Term::GnuScreen;
use Moo;
use File::Temp qw(tmpnam);
use autodie qw(:all);
use File::Which;
use IO::CaptureOutput qw(capture);
our $VERSION = '0.05';
BEGIN {
no strict 'refs';
my @commands = ( qw( acladd aclchg acldel aclgrp aclumask activity addacl allpartial
altscreen at attrcolor autodetach autonuke backtick bce bell_msg
bindkey blanker blankerprg break breaktype bufferfile c1 caption chacl
charset clear colon command compacthist console copy copy_reg
crlf debug defautonuke defbce defbreaktype defc1 defcharset defencoding
defescape defflow defgr defhstatus deflog deflogin defmode defmonitor
defnonblock defobuflimit defscrollback defshell defsilence defslowpaste
defutf8 defwrap defwritelock defzombie detach digraph dinfo displays
dumptermcap echo encoding escape eval fit flow focus gr
hardcopy_append hardcopydir hardstatus height help history hstatus idle
ignorecase info ins_reg lastmsg license lockscreen log logfile login
logtstamp mapdefault mapnotnext maptimeout markkeys maxwin monitor
msgminwait msgwait multiuser nethack next nonblock number obuflimit only
other partial password paste pastefont pow_break pow_detach pow_detach_msg
prev printcmd process quit readbuf readreg redisplay register remove
removebuf reset resize screen scrollback select sessionname setenv setsid
shell shelltitle silence silencewait sleep slowpaste source sorendition
split startup_message stuff su suspend term termcap terminfo termcapinfo
time title unsetenv utf8 vbell vbell_msg vbellwait version wall
width windowlist windows wrap writebuf writelock xoff xon zmodem zombie ) );
for my $name (@commands) {
*{__PACKAGE__ . "::$name"} = sub { shift->send_command($name,@_) }
}
my @rcommands = ( qw( bind kill meta chdir exec umask) );
for my $name (@rcommands) {
*{__PACKAGE__ . "::s$name"} = sub { shift->send_command($name,@_) }
}
}
has session => (is => 'rw' );
has window => (is => 'rw', default => sub { 0 } );
has executable => (is => 'rw', default => sub { which("screen") } );
has create => (is => 'ro', default => sub { 0 } );
has debugging => (is => 'rw', default => sub { 0 } );
sub BUILD {
my ($self) = @_;
if ($self->create) {
if (!$self->session) {
$self->session("term_gnuscreen.$$" . int(rand(10000)));
}
$self->call_screen('-m','-d');
}
return;
}
sub send_command {
my ($self,$cmd,@args) = @_;
die "No command supplied while trying to call screen via -X."
if !$cmd;
return $self->call_screen('-X', $cmd, @args) if $cmd;
}
sub call_screen {
my ($self,@parameter) = @_;
my @screencmd = ( $self->executable );
push @screencmd, '-S', $self->session if defined $self->session;
push @screencmd, '-p', $self->window if defined $self->window;
push @screencmd, @parameter;
if ($self->debugging) {
print STDERR "Command: " . join(" ",@screencmd) . "\n";
}
my ($stdout,$stderr);
eval {
capture { system(@screencmd) } \$stdout, \$stderr;
1;
} or do {
my $err;# = $!;
$err = $stderr if defined $stderr;
$err = $stdout if defined $stdout; # '*err*, stdout seems to be actual more helpful
die "$err";
};
return 1;
}
sub hardcopy {
my ($self,$file) = @_;
if (!$file) {
$file = tmpnam();
}
$self->send_command('hardcopy',$file);
return $file;
}
1;
__END__
=head1 NAME
Term::GnuScreen - control GNU screen
=head1 VERSION
Version 0.05
=head1 SYNOPSIS
Term::GnuScreen provides a simple interface to control a GNU screen
session via its command line interface.
use Term::GnuScreen;
my $screen = Term::GnuScreen->new();
$screen->windowlist;
$screen->hardcopy('/tmp/my_hardcopy');
=head1 CONSTRUCTION
=over 4
=item session
Sets the name of the screen session to which commands are send. If you
also set C<create> to a true value, this will become the new name of your
screen session. See I<-S> option for screen for a further discussion of
this argument.
=item create
If create is set to a true value, a new screen session is created
and detached automatically. If you do not provide a session name via
I<session>, this module generates one by calling C<"term_gnuscreen" . $$
. int(rand(10000))>. Settings this value after object creation has no
effect at the moment.
The newly created session will not be terminated after program execution.
=item window
Preselects a window. Defaults to 0. See I<-p> option of screen for a
further discussion of this argument.
=item executable
Return or set the screen binary to call. Defaults to the binary found
by C<File::Which::which("screen")>.
=item debugging
If debugging is set to a true value, all commands are printed to STDERR.
=back
=head1 METHODS
Term::GnuScreen implements all commands as stated in the texinfo document
shipped with GNU screen. Whenever you call a command it is send via GNU
screens -X parameter to the first running screen session and its current
window. You can change session and window with the according object
methods and construction parameters. Unless listed here, all remaining
arguments are handed over to screen without further modification.
The five commands bind, kill, meta, chdir, exec and umask are prefixed
with a I<s> (sbind, smeta, schdir, sexec and sumask) to distinguish them
from the built-ins with the same name.
=head2 call_screen
This command is the working horse of Term::GnuScreen. It simply builds
the command line to call and execute it.
=head2 send_command
Calls call_screen with the I<-X> and all supplied parameters. Most
functions are implemented by this method.
=head2 hardcopy
Write a hardcopy of the current window to a temporary file and returns
the filename unless the filename is supplied as first argument. If
the supplied filename is not absolute, the file is written relative to
C<hardcopydir>.
=head1 ERROR HANDLING
Simple dies in case screen -X did not return with a return value of
zero. Either $!, STDERR or STDOUT (which seems to be more helpful
most times) are provided as error message for further investigation.
=head1 AUTHOR
Mario Domgoergen E<lt>mdom@cpan.orgE<gt>
=head1 BUGS AND LIMITATIONS
It seems not to be possible to question a specific screen session
about its state, so this module basically just sends commands to a
screen session without knowing if the command succeeded or was even
syntactically correct.
This module needs a lot more testing.
Please report any bugs or feature requests to
C<bug-term-gnuscreen at rt.cpan.org>, or through the web interface
at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Term-GnuScreen>.
I will be notified, and then you'll automatically be notified of progress
on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Term::GnuScreen
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Term-GnuScreen>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/Term-GnuScreen>
=item * CPAN Ratings
L<http://cpanratings.perl.org/d/Term-GnuScreen>
=item * Search CPAN
L<http://search.cpan.org/dist/Term-GnuScreen>
=back
=head1 ACKNOWLEDGEMENTS
L<screen>
=head1 COPYRIGHT & LICENSE
Copyright 2013 Mario Domgoergen, all rights reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.