File Coverage

bin/wxcat
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             # Copyright (C) 2008 Eric L. Wilhelm
4              
5 1     1   549 use warnings;
  1         3  
  1         42  
6 1     1   6 use strict;
  1         2  
  1         59  
7              
8             =head1 NAME
9              
10             wxcat - pipe output to an unfocussed window
11              
12             =head1 SYNOPSIS
13              
14             This program use wxwidgets to print stdout to a window which does not
15             steal keyboard focus.
16              
17             ssh webserver tail -f error.log | wxcat --size 400x200
18              
19             The window goes away when the output stops (or you can use Ctrl+C.)
20              
21             Extra screen space is recommended.
22              
23             =cut
24              
25             package bin::wxcat;
26              
27 1     1   936 use Wx ();
  0            
  0            
28             use base 'Wx::App';
29              
30             use IO::Handle;
31             use Getopt::Helpful;
32              
33             use Class::Accessor::Classy;
34             ri 'frame';
35             ro 'handle';
36             ri 'closing';
37             no Class::Accessor::Classy;
38              
39             sub main {
40             my (@args) = @_;
41              
42             my %opt = (
43             size => '400x200',
44             scrollbar => 1,
45             );
46             my $hopt = Getopt::Helpful->new(
47             usage => 'foo | CALLER',
48             ['size=s' => \$opt{size}, '400x200', 'WxH size'],
49             # ['scrollbar!', => \$opt{scrollbar}, '', 'use scrollbar'],
50             ['version' => sub {
51             require bin::wxcat;
52             print __PACKAGE__->VERSION, "\n"; exit},
53             '','print package version and exit'],
54             '+help',
55             );
56             $hopt->Get_from(\@args);
57              
58             # TODO open file from @args
59              
60             my $fh = IO::Handle->new;
61             $fh->fdopen(fileno(STDIN), "r");
62             $fh->autoflush;
63              
64             my $app = __PACKAGE__->new(handle => $fh, %opt);
65             $app->MainLoop;
66             }
67             sub new {
68             my $package = shift;
69             my $self = $package->SUPER::new;
70             $self->setup(@_); # ugh
71             return($self);
72             }
73             # this is useless to me because I can't pass arguments to OnInit
74             sub OnInit {1};
75             sub setup {
76             my $self = shift;
77             my %args = @_;
78              
79             $self->{handle} = delete($args{handle});
80              
81             my $frame = $self->set_frame(wxcat::Frame->new(%args));
82             $frame->Show(1);
83              
84             my $fh = $self->handle or die "no handle!";
85             my $text_ctrl = $self->frame->text_ctrl;
86             {
87             my $is = {in => 0};
88             my $closing = 0;
89             Wx::Event::EVT_IDLE($self, sub {
90             my ($obj, $evt) = @_;
91              
92             # Im in ur idle
93             return if($is->{in});
94             local $is->{in} = 1;
95              
96             # and the get-out (TODO a timer?)
97             return if($closing);
98             #warn "idle\n";
99              
100             # now a soft read for the slow pipes
101             $fh->blocking(0);
102             if(! $fh->eof) {
103             $fh->blocking(1);
104             my $line = readline($fh);
105             $text_ctrl->AppendText($line);
106             # warn $line;
107             }
108             else {
109             unless($fh->error) {
110             warn "closing";
111             $closing = 1;
112             for(1..5) {sleep(1); Wx::Yield();}
113             $self->frame->Close; $self->ExitMainLoop;
114             }
115             # warn "eof (", $fh->error, ")";
116             $fh->clearerr;
117             Wx::Yield();
118             use Time::HiRes; Time::HiRes::sleep(0.1);
119             }
120             #Wx::WakeUpIdle(); # XXX wx 2.8.7 differences!
121             $evt->RequestMore;
122             });
123             }
124              
125             }
126              
127             =head1 AUTHOR
128              
129             Eric Wilhelm @
130              
131             http://scratchcomputing.com/
132              
133             =head1 BUGS
134              
135             If you found this module on CPAN, please report any bugs or feature
136             requests through the web interface at L. I will be
137             notified, and then you'll automatically be notified of progress on your
138             bug as I make changes.
139              
140             If you pulled this development version from my /svn/, please contact me
141             directly.
142              
143             =head1 COPYRIGHT
144              
145             Copyright (C) 2008 Eric L. Wilhelm, All Rights Reserved.
146              
147             =head1 NO WARRANTY
148              
149             Absolutely, positively NO WARRANTY, neither express or implied, is
150             offered with this software. You use this software at your own risk. In
151             case of loss, no person or entity owes you anything whatsoever. You
152             have been warned.
153              
154             =head1 LICENSE
155              
156             This program is free software; you can redistribute it and/or modify it
157             under the same terms as Perl itself.
158              
159             =cut
160              
161             ########################################################################
162             package wxcat::Frame;
163              
164             use warnings;
165             use strict;
166              
167             use wxPerl::Constructors;
168             use wxPerl::Styles qw(style wxVal);
169              
170             use base qw(wxPerl::Frame);
171              
172             use Class::Accessor::Classy;
173             ri qw(text_ctrl);
174             no Class::Accessor::Classy;
175              
176             sub new {
177             my $class = shift;
178             my (%opts) = @_;
179             $opts{size} = $opts{size} ? [split('x', $opts{size})] : [400,200],
180              
181             # XXX I can't really do much about this or what?!
182             delete($opts{scrollbar});
183              
184             my $parent;
185             my $title = '';
186             # TODO no_border as an option?
187             my $self = $class->SUPER::new($parent, $title, %opts,
188             style(
189             'stay_on_top|transparent_window',
190             frame => 'no_taskbar',
191             )
192             );
193             # XXX doubt I want to use such a plain text widget
194             $self->set_text_ctrl(wxPerl::TextCtrl->new($self, '',
195             style(
196             te => 'readonly|multiline',
197             ),
198             ));
199             #$self->text_ctrl->EnableScrolling(0,0);
200             $self->text_ctrl->SetScrollbar(&Wx::wxVERTICAL, 0, 0, 0, 1);
201             $self->text_ctrl->SetFont(
202             Wx::Font->new(10, 75, wxVal('normal'), wxVal('bold'), 0, '')
203             );
204              
205             return($self);
206             }
207              
208             ########################################################################
209             package main;
210              
211             if($0 eq __FILE__) {
212             bin::wxcat::main(@ARGV);
213             }
214              
215             # vi:ts=2:sw=2:et:sta
216             my $package = 'bin::wxcat';