File Coverage

lib/Kephra/App/Panel/Output.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Kephra::App::Panel::Output;
2             our $VERSION = '0.11';
3            
4 1     1   1124 use strict;
  1         4  
  1         42  
5 1     1   6 use warnings;
  1         3  
  1         27  
6 1     1   5 use Cwd();
  1         2  
  1         19  
7 1     1   461 use Wx qw(wxTheClipboard);
  0            
  0            
8             use Wx::Perl::ProcessStream qw(
9             EVT_WXP_PROCESS_STREAM_STDOUT
10             EVT_WXP_PROCESS_STREAM_STDERR
11             EVT_WXP_PROCESS_STREAM_EXIT
12             );
13             use Wx::DND;
14            
15             my $output;
16             my $proc;
17             sub _ref { if (ref $_[0] eq 'Wx::TextCtrl') {$output = $_[0]} else {$output} }
18             sub _config { Kephra::API::settings()->{app}{panel}{output} }
19             sub _splitter { $Kephra::app{splitter}{bottom} }
20             sub _process { $proc }
21             sub is_process { 1 if ref $_[0] eq 'Wx::Perl::ProcessStream::Process' }
22            
23             sub create {
24             my $win = Kephra::App::Window::_ref();
25             my $edit = Kephra::App::EditPanel::_ref();
26             my $output;
27             if (_ref()) {$output = _ref()}
28             else {
29             $output = Wx::TextCtrl->new
30             ($win, -1,'', [-1,-1], [-1,-1],
31             &Wx::wxTE_READONLY|&Wx::wxTE_PROCESS_ENTER|&Wx::wxTE_MULTILINE|&Wx::wxTE_LEFT);
32             }
33             _ref($output);
34             my $config = _config();
35             my $color = \&Kephra::Config::color;
36             $output->SetForegroundColour( &$color( $config->{fore_color} ) );
37             $output->SetBackgroundColour( &$color( $config->{back_color} ) );
38             $output->SetFont( Wx::Font->new
39             ($config->{font_size}, &Wx::wxFONTSTYLE_NORMAL, &Wx::wxNORMAL, &Wx::wxLIGHT, 0,
40             $config->{font_family})
41             );
42             #$output->SetEditable(0);
43            
44             Kephra::EventTable::add_call('panel.output.run', 'panel_output', sub {
45             });
46             Kephra::EventTable::add_call
47             ( 'app.splitter.bottom.changed', 'panel_notepad', sub {
48             if ( get_visibility() and not _splitter()->IsSplit() ) {
49             show( 0 );
50             return;
51             }
52             save_size();
53             });
54            
55             EVT_WXP_PROCESS_STREAM_STDOUT( $win, sub {
56             my ($self, $event) = @_;
57             $event->Skip(1);
58             say( $event->GetLine );
59             } );
60             EVT_WXP_PROCESS_STREAM_STDERR( $win, sub {
61             my ($self, $event) = @_;
62             $event->Skip(1);
63             say( $event->GetLine );
64             } );
65             EVT_WXP_PROCESS_STREAM_EXIT ( $win, sub {
66             my ($self, $event) = @_;
67             $event->Skip(1);
68             $event->GetProcess->Destroy;
69             Kephra::EventTable::trigger('panel.output.run');
70             } );
71             Wx::Event::EVT_LEFT_DOWN($output, sub {
72             my ($op, $event) = @_;
73             unless ($^O =~ /darwin/i) {
74             my ($beside, $col, $row) = $op->HitTest( Wx::Point->new($event->GetX, $event->GetY) );
75             my ($begin, $end) = $op->GetSelection;
76             if ($beside != &Wx::wxTE_HT_UNKNOWN and $begin != $end) {
77             my $pos = $op->XYToPosition($col, $row);
78             copy_selection() if $pos >= $begin and $pos <= $end;
79             }
80             }
81             $event->Skip;
82             });
83             Wx::Event::EVT_MIDDLE_DOWN($output, sub {
84             my ($op, $event) = @_;
85             Kephra::Edit::Search::set_find_item( $op->GetStringSelection() );
86             Kephra::Edit::Search::find_next();
87             });
88             Wx::Event::EVT_KEY_DOWN( $output, sub {
89             my ( $op, $event ) = @_;
90             my $key = $event->GetKeyCode;
91             if ($key == &Wx::WXK_RETURN) {
92             copy_selection();
93             } elsif ($key == &Wx::WXK_F12) {
94             Kephra::App::Panel::Notepad::append( $output->GetStringSelection() )
95             if $event->ShiftDown;
96             }
97             });
98            
99             $output->Show( get_visibility() );
100             $output;
101             }
102            
103             sub get_visibility { _config()->{visible} }
104             sub switch_visibility { show( get_visibility() ^ 1 ) }
105             sub ensure_visibility { switch_visibility() unless get_visibility() }
106             sub show {
107             my $visibile = shift;
108             my $config = _config();
109             $visibile = $config->{visible} unless defined $visibile;
110             my $win = Kephra::App::Window::_ref();
111             my $cpanel = $Kephra::app{panel}{center};
112             my $output = _ref();
113             my $splitter = _splitter();
114             if ($visibile) {
115             $splitter->SplitHorizontally( $cpanel, $output );
116             $splitter->SetSashPosition( -1*$config->{size}, 1);
117             } else {
118             $splitter->Unsplit();
119             $splitter->Initialize( $cpanel );
120             }
121             $output->Show($visibile);
122             $win->Layout;
123             $config->{visible} = $visibile;
124             Kephra::EventTable::trigger('panel.output.visible');
125             }
126            
127             sub save { save_size() }
128             sub save_size {
129             my $splitter = _splitter();
130             return unless $splitter->IsSplit();
131             my $wh=Kephra::App::Window::_ref()->GetSize->GetHeight;
132             _config()->{size} = -1*($wh-($wh-$splitter->GetSashPosition));
133             }
134            
135            
136             sub clear {
137             _ref()->Clear;
138             if (Wx::wxMAC()) {_ref()->SetFont
139             ( Wx::Font->new(_config()->{font_size}, &Wx::wxFONTSTYLE_NORMAL,
140             &Wx::wxNORMAL, &Wx::wxLIGHT, 0, _config()->{font_family})
141             )}
142             }
143             sub print { _ref()->AppendText( $_ ) for @_ }
144             sub say { &print; _ref()->AppendText( "\n" ) }
145             sub new_output {
146             ensure_visibility();
147             _config()->{append}
148             ? &print(_ref()->IsEmpty ? '' : "\n\n")
149             : &clear();
150             &print( @_ );
151             }
152            
153             sub copy_selection {
154             my $selection = _ref()->GetStringSelection();
155             return unless $selection;
156             wxTheClipboard->Open;
157             wxTheClipboard->SetData( Wx::TextDataObject->new( $selection ) );
158             wxTheClipboard->Close;
159            
160             }
161             #
162             sub display_inc { new_output('@INC:'."\n"); &say(" -$_") for @INC }
163             sub display_env {
164             new_output('%ENV:'."\n");
165             &say( " -$_:" . $ENV{$_} ) for sort keys %ENV;
166             }
167             sub display_selection_dec {
168             my $selection = Kephra::Edit::get_selection();
169             return unless defined $selection and $selection;
170             my @output = map { ' ' . $_ } unpack 'C*', $selection;
171             new_output(@output);
172             }
173             sub display_selection_hex {
174             my $selection = Kephra::Edit::get_selection();
175             return unless defined $selection and $selection;
176             my @output = map { sprintf '%3X', $_ } unpack 'C*', $selection;
177             new_output(@output);
178             }
179             # to be outsourced into interpreter plugin
180             sub run {
181             my $win = Kephra::App::Window::_ref();
182             my $doc = Kephra::Document::Data::get_file_path();
183             my $cmd = _config->{interpreter_path};
184             my $dir = Kephra::File::_dir();
185             Kephra::File::save();
186             if ($doc) {
187             my $cwd = Cwd::cwd();
188             chdir $dir;
189             my $proc = Wx::Perl::ProcessStream->OpenProcess
190             (qq~"$cmd" "$doc"~ , 'Interpreter-Plugin', $win); # -I$dir
191             chdir $cwd;
192             new_output();
193             Kephra::EventTable::trigger('panel.output.run');
194             if (not $proc) {}
195             } else {
196             my $l18n = Kephra::Config::Localisation::strings()->{app};
197             Kephra::App::StatusBar::info_msg
198             ($l18n->{menu}{document}.' '.$l18n->{general}{untitled}."\n" );
199             }
200             }
201            
202             sub is_running {
203             my $proc = _process();
204             $proc->IsAlive if is_process($proc);
205             }
206            
207             sub stop {
208             my $proc = _process();
209             if ( is_process($proc) ) {
210             $proc->KillProcess;
211             $proc->TerminateProcess;
212             Kephra::EventTable::trigger('panel.output.run');
213             }
214             }
215            
216             1;
217            
218             =head1 NAME
219            
220             Kephra::App::Panel::Output - output panel
221            
222             =head1 DESCRIPTION
223            
224             =cut