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 |