diff options
author | Martin Stone <1611702+d7415@users.noreply.github.com> | 2021-04-27 14:58:20 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-27 14:58:20 +0100 |
commit | f517b4bdc64ddd2c0252a9c053d1499e72268edc (patch) | |
tree | 9bc7ec16216abd5503395881109a3ade0ed6cdd0 | |
parent | ee507a374d9d09f4d68a955e8a4381ed6a8ef368 (diff) | |
parent | 0540f7bac3ef65e8fc83372ad9d76ee71e8710a1 (diff) |
Merge pull request #965 from ephase/feature/946
Add `--url` option for `khal new` and `{url}` for format in command line. Closes #946.
-rw-r--r-- | CHANGELOG.rst | 1 | ||||
-rw-r--r-- | doc/source/usage.rst | 5 | ||||
-rw-r--r-- | khal/cli.py | 5 | ||||
-rw-r--r-- | khal/controllers.py | 13 | ||||
-rw-r--r-- | khal/icalendar.py | 6 | ||||
-rw-r--r-- | khal/khalendar/event.py | 13 | ||||
-rw-r--r-- | khal/ui/__init__.py | 3 | ||||
-rw-r--r-- | khal/ui/editor.py | 5 | ||||
-rw-r--r-- | tests/event_test.py | 23 | ||||
-rw-r--r-- | tests/ics/event_dt_url.ics | 12 |
10 files changed, 78 insertions, 8 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a465025a..623b6465 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,6 +24,7 @@ not released `blank_line_before_day` option * FIX `new` keybinding in search no longer crash `ikhal` * NEW Improved sorting of events. Sort by `DTSTART`, `DTEND` then `SUMMARY`. +* NEW Add url input and `{url}` template option 0.10.2 ====== diff --git a/doc/source/usage.rst b/doc/source/usage.rst index 52c8ada4..af77cfb1 100644 --- a/doc/source/usage.rst +++ b/doc/source/usage.rst @@ -162,6 +162,9 @@ Several options are common to almost all of :program:`khal`'s commands returns name@mail.com + url + The URL embedded in the event, otherwise nothing. + By default, all-day events have no times. To see a start and end time anyway simply add `-full` to the end of any template with start/end, for instance `start-time` becomes `start-time-full` and will always show start and end times (instead @@ -409,6 +412,8 @@ Options * **-u, --until=UNTIL** specify until when a recurring event should run +* **--url** specify the URL element of the event + * **--alarms DURATION,...** will add alarm times as DELTAs comma separated for this event, *DURATION* should look like `1day 10minutes` or `1d3H10m`, negative *DURATIONs* will set alarm after the start of the event. diff --git a/khal/cli.py b/khal/cli.py index a49e68d2..e56f793c 100644 --- a/khal/cli.py +++ b/khal/cli.py @@ -345,10 +345,12 @@ def _get_cli(): help=('The format to print the event.')) @click.option('--alarms', '-m', help=('Alarm times for the new event as DELTAs comma separated')) + @click.option('--url', help=("URI for the event.")) @click.argument('info', metavar='[START [END | DELTA] [TIMEZONE] [SUMMARY] [:: DESCRIPTION]]', nargs=-1) @click.pass_context - def new(ctx, calendar, info, location, categories, repeat, until, alarms, format, interactive): + def new(ctx, calendar, info, location, categories, repeat, until, alarms, url, format, + interactive): '''Create a new event from arguments. START and END can be either dates, times or datetimes, please have a @@ -394,6 +396,7 @@ def _get_cli(): env={"calendars": ctx.obj['conf']['calendars']}, until=until, alarms=alarms, + url=url, format=format, ) except FatalError as error: diff --git a/khal/controllers.py b/khal/controllers.py index e4dbc472..56cd8baf 100644 --- a/khal/controllers.py +++ b/khal/controllers.py @@ -280,7 +280,7 @@ def khal_list(collection, daterange=None, conf=None, agenda_format=None, def new_interactive(collection, calendar_name, conf, info, location=None, categories=None, repeat=None, until=None, alarms=None, - format=None, env=None): + format=None, env=None, url=None): try: info = parse_datetime.eventinfofstr( info, conf['locale'], @@ -333,7 +333,7 @@ def new_interactive(collection, calendar_name, conf, info, location=None, event = new_from_args( collection, calendar_name, conf, format=format, env=env, location=location, categories=categories, - repeat=repeat, until=until, alarms=alarms, + repeat=repeat, until=until, alarms=alarms, url=url, **info) echo("event saved") @@ -344,7 +344,7 @@ def new_interactive(collection, calendar_name, conf, info, location=None, def new_from_string(collection, calendar_name, conf, info, location=None, categories=None, repeat=None, until=None, alarms=None, - format=None, env=None): + url=None, format=None, env=None): """construct a new event from a string and add it""" info = parse_datetime.eventinfofstr( info, conf['locale'], @@ -355,14 +355,14 @@ def new_from_string(collection, calendar_name, conf, info, location=None, new_from_args( collection, calendar_name, conf, format=format, env=env, location=location, categories=categories, repeat=repeat, - until=until, alarms=alarms, **info + until=until, alarms=alarms, url=url, **info ) def new_from_args(collection, calendar_name, conf, dtstart=None, dtend=None, summary=None, description=None, allday=None, location=None, categories=None, repeat=None, until=None, alarms=None, - timezone=None, format=None, env=None): + timezone=None, url=None, format=None, env=None): """Create a new event from arguments and add to vdirs""" if isinstance(categories, str): categories = list([category.strip() for category in categories.split(',')]) @@ -370,7 +370,7 @@ def new_from_args(collection, calendar_name, conf, dtstart=None, dtend=None, event = new_vevent( locale=conf['locale'], location=location, categories=categories, repeat=repeat, until=until, alarms=alarms, dtstart=dtstart, - dtend=dtend, summary=summary, description=description, timezone=timezone, + dtend=dtend, summary=summary, description=description, timezone=timezone, url=url, ) except ValueError as error: raise FatalError(error) @@ -428,6 +428,7 @@ def edit_event(event, collection, locale, allow_quit=False, width=80): options["categories"] = {"short": "c", "attr": "categories", "none": True} options["alarm"] = {"short": "a"} options["Delete"] = {"short": "D"} + options["url"] = {"short": "u", "attr": "url", "none": True} now = dt.datetime.now() diff --git a/khal/icalendar.py b/khal/icalendar.py index 735f4ce9..121c07ee 100644 --- a/khal/icalendar.py +++ b/khal/icalendar.py @@ -71,7 +71,7 @@ def split_ics(ics, random_uid=False, default_timezone=None): def new_event(locale, dtstart=None, dtend=None, summary=None, timezone=None, allday=False, description=None, location=None, categories=None, - repeat=None, until=None, alarms=None): + repeat=None, until=None, alarms=None, url=None): """create a new event :param dtstart: starttime of that event @@ -87,6 +87,8 @@ def new_event(locale, dtstart=None, dtend=None, summary=None, timezone=None, :param allday: if set to True, we will not transform dtstart and dtend to datetime :type allday: bool + :param url: url of the event + :type url: string :returns: event :rtype: icalendar.Event """ @@ -116,6 +118,8 @@ def new_event(locale, dtstart=None, dtend=None, summary=None, timezone=None, event.add('location', location) if categories: event.add('categories', categories) + if url: + event.add('url', icalendar.vUri(url)) if repeat and repeat != "none": rrule = rrulefstr(repeat, until, locale) event.add('rrule', rrule) diff --git a/khal/khalendar/event.py b/khal/khalendar/event.py index 8c5f6ff3..79991daa 100644 --- a/khal/khalendar/event.py +++ b/khal/khalendar/event.py @@ -322,6 +322,18 @@ class Event(object): else: return email + @property + def url(self): + if 'URL' not in self._vevents[self.ref]: + return '' + return self._vevents[self.ref]['URL'] + + def update_url(self, url): + if url: + self._vevents[self.ref]['URL'] = url + else: + self._vevents[self.ref].pop('URL') + @staticmethod def _create_calendar(): """ @@ -618,6 +630,7 @@ class Event(object): attributes["all-day"] = allday attributes["categories"] = self.categories attributes['uid'] = self.uid + attributes['url'] = self.url if "calendars" in env and self.calendar in env["calendars"]: cal = env["calendars"][self.calendar] diff --git a/khal/ui/__init__.py b/khal/ui/__init__.py index ddf987e1..b08a17de 100644 --- a/khal/ui/__init__.py +++ b/khal/ui/__init__.py @@ -960,6 +960,9 @@ class EventDisplay(urwid.WidgetWrap): if event.categories != '': lines.append(urwid.Text('Categories: ' + event.categories)) + if event.url != '': + lines.append(urwid.Text('URL: ' + event.url)) + # start and end time/date if event.allday: startstr = event.start_local.strftime(self._conf['locale']['dateformat']) diff --git a/khal/ui/editor.py b/khal/ui/editor.py index 058226b3..c278eb67 100644 --- a/khal/ui/editor.py +++ b/khal/ui/editor.py @@ -339,6 +339,7 @@ class EventEditor(urwid.WidgetWrap): self.description = event.description self.location = event.location self.categories = event.categories + self.url = event.url self.startendeditor = StartEndEditor( event.start_local, event.end_local, self._conf, self.start_datechange, self.end_datechange, @@ -376,6 +377,9 @@ class EventEditor(urwid.WidgetWrap): self.categories = urwid.AttrMap(ExtendedEdit( caption=('', 'Categories: '), edit_text=self.categories), 'edit' ) + self.url = urwid.AttrMap(ExtendedEdit( + caption=('', 'URL: '), edit_text=self.url), 'edit' + ) self.alarms = AlarmsEditor(self.event) self.pile = NListBox(urwid.SimpleFocusListWalker([ self.summary, @@ -384,6 +388,7 @@ class EventEditor(urwid.WidgetWrap): self.location, self.categories, self.description, + self.url, divider, self.startendeditor, self.recurrenceeditor, diff --git a/tests/event_test.py b/tests/event_test.py index 943fff32..3de88ca2 100644 --- a/tests/event_test.py +++ b/tests/event_test.py @@ -56,6 +56,17 @@ def test_update_simple(): assert normalize_component(event.raw) == normalize_component(event_updated.raw) +def test_add_url(): + event = Event.fromString(_get_text('event_dt_simple'), **EVENT_KWARGS) + event.update_url('https://github.com/pimutils/khal') + assert 'URL:https://github.com/pimutils/khal' in event.raw + + +def test_get_url(): + event = Event.fromString(_get_text('event_dt_url'), **EVENT_KWARGS) + assert event.url == "https://github.com/pimutils/khal" + + def test_no_end(): """reading an event with neither DTEND nor DURATION""" event = Event.fromString(_get_text('event_dt_no_end'), **EVENT_KWARGS) @@ -77,6 +88,12 @@ def test_do_not_save_empty_description(): assert 'DESCRIPTION' not in event.raw +def test_do_not_save_empty_url(): + event = Event.fromString(_get_text('event_dt_simple'), **EVENT_KWARGS) + event.update_url('') + assert 'URL' not in event.raw + + def test_remove_existing_location_if_set_to_empty(): event = Event.fromString(_get_text('event_dt_simple_updated'), **EVENT_KWARGS) event.update_location('') @@ -89,6 +106,12 @@ def test_remove_existing_description_if_set_to_empty(): assert 'DESCRIPTION' not in event.raw +def test_remove_existing_url_if_set_to_empty(): + event = Event.fromString(_get_text('event_dt_url'), **EVENT_KWARGS) + event.update_url('') + assert 'URL' not in event.raw + + def test_update_remove_categories(): event = Event.fromString(_get_text('event_dt_simple_updated'), **EVENT_KWARGS) event_nocat = Event.fromString(_get_text('event_dt_simple_nocat'), **EVENT_KWARGS) diff --git a/tests/ics/event_dt_url.ics b/tests/ics/event_dt_url.ics new file mode 100644 index 00000000..b2cf7ca3 --- /dev/null +++ b/tests/ics/event_dt_url.ics @@ -0,0 +1,12 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//PIMUTILS.ORG//NONSGML khal / icalendar //EN +BEGIN:VEVENT +SUMMARY:An Event +URL:https://github.com/pimutils/khal +DTSTART;TZID=Europe/Berlin;VALUE=DATE-TIME:20140409T093000 +DTEND;TZID=Europe/Berlin;VALUE=DATE-TIME:20140409T103000 +DTSTAMP;VALUE=DATE-TIME:20140401T234817Z +UID:V042MJ8B3SJNFXQOJL6P53OFMHJE8Z3VZWOU +END:VEVENT +END:VCALENDAR |