Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
5 changes: 4 additions & 1 deletion doc/source/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ Several options are common to almost all of :program:`khal`'s commands
alarm-symbol
An alarm symbol (alarm clock) if the event has at least one alarm.

alarms-list
A comma-separated list of alarms for the event (e.g., `alarm1@-15m, getready@-1h`).

location
The event location.

Expand Down Expand Up @@ -222,7 +225,7 @@ Several options are common to almost all of :program:`khal`'s commands
end-date-long, end-time, start-full, start-long-full,
start-date-full, start-date-long-full, start-time-full,
end-full, end-long-full, end-date-full, end-date-long-full,
end-time-full, repeat-symbol, location, calendar,
end-time-full, repeat-symbol, alarms-list, location, calendar,
calendar-color, start-style, to-style, end-style,
start-end-time-style, end-necessary, end-necessary-long,
status, cancelled, organizer, url, duration, duration-full,
Expand Down
11 changes: 10 additions & 1 deletion khal/khalendar/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import logging
import os
from collections.abc import Callable
from typing import Any

import icalendar
import icalendar.cal
Expand Down Expand Up @@ -612,7 +613,7 @@ def attributes(
"""
env = env or {}

attributes = {}
attributes: dict[str, Any] = {}
if isinstance(relative_to, tuple):
relative_to_start, relative_to_end = relative_to
else:
Expand Down Expand Up @@ -734,6 +735,14 @@ def attributes(
attributes["repeat-symbol"] = self._recur_str
attributes["repeat-pattern"] = self.recurpattern
attributes["alarm-symbol"] = self._alarm_str
attributes["alarms-list"] = [
{
"delta": alarm[0].total_seconds(),
"description": str(alarm[1]),
"delta-formatted": timedelta2str(alarm[0]),
}
for alarm in self.alarms
]
attributes["status-symbol"] = self._status_str
attributes["partstat-symbol"] = self._partstat_str
attributes["title"] = self.summary
Expand Down
8 changes: 7 additions & 1 deletion khal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ def fmt(rows):
if "calendar-color" in row:
row["calendar-color"] = get_color(row["calendar-color"])

if "alarms-list" in row and isinstance(row["alarms-list"], list):
row["alarms-list"] = ", ".join(
alarm["description"] + "@" + alarm["delta-formatted"]
for alarm in row["alarms-list"]
)

s = format_string.format(**row)

if colors:
Expand Down Expand Up @@ -245,7 +251,7 @@ def fmt(rows):
"end-necessary-long",
"repeat-symbol",
"repeat-pattern",
"title",
"alarms-listtitle",
Comment thread
DhruvaSambrani marked this conversation as resolved.
Outdated
"organizer",
"description",
"location",
Expand Down
24 changes: 24 additions & 0 deletions tests/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,30 @@ def test_list_json(runner):
assert result.output.startswith(expected)


def test_list_alarms(runner):
runner = runner(days=2)
now = dt.datetime.now().strftime("%d.%m.%Y")
runner.invoke(main_khal, f"new {now} 18:00 myevent --alarms -15m,1h".split())
args = ["list", "--format", "{alarms-list}", "--day-format", ""]
result = runner.invoke(main_khal, args)
assert not result.exception
assert result.output.strip() == "@15m, @-1h"


def test_list_alarms_json(runner):
runner = runner()
now = dt.datetime.now().strftime("%d.%m.%Y")
runner.invoke(main_khal, f"new {now} 18:00 myevent --alarms 15m,1h".split())
args = ["list", "--json", "alarms-list"]
result = runner.invoke(main_khal, args)
expected = '[{"alarms-list": [\
{"delta": -900.0, "description": "", "delta-formatted": "-15m"},\
{"delta": -3600.0, "description": "", "delta-formatted": "-1h"}\
]}]'
assert not result.exception
assert result.output.startswith(expected)


def test_search(runner):
runner = runner(days=2)
now = dt.datetime.now().strftime("%d.%m.%Y")
Expand Down
22 changes: 22 additions & 0 deletions tests/event_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,28 @@ def test_event_alarm():
assert event.alarms == [(dt.timedelta(-1, 82800), vText("new event"))]


def test_event_alarm_list():
"""test the content of `alarms-list` attribute"""
event = Event.fromString(_get_text("event_dt_simple"), **EVENT_KWARGS)
assert event.alarms == []
event.update_alarms(
[(dt.timedelta(minutes=30), "alarm 1"), (-dt.timedelta(hours=1, minutes=30), "alarm 2")]
)
attributes = event.attributes(dt.date.today())
assert attributes["alarms-list"] == [
{"delta": 1800.0, "description": "alarm 1", "delta-formatted": "30m"},
{"delta": -5400.0, "description": "alarm 2", "delta-formatted": "-1h -30m"},
]


def test_event_no_alarms_list():
"""test that `alarms-list` is empty for an event with no alarms"""
event = Event.fromString(_get_text("event_dt_simple"), **EVENT_KWARGS)
assert event.alarms == []
attributes = event.attributes(dt.date.today())
assert attributes["alarms-list"] == []


def test_event_attendees():
event = Event.fromString(_get_text("event_dt_simple"), **EVENT_KWARGS)
assert event.attendees == ""
Expand Down
Loading