-
-
Notifications
You must be signed in to change notification settings - Fork 264
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
Add support for keywords in searchbar #1258
base: main
Are you sure you want to change the base?
Conversation
d0a9d62
to
0074cb4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mounilKshah This does work better 👍
I've left feedback mainly on the second commit since it represents better the final state you have right now.
For tests on the current-narrow -> search-text function, the inputs for cases should be achievable from browsing how we handle non-search narrows.
I'd suggest you first split into commits to add each function, then use them together in core.py for 3 commits. Then some tests for each new function in the relevant commit. Covering streams/topics with tests would be good first. More narrow cases may flow quicker once you have the general code/test format :)
zulipterminal/core.py
Outdated
# if the user is currently inside a narrow, update search text to accomodate that | ||
if len(self.model.narrow) > 0: | ||
final_search_query = self.update_search_text_for_narrow(text) | ||
search_query, search_narrow = self.check_for_prefixes(final_search_query) | ||
self.model.narrow = search_narrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note the conditional fails right now if in all messages - I know that's not covered yet :)
Your logic appears to be as follows, so let me know if there's a difference. The first method, which you've prefixed with update_
, adds text onto the search query text
and returns it. The second method extracts the special prefixes in the result, and converts to the tuple. Also, this PR force sets the narrow - so we need to be extra careful there, like in the previous iteration where it was set to all-messages if no stream (search) text was entered!
If the logic as described above is correct, it probably sounds rather complex, difficult to test, and maybe you even wonder why I suggested this approach?
The difference is that we don't need to pass the original search text between functions here. The fundamental operations are:
- generate search text for current narrow (the model knows the current narrow, so no args)
- combine that text with the (current) user-entered search text
- translate total search text into
<some format for doing search>
(the tuple right now)
This means the first function can be tested very easily given a list of 'standard' non-search narrows we support, and the last with expected inputs from the first (along with various search strings). So depending how you express this, 3 commits might be appropriate in the end.
Later, the first function can be used to prefill the UI instead :)
zulipterminal/core.py
Outdated
# In cases where '+' is already present in stream and/or topic name, it is converted to '%2B' | ||
# then the spaces in stream and topic names are converted to '+' | ||
if self.model.narrow[0][0] == "stream": | ||
search_query += f" {self.model.narrow[0][0]}:{self.model.narrow[0][1].replace('+', '%2B').replace(' ', '+')}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The logic here may change, but note that due to the guaranteed equality, we can use
"stream"
instead to simplify. - It may also be clearer generally if you express what large expressions, here with the replace methods represent (ie. with a new variable) and why it's there (by name?).
zulipterminal/core.py
Outdated
search_query += f" {self.model.narrow[0][0]}:{self.model.narrow[0][1].replace('+', '%2B').replace(' ', '+')}" | ||
if len(self.model.narrow) > 1: | ||
if self.model.narrow[1][0] == "topic": | ||
self.model.narrow[1][1].replace(" ", "+") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be a duplicate?
zulipterminal/core.py
Outdated
self.model.narrow[1][1].replace(" ", "+") | ||
search_query += f" {self.model.narrow[1][0]}:{self.model.narrow[1][1].replace('+', '%2B').replace(' ', '+')}" | ||
return search_query | ||
|
||
def check_for_prefixes(self, query: str) -> Tuple[str, List[List[str]]]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name while WIP doesn't matter too much, but now we're firming up the logic, let's make this name more expressive. If I see check_for_prefixes(something)
in code, it doesn't tell me what it does (I can think of various meanings), or why it returns what it does do - I can look it up in an editor or IDE, but better to read right there :)
So, maybe think what goes in the blank:
search_query, search_narrow = self.<BLANK>(final_search_query)
While some/many ZT functions don't have docstrings (or comments) since they're older, some are very simple and ideally well-named that it may be sufficient to understand what's happening when they're used without them.
You might also rename the other function, if you change the logic of what it does.
zulipterminal/core.py
Outdated
new_narrow.append(word.split(":")) | ||
new_narrow.append( | ||
[ | ||
word.split(":")[0], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're doing the same word.split operation a lot here, potentially repeatedly, and it likely will appear in other branches I suspect :)
0074cb4
to
20011a7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mounilKshah This looks more readable and complete, including with the tests 👍
Once you finish the code and tests for the few existing narrows, along with the final (refactor) commit to replace the existing functions with the new functions, this will be mergeable. The functionality may not seem changed, but this refactor will enable supporting more search options in future :)
Note for tests, if you note the changes to tests (separate line) in the git log, there's no need to include it in the commit title.
b43fb25
to
1c8c832
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mounilKshah The extra commit means I can test this, and it appears to work fairly well from manual testing - and the test cases are reassuring too 👍
I left some final comments. This is essentially mergeable with some textual adjustments, it's only my concern re unexpectedly safely/unsafely changing the narrow or not, due to this likely being the end of the Summer work on this.
zulipterminal/core.py
Outdated
text_without_keyword, search_narrow = self.extract_keywords_from_search_query( | ||
modified_search_text | ||
) | ||
self.model.narrow = search_narrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My primary remaining concern, given we're potentially taking a pause on this after your work, is this direct setting of the narrow here. Doing so means we potentially don't update other data which would otherwise be set, via eg. model.set_narrow or _narrow_to or something which also updated the UI.
Right now the positive is that the narrow shouldn't change, unless a user enters extra search text - and not all combinations work. For now I'd suggest we alert the user with a simple warning popup (popup_with_message), if the search looks like a complicated search which would require setting the narrow, ie. if the old and new narrows wouldn't match.
Examples of cases where this can happen is being in all messages, and adding eg. is:starred some search text
, in which case the narrow changes. That 'works', but then adding stream:general
or similar does not. So it'd be good to be consistent for now.
b830a53
to
4bba34d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mounilKshah I'd apparently started a review for this but not finished, so just did so. Looks close to a safe refactor.
I thought we might be able to progress further with just search-specific narrow details. We may be able to and you're welcome to investigate, but we may need to refactor the narrow handling more first. Right now that's spread over many locations, possibly with duplicate logic.
for word in query.split(" "): | ||
if word.startswith("stream:"): | ||
stream_prefix_present_flag = True | ||
stream = word.split(":")[1].replace("+", " ").replace("%2B", "+") | ||
self.set_narrow(stream=stream) | ||
elif word.startswith("topic:") and stream_prefix_present_flag: | ||
topic = word.split(":")[1].replace("+", " ").replace("%2B", "+") | ||
self.set_narrow(stream=stream, topic=topic) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can lead to lead to two narrowing operations for a topic narrow. That's not necessarily bad, but it should be noted, or else worked around.
zulipterminal/model.py
Outdated
def extract_keywords_from_search_query(self, query: str) -> str: | ||
""" | ||
This function checks for prefixes in the search string and returns | ||
a newly created narrow as per the prefixes and the query without the prefixes. | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update this name given the new implementation.
zulipterminal/model.py
Outdated
@@ -285,6 +285,38 @@ def is_search_narrow(self) -> bool: | |||
""" | |||
return "search" in [subnarrow[0] for subnarrow in self.narrow] | |||
|
|||
def extract_keywords_from_search_query(self, query: str) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function no longer just extracts keywords, it also sets the base narrow.
zulipterminal/model.py
Outdated
@@ -278,6 +278,31 @@ def get_focus_in_current_narrow(self) -> Union[int, Set[None]]: | |||
def set_focus_in_current_narrow(self, focus_message: int) -> None: | |||
self.index["pointer"][repr(self.narrow)] = focus_message | |||
|
|||
def addtional_search_text_for_current_narrow(self) -> str: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling?
([["stream", "Stream 1"]], [["stream", "Stream 1"], ["search", "FOO"]]), | ||
( | ||
[["pm_with", "foo@zulip.com"], ["search", "BOO"]], | ||
[["pm_with", "foo@zulip.com"], ["search", "FOO"]], | ||
[["pm_with", "person1@example.com"], ["search", "BOO"]], | ||
[["pm_with", "person1@example.com"], ["search", "FOO"]], | ||
), | ||
( | ||
[["stream", "PTEST"], ["topic", "RDS"]], | ||
[["stream", "PTEST"], ["topic", "RDS"], ["search", "FOO"]], | ||
[["stream", "Stream 1"], ["topic", "RDS"]], | ||
[["stream", "Stream 1"], ["topic", "RDS"], ["search", "FOO"]], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these changes just tidying, or required? If tidying, better to keep in a separate commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are required changes. The final_narrow
is created only when the narrow exists in the org, else the test case fails.
This commit contains Model.extract_keywords_from_search_query() which is used to extract keywords written in the search query and sets the narrow accordingly. Tests are also included in this commit.
This commit contains Model.addtional_search_text_for_current_narrow() which generates string from the current narrow. Tests for the function have also been added.
4bba34d
to
3c73a6b
Compare
This commit contains function calls used to modify search text entered, as per the current narrow. Tests have also been updated accordingly.
3c73a6b
to
912bcbc
Compare
Hello @mounilKshah, it seems like you have referenced #638 in your pull request description, but you have not referenced them in your commit message description(s). Referencing an issue in a commit message automatically closes the corresponding issue when the commit is merged, which makes the issue tracker easier to manage. Please run An example of a correctly-formatted commit:
To learn how to write a great commit message, please refer to our guide. |
Heads up @mounilKshah, we just merged some commits that conflict with the changes you made in this pull request! You can review this repository's recent commits to see where the conflicts occur. Please rebase your feature branch against the |
What does this PR do?
This PR is to add support for keywords in search bar.
Fixes #638
Channel discussion:
Expand search support #T638 #T1258
Tested?
Commit flow
Notes & Questions