Skip to content
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

issue:#1229 Add multi-keyword search #1377

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ Julian Wollrath
Mattori Birnbaum - me [at] mattori [dot] com - https://mattori.com
Pi R
Alnoman Kamil - noman [at] kamil [dot] gr - https://kamil.gr
Johan XU - xujohan [at] outlook [dot] fr
23 changes: 23 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@ Package maintainers and users who have to manually update their installation
may want to subscribe to `GitHub's tag feed
<https://github.com/geier/khal/tags.atom>`_.

####################################
Added Multi-Keyword Search Capability

Support for multi-keyword search:
The search in command cli.py has been updated to accept a list of search terms
(SEARCH_STRINGS) instead of a single term (SEARCH_STRING). This allows users
to search for events matching one or more specified keywords.

Key Changes:

Replaced search_string argument:
The single search_string argument has been replaced with search_strings,
enabling variable-length keyword input (nargs=-1).
Each search term is processed in a loop, and matching results are added to a
unified set of events.

Consolidation of search results:
Events matching each keyword are combined using a set (all_events) to eliminate
duplicates.
A new event_set is introduced to ensure that events with identical descriptions
are displayed only once.
The final results are sorted and displayed.

0.11.4
======
not released yet
Expand Down
23 changes: 15 additions & 8 deletions khal/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,9 @@ def printics(ctx, ics, format):
@click.option('--format', '-f',
help=('The format of the events.'))
@click.option('--json', help=("Fields to output in json"), multiple=True)
@click.argument('search_string')
@click.argument('search_strings', nargs=-1)
@click.pass_context
def search(ctx, format, json, search_string, include_calendar, exclude_calendar):
def search(ctx, format, json, search_strings, include_calendar, exclude_calendar):
'''Search for events matching SEARCH_STRING.

For recurring events, only the master event and different overwritten
Expand All @@ -461,7 +461,10 @@ def search(ctx, format, json, search_string, include_calendar, exclude_calendar)
ctx.obj['conf'],
multi_calendar_select(ctx, include_calendar, exclude_calendar)
)
events = sorted(collection.search(search_string))
all_events = set()
for term in search_strings:
all_events.update(collection.search(term))
events = sorted(all_events)
event_column = []
term_width, _ = get_terminal_size()
now = dt.datetime.now()
Expand All @@ -470,14 +473,18 @@ def search(ctx, format, json, search_string, include_calendar, exclude_calendar)
formatter = human_formatter(format)
else:
formatter = json_formatter(json)
events_set = set()
for event in events:
desc = textwrap.wrap(formatter(
event.attributes(relative_to=now, env=env)), term_width)
event_column.extend(
[colored(d, event.color,
bold_for_light_color=ctx.obj['conf']['view']['bold_for_light_color'])
for d in desc]
)
event_key = ' '.join(desc)
if event_key not in events_set:
events_set.add(event_key)
event_column.extend(
[colored(d, event.color,
bold_for_light_color=ctx.obj['conf']['view']['bold_for_light_color'])
for d in desc]
)
if event_column:
click.echo('\n'.join(event_column))
else:
Expand Down
26 changes: 26 additions & 0 deletions tests/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,3 +1018,29 @@ def test_list_now(runner, tmpdir):

result = runner.invoke(main_khal, ['list', 'now'])
assert not result.exception

def test_multi_keyword_search(runner):
"""
Test the multi-keyword search functionality with event deduplication.
"""
runner = runner()

result = runner.invoke(main_khal, "new 14.12.2024 10:00-11:00 meeting conference".split())
assert not result.exception
result = runner.invoke(main_khal, "new 14.12.2024 12:00-13:00 birthday".split())
assert not result.exception
result = runner.invoke(main_khal, "new 14.12.2024 10:00-11:00 duplicate meeting".split())
assert not result.exception

search_args = ['search', 'meeting', 'conference']
result = runner.invoke(main_khal, search_args)

expected_output = [
"14.12.2024 10:00-11:00: meeting conference",
"14.12.2024 10:00-11:00 duplicate meeting"
]
output_lines = result.output.strip().split('\n')
assert sorted(output_lines) == sorted(expected_output), (
f"Expected: {expected_output}, Got: {output_lines}"
)
assert not result.exception