Skip to content

BHoM Tkinter: searchable list box - #255

Open
Felix-Mallinder wants to merge 2 commits into
developfrom
Python_Toolkit-#243-searchable-list-box
Open

Felix-Mallinder wants to merge 2 commits into
developfrom
Python_Toolkit-#243-searchable-list-box

Conversation

@Felix-Mallinder

@Felix-Mallinder Felix-Mallinder commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

NOTE: Depends on

Issues addressed by this PR

Closes #243

Test files

Quick test at the bottom of file

Changelog

  • add SearchableListBox

Additional comments

@Felix-Mallinder Felix-Mallinder self-assigned this Oct 21, 2026
@Felix-Mallinder Felix-Mallinder added the type:feature New capability or enhancement label Oct 21, 2026
@Felix-Mallinder Felix-Mallinder linked an issue Oct 21, 2026 that may be closed by this pull request

@Tom-Kingstone Tom-Kingstone left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see comments below

Comment on lines +34 to +67
def fuzzy_score(query: str, text: str) -> Optional[float]:
"""Score how well `query` matches `text` (higher is better), or None if it does not match.

Every whitespace-separated word of the query must match the text, in one of these ways (best first):
- contained in the text, with a bonus when it starts a word ("lon" in "London_TRY")
- its letters appear in order with only small gaps ("ldn" in "London"), scored down by the gaps
- a close misspelling of one of the text's words ("birmigham" for "Birmingham"), words of 4+ letters
An empty query matches everything with score 0.
"""
text_l = text.lower()
tokens = [t for t in query.lower().split() if t]
if not tokens:
return 0.0
words = [w for w in _WORD_SPLIT.split(text_l) if w]
score = 0.0
for token in tokens:
index = text_l.find(token)
if index >= 0:
starts_word = index == 0 or not text_l[index - 1].isalnum()
score += 100 + (20 if starts_word else 0) - min(index, 20) * 0.5
continue
gaps = _subsequence_gaps(token, text_l)
# Letters in order only count when they are close together, otherwise short words match almost anything.
if gaps is not None and gaps <= max(3, len(token)):
score += max(60 - gaps * 4, 20)
continue
similar = [w for w in words if abs(len(w) - len(token)) <= _TYPO_MAX_LENGTH_DIFF]
if len(token) >= _TYPO_MIN_LENGTH and similar:
ratio = max(difflib.SequenceMatcher(None, token, w).ratio() for w in similar)
if ratio >= _TYPO_MIN_RATIO:
score += ratio * 50
continue
return None
return score

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there not a fuzzy matching library for python? We use one for c# so if you want we could do this via pythonnet instead, I don't see why we need to implement our own fuzzy match method

Comment on lines +164 to +165
def _visible(self) -> List[str]:
return self.list_box.get_options()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this mean???

if you need a private alias for self.list_box.get_options(), you might want to call the method _get_options instead. This will make other methods that use this easier to read

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

Labels

type:feature New capability or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Searchable list box

2 participants