99 CHECK (not regex_search (input, mat, ACCEPT_MARKUP));
101 input =
" Hallelujah ";
102 CHECK (not regex_search (input, mat, ACCEPT_MARKUP));
104 input =
" stale${beer}forever";
105 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
106 CHECK (mat.position() == 6);
107 CHECK (mat.length() == 7);
108 CHECK (mat.prefix() ==
" stale"_expect);
109 CHECK (mat.suffix() ==
"forever"_expect);
110 CHECK (mat[0] ==
"${beer}"_expect);
111 CHECK (not mat[1].matched);
112 CHECK (not mat[2].matched);
113 CHECK (not mat[3].matched);
114 CHECK (not mat[4].matched);
115 CHECK (mat[5] ==
"beer"_expect);
117 input =
" watch ${for stale}${beer} whatever ";
118 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
119 CHECK (mat.position() == 7);
120 CHECK (mat.length() == 12);
121 CHECK (mat.prefix() ==
" watch "_expect);
122 CHECK (mat.suffix() ==
"${beer} whatever "_expect);
123 CHECK (mat[0] ==
"${for stale}"_expect);
124 CHECK (not mat[2].matched);
125 CHECK (not mat[3].matched);
126 CHECK (mat[4] ==
"for"_expect);
127 CHECK (mat[5] ==
"stale"_expect);
129 input =
" work ${ end if beer \t } however ";
130 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
131 CHECK (mat.position() == 6);
132 CHECK (mat.length() == 19);
133 CHECK (mat.prefix() ==
" work "_expect);
134 CHECK (mat.suffix() ==
" however "_expect);
135 CHECK (mat[0] ==
"${ end if beer \t }"_expect);
136 CHECK (mat[3] ==
"end "_expect);
137 CHECK (mat[4] ==
"if"_expect);
138 CHECK (mat[5] ==
"beer"_expect);
140 input =
" catch ${endgame stale}${endfor brown.beer} ever ";
141 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
142 CHECK (mat.position() == 23);
143 CHECK (mat.length() == 20);
144 CHECK (mat.prefix() ==
" catch ${endgame stale}"_expect);
145 CHECK (mat.suffix() ==
" ever "_expect);
146 CHECK (mat[0] ==
"${endfor brown.beer}"_expect);
147 CHECK (mat[3] ==
"end"_expect);
148 CHECK (mat[4] ==
"for"_expect);
149 CHECK (mat[5] ==
"brown.beer"_expect);
151 input =
" catch ${else} ever ";
152 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
153 CHECK (mat.position() == 7);
154 CHECK (mat.length() == 7);
155 CHECK (mat.prefix() ==
" catch "_expect);
156 CHECK (mat.suffix() ==
" ever "_expect);
157 CHECK (mat[0] ==
"${else}"_expect);
158 CHECK (mat[2] ==
"else"_expect);
159 CHECK (not mat[1].matched);
160 CHECK (not mat[3].matched);
161 CHECK (not mat[4].matched);
162 CHECK (not mat[5].matched);
164 input =
" catch ${else if} fever \\${can.beer} ";
165 CHECK (regex_search (input, mat, ACCEPT_MARKUP));
166 CHECK (mat.position() == 24);
167 CHECK (mat.length() == 2);
168 CHECK (mat.prefix() ==
" catch ${else if} fever "_expect);
169 CHECK (mat.suffix() ==
"{can.beer} "_expect);
170 CHECK (mat[0] ==
"\\$"_expect);
171 CHECK (not mat[2].matched);
172 CHECK (not mat[3].matched);
173 CHECK (not mat[4].matched);
174 CHECK (not mat[5].matched);
175 CHECK (mat[1] ==
"\\$"_expect);
180 input =
"one ${two} three \\${four} ${if high} five";
183 .transform ([](smatch mat){
return mat.str(); }))
185 "${two}, \\$, ${if high}"_expect);
189 auto parser = text_template::parse (input);
190 CHECK (not isnil(parser));
191 CHECK (parser->syntax == TagSyntax::KEYID);
192 CHECK (parser->lead ==
"one "_expect);
193 CHECK (parser->key ==
"two"_expect);
196 CHECK (parser->syntax == TagSyntax::ESCAPE);
197 CHECK (parser->lead ==
" three "_expect);
198 CHECK (parser->key ==
""_expect);
201 CHECK (parser->syntax == TagSyntax::IF);
202 CHECK (parser->lead ==
"${four} "_expect);
203 CHECK (parser->key ==
"high"_expect);
205 CHECK (isnil (parser));
213 Prefix-1 ${some.key} next one is \${escaped}
214 Prefix-2 ${if cond1} active ${else} inactive ${end if
215}Prefix-3 ${if cond2} active2${end if cond2} more
216 Prefix-4 ${for data} fixed ${embedded}
217 Pre-5 ${if nested}nested-active${
218 else }nested-inactive${ end
219 if nested}loop-suffix${else}${end
222 auto actions = TextTemplate::compile (input);
223 CHECK (25 == actions.size());
225 CHECK (actions[ 0].code == TextTemplate::Code::TEXT);
226 CHECK (actions[ 0].val ==
"\n Prefix-1 "_expect);
227 CHECK (actions[ 0].refIDX == 0);
229 CHECK (actions[ 1].code == TextTemplate::Code::KEY);
230 CHECK (actions[ 1].val ==
"some.key"_expect);
232 CHECK (actions[ 2].code == TextTemplate::Code::TEXT);
233 CHECK (actions[ 2].val ==
" next one is "_expect);
235 CHECK (actions[ 3].code == TextTemplate::Code::TEXT);
236 CHECK (actions[ 3].val ==
"${escaped}\n Prefix-2 "_expect);
238 CHECK (actions[ 4].code == TextTemplate::Code::COND);
239 CHECK (actions[ 4].val ==
"cond1"_expect);
240 CHECK (actions[ 4].refIDX == 7 );
242 CHECK (actions[ 5].code == TextTemplate::Code::TEXT);
243 CHECK (actions[ 5].val ==
" active "_expect);
245 CHECK (actions[ 6].code == TextTemplate::Code::JUMP);
246 CHECK (actions[ 6].val ==
""_expect);
247 CHECK (actions[ 6].refIDX == 8 );
249 CHECK (actions[ 7].code == TextTemplate::Code::TEXT);
250 CHECK (actions[ 7].val ==
" inactive "_expect);
252 CHECK (actions[ 8].code == TextTemplate::Code::TEXT);
253 CHECK (actions[ 8].val ==
"Prefix-3 "_expect);
255 CHECK (actions[ 9].code == TextTemplate::Code::COND);
256 CHECK (actions[ 9].val ==
"cond2"_expect);
257 CHECK (actions[ 9].refIDX == 11 );
259 CHECK (actions[10].code == TextTemplate::Code::TEXT);
260 CHECK (actions[10].val ==
" active2"_expect);
262 CHECK (actions[11].code == TextTemplate::Code::TEXT);
263 CHECK (actions[11].val ==
" more\n Prefix-4 "_expect);
265 CHECK (actions[12].code == TextTemplate::Code::ITER);
266 CHECK (actions[12].val ==
"data"_expect);
267 CHECK (actions[12].refIDX == 23 );
269 CHECK (actions[13].code == TextTemplate::Code::TEXT);
270 CHECK (actions[13].val ==
" fixed "_expect);
272 CHECK (actions[14].code == TextTemplate::Code::KEY);
273 CHECK (actions[14].val ==
"embedded"_expect);
275 CHECK (actions[15].code == TextTemplate::Code::TEXT);
276 CHECK (actions[15].val ==
"\n Pre-5 "_expect);
278 CHECK (actions[16].code == TextTemplate::Code::COND);
279 CHECK (actions[16].val ==
"nested"_expect);
280 CHECK (actions[16].refIDX == 19 );
282 CHECK (actions[17].code == TextTemplate::Code::TEXT);
283 CHECK (actions[17].val ==
"nested-active"_expect);
285 CHECK (actions[18].code == TextTemplate::Code::JUMP);
286 CHECK (actions[18].val ==
""_expect);
287 CHECK (actions[18].refIDX == 20 );
289 CHECK (actions[19].code == TextTemplate::Code::TEXT);
290 CHECK (actions[19].val ==
"nested-inactive"_expect);
292 CHECK (actions[20].code == TextTemplate::Code::TEXT);
293 CHECK (actions[20].val ==
"loop-suffix"_expect);
295 CHECK (actions[21].code == TextTemplate::Code::LOOP);
296 CHECK (actions[21].val ==
""_expect);
297 CHECK (actions[21].refIDX == 12 );
299 CHECK (actions[22].code == TextTemplate::Code::JUMP);
300 CHECK (actions[22].val ==
""_expect);
301 CHECK (actions[22].refIDX == 24 );
303 CHECK (actions[23].code == TextTemplate::Code::TEXT);
304 CHECK (actions[23].val ==
""_expect);
306 CHECK (actions[24].code == TextTemplate::Code::TEXT);
307 CHECK (actions[24].val ==
" tail...\n"_expect);
308 CHECK (actions[24].refIDX == 0);
312 VERIFY_FAIL (
"TextTemplate spec without active placeholders"
313 , TextTemplate::compile(
"O tempora O mores"));
315 VERIFY_FAIL (
"Tag without key: ...horror ${<placeholder> |↯|}"
316 , TextTemplate::compile(
"horror ${ } vacui"));
319 , TextTemplate::compile(
"horror ${if} late"));
322 , TextTemplate::compile(
"horror ${for} all"));
325 , TextTemplate::compile(
"horror ${else} deaf"));
327 VERIFY_FAIL (
"unqualified \"end\" without logic-keyword"
328 , TextTemplate::compile(
"horror without ${end}"));
330 VERIFY_FAIL (
"Unbalanced Logic: expect ${end ?? } -- found ...horror ${end |↯|for }"
331 , TextTemplate::compile(
"horror ${end for} ever"));
333 VERIFY_FAIL (
"Unbalanced Logic: expect ${end for free} -- found ... horror ${end |↯|if }"
334 , TextTemplate::compile(
"${for free} horror ${end if}"));
336 VERIFY_FAIL (
"Unbalanced Logic: expect ${end for free} -- found ... yet ${end |↯|for me}"
337 , TextTemplate::compile(
"${if wee} horror ${for free} yet ${end for me}"));
339 VERIFY_FAIL (
"Conflicting ... precipitous ${else} ⟷ ... callous |↯|${else}"
340 , TextTemplate::compile(
"${if smarmy} precipitous ${else} callous ${else} horror"));
342 VERIFY_FAIL (
"Unclosed Logic tags: |↯|${end if sleazy} missing"
343 , TextTemplate::compile(
"${if sleazy} precipitous ${else} horror"));
345 VERIFY_FAIL (
"Unclosed Logic tags: |↯|${end for horror} missing"
346 , TextTemplate::compile(
"${for horror}${if flimsy} atrocious ${end if} precipitous"));
452 auto binding = text_template::DataSource{data};
453 CHECK (
meta::typeStr(binding) ==
"text_template::DataSource<map<string, string>, void>"_expect );
454 CHECK ( binding.contains(
"a"));
455 CHECK (not binding.contains(
"b"));
456 CHECK (binding.retrieveContent(
"a") ==
"5"_expect );
457 CHECK (binding.retrieveContent(
"i") ==
"p,q,r"_expect );
458 CHECK (binding.retrieveContent(
"i.q.aa") ==
"222"_expect );
459 CHECK (not binding.isSubScope());
461 auto it = binding.getSequence(
"i");
463 CHECK (*it ==
"i.p."_expect );
464 CHECK (
meta::typeStr(it) ==
"IterExplorer<IterableDecorator<CheckedCore<iter_explorer::Transformer<iter_explorer::BaseAdapter<RegexSearchIter>, string> > > >"_expect );
466 auto subBind = binding.openContext(it);
467 CHECK (subBind.isSubScope());
468 CHECK ((meta::is_same<
decltype(binding),
decltype(subBind)>()));
469 CHECK ( subBind.contains(
"a"));
470 CHECK (not subBind.contains(
"b"));
471 CHECK (not subBind.contains(
"aa"));
472 CHECK ( subBind.contains(
"i"));
473 CHECK (subBind.retrieveContent(
"i") ==
"p,q,r"_expect );
474 CHECK (subBind.retrieveContent(
"a") ==
"11"_expect );
478 CHECK (*it ==
"i.q."_expect );
481 CHECK (subBind.retrieveContent(
"a") ==
"11"_expect );
483 subBind = binding.openContext(it);
484 CHECK (subBind.isSubScope());
485 CHECK (subBind.contains(
"a"));
486 CHECK (subBind.contains(
"aa"));
487 CHECK (subBind.retrieveContent(
"a") ==
"22"_expect );
488 CHECK (subBind.retrieveContent(
"aa") ==
"222"_expect);
489 CHECK (subBind.retrieveContent(
"i.p.a") ==
"11"_expect );
490 CHECK (subBind.retrieveContent(
"i.q.a") ==
"22"_expect );
494 CHECK (*it ==
"i.r."_expect );
496 subBind = binding.openContext(it);
497 CHECK ( subBind.contains(
"a"));
498 CHECK (not subBind.contains(
"aa"));
499 CHECK (subBind.retrieveContent(
"a") ==
"5"_expect );
500 CHECK (subBind.retrieveContent(
"i.p.a") ==
"11"_expect );
501 CHECK (subBind.retrieveContent(
"i.q.a") ==
"22"_expect );
522 auto root = MakeRec()
538 auto binding = text_template::DataSource{root};
539 CHECK (
meta::typeStr(binding) ==
"text_template::DataSource<GenNode, void>"_expect );
540 CHECK ( binding.contains(
"a"));
541 CHECK (not binding.contains(
"b"));
542 CHECK (binding.retrieveContent(
"a") ==
"5"_expect );
543 CHECK (binding.retrieveContent(
"i") ==
"{|{a=11}, {a=22, aa=222}, {}}"_expect );
544 CHECK (not binding.isSubScope());
546 auto it = binding.getSequence(
"i");
548 CHECK (renderCompact(*it) ==
"{a=11}");
549 CHECK (*it == root.data.get<Rec>().get(
"i").data.get<Rec>().child(0));
551 auto subBind = binding.openContext(it);
552 CHECK (subBind.isSubScope());
553 CHECK ((meta::is_same<
decltype(binding),
decltype(subBind)>()));
554 CHECK ( subBind.contains(
"a"));
555 CHECK (not subBind.contains(
"b"));
556 CHECK (not subBind.contains(
"aa"));
557 CHECK ( subBind.contains(
"i"));
558 CHECK (subBind.retrieveContent(
"i") ==
"{|{a=11}, {a=22, aa=222}, {}}"_expect );
559 CHECK (subBind.retrieveContent(
"a") ==
"11"_expect );
563 CHECK (renderCompact(*it) ==
"{a=22, aa=222}");
564 CHECK (subBind.retrieveContent(
"a") ==
"11"_expect );
566 subBind = binding.openContext(it);
567 CHECK (subBind.isSubScope());
568 CHECK (subBind.contains(
"a"));
569 CHECK (subBind.contains(
"aa"));
570 CHECK (subBind.retrieveContent(
"a") ==
"22"_expect );
571 CHECK (subBind.retrieveContent(
"aa") ==
"222"_expect);
575 CHECK (renderCompact(*it) ==
"{}");
577 subBind = binding.openContext(it);
578 CHECK ( subBind.contains(
"a"));
579 CHECK (not subBind.contains(
"aa"));
580 CHECK (subBind.retrieveContent(
"a") ==
"5"_expect );
587 TextTemplate tt{
"${for i}a=${a} ${if aa}and aa=${aa} ${endif}${endfor}."};
588 CHECK (tt.render(root) ==
"a=11 a=22 and aa=222 a=5 ."_expect);