On Thu, 7 Feb 2019 at 13:30, Nicolas Goaziou <m...@nicolasgoaziou.fr> wrote:
> If you think that's a feature Org ought to provide, please consider > sending a patch about it. Well, certainly. I may not have had the best discipline in writing these, so turning them into patches is a bit painful. Let me know if I can make things better. (I believe my FSF paperwork is still alright, if need be.) PATCHES 0001 & 0006 ox-icalendar.el: Enable bumping overdue TODOs and deadline warnings. * lisp/ox-icalendar.el (org-icalendar-bump-todos, org-icalendar-warn-deadlines): New customizable variables. (org-icalendar-today-timestamp, org-icalendar-days-until-timestamp): New internal functions. (org-icalendar-entry): Implement behavior. * doc/org-manual.org (iCalendar Export): Document. -------------------------------------------------------------------------------- PATCHES 0002 & 0005 ox-icalendar.el: Use tags in summary, if so desired. * lisp/ox-icalendar.el (org-icalendar-summary-uses-tags): New customizable variable. (org-icalendar-entry): Implement behavior. * doc/org-manual.org (iCalendar Export): Document. -------------------------------------------------------------------------------- PATCH 0003 ox-icalendar.el: Add a VTIMEZONE block. * lisp/ox-icalendar.el (org-icalendar--vcalendar): Add a VTIMEZONE block.
From c7c0f17d0902d3d89503d1dc24f248ee9bdfab1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= <mich...@cadilhac.name> Date: Thu, 7 Feb 2019 12:20:51 +0000 Subject: [PATCH 3/6] Be a bit more compliant with iCalendar standard by having a VTIMEZONE block. --- lisp/ox-icalendar.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el index 5e7f2804a..a5b586434 100644 --- a/lisp/ox-icalendar.el +++ b/lisp/ox-icalendar.el @@ -897,11 +897,15 @@ X-WR-CALNAME:%s PRODID:-//%s//Emacs with Org mode//EN X-WR-TIMEZONE:%s X-WR-CALDESC:%s -CALSCALE:GREGORIAN\n" +CALSCALE:GREGORIAN +BEGIN:VTIMEZONE +TZID:%s +END:VTIMEZONE\n" (org-icalendar-cleanup-string name) (org-icalendar-cleanup-string owner) (org-icalendar-cleanup-string tz) - (org-icalendar-cleanup-string description)) + (org-icalendar-cleanup-string description) + (org-icalendar-cleanup-string tz)) contents "END:VCALENDAR\n")) -- 2.19.2
From 80f013e60b6a0330c5f13402ef46b1b4a68ce6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= <mich...@cadilhac.name> Date: Thu, 7 Feb 2019 12:19:28 +0000 Subject: [PATCH 1/6] Introduce ways to bump overdue TODOs today, and warn of forthcoming deadlines. --- lisp/ox-icalendar.el | 99 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el index 3d6d0b263..2bf2cd89a 100644 --- a/lisp/ox-icalendar.el +++ b/lisp/ox-icalendar.el @@ -119,6 +119,20 @@ This is a list with possibly several symbols in it. Valid symbols are: (const :tag "SCHEDULED in TODO entries become start date" todo-start))) +(defcustom org-icalendar-bump-todos nil + "Non-nil means that pending TODO VEVENTs are bumped to today. +In addition, if non-nil, the number of late days is indicated in the summary." + :group 'org-export-icalendar + :type 'boolean) + +(defcustom org-icalendar-warn-deadlines nil + "Non-nil means that a new VEVENT is created today to warn for deadlines. +This only applies to TODOs that are not done. Relies on +`org-deadline-warning-days' for the number of days during which the warning +is created." + :group 'org-export-icalendar + :type 'boolean) + (defcustom org-icalendar-categories '(local-tags category) "Items that should be entered into the \"categories\" field. @@ -481,6 +495,28 @@ or subject for the event." (concat folded-line "\r\n " (substring line chunk-start)))))) (org-split-string s "\n") "\r\n"))) +(defun org-icalendar-today-timestamp () + "Return a TIMESTAMP object for today, at 00:00." + (let ((dt (decode-time))) + (list 'timestamp + (nconc (list :year-start (nth 5 dt) + :year-end (nth 5 dt) + :month-start (nth 4 dt) + :month-end (nth 4 dt) + :day-start (nth 3 dt) + :day-end (nth 3 dt)))))) + +(defun org-icalendar-days-until-timestamp (timestamp) + "Return the number of days until TIMESTAMP. + +If TIMESTAMP occurs today, return 0. +If TIMESTAMP occurs yesterday, return -1." + (floor + (/ (float-time + (time-subtract (org-timestamp--to-internal-time timestamp) + (apply 'encode-time + (append '(0 0 0) (nthcdr 3 (decode-time)))))) + (* 60 60 24)))) ;;; Filters @@ -567,19 +603,70 @@ inlinetask within the section." ;; "VEVENT" component from scheduled, deadline, or any ;; timestamp in the entry. (let ((deadline (org-element-property :deadline entry))) - (and deadline + (when (and deadline (memq (if todo-type 'event-if-todo 'event-if-not-todo) - org-icalendar-use-deadline) + org-icalendar-use-deadline)) + (let ((days-until-deadline + (org-icalendar-days-until-timestamp deadline))) + (cond + ;; Case 1: Just export the event if... + ((or + ;; Not a pending TODO. + (not (eq todo-type 'todo)) + ;; Is due today. + (= days-until-deadline 0) + ;; Overdue but no bumping. + (and (not org-icalendar-bump-todos) + (< days-until-deadline 0)) + ;; In the future but no warning. + (and (not org-icalendar-warn-deadlines) + (> days-until-deadline 0))) (org-icalendar--vevent entry deadline (concat "DL-" uid) - (concat "DL: " summary) loc desc cat tz class))) + (concat "DL: " summary) loc desc cat tz class)) + + ;; Case 2: pending TODO overdue and should bump. + ((and org-icalendar-bump-todos + (< days-until-deadline 0)) + (org-icalendar--vevent + entry (org-icalendar-today-timestamp) (concat "DL-" uid) + (concat "DL (" (number-to-string (- days-until-deadline)) + "x): " summary) + loc desc cat tz class)) + ;; Case 3: in the future and should warn. + (t + (concat + ;; If in the warning zone. + (when (<= days-until-deadline org-deadline-warning-days) + (org-icalendar--vevent + entry (org-icalendar-today-timestamp) (concat "DL-" uid) + (concat "DL (in " (number-to-string days-until-deadline) + "d.): " summary) + loc desc cat tz class)) + (org-icalendar--vevent + entry deadline (concat "DL-" uid) + (concat "DL: " summary) loc desc cat tz class))))))) (let ((scheduled (org-element-property :scheduled entry))) - (and scheduled + (when (and scheduled (memq (if todo-type 'event-if-todo 'event-if-not-todo) - org-icalendar-use-scheduled) + org-icalendar-use-scheduled)) + (let ((days-until-scheduled + (org-icalendar-days-until-timestamp scheduled))) + (cond + ;; Already done, due in the future or today, or no bumps. + ((or (not (eq todo-type 'todo)) + (>= days-until-scheduled 0) + (not org-icalendar-bump-todos)) (org-icalendar--vevent entry scheduled (concat "SC-" uid) - (concat "S: " summary) loc desc cat tz class))) + (concat "S: " summary) loc desc cat tz class)) + ;; Overdue and should bump. + (t + (org-icalendar--vevent + entry (org-icalendar-today-timestamp) (concat "SC-" uid) + (concat "S (" (number-to-string (- days-until-scheduled)) "x): " + summary) + loc desc cat tz class)))))) ;; When collecting plain timestamps from a headline and its ;; title, skip inlinetasks since collection will happen once ;; ENTRY is one of them. -- 2.19.2
From 95b8586a4886051eb09e7ef34e1b9f60a040bfb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= <mich...@cadilhac.name> Date: Thu, 7 Feb 2019 12:20:24 +0000 Subject: [PATCH 2/6] Include tags in SUMMARY if so desired. --- lisp/ox-icalendar.el | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el index 2bf2cd89a..5e7f2804a 100644 --- a/lisp/ox-icalendar.el +++ b/lisp/ox-icalendar.el @@ -119,6 +119,12 @@ This is a list with possibly several symbols in it. Valid symbols are: (const :tag "SCHEDULED in TODO entries become start date" todo-start))) +(defcustom org-icalendar-summary-uses-tags nil + "Non-nil means that TITLE+TAGS is used when SUMMARY is not provided. +If nil, then TITLE is used alone." + :group 'org-export-icalendar + :type 'boolean) + (defcustom org-icalendar-bump-todos nil "Non-nil means that pending TODO VEVENTs are bumped to today. In addition, if non-nil, the number of late days is indicated in the summary." @@ -598,6 +604,13 @@ inlinetask within the section." (tz (org-export-get-node-property :TIMEZONE entry (org-property-inherit-p "TIMEZONE")))) + (when (and org-icalendar-summary-uses-tags + (not (org-element-property :SUMMARY entry))) + (let ((tags (apply 'concat + (mapcar (lambda (x) (concat ":" x)) + (org-export-get-tags entry info nil t))))) + (when tags + (setq summary (concat summary " " tags ":"))))) (concat ;; Events: Delegate to `org-icalendar--vevent' to generate ;; "VEVENT" component from scheduled, deadline, or any -- 2.19.2
From 66b5d7c5fa35fad6961353093bc93aee36cef039 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= <mich...@cadilhac.name> Date: Thu, 7 Feb 2019 14:35:13 +0000 Subject: [PATCH 6/6] Document org-icalendar-{bump-todos,warn-deadlines}. --- doc/org-manual.org | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/org-manual.org b/doc/org-manual.org index 5ad57d3a9..ca5d62394 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -15052,6 +15052,18 @@ TODO items for setting the start and due dates for the iCalendar TODO entry. Consult the ~org-icalendar-use-deadline~ and ~org-icalendar-use-scheduled~ variables for more details. +#+vindex: org-icalendar-bump-todos +#+vindex: org-icalendar-warn-deadlines +An important difference between the Org Agenda and the exported +calendar is that overdue tasks and deadline warnings are not treated +in any special way by default. To change this, configure the +variables ~org-icalendar-bump-todos~ and +~org-icalendar-warn-deadlines~. Setting the first variable will move +overdue TODOs to the current day, their titles being changed to +reflect how late the task is. Setting the second variable adds an +event on the current day if a deadline event is due in the next +~org-deadline-warning-days~ days. + #+vindex: org-icalendar-categories #+vindex: org-icalendar-alarm-time #+vindex: org-icalendar-summary-uses-tags -- 2.19.2
From f6b2ced66e85ed29b03e2c7ad75fa3bd37da22c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= <mich...@cadilhac.name> Date: Thu, 7 Feb 2019 14:09:07 +0000 Subject: [PATCH 5/6] Give more options for using tags in summary. --- doc/org-manual.org | 5 ++++- lisp/ox-icalendar.el | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/doc/org-manual.org b/doc/org-manual.org index 25d315654..5ad57d3a9 100644 --- a/doc/org-manual.org +++ b/doc/org-manual.org @@ -15054,11 +15054,14 @@ entry. Consult the ~org-icalendar-use-deadline~ and #+vindex: org-icalendar-categories #+vindex: org-icalendar-alarm-time +#+vindex: org-icalendar-summary-uses-tags For tags on the headline, the iCalendar export back-end makes them into iCalendar categories. To tweak the inheritance of tags and TODO states, configure the variable ~org-icalendar-categories~. To assign clock alarms based on time, configure the ~org-icalendar-alarm-time~ -variable. +variable. Additionally, the variable +~org-icalendar-summary-uses-tags~ can be configured to have tags +appear in the title of the event, when SUMMARY is not provided. #+vindex: org-icalendar-store-UID #+cindex: @samp{ID}, property diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el index 4c9bd8340..a34904101 100644 --- a/lisp/ox-icalendar.el +++ b/lisp/ox-icalendar.el @@ -120,10 +120,17 @@ This is a list with possibly several symbols in it. Valid symbols are: todo-start))) (defcustom org-icalendar-summary-uses-tags nil - "Non-nil means that TITLE+TAGS is used when SUMMARY is not provided. -If nil, then TITLE is used alone." + "Whether tags should be added to the title to create the summary. + +If a SUMMARY is provided in the entry, this is irrelevant. +If non-nil, it can be set to `local-tags' or `all-tags' indicating which tags +are used to make up the summary: only tags defined in the current line or all +tags including inherited ones, respectively." :group 'org-export-icalendar - :type 'boolean) + :type '(choice + (const :tag "Use the tags defined in current line" local-tags) + (const :tag "Use all tags, including inherited ones" all-tags) + (const :tag "Do not use tags in summary" nil))) (defcustom org-icalendar-bump-todos nil "Non-nil means that pending TODO VEVENTs are bumped to today. @@ -607,8 +614,11 @@ inlinetask within the section." (when (and org-icalendar-summary-uses-tags (not (org-element-property :SUMMARY entry))) (let ((tags (apply 'concat - (mapcar (lambda (x) (concat ":" x)) - (org-export-get-tags entry info nil t))))) + (mapcar + (lambda (x) (concat ":" x)) + (org-export-get-tags + entry info nil + (eq org-icalendar-summary-uses-tags 'all-tags)))))) (when tags (setq summary (concat summary " " tags ":"))))) (concat -- 2.19.2