summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Stone <1611702+d7415@users.noreply.github.com>2021-04-27 14:58:20 +0100
committerGitHub <noreply@github.com>2021-04-27 14:58:20 +0100
commitf517b4bdc64ddd2c0252a9c053d1499e72268edc (patch)
tree9bc7ec16216abd5503395881109a3ade0ed6cdd0
parentee507a374d9d09f4d68a955e8a4381ed6a8ef368 (diff)
parent0540f7bac3ef65e8fc83372ad9d76ee71e8710a1 (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.rst1
-rw-r--r--doc/source/usage.rst5
-rw-r--r--khal/cli.py5
-rw-r--r--khal/controllers.py13
-rw-r--r--khal/icalendar.py6
-rw-r--r--khal/khalendar/event.py13
-rw-r--r--khal/ui/__init__.py3
-rw-r--r--khal/ui/editor.py5
-rw-r--r--tests/event_test.py23
-rw-r--r--tests/ics/event_dt_url.ics12
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