Skip to content

Commit

Permalink
beautiful now
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Dec 9, 2024
1 parent 6047c15 commit 27264c7
Showing 1 changed file with 27 additions and 46 deletions.
73 changes: 27 additions & 46 deletions src/textual/fuzzy.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@

from __future__ import annotations

from dataclasses import dataclass, field
from re import IGNORECASE, compile, escape, finditer
from typing import Iterable
from typing import Iterable, NamedTuple

import rich.repr
from rich.style import Style
Expand All @@ -18,19 +17,21 @@
from textual.cache import LRUCache


@dataclass
class FuzzyMatch:
class Search(NamedTuple):
candidate_offset: int = 0
query_offset: int = 0
offsets: list[int] = field(default_factory=list)
offsets: tuple[int, ...] = ()

def advance(self, new_offset: int) -> FuzzyMatch:
return FuzzyMatch(new_offset, self.query_offset, self.offsets.copy())
def branch(self, offset: int) -> tuple[Search, Search]:
return (
Search(offset + 1, self.query_offset + 1, self.offsets + (offset,)),
Search(offset + 1, self.query_offset, self.offsets),
)


def match(
query: str, candidate: str, case_sensitive: bool = False
) -> Iterable[list[int]]:
) -> Iterable[tuple[int, ...]]:
if not case_sensitive:
query = query.lower()
candidate = candidate.lower()
Expand All @@ -49,45 +50,25 @@ def match(
]
)

stack: list[FuzzyMatch] = [FuzzyMatch(0, 0, [])]
stack: list[Search] = [Search()]
push = stack.append
pop = stack.pop
query_size = len(query)

while stack:
match = stack[-1]

if match.candidate_offset >= len(candidate) or match.query_offset >= len(query):
stack.pop()
continue

try:
offset = candidate.index(query[match.query_offset], match.candidate_offset)
except ValueError:
# Current math was unsuccessful
stack.pop()
continue

advance_match = match.advance(offset + 1)
match.offsets.append(offset)
match.candidate_offset = offset + 1
match.query_offset += 1

if match.query_offset == len(query):
# Full match
yield match.offsets.copy()
stack.pop()

stack.append(advance_match)

# else:
# match.candidate_offset += 1
# stack.append(match_copy)

# if query[match.query_offset] == candidate[match.candidate_offset]:
# match_copy = match.copy()
# match_copy.query_offset += 1
# if match_copy.query_offset == len(query):
# yield match_copy.offsets.copy()
# match_copy.offsets.append(match.candidate_offset)
# stack.append(match_copy)
search = stack[-1]
offset = candidate.find(
query[search.query_offset],
search.candidate_offset,
)
if offset == -1:
pop()
else:
advance_branch, stack[-1] = search.branch(offset)
if advance_branch.query_offset == query_size:
yield advance_branch.offsets
else:
push(advance_branch)


@rich.repr.auto
Expand Down Expand Up @@ -214,7 +195,7 @@ def highlight(self, candidate: str) -> Text:
from rich import print
from rich.text import Text

for offsets in match("ee", TEST):
for offsets in match("shot", TEST):
text = Text(TEST)
for offset in offsets:
text.stylize("reverse", offset, offset + 1)
Expand Down

0 comments on commit 27264c7

Please sign in to comment.