From: Jack Kamm <jackkamm@gmail.com>
To: emacs-orgmode@gnu.org
Cc: mail@nicolasgoaziou.fr
Subject: [RFC] ox-icalendar: Unscheduled tasks & repeating tasks
Date: Sun, 26 Mar 2023 11:56:31 -0700 [thread overview]
Message-ID: <874jq75okg.fsf@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1636 bytes --]
Hello,
The attached 2 patches add support for exporting unscheduled tasks and
repeating tasks to iCalendar, respectively.
For patch 1 (unscheduled tasks):
Currently, ox-icalendar does not allow creating an iCalendar task
without a scheduled start date. If an Org TODO is missing a SCHEDULED
timestamp, then ox-icalendar sets today as the scheduled start date for
the exported task.
Patch 1 changes this by adding a new customization
org-icalendar-todo-force-scheduling. When non-nil, the start date is set
to today (same as the current behavior). When nil, unscheduled Org TODOs
are instead exported without a start date.
I also propose the default value to be nil. Note, this is
backwards-incompatible with the previous behavior!
But I think it should be the default anyways, because IMO it is the more
correct and useful behavior. An iCalendar VTODO without a DTSTART
property is valid, and has the same meaning as an Org TODO without a
SCHEDULED timestamp. Also, all the iCalendar programs I have tried
support unscheduled tasks, including Thunderbird, Evolution, Nextcloud,
and Tasks.org.
For patch 2 (repeating timestamps):
I add recurrence rule (RRULE) export for repeating SCHEDULED and
DEADLINE timestamps in TODOs, similar to how repeating non-TODO events
are currently handled.
The main complication here is that iCalendar's RRULE applies to both
DTSTART and DUE properties; by contrast, Org's SCHEDULED and DEADLINE
timestamps may have different repeaters. I am not sure the best way to
handle the case where SCHEDULED and DEADLINE have different repeaters,
so in that case I issue a warning and skip the repeater.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-ox-icalendar-Allow-exporting-unscheduled-VTODOs.patch --]
[-- Type: text/x-patch, Size: 4258 bytes --]
From 1bd268ab260d5077d7456c0d64fea36128772f86 Mon Sep 17 00:00:00 2001
From: Jack Kamm <jackkamm@gmail.com>
Date: Sun, 26 Mar 2023 07:43:53 -0700
Subject: [PATCH 1/2] ox-icalendar: Allow exporting unscheduled VTODOs
* lisp/ox-icalendar.el (org-icalendar-todo-force-scheduling): New
option to revert to previous export behavior of unscheduled TODOs.
(org-icalendar--vtodo): Don't force unscheduled TODOs to have a
scheduled start time of today, unless
`org-icalendar-todo-force-scheduling' is set.
---
etc/ORG-NEWS | 15 +++++++++++++++
lisp/ox-icalendar.el | 32 +++++++++++++++++++++-----------
2 files changed, 36 insertions(+), 11 deletions(-)
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index ac233a986..fb4f82b29 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -23,6 +23,15 @@ If you still want to use python-mode with ob-python, you might
consider [[https://gitlab.com/jackkamm/ob-python-mode-mode][ob-python-mode-mode]], where the code to support python-mode
has been ported to.
+*** Icalendar export of TODOs no longer forces a start time
+
+For TODOs without a scheduled start time, ox-icalendar no longer
+forces them to have a scheduled start time of today when exporting.
+This makes it possible to create icalendar TODOs without a start time.
+
+To revert to the old behavior, set the new custom option
+~org-icalendar-todo-force-scheduling~ to non-nil.
+
** New and changed options
*** New ~org-cite-natbib-export-bibliography~ option defining fallback bibliography style
@@ -111,6 +120,12 @@ backend used for evaluation of ClojureScript.
official [[https://clojure.org/guides/deps_and_cli][Clojure CLI tools]].
The command can be customized with ~ob-clojure-cli-command~.
+*** New ~org-icalendar-todo-force-scheduling~ option for old ox-icalendar TODO scheduling behavior
+
+Set ~org-icalendar-todo-force-scheduling~ to non-nil to revert to the
+old ox-icalendar TODO export behavior, that forced all exported TODOs
+to have a scheduled start time.
+
** New features
*** Add support for ~logind~ idle time in ~org-user-idle-seconds~
diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el
index 81a77a770..63aefcc84 100644
--- a/lisp/ox-icalendar.el
+++ b/lisp/ox-icalendar.el
@@ -231,6 +231,12 @@ (defcustom org-icalendar-include-todo nil
(repeat :tag "Specific TODO keywords"
(string :tag "Keyword"))))
+(defcustom org-icalendar-todo-force-scheduling nil
+ "Non-nil means unscheduled tasks are exported as scheduled.
+The current date is used as the scheduled time for such tasks."
+ :group 'org-export-icalendar
+ :type 'boolean)
+
(defcustom org-icalendar-include-bbdb-anniversaries nil
"Non-nil means a combined iCalendar file should include anniversaries.
The anniversaries are defined in the BBDB database."
@@ -776,21 +782,25 @@ (defun org-icalendar--vtodo
Return VTODO component as a string."
(let ((start (or (and (memq 'todo-start org-icalendar-use-scheduled)
(org-element-property :scheduled entry))
- ;; If we can't use a scheduled time for some
- ;; reason, start task now.
- (let ((now (decode-time)))
- (list 'timestamp
- (list :type 'active
- :minute-start (nth 1 now)
- :hour-start (nth 2 now)
- :day-start (nth 3 now)
- :month-start (nth 4 now)
- :year-start (nth 5 now)))))))
+ (when org-icalendar-todo-force-scheduling
+ ;; If we can't use a scheduled time for some
+ ;; reason, start task now.
+ (let ((now (decode-time)))
+ (list 'timestamp
+ (list :type 'active
+ :minute-start (nth 1 now)
+ :hour-start (nth 2 now)
+ :day-start (nth 3 now)
+ :month-start (nth 4 now)
+ :year-start (nth 5 now))))))))
(org-icalendar-fold-string
(concat "BEGIN:VTODO\n"
"UID:TODO-" uid "\n"
(org-icalendar-dtstamp) "\n"
- (org-icalendar-convert-timestamp start "DTSTART" nil timezone) "\n"
+ (when start
+ (concat (org-icalendar-convert-timestamp
+ start "DTSTART" nil timezone)
+ "\n"))
(and (memq 'todo-due org-icalendar-use-deadline)
(org-element-property :deadline entry)
(concat (org-icalendar-convert-timestamp
--
2.39.2
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-ox-icalendar-Support-repeating-timestamps-in-TODOs.patch --]
[-- Type: text/x-patch, Size: 5652 bytes --]
From 8348f5b8c56087f0fb8cdd775a816f63cb57f38f Mon Sep 17 00:00:00 2001
From: Jack Kamm <jackkamm@gmail.com>
Date: Sun, 26 Mar 2023 10:37:47 -0700
Subject: [PATCH 2/2] ox-icalendar: Support repeating timestamps in TODOs
* lisp/ox-icalendar.el (org-icalendar--rrule): New helper function to
generate RRULE.
(org-icalendar--vevent): Use `org-icalendar--rrule' instead of
generating the RRULE directly.
(org-icalendar--vtodo): Generate RRULE for repeating scheduled and
deadline timestamps.
---
etc/ORG-NEWS | 13 ++++++++++++
lisp/ox-icalendar.el | 50 +++++++++++++++++++++++++++++++++-----------
2 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index fb4f82b29..3919b240e 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -159,6 +159,19 @@ Running shell blocks with the ~:session~ header freezes Emacs until
execution completes. The new ~:async~ header allows users to continue
editing with Emacs while a ~:session~ block executes.
+*** Add support for repeating tasks in iCalendar export
+
+Repeating Scheduled and Deadline timestamps in TODOs are now exported
+as recurring tasks in iCalendar export.
+
+Note that in Org-mode, the repeaters for the Scheduled and Deadline
+timestamps can be different; whereas in iCalendar, the recurrence rule
+applies to both the scheduled start time and the deadline due date.
+
+In case the timestamp repeaters contradict, the correct export
+behavior is not well-defined. Currently, Org-mode will issue a
+warning and skip the repeaters in this case.
+
** Miscellaneous
*** Remove undocumented ~:target~ header parameter in ~ob-clojure~
diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el
index 63aefcc84..179795ac9 100644
--- a/lisp/ox-icalendar.el
+++ b/lisp/ox-icalendar.el
@@ -726,6 +726,13 @@ (defun org-icalendar-entry (entry contents info)
;; Don't forget components from inner entries.
contents))))
+(defun org-icalendar--rrule (unit value)
+ (format "RRULE:FREQ=%s;INTERVAL=%d\n"
+ (cl-case unit
+ (hour "HOURLY") (day "DAILY") (week "WEEKLY")
+ (month "MONTHLY") (year "YEARLY"))
+ value))
+
(defun org-icalendar--vevent
(entry timestamp uid summary location description categories timezone class)
"Create a VEVENT component.
@@ -752,12 +759,9 @@ (\"PUBLIC\", \"CONFIDENTIAL\", and \"PRIVATE\") are predefined, others
(org-icalendar-convert-timestamp timestamp "DTSTART" nil timezone) "\n"
(org-icalendar-convert-timestamp timestamp "DTEND" t timezone) "\n"
;; RRULE.
- (when (org-element-property :repeater-type timestamp)
- (format "RRULE:FREQ=%s;INTERVAL=%d\n"
- (cl-case (org-element-property :repeater-unit timestamp)
- (hour "HOURLY") (day "DAILY") (week "WEEKLY")
- (month "MONTHLY") (year "YEARLY"))
- (org-element-property :repeater-value timestamp)))
+ (org-icalendar--rrule
+ (org-element-property :repeater-unit timestamp)
+ (org-element-property :repeater-value timestamp))
"SUMMARY:" summary "\n"
(and (org-string-nw-p location) (format "LOCATION:%s\n" location))
(and (org-string-nw-p class) (format "CLASS:%s\n" class))
@@ -792,7 +796,9 @@ (defun org-icalendar--vtodo
:hour-start (nth 2 now)
:day-start (nth 3 now)
:month-start (nth 4 now)
- :year-start (nth 5 now))))))))
+ :year-start (nth 5 now)))))))
+ (due (and (memq 'todo-due org-icalendar-use-deadline)
+ (org-element-property :deadline entry))))
(org-icalendar-fold-string
(concat "BEGIN:VTODO\n"
"UID:TODO-" uid "\n"
@@ -801,11 +807,31 @@ (defun org-icalendar--vtodo
(concat (org-icalendar-convert-timestamp
start "DTSTART" nil timezone)
"\n"))
- (and (memq 'todo-due org-icalendar-use-deadline)
- (org-element-property :deadline entry)
- (concat (org-icalendar-convert-timestamp
- (org-element-property :deadline entry) "DUE" nil timezone)
- "\n"))
+ (when due
+ (concat (org-icalendar-convert-timestamp
+ due "DUE" nil timezone)
+ "\n"))
+ ;; RRULE
+ (let ((start-repeater-unit (org-element-property
+ :repeater-unit start))
+ (start-repeater-value (org-element-property
+ :repeater-value start))
+ (due-repeater-unit (org-element-property
+ :repeater-unit due))
+ (due-repeater-value (org-element-property
+ :repeater-value due)))
+ (when (or start-repeater-value due-repeater-value)
+ (if (and start due
+ (not (and (eql start-repeater-unit
+ due-repeater-unit)
+ (eql start-repeater-value
+ due-repeater-value))))
+ (progn (warn "Scheduled and Deadline repeaters are not equal. Skipping repeater export.")
+ nil)
+ (org-icalendar--rrule (or start-repeater-unit
+ due-repeater-unit)
+ (or start-repeater-value
+ due-repeater-value)))))
"SUMMARY:" summary "\n"
(and (org-string-nw-p location) (format "LOCATION:%s\n" location))
(and (org-string-nw-p class) (format "CLASS:%s\n" class))
--
2.39.2
next reply other threads:[~2023-03-26 18:57 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-26 18:56 Jack Kamm [this message]
2023-03-27 11:59 ` [RFC] ox-icalendar: Unscheduled tasks & repeating tasks Ihor Radchenko
2023-03-31 5:55 ` Jack Kamm
2023-03-31 13:07 ` Ihor Radchenko
2023-03-31 15:50 ` Jack Kamm
2023-03-31 17:51 ` Ihor Radchenko
2023-03-31 22:20 ` Jack Kamm
2023-04-01 8:30 ` Ihor Radchenko
2023-04-02 0:47 ` Jack Kamm
2023-04-02 8:48 ` Ihor Radchenko
2023-04-02 15:34 ` Jack Kamm
2023-04-02 16:32 ` Ihor Radchenko
2023-04-14 16:57 ` Jack Kamm
2023-04-14 18:46 ` Ihor Radchenko
2023-04-15 3:13 ` Jack Kamm
2023-04-15 9:56 ` Ihor Radchenko
2023-04-16 17:19 ` Jack Kamm
2023-06-11 15:35 ` [PATCH] " Jack Kamm
2023-06-12 10:36 ` Ihor Radchenko
2023-06-17 17:32 ` Jack Kamm
2023-06-18 11:28 ` Ihor Radchenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874jq75okg.fsf@gmail.com \
--to=jackkamm@gmail.com \
--cc=emacs-orgmode@gnu.org \
--cc=mail@nicolasgoaziou.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).