@@ -79,6 +79,12 @@ std::strong_ordering Letter::operator<=>(const Letter& other) const
79
79
}
80
80
81
81
82
+ RegexPattern::~RegexPattern ()
83
+ {
84
+ pcre2_code_free (mPattern );
85
+ }
86
+
87
+
82
88
TriggerTree::TriggerTree (std::filesystem::path matchFile, std::vector<std::filesystem::path> includes, std::vector<std::filesystem::path> excludes)
83
89
: mMatchFile(std::move(matchFile))
84
90
, mIncludes(std::move(includes))
@@ -166,7 +172,10 @@ void TriggerTree::Reconstruct(std::string_view matchesString, std::function<void
166
172
};
167
173
// TODO: Warn about empty triggers or replaces
168
174
175
+ mRegexMatches .clear ();
176
+
169
177
// / First iteration. Construct the tree, preprocessing the data to be easy to use.
178
+ // / Regex matches will be fully processed here.
170
179
TempNode root;
171
180
std::vector<std::pair<const Match*, const std::wstring*>> triggersOverwritten;
172
181
for (const Match& match : matchesFiltered)
@@ -293,14 +302,14 @@ void TriggerTree::Reconstruct(std::string_view matchesString, std::function<void
293
302
logger.Log (ELogLevel::ERROR, std::format (L" Regex compilation failed: {}\n "
294
303
" File: {}, Original Trigger: {}, After Preprocess: {}, Error Offset: {}" ,
295
304
errMsg, mMatchFile .generic_wstring (), regexTrigger, triggerStr, errOffset));
296
-
305
+ // TODO: Notification
297
306
pcre2_code_free (pattern);
298
307
continue ;
299
308
}
300
309
301
310
pcre2_jit_compile (pattern, PCRE2_JIT_COMPLETE); // Don't care if it failed or not. It'll automatically fallback to non-jit if so.
302
311
303
- // TODO: Store
312
+ mRegexMatches . emplace_back (pattern, doNeedFullComposite, replaceType, replaceStr, doKeepComposite);
304
313
305
314
STOP
306
315
continue ;
@@ -479,6 +488,7 @@ void TriggerTree::Reconstruct(std::string_view matchesString, std::function<void
479
488
STOP
480
489
}
481
490
491
+ mHasRegexMatches = !mRegexMatches .empty ();
482
492
mTreeHeight = height;
483
493
mIsConstructingTriggerTree .store (false );
484
494
if (onFinish && !didCallOnFinish)
@@ -545,6 +555,11 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
545
555
mAgents .reserve (mTreeHeight );
546
556
mNextIterationAgents .reserve (mTreeHeight );
547
557
mStroke .resize (std::max (mTreeHeight , 1U ), 0 );
558
+ if (mHasRegexMatches )
559
+ {
560
+ mStrokeForRegex .clear ();
561
+ mStrokeForRegex .resize (std::max (get_config ().maxStrokeLengthForRegex , 1 ), 0 );
562
+ }
548
563
mRootAgent = { &mTree .front (), static_cast <int >(mTreeHeight ) };
549
564
}
550
565
@@ -562,6 +577,7 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
562
577
if (length >= 0 && inputs[0 ].letter == L' \b ' )
563
578
{
564
579
std::ranges::shift_right (mStroke , 1 );
580
+ std::ranges::shift_right (mStrokeForRegex , 1 );
565
581
566
582
// The input size is bigger than 1 only if letters are composed in the imm simulator.
567
583
// But a backspace can't be used to finish composing(other than clearing one completely),
@@ -645,6 +661,15 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
645
661
return false ;
646
662
};
647
663
664
+ const auto lambdaCheckRegexMatches = [this , length, inputs](wchar_t inputLetter, bool isBeingComposed, int inputIndex)
665
+ {
666
+ for (const auto & [pattern, doNeedFullComposite, replaceType, replaceStr, doKeepComposite] : mRegexMatches )
667
+ {
668
+ }
669
+
670
+ return false ;
671
+ };
672
+
648
673
for (int i = 0 ; i < length; i++)
649
674
{
650
675
const auto [inputLetter, isBeingComposed] = inputs[i];
@@ -653,6 +678,22 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
653
678
{
654
679
std::ranges::shift_left (mStroke , 1 );
655
680
mStroke .back () = inputLetter;
681
+
682
+ if (mHasRegexMatches )
683
+ {
684
+ if (L' 가' <= inputLetter && inputLetter <= L' 힣' )
685
+ {
686
+ std::wstring normalized = Letter::COMPOSITE_ENCLOSURE + normalize_hangeul (std::wstring_view{ &inputLetter, 1 }) + Letter::COMPOSITE_ENCLOSURE;
687
+ const size_t size = normalized.size ();
688
+ std::ranges::shift_left (mStrokeForRegex , size);
689
+ normalized.copy (&*(mStrokeForRegex .end () - size), size);
690
+ }
691
+ else
692
+ {
693
+ std::ranges::shift_left (mStrokeForRegex , 1 );
694
+ mStrokeForRegex .back () = inputLetter;
695
+ }
696
+ }
656
697
}
657
698
658
699
// Check for triggers in the root node first.
@@ -669,6 +710,11 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
669
710
}
670
711
}
671
712
713
+ if (!isTriggerFound)
714
+ {
715
+ isTriggerFound = lambdaCheckRegexMatches (inputLetter, isBeingComposed, i);
716
+ }
717
+
672
718
if (isTriggerFound)
673
719
{
674
720
mNextIterationAgents .clear ();
@@ -692,7 +738,7 @@ void TriggerTree::OnInput(const InputMessage(&inputs)[MAX_INPUT_COUNT], int leng
692
738
void TriggerTree::replaceString (const Ending& ending, const Agent& agent, std::wstring_view stroke,
693
739
const InputMessage (&inputs)[MAX_INPUT_COUNT], int inputLength, int inputIndex, bool doNeedFullComposite)
694
740
{
695
- const auto & [replaceStringIndex, replaceType , replaceStringLength, backspaceCount, cursorMoveCount,
741
+ const auto & [replaceType, replaceStringIndex , replaceStringLength, backspaceCount, cursorMoveCount,
696
742
propagateCase, uppercaseStyle, keepComposite] = ending;
697
743
698
744
const std::wstring_view originalReplaceString{ mReplaceStrings .data () + replaceStringIndex, replaceStringLength };
0 commit comments