Skip to content

Commit 31baa90

Browse files
committed
Fix #60: Don't match keywords when the keyword is (partially) inside and <atom> tag
1 parent c9c708d commit 31baa90

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

src/data/keyword.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ String expand_keywords(const String& tagged_str, vector<KeywordMatch> const& mat
519519
skip_tags_for_keyword(false, true);
520520
if (it == end) break;
521521
// is there a match here?
522+
if (atom == 0) // don't expand keywords that are inside <atom> tags
522523
while (match_it != matches.end() && match_it->pos <= untagged_pos) {
523524
if (match_it->pos > untagged_pos) {
524525
++match_it;
@@ -553,7 +554,7 @@ String expand_keywords(const String& tagged_str, vector<KeywordMatch> const& mat
553554
// * Whether the case matches
554555
// Add these things to the context
555556
// Return iterator after the whole match
556-
String::const_iterator keyword_match_detail(String::const_iterator it, String::const_iterator end, KeywordMatch const& kw_match, Context& ctx) {
557+
tuple<bool,String::const_iterator> keyword_match_detail(String::const_iterator it, String::const_iterator end, KeywordMatch const& kw_match, Context& ctx) {
557558
Keyword const& keyword = *kw_match.keyword;
558559
Regex::Results const& match = kw_match.match;
559560

@@ -563,6 +564,9 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
563564
bool correct_case = true;
564565
String::const_iterator match_str_it = keyword.match.begin();
565566

567+
// in tags?
568+
int atom = 0;
569+
566570
// Combined tagged match string
567571
String total;
568572

@@ -583,7 +587,8 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
583587
// we start counting at 1, so
584588
// sub = 1 mod 2 -> text
585589
// sub = 0 mod 2 -> parameter
586-
if ((sub % 2) == 0) {
590+
bool is_parameter = (sub % 2) == 0;
591+
if (is_parameter) {
587592
// parameter
588593
KeywordParam& kwp = *keyword.parameters[(sub - 2) / 2];
589594
String param = match.str(sub); // untagged version
@@ -643,7 +648,8 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
643648
ctx.setVariable(String(_("param")) << (int)(sub / 2), script_param);
644649

645650
} else {
646-
// Plain text, check if the case matches
651+
// Plain text with exact match
652+
// check if the case matches
647653
if (correct_case) {
648654
while (it != part_end) {
649655
it = skip_all_tags(it, part_end);
@@ -664,17 +670,31 @@ String::const_iterator keyword_match_detail(String::const_iterator it, String::c
664670
}
665671
}
666672
}
673+
// count <atom> tags
674+
for (String::const_iterator pit = part.begin(); pit != part.end();) {
675+
if (*pit == '<') {
676+
if (is_tag(pit, part.end(), "<atom")) atom++;
677+
else if(is_tag(pit, part.end(), "</atom")) atom--;
678+
pit = skip_tag(pit, part.end());
679+
} else {
680+
if (atom > 0 && !is_parameter) {
681+
// the fixed parts of a keyword should not be in atom tags
682+
return {false,it};
683+
}
684+
++pit;
685+
}
686+
}
667687
// build total match
668688
total += part;
669689
// next part starts after this
670690
it = part_end;
671691
}
672-
assert_tagged(total);
692+
assert_tagged(total, false); // note: tags might not be entirely balanced
673693
ctx.setVariable(_("keyword"), to_script(total));
674694
ctx.setVariable(_("mode"), to_script(keyword.mode));
675695
ctx.setVariable(_("correct_case"), to_script(correct_case));
676696
ctx.setVariable(_("used_placeholders"), to_script(used_placeholders));
677-
return it;
697+
return {true, it};
678698
};
679699

680700
// expand a keyword that matches at it
@@ -686,7 +706,8 @@ tuple<bool, String::const_iterator> expand_keyword(String::const_iterator it, St
686706
LocalScope scope(ctx);
687707

688708
// Get details of the match
689-
String::const_iterator after = keyword_match_detail(it, end, kw_match, ctx);
709+
auto [ok, after] = keyword_match_detail(it, end, kw_match, ctx);
710+
if (!ok) return {false,it};
690711

691712
// Final check whether the keyword matches
692713
if (options.match_condition && options.match_condition->eval(ctx)->toBool() == false) {

0 commit comments

Comments
 (0)