Skip to content

Searchable, Filterable List with Selection Callbacks #653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from

Conversation

badranX
Copy link
Contributor

@badranX badranX commented Feb 13, 2025

This is related to #73. This patch adds support for filtering choices. It adds a new component, FilterList, instead of modifying the existing List. FilterList enables searching/filtering dynamically. FilterList also provides a callback that triggers when the user moves between choices.

Note: I tried to minimize changes to the original library files to avoid increasing complexity. I need this for a personal project, it would be nice to just import this library.

Edit: Please tell me it's possible to integrate these changes, so I can continue writing docs/tests for it.

@Cube707
Copy link
Collaborator

Cube707 commented Mar 10, 2025

please rebase onto current master

Copy link
Collaborator

@Cube707 Cube707 left a comment

Choose a reason for hiding this comment

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

currently broken:

  • not all elements get cleared after filtering
  • pressing space resets the filtering, but doesn't remove the hint

Comment on lines 5 to 11
try:
from fuzzyfinder import fuzzyfinder
except ImportError:
raise ImportError(
"The required package 'fuzzyfinder' is not installed. Install it using:\n\n"
" pip install fuzzyfinder\n"
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I am not the biggest fan of this.
I get where you comming with thee examples not beeing a real dependency, I would still prefere a more proper version

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed this :)


def filter_func(text, collection):
g = fuzzyfinder(text, collection, accessor=lambda x: str(x))
return list(g)
Copy link
Collaborator

Choose a reason for hiding this comment

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

why does this require a cast to list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed the cast 👍

Comment on lines 37 to 39
def callback_listener(item):
with open('choice_logs.txt', 'a') as f:
f.write(str(item) + '\n')
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would prefer a demo to not write stuff to disk

How about updating a global var and printing that at the end?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to a global var and simplified the example 👍

Comment on lines 80 to 84
def apply_filter(self, filter_func):
self._filtered_choices = filter_func(self.unfiltered_choices_generator)

def remove_filter(self):
self._filtered_choices = None
Copy link
Collaborator

Choose a reason for hiding this comment

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

these are only relevant to the new class and shouldn't be inherited by every type of question

Comment on lines 100 to 105
choices = self._filtered_choices or self._choices
for choice in self._solve(choices):
yield (TaggedValue(*choice) if isinstance(choice, tuple) and len(choice) == 2 else choice)

@property
def unfiltered_choices_generator(self):
Copy link
Collaborator

Choose a reason for hiding this comment

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

same here, override the property for the new class instead of adding a new, second property and adding overhead to all other classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I isolated all filter_list features away from other classes.

@@ -42,6 +41,7 @@ def render(self, question, answers=None):
def _event_loop(self, render):
try:
while True:
self.clear_eos()
Copy link
Collaborator

Choose a reason for hiding this comment

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

not sure if this a unintended side effects, I will have to think about this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I removed this change in the last commit. Clearing is done in _filter_list.py though now

@badranX
Copy link
Contributor Author

badranX commented Mar 10, 2025

Thanks for the insightful review! I'll get back to this PR as soon as possible.

@badranX
Copy link
Contributor Author

badranX commented Mar 14, 2025

FIxed the issues and I isolated filter_list features away from everything else like you asked. I hope it's ok like this. I'm not sure about delegating clearing to _filter_list, but at least it won't affect anything else.
I'll write tests/docs in my next free time 😅

@badranX
Copy link
Contributor Author

badranX commented Mar 23, 2025

  • Removed the "Selection Callbacks" part. I think it's not important.
  • Overloaded the single FilterList example with tag/hints/carousel/other features.
  • Added 0 change to the original behaviour of the library, this PR can be reverted easily if proved hard to maintain.
  • On not found, it returns the user "not-found" query, similar to +Other.

Please tell me if docs are needed or any other changes. Since it behaves similarly to List, I think the example is enough.

Edit:

  • The commit history is large, squashing into a single commit would be an option.
  • A lot of repeated code between List & FilterList specially in tests.

@badranX badranX requested a review from Cube707 April 18, 2025 08:27
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.

2 participants