line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package CodeGen::Cpppp::Template; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $VERSION = '0.001_04'; # TRIAL VERSION |
4
|
|
|
|
|
|
|
# ABSTRACT: Template objects created by parsing and compiling cpppp |
5
|
|
|
|
|
|
|
|
6
|
7
|
|
|
7
|
|
88
|
use v5.20; |
|
7
|
|
|
|
|
36
|
|
7
|
7
|
|
|
7
|
|
36
|
use warnings; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
184
|
|
8
|
7
|
|
|
7
|
|
37
|
use Carp; |
|
7
|
|
|
|
|
24
|
|
|
7
|
|
|
|
|
458
|
|
9
|
7
|
|
|
7
|
|
87
|
use experimental 'signatures', 'postderef'; |
|
7
|
|
|
|
|
20
|
|
|
7
|
|
|
|
|
43
|
|
10
|
7
|
|
|
7
|
|
1144
|
use Scalar::Util 'looks_like_number'; |
|
7
|
|
|
|
|
17
|
|
|
7
|
|
|
|
|
460
|
|
11
|
7
|
|
|
7
|
|
4803
|
use Hash::Util; |
|
7
|
|
|
|
|
21545
|
|
|
7
|
|
|
|
|
42
|
|
12
|
7
|
|
|
7
|
|
3596
|
use CodeGen::Cpppp::Output; |
|
7
|
|
|
|
|
18
|
|
|
7
|
|
|
|
|
308
|
|
13
|
7
|
|
|
7
|
|
2950
|
use CodeGen::Cpppp::AntiCharacter; |
|
7
|
|
|
|
|
21
|
|
|
7
|
|
|
|
|
194
|
|
14
|
7
|
|
|
7
|
|
44
|
use Exporter (); |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
203
|
|
15
|
|
|
|
|
|
|
require version; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use constant { |
18
|
7
|
|
|
|
|
2519
|
PUBLIC => 'public', |
19
|
|
|
|
|
|
|
PROTECTED => 'protected', |
20
|
|
|
|
|
|
|
PRIVATE => 'private', |
21
|
7
|
|
|
7
|
|
37
|
}; |
|
7
|
|
|
|
|
17
|
|
22
|
|
|
|
|
|
|
our @EXPORT_OK= qw( PUBLIC PROTECTED PRIVATE ); |
23
|
|
|
|
|
|
|
our %EXPORT_TAGS= ( |
24
|
|
|
|
|
|
|
'v0' => \@EXPORT_OK, |
25
|
|
|
|
|
|
|
); |
26
|
15
|
|
|
15
|
|
28
|
sub _tag_for_version($ver) { |
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
22
|
|
27
|
15
|
|
|
|
|
60
|
return ':v0'; |
28
|
|
|
|
|
|
|
} |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub import { |
31
|
22
|
|
|
22
|
|
54
|
my $class= $_[0]; |
32
|
22
|
|
|
|
|
56
|
my $caller= caller; |
33
|
22
|
|
|
|
|
95
|
for (my $i= 1; $i < @_; $i++) { |
34
|
15
|
50
|
|
|
|
64
|
if ($_[$i] eq '-setup') { |
35
|
15
|
|
|
|
|
197
|
my $ver= version->parse($_[$i+1]); |
36
|
15
|
|
|
|
|
91
|
splice(@_, $i, 2, _tag_for_version($ver)); |
37
|
15
|
|
|
|
|
57
|
$class->_setup_derived_package($caller, $ver); |
38
|
|
|
|
|
|
|
} |
39
|
|
|
|
|
|
|
} |
40
|
22
|
|
|
|
|
47495
|
goto \&Exporter::import; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
our $_next_pkg= 1; |
44
|
15
|
|
|
15
|
|
33
|
sub _create_derived_package($class, $version, $parse_data) { |
|
15
|
|
|
|
|
35
|
|
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
23
|
|
45
|
15
|
|
|
|
|
43
|
my $pkg= 'CodeGen::Cpppp::Template::_'.$_next_pkg++; |
46
|
7
|
|
|
7
|
|
53
|
no strict 'refs'; |
|
7
|
|
|
|
|
15
|
|
|
7
|
|
|
|
|
2785
|
|
47
|
15
|
|
|
|
|
35
|
@{"${pkg}::ISA"}= ( $class ); |
|
15
|
|
|
|
|
360
|
|
48
|
15
|
|
|
|
|
53
|
${"${pkg}::_parse_data"}= $parse_data; |
|
15
|
|
|
|
|
104
|
|
49
|
|
|
|
|
|
|
# Create accessors for all of the attributes declared in the template. |
50
|
15
|
|
|
|
|
69
|
for (keys $parse_data->{template_parameter}->%*) { |
51
|
13
|
|
|
|
|
28
|
my $name= $_; |
52
|
13
|
|
|
8
|
|
39
|
*{"${pkg}::$name"}= sub { $_[0]{$name} }; |
|
13
|
|
|
|
|
97
|
|
|
8
|
|
|
|
|
37
|
|
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
# Expose all of the functions declared in the template |
55
|
15
|
|
|
|
|
57
|
for (keys $parse_data->{template_method}->%*) { |
56
|
3
|
|
|
|
|
7
|
my $name= $_; |
57
|
3
|
|
|
|
|
32
|
*{"${pkg}::$name"}= sub { |
58
|
2
|
50
|
|
2
|
|
1445
|
my $m= shift->{template_method}{$name} |
59
|
|
|
|
|
|
|
or croak "Template execution did not define method '$name'"; |
60
|
2
|
|
|
|
|
7
|
goto $m; |
61
|
3
|
|
|
|
|
15
|
}; |
62
|
|
|
|
|
|
|
} |
63
|
15
|
|
|
|
|
52
|
$pkg; |
64
|
|
|
|
|
|
|
} |
65
|
|
|
|
|
|
|
|
66
|
15
|
|
|
15
|
|
30
|
sub _setup_derived_package($class, $pkg, $version) { |
|
15
|
|
|
|
|
28
|
|
|
15
|
|
|
|
|
20
|
|
|
15
|
|
|
|
|
23
|
|
|
15
|
|
|
|
|
20
|
|
67
|
15
|
|
|
|
|
95
|
strict->import; |
68
|
15
|
|
|
|
|
131
|
warnings->import; |
69
|
15
|
|
|
|
|
79
|
utf8->import; |
70
|
15
|
|
|
|
|
153
|
experimental->import(qw( lexical_subs signatures postderef )); |
71
|
|
|
|
|
|
|
|
72
|
7
|
|
|
7
|
|
56
|
no strict 'refs'; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
1469
|
|
73
|
15
|
50
|
|
|
|
2010
|
@{"${pkg}::ISA"}= ( $class ) unless @{"${pkg}::ISA"}; |
|
0
|
|
|
|
|
0
|
|
|
15
|
|
|
|
|
141
|
|
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
15
|
|
|
15
|
|
35
|
sub _gen_perl_scope_functions($class, $version) { |
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
25
|
|
|
15
|
|
|
|
|
20
|
|
77
|
|
|
|
|
|
|
return ( |
78
|
15
|
|
|
|
|
418
|
'# line '. __LINE__ . ' "' . __FILE__ . '"', |
79
|
|
|
|
|
|
|
'my sub param { unshift @_, $self; goto $self->can("_init_param") }', |
80
|
|
|
|
|
|
|
'my sub define { unshift @_, $self; goto $self->can("define_template_macro") }', |
81
|
|
|
|
|
|
|
'my sub section { unshift @_, $self; goto $self->can("current_output_section") }', |
82
|
|
|
|
|
|
|
'my sub template { unshift @_, $self->context; goto $self->context->can("new_template") }', |
83
|
|
|
|
|
|
|
'my $trim_comma= CodeGen::Cpppp::AntiCharacter->new(qr/,/, qr/\s*/);', |
84
|
|
|
|
|
|
|
'my $trim_ws= CodeGen::Cpppp::AntiCharacter->new(qr/\s*/);', |
85
|
|
|
|
|
|
|
); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
61
|
|
|
61
|
|
93
|
sub _parse_data($class) { |
|
61
|
|
|
|
|
93
|
|
|
61
|
|
|
|
|
80
|
|
89
|
61
|
100
|
|
|
|
147
|
$class = ref $class if ref $class; |
90
|
7
|
|
|
7
|
|
54
|
no strict 'refs'; |
|
7
|
|
|
|
|
26
|
|
|
7
|
|
|
|
|
910
|
|
91
|
61
|
|
|
|
|
93
|
return ${"${class}::_parse_data"}; |
|
61
|
|
|
|
|
279
|
|
92
|
|
|
|
|
|
|
} |
93
|
|
|
|
|
|
|
|
94
|
6
|
|
|
6
|
0
|
41
|
sub context { $_[0]{context} } |
95
|
|
|
|
|
|
|
|
96
|
24
|
|
|
24
|
0
|
1644
|
sub new($class, @args) { |
|
24
|
|
|
|
|
43
|
|
|
24
|
|
|
|
|
43
|
|
|
24
|
|
|
|
|
32
|
|
97
|
7
|
|
|
7
|
|
49
|
no strict 'refs'; |
|
7
|
|
|
|
|
14
|
|
|
7
|
|
|
|
|
19303
|
|
98
|
24
|
50
|
66
|
|
|
159
|
my %attrs= @args == 1 && ref $args[0]? $args[0]->%* |
|
|
100
|
|
|
|
|
|
99
|
|
|
|
|
|
|
: !(@args&1)? @args |
100
|
|
|
|
|
|
|
: croak "Expected even-length list or hashref"; |
101
|
24
|
|
|
|
|
87
|
my $parse= $class->_parse_data; |
102
|
|
|
|
|
|
|
# Make sure each attr is the correct type of ref, for the params. |
103
|
24
|
|
|
|
|
72
|
for (keys %attrs) { |
104
|
18
|
100
|
|
|
|
45
|
if (my $p= $parse->{template_parameter}{$_}) { |
105
|
10
|
100
|
|
|
|
56
|
if ($p eq '@') { ref $attrs{$_} eq 'ARRAY' or croak("Expected ARRAY for parameter $_"); } |
|
2
|
100
|
|
|
|
237
|
|
|
|
100
|
|
|
|
|
|
106
|
3
|
100
|
|
|
|
110
|
elsif ($p eq '%') { ref $attrs{$_} eq 'HASH' or croak("Expected HASH for parameter $_"); } |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
else { |
109
|
8
|
50
|
|
|
|
44
|
croak("Unknown parameter '$_' to template $parse->{filename}") |
110
|
|
|
|
|
|
|
unless $class->can($_); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
my $self= bless { |
115
|
22
|
|
|
|
|
237
|
(map +($_ => $parse->{$_}), qw( |
116
|
|
|
|
|
|
|
autocomma autoindent autostatementline autocolumn |
117
|
|
|
|
|
|
|
context |
118
|
|
|
|
|
|
|
)), |
119
|
|
|
|
|
|
|
output => CodeGen::Cpppp::Output->new, |
120
|
|
|
|
|
|
|
current_output_section => 'private', |
121
|
|
|
|
|
|
|
%attrs, |
122
|
|
|
|
|
|
|
}, $class; |
123
|
|
|
|
|
|
|
Scalar::Util::weaken($self->{context}) |
124
|
22
|
100
|
|
|
|
137
|
if $self->{context}; |
125
|
22
|
|
|
|
|
197
|
$self->BUILD(\%attrs); |
126
|
22
|
|
|
|
|
226
|
$self; |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
0
|
|
|
0
|
0
|
0
|
sub coerce_parameters($class, $params) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
130
|
0
|
|
|
|
|
0
|
my %ret; |
131
|
0
|
|
|
|
|
0
|
my $parse= $class->_parse_data; |
132
|
0
|
|
|
|
|
0
|
for my $k (keys $parse->{template_parameter}->%*) { |
133
|
0
|
|
|
|
|
0
|
my $p= $parse->{template_parameter}{$k}; |
134
|
0
|
|
0
|
|
|
0
|
my $v= $params->{$p.$k} // $params->{$k}; |
135
|
0
|
0
|
|
|
|
0
|
next unless defined $v; |
136
|
0
|
0
|
|
|
|
0
|
if ($p eq '@') { |
|
|
0
|
|
|
|
|
|
137
|
0
|
0
|
|
|
|
0
|
$v= ref $v eq 'HASH'? [ keys %$v ] : [ $v ] |
|
|
0
|
|
|
|
|
|
138
|
|
|
|
|
|
|
unless ref $v eq 'ARRAY'; |
139
|
|
|
|
|
|
|
} elsif ($p eq '%') { |
140
|
|
|
|
|
|
|
# If it isn't a hash, treat it like a list that needs added to a set |
141
|
0
|
0
|
|
|
|
0
|
$v= { map +($_ => 1), ref $v eq 'ARRAY'? @$v : ($v) } |
|
|
0
|
|
|
|
|
|
142
|
|
|
|
|
|
|
unless ref $v eq 'HASH'; |
143
|
|
|
|
|
|
|
} |
144
|
0
|
|
|
|
|
0
|
$ret{$k}= $v; |
145
|
|
|
|
|
|
|
} |
146
|
0
|
|
|
|
|
0
|
\%ret; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
9
|
|
|
9
|
0
|
17
|
sub current_output_section($self, $new=undef) { |
|
9
|
|
|
|
|
13
|
|
|
9
|
|
|
|
|
14
|
|
|
9
|
|
|
|
|
14
|
|
150
|
9
|
50
|
|
|
|
21
|
if (defined $new) { |
151
|
9
|
50
|
|
|
|
24
|
$self->output->has_section($new) |
152
|
|
|
|
|
|
|
or croak "No defined output section '$new'"; |
153
|
9
|
|
|
|
|
28
|
$self->_finish_render; |
154
|
9
|
|
|
|
|
18
|
$self->{current_output_section}= $new; |
155
|
|
|
|
|
|
|
} |
156
|
9
|
|
|
|
|
20
|
$self->{current_output_section}; |
157
|
|
|
|
|
|
|
} |
158
|
|
|
|
|
|
|
|
159
|
30
|
|
|
30
|
0
|
45
|
sub flush($self) { |
|
30
|
|
|
|
|
42
|
|
|
30
|
|
|
|
|
44
|
|
160
|
30
|
|
|
|
|
97
|
$self->_finish_render; |
161
|
30
|
|
|
|
|
132
|
$self; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
27
|
|
|
27
|
0
|
2317
|
sub output($self) { |
|
27
|
|
|
|
|
44
|
|
|
27
|
|
|
|
|
37
|
|
165
|
27
|
|
|
|
|
108
|
$self->flush->{output}; |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
28
|
|
|
28
|
|
63
|
sub _init_param($self, $name, $ref, @initial_value) { |
|
28
|
|
|
|
|
45
|
|
|
28
|
|
|
|
|
36
|
|
|
28
|
|
|
|
|
38
|
|
|
28
|
|
|
|
|
53
|
|
|
28
|
|
|
|
|
43
|
|
169
|
28
|
100
|
|
|
|
64
|
if (exists $self->{$name}) { |
170
|
|
|
|
|
|
|
# Assign the value received from constructor to the variable in the template |
171
|
|
|
|
|
|
|
ref $ref eq 'SCALAR'? ($$ref= $self->{$name}) |
172
|
1
|
50
|
|
|
|
5
|
: ref $ref eq 'ARRAY' ? (@$ref= @{$self->{$name} || []}) |
173
|
8
|
50
|
|
|
|
36
|
: ref $ref eq 'HASH' ? (%$ref= %{$self->{$name} || {}}) |
|
2
|
50
|
|
|
|
12
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
174
|
|
|
|
|
|
|
: croak "Unhandled ref type ".ref($ref); |
175
|
|
|
|
|
|
|
} else { |
176
|
20
|
50
|
|
|
|
65
|
ref $ref eq 'SCALAR'? ($$ref= $initial_value[0]) |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
177
|
|
|
|
|
|
|
: ref $ref eq 'ARRAY' ? (@$ref= @initial_value) |
178
|
|
|
|
|
|
|
: ref $ref eq 'HASH' ? (%$ref= @initial_value) |
179
|
|
|
|
|
|
|
: croak "Unhandled ref type ".ref($ref); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# Now store the variable of the template directly into this hash |
183
|
|
|
|
|
|
|
ref $ref eq 'SCALAR'? Hash::Util::hv_store(%$self, $name, $$ref) |
184
|
28
|
100
|
|
|
|
106
|
: ($self->{$name}= $ref); |
185
|
28
|
|
|
|
|
64
|
$ref; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
0
|
|
|
0
|
0
|
0
|
sub define_template_macro($self, $name, $code) { |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
189
|
0
|
|
|
|
|
0
|
$self->{template_macro}{$name}= $code; |
190
|
|
|
|
|
|
|
} |
191
|
|
|
|
|
|
|
|
192
|
3
|
|
|
3
|
0
|
26
|
sub define_template_method($self, $name, $code) { |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
5
|
|
193
|
3
|
|
|
|
|
24
|
$self->{template_method}{$name}= $code; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
39
|
|
|
39
|
|
50
|
sub _finish_render($self) { |
|
39
|
|
|
|
|
57
|
|
|
39
|
|
|
|
|
50
|
|
197
|
39
|
100
|
|
|
|
100
|
return unless defined $self->{current_out}; |
198
|
|
|
|
|
|
|
# Second pass, adjust whitespace of all column markers so they line up. |
199
|
|
|
|
|
|
|
# Iterate from leftmost column rightward. |
200
|
30
|
|
|
|
|
48
|
for my $group_i (sort { $a <=> $b } keys %{$self->{current_out_colgroup_state}}) { |
|
1
|
|
|
|
|
7
|
|
|
30
|
|
|
|
|
126
|
|
201
|
|
|
|
|
|
|
delete $self->{current_out_colgroup_state}{$group_i} |
202
|
4
|
50
|
|
|
|
15
|
if $self->{current_out_colgroup_state}{$group_i} == 2; |
203
|
4
|
|
|
|
|
10
|
my $token= _colmarker($group_i); |
204
|
|
|
|
|
|
|
# Find the longest prefix (excluding trailing whitespace) |
205
|
|
|
|
|
|
|
# Also find the max number of digits following column. |
206
|
4
|
|
|
|
|
13
|
my ($maxcol, $maxdigit)= (0,0); |
207
|
4
|
|
|
|
|
7
|
my ($linestart, $col); |
208
|
4
|
|
|
|
|
177
|
while ($self->{current_out} =~ /[ ]* $token (-? 0x[A-Fa-f0-9]+ | -? \d+)? /gx) { |
209
|
20
|
|
|
|
|
102
|
$linestart= rindex($self->{current_out}, "\n", $-[0])+1; |
210
|
20
|
|
|
|
|
67
|
$col= $-[0] - $linestart; |
211
|
20
|
100
|
|
|
|
40
|
$maxcol= $col if $col > $maxcol; |
212
|
20
|
100
|
100
|
|
|
169
|
$maxdigit= length $1 if defined $1 && length $1 > $maxdigit; |
213
|
|
|
|
|
|
|
} |
214
|
4
|
|
|
|
|
135
|
$self->{current_out} =~ s/[ ]* $token (?= (-? 0x[A-Fa-f0-9]+ | -? \d+)? )/ |
215
|
20
|
|
|
|
|
124
|
$linestart= rindex($self->{current_out}, "\n", $-[0])+1; |
216
|
20
|
100
|
|
|
|
187
|
" "x(1 + $maxcol - ($-[0] - $linestart) + ($1? $maxdigit - length($1) : 0)) |
217
|
|
|
|
|
|
|
/gex; |
218
|
|
|
|
|
|
|
} |
219
|
30
|
|
|
|
|
127
|
$self->{output}->append($self->{current_output_section} => $self->{current_out}); |
220
|
30
|
|
|
|
|
65
|
$self->{current_out}= ''; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
|
223
|
13
|
|
|
13
|
|
22
|
sub _colmarker($colgroup_id) { join '', "\x{200A}", map chr(0x2000+$_), split //, $colgroup_id; } |
|
13
|
|
|
|
|
20
|
|
|
13
|
|
|
|
|
16
|
|
|
13
|
|
|
|
|
125
|
|
224
|
0
|
0
|
0
|
0
|
|
0
|
sub _str_esc { join '', map +(ord($_) > 0x7e || ord($_) < 0x21? sprintf("\\x{%X}",ord) : $_), split //, $_[0] } |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
sub _render_code_block { |
227
|
37
|
|
|
37
|
|
263
|
my ($self, $i, @expr_subs)= @_; |
228
|
37
|
|
|
|
|
99
|
my $block= $self->_parse_data->{code_block_templates}[$i]; |
229
|
37
|
|
|
|
|
80
|
my $text= $block->{text}; |
230
|
37
|
|
100
|
|
|
147
|
my $out= \($self->{current_out} //= ''); |
231
|
37
|
|
|
|
|
66
|
my $at= 0; |
232
|
37
|
|
|
|
|
61
|
my %colmarker; |
233
|
|
|
|
|
|
|
my $prev_colmark; |
234
|
|
|
|
|
|
|
# First pass, perform substitutions and record new column markers |
235
|
37
|
|
|
|
|
61
|
my $subst= $block->{subst}; |
236
|
37
|
|
|
|
|
91
|
for (my $i= 0; $i < @$subst; $i++) { |
237
|
139
|
|
|
|
|
240
|
my $s= $subst->[$i]; |
238
|
139
|
|
|
|
|
339
|
$$out .= substr($text, $at, $s->{pos} - $at); |
239
|
139
|
|
|
|
|
233
|
$at= $s->{pos} + $s->{len}; |
240
|
139
|
100
|
|
|
|
324
|
if ($s->{colgroup}) { |
|
|
50
|
|
|
|
|
|
241
|
20
|
|
66
|
|
|
62
|
my $mark= $colmarker{$s->{colgroup}} //= _colmarker($s->{colgroup}); |
242
|
20
|
|
|
|
|
40
|
$$out .= $mark; |
243
|
20
|
|
|
|
|
29
|
$prev_colmark= $s; |
244
|
20
|
100
|
|
|
|
64
|
$self->{current_out_colgroup_state}{$s->{colgroup}}= $s->{last}? 2 : 1; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
elsif (defined $s->{eval_idx}) { |
247
|
119
|
50
|
|
|
|
255
|
my $fn= $expr_subs[$s->{eval_idx}] |
248
|
|
|
|
|
|
|
or die; |
249
|
|
|
|
|
|
|
# Avoid using $_ up to this point so that $_ pases through |
250
|
|
|
|
|
|
|
# from the surrounding code into the evals |
251
|
119
|
|
|
|
|
256
|
my @out= $fn->($self, $out); |
252
|
|
|
|
|
|
|
# Expand arrayref and coderefs in the returned list |
253
|
119
|
50
|
66
|
|
|
489
|
@out= @{$out[0]} if @out == 1 && ref $out[0] eq 'ARRAY'; |
|
0
|
|
|
|
|
0
|
|
254
|
119
|
|
33
|
|
|
313
|
ref eq 'CODE' && ($_= $_->($self, $out)) for @out; |
255
|
119
|
|
|
|
|
284
|
@out= grep defined, @out; |
256
|
|
|
|
|
|
|
# Now decide what to join them with. |
257
|
119
|
|
|
|
|
214
|
my $join_sep= $"; |
258
|
119
|
|
|
|
|
167
|
my $indent= ''; |
259
|
119
|
|
|
|
|
3617
|
my ($last_char)= ($$out =~ /(\S) (\s*) \Z/x); |
260
|
119
|
|
|
|
|
364
|
my $cur_line= substr($$out, rindex($$out, "\n")+1); |
261
|
119
|
|
|
|
|
259
|
my $inline= $cur_line =~ /\S/; |
262
|
119
|
50
|
|
|
|
244
|
if ($self->{autoindent}) { |
263
|
119
|
|
|
|
|
747
|
($indent= $cur_line) =~ s/\S/ /g; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
# Special handling if the user requested a list substitution |
266
|
119
|
100
|
|
|
|
285
|
if (ord $s->{eval} == ord '@') { |
267
|
11
|
50
|
|
|
|
26
|
$last_char= '' unless defined $last_char; |
268
|
11
|
100
|
100
|
|
|
124
|
if ($self->{autostatementline} && ($last_char eq '{' || $last_char eq ';') |
|
|
50
|
66
|
|
|
|
|
|
|
0
|
100
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
269
|
|
|
|
|
|
|
&& substr($text, $s->{pos}+$s->{len}, 1) eq ';' |
270
|
|
|
|
|
|
|
) { |
271
|
3
|
|
|
|
|
10
|
@out= grep /\S/, @out; # remove items that are only whitespace |
272
|
3
|
50
|
33
|
|
|
28
|
if (!$inline && substr($text, $s->{pos}+$s->{len}, 2) eq ";\n") { |
273
|
3
|
|
|
|
|
8
|
$join_sep= ";\n"; |
274
|
|
|
|
|
|
|
# If no elements, remove the whole line. |
275
|
3
|
100
|
|
|
|
8
|
if (!@out) { |
276
|
2
|
|
|
|
|
33
|
$$out =~ s/[ \t]+\Z//; |
277
|
2
|
|
|
|
|
5
|
$at+= 2; # skip over ";\n" |
278
|
|
|
|
|
|
|
} |
279
|
|
|
|
|
|
|
} else { |
280
|
0
|
|
|
|
|
0
|
$join_sep= "; "; |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
elsif ($self->{autocomma} && ($last_char eq ',' || $last_char eq '(' || $last_char eq '{')) { |
284
|
8
|
|
|
|
|
35
|
@out= grep /\S/, @out; # remove items that are only whitespace |
285
|
8
|
100
|
|
|
|
22
|
$join_sep= $inline? ', ' : ",\n"; |
286
|
|
|
|
|
|
|
# If no items, or the first nonwhitespace character is a comma, |
287
|
|
|
|
|
|
|
# remove the previous comma |
288
|
8
|
100
|
66
|
|
|
37
|
if (!@out || $out[0] =~ /^\s*,/) { |
289
|
2
|
|
|
|
|
13
|
$$out =~ s/,(\s*)\Z/$1/; |
290
|
|
|
|
|
|
|
} |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
elsif ($self->{autoindent} && !$inline && $join_sep !~ /\n/) { |
293
|
0
|
|
|
|
|
0
|
$join_sep .= "\n"; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
} |
296
|
119
|
100
|
|
|
|
223
|
if (@out) { |
297
|
|
|
|
|
|
|
# 'join' doesn't respect concat magic on AntiCharacter :-( |
298
|
114
|
|
|
|
|
172
|
my $str= shift @out; |
299
|
114
|
|
|
|
|
248
|
$str .= $join_sep . $_ for @out; |
300
|
|
|
|
|
|
|
# Autoindent: if new text contains newline, add current indent to start of each line. |
301
|
114
|
100
|
66
|
|
|
350
|
if ($self->{autoindent} && $indent) { |
302
|
108
|
|
|
|
|
235
|
$str =~ s/\n/\n$indent/g; |
303
|
|
|
|
|
|
|
} |
304
|
114
|
|
|
|
|
419
|
$$out .= $str; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
} |
308
|
37
|
|
|
|
|
260
|
$$out .= substr($text, $at); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
1; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
__END__ |