Skip to content

Commit 5a4e8e3

Browse files
feat: add |||- chomped text block syntax (#1175)
* feat: add |||- chomped text block syntax Resolves #289 * revert MathJax change The optable in the MathJax code is not related to Jsonnet's syntax, and should not have `|||-` added. --------- Co-authored-by: John Bartholomew <[email protected]>
1 parent 92b7747 commit 5a4e8e3

6 files changed

+86
-11
lines changed

core/formatter.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,11 @@ class Unparser {
500500
o << encode_utf8(ast->value);
501501
o << "'";
502502
} else if (ast->tokenKind == LiteralString::BLOCK) {
503-
o << "|||\n";
503+
o << "|||";
504+
if (ast->value.back() != U'\n') {
505+
o << "-";
506+
}
507+
o << "\n";
504508
if (ast->value.c_str()[0] != U'\n')
505509
o << ast->blockIndent;
506510
for (const char32_t *cp = ast->value.c_str(); *cp != U'\0'; ++cp) {
@@ -513,6 +517,9 @@ class Unparser {
513517
o << ast->blockIndent;
514518
}
515519
}
520+
if (ast->value.back() != U'\n') {
521+
o << "\n";
522+
}
516523
o << ast->blockTermIndent << "|||";
517524
} else if (ast->tokenKind == LiteralString::VERBATIM_DOUBLE) {
518525
o << "@\"";

core/lexer.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,13 @@ Tokens jsonnet_lex(const std::string &filename, const char *input)
704704
// Text block
705705
if (*c == '|' && *(c + 1) == '|' && *(c + 2) == '|') {
706706
c += 3; // Skip the "|||".
707+
708+
bool chomp_trailing_nl = false;
709+
if (*c == '-') {
710+
chomp_trailing_nl = true;
711+
c++;
712+
}
713+
707714
while (is_horz_ws(*c)) ++c; // Chomp whitespace at end of line.
708715
if (*c != '\n') {
709716
auto msg = "text block syntax requires new line after |||.";
@@ -762,6 +769,10 @@ Tokens jsonnet_lex(const std::string &filename, const char *input)
762769
c += 3; // Leave after the last |
763770
data = block.str();
764771
kind = Token::STRING_BLOCK;
772+
if (chomp_trailing_nl) {
773+
assert(data.back() == '\n');
774+
data.pop_back();
775+
}
765776
break; // Out of the while loop.
766777
}
767778
}

doc/js/codemirror-mode-jsonnet.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@
176176
}
177177

178178
// Enter text block.
179-
if (stream.match(/\|\|\|/)) {
179+
if (stream.match(/\|\|\|-?/)) {
180180
state.textBlock = true;
181181
state.textBlockIndent = null;
182182
return "string";

doc/ref/spec.html

+13-9
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,19 @@ <h2 id="lexing">Lexing</h2>
168168
subsequent non-quoted <code>'</code>
169169
</li>
170170
<li>
171-
Text block, beginning with <code>|||</code>, followed by optional whitespace and a
172-
new-line. The next non-empty line must be prefixed with some non-zero length
173-
whitespace <i>W</i>. The block ends at the first subsequent line that is non-empty
174-
and does not begin with <i>W</i>, and it is an error if this line does not contain
175-
some optional whitespace followed by <code>|||</code>. The content of the string is
176-
the concatenation of all the lines between the two <code>|||</code>, which either
177-
begin with <i>W</i> (in which case that prefix is stripped) or they are empty lines
178-
(in which case they remain as empty lines). The line ending style in the file is
179-
preserved in the string. This form cannot be used in <code>import</code> statements.
171+
Text block, beginning with <code>|||</code> followed by an optional
172+
<code>-</code>, then optional whitespace and a new-line. The next non-empty
173+
line must be prefixed with some non-zero length whitespace <i>W</i>. The
174+
block ends at the first subsequent line that is non-empty and does not begin
175+
with <i>W</i>, and it is an error if this line does not contain some
176+
optional whitespace followed by <code>|||</code>. The content of the string
177+
is the concatenation of all the lines between the two <code>|||</code>,
178+
which either begin with <i>W</i> (in which case that prefix is stripped) or
179+
they are empty lines (in which case they remain as empty lines). The line
180+
ending style in the file is preserved in the string. If the beginning
181+
<code>|||</code> was followed by <code>-</code> then the final new-line is
182+
stripped from the resulting string. This form cannot be used in
183+
<code>import</code> statements.
180184
</li>
181185
</ul>
182186
<p>

test_suite/text_block.jsonnet

+27
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,33 @@ local bash_mixed = |||
5858
std.assertEqual(bash_golden, bash_mixed) &&
5959

6060

61+
// Chomp trailing newline
62+
local str1 = |||-
63+
foo bar baz
64+
|||;
65+
66+
std.assertEqual(str1, "foo bar baz") &&
67+
68+
69+
// Chomp just one trailing newline
70+
local str1 = |||-
71+
foo bar baz
72+
73+
|||;
74+
75+
std.assertEqual(str1, "foo bar baz\n") &&
76+
77+
78+
// Concatenate chomped blocks
79+
local str1 = |||-
80+
foo bar baz
81+
||| + " " + |||-
82+
biz buzz
83+
|||;
84+
85+
std.assertEqual(str1, "foo bar baz biz buzz") &&
86+
87+
6188
// More indent
6289
local str1 = |||
6390
text

test_suite/text_block.jsonnet.fmt.golden

+26
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,32 @@ local bash_mixed = |||
5858
std.assertEqual(bash_golden, bash_mixed) &&
5959

6060

61+
// Chomp trailing newline
62+
local str1 = |||-
63+
foo bar baz
64+
|||;
65+
66+
std.assertEqual(str1, 'foo bar baz') &&
67+
68+
69+
// Chomp just one trailing newline
70+
local str1 = |||
71+
foo bar baz
72+
|||;
73+
74+
std.assertEqual(str1, 'foo bar baz\n') &&
75+
76+
77+
// Concatenate chomped blocks
78+
local str1 = |||-
79+
foo bar baz
80+
||| + ' ' + |||-
81+
biz buzz
82+
|||;
83+
84+
std.assertEqual(str1, 'foo bar baz biz buzz') &&
85+
86+
6187
// More indent
6288
local str1 = |||
6389
text

0 commit comments

Comments
 (0)