| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
1
|
|
|
1
|
|
11
|
use v5.36.0; |
|
|
1
|
|
|
|
|
2
|
|
|
2
|
|
|
|
|
|
|
package Sieve::Generator::Element::Command 0.003; |
|
3
|
|
|
|
|
|
|
# ABSTRACT: a single Sieve command statement |
|
4
|
|
|
|
|
|
|
|
|
5
|
1
|
|
|
1
|
|
4
|
use Moo; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
9
|
|
|
6
|
|
|
|
|
|
|
with 'Sieve::Generator::Element'; |
|
7
|
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
308
|
use Params::Util qw(_ARRAY0); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
799
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#pod =head1 DESCRIPTION |
|
11
|
|
|
|
|
|
|
#pod |
|
12
|
|
|
|
|
|
|
#pod A command is a single semicolon-terminated Sieve statement, such as C, |
|
13
|
|
|
|
|
|
|
#pod C, or C. It consists of an identifier followed by |
|
14
|
|
|
|
|
|
|
#pod zero or more arguments. |
|
15
|
|
|
|
|
|
|
#pod |
|
16
|
|
|
|
|
|
|
#pod =attr identifier |
|
17
|
|
|
|
|
|
|
#pod |
|
18
|
|
|
|
|
|
|
#pod This attribute holds the name of the Sieve command, such as C, |
|
19
|
|
|
|
|
|
|
#pod C, or C. |
|
20
|
|
|
|
|
|
|
#pod |
|
21
|
|
|
|
|
|
|
#pod =cut |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has identifier => (is => 'ro', required => 1); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
#pod =attr semicolon |
|
26
|
|
|
|
|
|
|
#pod |
|
27
|
|
|
|
|
|
|
#pod This attribute can be set to false during construction to suppress its trailing |
|
28
|
|
|
|
|
|
|
#pod semicolon. This is useful for making tests, which are just commands without |
|
29
|
|
|
|
|
|
|
#pod semicolons or blocks after them. |
|
30
|
|
|
|
|
|
|
#pod |
|
31
|
|
|
|
|
|
|
#pod =cut |
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
has semicolon => ( |
|
34
|
|
|
|
|
|
|
is => 'ro', |
|
35
|
|
|
|
|
|
|
default => 1, |
|
36
|
|
|
|
|
|
|
); |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
#pod =attr autowrap |
|
39
|
|
|
|
|
|
|
#pod |
|
40
|
|
|
|
|
|
|
#pod This attribute can be set false during construction to suppress automatic |
|
41
|
|
|
|
|
|
|
#pod multiline formatting if this command runs lone. |
|
42
|
|
|
|
|
|
|
#pod |
|
43
|
|
|
|
|
|
|
#pod =cut |
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
has autowrap => ( |
|
46
|
|
|
|
|
|
|
is => 'ro', |
|
47
|
|
|
|
|
|
|
default => 1, |
|
48
|
|
|
|
|
|
|
); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
#pod =attr block |
|
51
|
|
|
|
|
|
|
#pod |
|
52
|
|
|
|
|
|
|
#pod This attribute holds an optional L to render |
|
53
|
|
|
|
|
|
|
#pod after the arguments instead of a semicolon. This models the Sieve grammar rule |
|
54
|
|
|
|
|
|
|
#pod C for commands like |
|
55
|
|
|
|
|
|
|
#pod C that take a block body. When set, the C attribute |
|
56
|
|
|
|
|
|
|
#pod is ignored. |
|
57
|
|
|
|
|
|
|
#pod |
|
58
|
|
|
|
|
|
|
#pod =cut |
|
59
|
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
has block => (is => 'ro'); |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
#pod =attr tagged_args |
|
63
|
|
|
|
|
|
|
#pod |
|
64
|
|
|
|
|
|
|
#pod This attribute holds the list of tagged arguments to the command, given as a |
|
65
|
|
|
|
|
|
|
#pod hashref. The values in the hashref will be array references of objects doing |
|
66
|
|
|
|
|
|
|
#pod L, which will follow the tag name. |
|
67
|
|
|
|
|
|
|
#pod |
|
68
|
|
|
|
|
|
|
#pod The accessor will return a list of pairs. |
|
69
|
|
|
|
|
|
|
#pod |
|
70
|
|
|
|
|
|
|
#pod =cut |
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
has _tagged_args => ( |
|
73
|
|
|
|
|
|
|
is => 'ro', |
|
74
|
|
|
|
|
|
|
default => sub { {} }, |
|
75
|
|
|
|
|
|
|
init_arg => 'tagged_args' |
|
76
|
|
|
|
|
|
|
); |
|
77
|
|
|
|
|
|
|
|
|
78
|
82
|
|
|
82
|
1
|
79
|
sub tagged_args ($self) { |
|
|
82
|
|
|
|
|
77
|
|
|
|
82
|
|
|
|
|
81
|
|
|
79
|
82
|
|
|
|
|
119
|
my $tagged_args = $self->_tagged_args; |
|
80
|
82
|
|
|
|
|
187
|
return $tagged_args->%{ sort keys %$tagged_args }; |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
#pod =attr positional_args |
|
84
|
|
|
|
|
|
|
#pod |
|
85
|
|
|
|
|
|
|
#pod This attribute holds the list of positional arguments to the command. Each |
|
86
|
|
|
|
|
|
|
#pod argument should be an object doing L. |
|
87
|
|
|
|
|
|
|
#pod |
|
88
|
|
|
|
|
|
|
#pod =cut |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
has _positional_args => ( |
|
91
|
|
|
|
|
|
|
is => 'ro', |
|
92
|
|
|
|
|
|
|
default => sub { [] }, |
|
93
|
|
|
|
|
|
|
init_arg => 'positional_args' |
|
94
|
|
|
|
|
|
|
); |
|
95
|
|
|
|
|
|
|
|
|
96
|
82
|
|
|
82
|
1
|
144
|
sub positional_args { $_[0]->_positional_args->@* } |
|
97
|
|
|
|
|
|
|
|
|
98
|
20
|
|
|
20
|
0
|
21
|
sub children ($self) { |
|
|
20
|
|
|
|
|
21
|
|
|
|
20
|
|
|
|
|
16
|
|
|
99
|
20
|
|
|
|
|
19
|
my @children; |
|
100
|
|
|
|
|
|
|
|
|
101
|
20
|
|
|
|
|
23
|
my @tagged_pairs = $self->tagged_args; |
|
102
|
20
|
|
|
|
|
41
|
while (my ($name, $values) = splice @tagged_pairs, 0, 2) { |
|
103
|
0
|
|
|
|
|
0
|
push @children, @$values; |
|
104
|
|
|
|
|
|
|
} |
|
105
|
|
|
|
|
|
|
|
|
106
|
20
|
|
|
|
|
23
|
push @children, $self->positional_args; |
|
107
|
20
|
50
|
|
|
|
30
|
push @children, $self->block if $self->block; |
|
108
|
|
|
|
|
|
|
|
|
109
|
20
|
|
|
|
|
44
|
return @children; |
|
110
|
|
|
|
|
|
|
} |
|
111
|
|
|
|
|
|
|
|
|
112
|
59
|
|
|
59
|
0
|
602
|
sub as_sieve ($self, $i = undef) { |
|
|
59
|
|
|
|
|
108
|
|
|
|
59
|
|
|
|
|
64
|
|
|
|
59
|
|
|
|
|
63
|
|
|
113
|
59
|
|
100
|
|
|
104
|
$i //= 0; |
|
114
|
|
|
|
|
|
|
|
|
115
|
59
|
|
|
|
|
103
|
my $oneline = $self->_as_sieve_oneline($i); |
|
116
|
|
|
|
|
|
|
|
|
117
|
59
|
100
|
100
|
|
|
196
|
if (!$self->autowrap || length $oneline < 72) { |
|
118
|
57
|
|
|
|
|
112
|
return $oneline; |
|
119
|
|
|
|
|
|
|
} |
|
120
|
|
|
|
|
|
|
|
|
121
|
2
|
|
|
|
|
5
|
return $self->_as_sieve_multiline($i); |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
60
|
|
|
60
|
|
639
|
sub _as_sieve_oneline ($self, $i = undef) { |
|
|
60
|
|
|
|
|
96
|
|
|
|
60
|
|
|
|
|
58
|
|
|
|
60
|
|
|
|
|
82
|
|
|
125
|
60
|
|
100
|
|
|
117
|
my $indent = q{ } x ($i // 0); |
|
126
|
|
|
|
|
|
|
|
|
127
|
60
|
|
|
|
|
102
|
my $str = $indent . $self->identifier; |
|
128
|
|
|
|
|
|
|
|
|
129
|
60
|
|
|
|
|
78
|
my @tagged_pairs = $self->tagged_args; |
|
130
|
60
|
|
|
|
|
142
|
while (my ($name, $values) = splice @tagged_pairs, 0, 2) { |
|
131
|
26
|
|
|
|
|
81
|
$str .= " :$name"; |
|
132
|
26
|
|
|
|
|
42
|
for my $v (@$values) { |
|
133
|
17
|
|
|
|
|
31
|
my $rendered = $v->as_sieve(0); |
|
134
|
17
|
50
|
|
|
|
56
|
$str .= $str =~ /\n\z/ ? $rendered : " $rendered"; |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
60
|
|
|
|
|
84
|
for my $arg ($self->positional_args) { |
|
139
|
27
|
|
|
|
|
74
|
my $rendered = $arg->as_sieve(0); |
|
140
|
27
|
100
|
|
|
|
77
|
$str .= $str =~ /\n\z/ ? $rendered : " $rendered"; |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
60
|
100
|
|
|
|
155
|
if ($self->block) { |
|
|
|
100
|
|
|
|
|
|
|
144
|
2
|
|
50
|
|
|
9
|
my $blk = $self->block->as_sieve($i // 0); |
|
145
|
2
|
50
|
|
|
|
7
|
$str .= $str =~ /\n\z/ ? $blk : " $blk"; |
|
146
|
|
|
|
|
|
|
} elsif ($self->semicolon) { |
|
147
|
34
|
|
|
|
|
49
|
$str .= ";"; |
|
148
|
|
|
|
|
|
|
} |
|
149
|
|
|
|
|
|
|
|
|
150
|
60
|
|
|
|
|
99
|
return $str; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
|
|
153
|
2
|
|
|
2
|
|
3
|
sub _as_sieve_multiline ($self, $i = undef) { |
|
|
2
|
|
|
|
|
2
|
|
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
2
|
|
|
154
|
2
|
|
50
|
|
|
18
|
my $indent = q{ } x ($i // 0); |
|
155
|
2
|
|
|
|
|
6
|
my $indent2 = q{ } x (1 + length $self->identifier); |
|
156
|
|
|
|
|
|
|
|
|
157
|
2
|
|
|
|
|
4
|
my $str = $indent . $self->identifier; |
|
158
|
2
|
|
|
|
|
3
|
my $n = 0; |
|
159
|
|
|
|
|
|
|
|
|
160
|
2
|
|
|
|
|
3
|
my @pair_queue = $self->tagged_args; |
|
161
|
2
|
|
|
|
|
6
|
for my $i (grep {; $_ % 2 == 0 } keys @pair_queue) { |
|
|
20
|
|
|
|
|
27
|
|
|
162
|
10
|
|
|
|
|
16
|
$pair_queue[$i] = ":$pair_queue[$i]"; |
|
163
|
|
|
|
|
|
|
} |
|
164
|
|
|
|
|
|
|
|
|
165
|
2
|
|
|
|
|
4
|
push @pair_queue, map {; $_->as_sieve(0), [] } $self->positional_args; |
|
|
0
|
|
|
|
|
0
|
|
|
166
|
|
|
|
|
|
|
|
|
167
|
2
|
|
|
|
|
7
|
while (my ($name, $values) = splice @pair_queue, 0, 2) { |
|
168
|
10
|
100
|
|
|
|
17
|
$str .= $n++ ? "$indent$indent2" : q{ }; |
|
169
|
10
|
|
|
|
|
12
|
$str .= "$name"; |
|
170
|
|
|
|
|
|
|
|
|
171
|
10
|
50
|
|
|
|
14
|
if (@$values) { |
|
172
|
10
|
|
|
|
|
11
|
$str .= " " . join(q{ }, map {; $_->as_sieve(0) } @$values); |
|
|
10
|
|
|
|
|
15
|
|
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
10
|
100
|
|
|
|
22
|
if (@pair_queue) { |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
176
|
8
|
|
|
|
|
13
|
$str .= "\n"; |
|
177
|
|
|
|
|
|
|
} elsif ($self->block) { |
|
178
|
0
|
|
0
|
|
|
0
|
$str .= " " . $self->block->as_sieve($i // 0); |
|
179
|
|
|
|
|
|
|
} elsif ($self->semicolon) { |
|
180
|
2
|
|
|
|
|
5
|
$str .= ";"; |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
|
|
184
|
2
|
|
|
|
|
7
|
return $str; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
|
|
|
|
|
|
|
|
187
|
1
|
|
|
1
|
|
6
|
no Moo; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
5
|
|
|
188
|
|
|
|
|
|
|
1; |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
__END__ |