Skip to content

Commit

Permalink
refactor: add find_spans
Browse files Browse the repository at this point in the history
  • Loading branch information
Nytelife26 committed Jul 20, 2024
1 parent d4f2ee4 commit bb766a6
Showing 1 changed file with 20 additions and 8 deletions.
28 changes: 20 additions & 8 deletions proselint/checks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -357,21 +357,33 @@ def check_matching_quotes(chars: tuple[str, str]) -> bool:
)


@functools.lru_cache
def find_quoted_ranges(text: str) -> list[tuple[int, int]]:
"""Find the range of a quote pair."""
active_quotes: list[tuple[str, int]] = [
(_m.group(0), _m.start()) for _m in re.finditer(r"[\"'“”]", text)
# NOTE: regex implementation is ~3x faster than previously, but this could
# still be optimized further.
return find_spans(text, r"[\"'“”]", check_matching_quotes)


# TODO: allow this to return unmatched spans, to provide a way to check for
# entries that are unmatched, like in misc.braces
def find_spans(
text: str, regex: str, predicate: Callable[[tuple[str, str]], bool]
) -> list[tuple[int, int]]:
"""Find spans of matching characters (e.g. braces, quotes)."""
active: list[tuple[str, int]] = [
(_m.group(0), _m.start()) for _m in re.finditer(regex, text)
]
prev_quotes: list[tuple[str, int]] = []
prev: list[tuple[str, int]] = []
spans: list[tuple[int, int]] = []
for quote, span_end in active_quotes:
for potential, span_start in reversed(prev_quotes):
if check_matching_quotes((quote, potential)):
prev_quotes.pop()
for char, span_end in active:
for potential, span_start in reversed(prev):
if predicate((char, potential)):
prev.pop()
spans.append((span_start, span_end))
break
else:
prev_quotes.append((quote, span_end))
prev.append((char, span_end))
return spans


Expand Down

0 comments on commit bb766a6

Please sign in to comment.