diff --git a/.jules/bolt.md b/.jules/bolt.md index c6c0104c8..5762283c6 100644 --- a/.jules/bolt.md +++ b/.jules/bolt.md @@ -18,3 +18,6 @@ ## 2024-05-18 - Pre-compile Regex in VoiceInputManager **Learning:** `VoiceInputManager.syncRecognizedText` instantiates `Regex("[,.?!;:]")` inside a frequent method call, increasing allocation pressure on voice typing hot paths. **Action:** Extract repeated `Regex` instantiations in input hot paths (such as `syncRecognizedText`) into companion object private constants to reduce memory allocation and compilation overhead. +## 2024-05-18 - Pre-compile Regex in OCR formatting +**Learning:** `OcrTextFormatter.formatLines` instantiated `Regex` for bullet removal inline every time it was called when `stripBullets` was true. This causes unnecessary allocation and compilation overhead when parsing OCR lines. +**Action:** Extract frequently used formatting regexes (such as `bulletRegex`) into `object` or companion object private constants (`private val BULLET_REGEX`) to optimize regex reuse and eliminate unnecessary compilation per text parsing operation. diff --git a/app/src/main/java/helium314/keyboard/latin/ocr/OcrTextFormatter.kt b/app/src/main/java/helium314/keyboard/latin/ocr/OcrTextFormatter.kt index 705172a9f..ea22593b3 100644 --- a/app/src/main/java/helium314/keyboard/latin/ocr/OcrTextFormatter.kt +++ b/app/src/main/java/helium314/keyboard/latin/ocr/OcrTextFormatter.kt @@ -7,6 +7,8 @@ import java.util.Locale object OcrTextFormatter { + private val BULLET_REGEX = Regex("""^(\s*[-*•–—►▪▫]|\[[ xX]?\]|\d+[\.\)]|[a-zA-Z][\.\)])\s*""") + fun format(context: Context, rawLines: List): List { val prefs = context.prefs() val keepLineBreaks = prefs.getBoolean(OcrPluginLoader.PREF_OCR_KEEP_LINE_BREAKS, true) @@ -51,8 +53,7 @@ object OcrTextFormatter { } } if (stripBullets) { - val bulletRegex = Regex("""^(\s*[-*•–—►▪▫]|\[[ xX]?\]|\d+[\.\)]|[a-zA-Z][\.\)])\s*""") - lines = lines.map { it.replace(bulletRegex, "") } + lines = lines.map { it.replace(BULLET_REGEX, "") } } if (trimWhitespace) { lines = lines.map { it.trim() }.filter { it.isNotEmpty() }