Skip to content

Commit 678459b

Browse files
yoshikazusawaLeont
authored andcommitted
Supports additional indicators on block scalars
ref: https://yaml-multiline.info/
1 parent 09d5929 commit 678459b

File tree

2 files changed

+135
-21
lines changed

2 files changed

+135
-21
lines changed

lib/TAP/Parser/YAMLish/Reader.pm

Lines changed: 59 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -137,23 +137,9 @@ sub _read_scalar {
137137
return {} if $string eq '{}';
138138
return [] if $string eq '[]';
139139

140-
if ( $string eq '>' || $string eq '|' ) {
141-
142-
my ( $line, $indent ) = $self->_peek;
143-
die "Multi-line scalar content missing" unless defined $line;
144-
145-
my @multiline = ($line);
146-
147-
while (1) {
148-
$self->_next;
149-
my ( $next, $ind ) = $self->_peek;
150-
last if $ind < $indent;
151-
152-
my $pad = $string eq '|' ? ( ' ' x ( $ind - $indent ) ) : '';
153-
push @multiline, $pad . $next;
154-
}
155-
156-
return join( ( $string eq '>' ? ' ' : "\n" ), @multiline ) . "\n";
140+
if ( $string =~ /^([>|])([+-]?)([1-9]?)$/ ) {
141+
my ( $style, $chomping, $indent_base ) = ( $1, $2, $3 );
142+
return $self->_read_block_scalar( $style, $chomping, $indent_base );
157143
}
158144

159145
if ( $string =~ /^ ' (.*) ' $/x ) {
@@ -175,6 +161,62 @@ sub _read_scalar {
175161
return $string;
176162
}
177163

164+
sub _read_block_scalar {
165+
my ( $self, $style, $chomping, $indent_base ) = @_;
166+
167+
my ( $line, $line_indent ) = $self->_peek;
168+
die "Multi-line scalar content missing" unless defined $line;
169+
170+
$indent_base ||= $line_indent;
171+
172+
my $pad = ' ' x ( $line_indent - $indent_base );
173+
my @multi_lines = [ $pad, $line ];
174+
175+
while (1) {
176+
$self->_next;
177+
my ( $content, $line_indent ) = $self->_peek;
178+
last if $line_indent < $indent_base;
179+
180+
my $pad = ' ' x ( $line_indent - $indent_base );
181+
push @multi_lines, [ $pad, $content ];
182+
}
183+
184+
my $block = '';
185+
my $previous_line;
186+
187+
for my $current_line ( @multi_lines ) {
188+
my ( $pad, $content ) = @$current_line;
189+
unless ( defined $previous_line ) {
190+
$block .= join( '', $pad, $content );
191+
$previous_line = $current_line;
192+
next;
193+
}
194+
195+
if ( $style eq '>'
196+
&& length $content > 0
197+
&& length $pad == 0
198+
&& length $previous_line->[0] == 0
199+
&& length $previous_line->[1] > 0 )
200+
{
201+
$block .= ' ' . $content;
202+
} else {
203+
$block .= join( '', "\n", $pad, $content );
204+
}
205+
$previous_line = $current_line;
206+
}
207+
208+
$block .= "\n";
209+
210+
if ( $chomping eq '-' ) {
211+
$block =~ s/\n+$//;
212+
} elsif ( $chomping eq '+' ) {
213+
# noop: keep newlines
214+
} else {
215+
$block =~ s/\n+$/\n/;
216+
}
217+
return $block;
218+
}
219+
178220
sub _read_nested {
179221
my $self = shift;
180222

t/yamlish.t

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,50 @@ BEGIN {
4040
],
4141
out => "Hello, World",
4242
},
43-
{ name => 'Hello World 4',
43+
{ name => 'Block Scalars with folded style',
4444
in => [
4545
'--- >',
4646
' Hello,',
47-
' World',
47+
' World',
4848
'...',
4949
],
5050
out => "Hello, World\n",
5151
},
52-
{ name => 'Hello World Block',
52+
{ name => 'Block Scalars with folded style including extra indentation',
53+
in => [
54+
'--- >',
55+
' Hello,',
56+
' World',
57+
' with extra',
58+
' indentation',
59+
'...',
60+
],
61+
out => "Hello, World\n with extra\n indentation\n",
62+
},
63+
{ name => 'Hello World with folded style and no newline at end',
64+
in => [
65+
'--- >-',
66+
' Hello,',
67+
' World',
68+
' ',
69+
'...',
70+
],
71+
out => "Hello, World",
72+
},
73+
{ name => 'Hello World with folded style and keeping newlines from end',
74+
in => [
75+
'--- >+',
76+
' Hello,',
77+
' World',
78+
' ',
79+
' ',
80+
' Hello World again',
81+
' ',
82+
'...',
83+
],
84+
out => "Hello, World\n \n\nHello World again\n\n",
85+
},
86+
{ name => 'Hello World with literal style',
5387
in => [
5488
'--- |',
5589
' Hello,',
@@ -58,7 +92,45 @@ BEGIN {
5892
],
5993
out => "Hello,\n World\n",
6094
},
61-
{ name => 'Hello World 5',
95+
{ name => 'Hello World with literal style and no newline at end',
96+
in => [
97+
'--- |-',
98+
' Hello,',
99+
' World',
100+
'...',
101+
],
102+
out => "Hello,\n World",
103+
},
104+
{ name => 'Hello World with literal style and keeping newlines from end',
105+
in => [
106+
'--- |+',
107+
' Hello,',
108+
' World',
109+
' ',
110+
' ',
111+
'...',
112+
],
113+
out => "Hello,\n World\n\n \n",
114+
},
115+
{ name => 'Hello World with literal style and no newline at end and indentation indicator',
116+
in => [
117+
'--- |-3',
118+
' Hello,',
119+
' World',
120+
'...',
121+
],
122+
out => " Hello,\n World",
123+
},
124+
{ name => 'Hello World with indentation indicator',
125+
in => [
126+
'--- >1',
127+
' Hello,',
128+
' World',
129+
'...',
130+
],
131+
out => " Hello,\n World\n",
132+
},
133+
{ name => 'Hello World with broken indentation',
62134
in => [
63135
'--- >',
64136
' Hello,',

0 commit comments

Comments
 (0)