Skip to content

fix: apply text replacements that overlap a match inside a word - #140

Open
RaphaelFakhri wants to merge 1 commit into
anomalyco:mainfrom
RaphaelFakhri:fix/text-replacement-overlapping-phrases
Open

RaphaelFakhri wants to merge 1 commit into
anomalyco:mainfrom
RaphaelFakhri:fix/text-replacement-overlapping-phrases

Conversation

@RaphaelFakhri

Copy link
Copy Markdown

Summary

ReplacementSet::replace collected candidates with Regex::find_iter and then dropped matches that fail the word-boundary check. find_iter never revisits a span it has already returned, so a rejected match inside a word hid any overlapping whole-phrase match that starts later in that span.

This affects phrases whose start repeats their end, such as stutter fixes:

  • Rule I I -> I: Hi I I think so. stays unchanged, because i I inside Hi I is found first and rejected.
  • Rule the the -> the: Breathe the the air. stays unchanged, because the the starting inside Breathe is found first and rejected.

The fix searches with Regex::find_at and, after a rejected match, resumes one character after its start. Accepted matches still advance past their end, so selection, ordering, and deletion behavior are unchanged.

Tests

  • Adds a_match_inside_a_word_does_not_hide_an_overlapping_whole_phrase and a_rejected_match_ending_in_a_multibyte_character_resumes_on_a_character_boundary in src/text_replacements.rs.
  • Both new tests fail without the fix (left: "Hi I I think so." and left: "Café é é.") and pass with it. All 7 text_replacements tests pass.
  • cargo fmt --check and git diff --check are clean.

text_replacements is compiled only on macOS. The tests ran on Linux by compiling this exact module file in a scratch crate with a stub TextReplacement and regex = "=1.13.1", plus cargo clippy --all-targets -- -D warnings on that crate. The full macOS cargo test and Clippy run were not performed.

Fixes #139

A literal phrase match that fails the word-boundary check consumed its span, so an overlapping whole-phrase match starting later in that span was never considered. With a rule "I I" -> "I", "Hi I I think" stayed unchanged. Resume the search one character after a rejected match.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Text replacement skips a phrase that overlaps a match inside a word

1 participant