Ihor Radchenko <yanta...@posteo.net> writes:

> Would it make sense to throw a warning instead of silently skipping ~++~
> and ~.+~ repeaters?
> I think it would make sense to link to this variable in the
> `org-icalendar-use-scheduled' docstring and possibly in the manual.

Thanks, I agree.  I've updated the patch to add a warning for the
nonstandard repeaters (plus a unit test), and also added links to
`org-icalendar-todo-unscheduled-start' in the manual and
`org-icalendar-use-scheduled' docstring.

For convenience I attach these as separate patches here.  If it looks
OK I will squash with the prior patch before applying to main.

>From 80c05e00335062cc96bdcd85ec507066af4a1d3b Mon Sep 17 00:00:00 2001
From: Jack Kamm <jackk...@gmail.com>
Date: Sat, 17 Jun 2023 07:55:17 -0700
Subject: [PATCH 2/3] ox-icalendar: Display warning for unsupported repeaters

This commit to be squashed with the previous one

* lisp/ox-icalendar.el (org-icalendar--repeater-type): Helper function
to get the repeater type, and display warning if not supported.
* testing/lisp/test-ox-icalendar.el
(test-ox-icalendar/warn-unsupported-repeater): Unit test to warn for
unsupported repeater types.
 lisp/ox-icalendar.el              | 30 +++++++++++++++++++++---------
 testing/lisp/test-ox-icalendar.el | 14 ++++++++++++++
 2 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el
index 8c569752b..0dbc623b4 100644
--- a/lisp/ox-icalendar.el
+++ b/lisp/ox-icalendar.el
@@ -810,6 +810,23 @@ (\"PUBLIC\", \"CONFIDENTIAL\", and \"PRIVATE\") are predefined, others
 	    (org-icalendar--valarm entry timestamp summary)
+(defun org-icalendar--repeater-type (elem)
+  "Return ELEM's repeater-type if supported, else warn and return nil."
+  (let ((repeater-value (org-element-property :repeater-value elem))
+        (repeater-type (org-element-property :repeater-type elem)))
+    (cond
+     ((not (and repeater-type
+                repeater-value
+                (> repeater-value 0)))
+      nil)
+     ;; TODO Add catch-up to supported repeaters (use EXDATE to implement)
+     ((not (memq repeater-type '(cumulate)))
+      (org-display-warning
+       (format "Repeater-type %s not currently supported by iCalendar export"
+               (symbol-name repeater-type)))
+      nil)
+     (repeater-type))))
 (defun org-icalendar--vtodo
     (entry uid summary location description categories timezone class)
   "Create a VTODO component.
@@ -826,13 +843,8 @@ (defun org-icalendar--vtodo
 		  (org-element-property :scheduled entry)))
          (dl (and (memq 'todo-due org-icalendar-use-deadline)
                   (org-element-property :deadline entry)))
-         ;; TODO Implement catch-up repeaters using EXDATE
-         (sc-repeat-p (and (eq (org-element-property :repeater-type sc)
-                               'cumulate)
-                           (> (org-element-property :repeater-value sc) 0)))
-         (dl-repeat-p (and (eq (org-element-property :repeater-type dl)
-                               'cumulate)
-                           (> (org-element-property :repeater-value dl) 0)))
+         (sc-repeat-p (org-icalendar--repeater-type sc))
+         (dl-repeat-p (org-icalendar--repeater-type dl))
          (repeat-value (or (org-element-property :repeater-value sc)
                            (org-element-property :repeater-value dl)))
          (repeat-unit (or (org-element-property :repeater-unit sc)
@@ -881,14 +893,14 @@ (defun org-icalendar--vtodo
                              (eq repeat-unit (org-element-property
                                               :repeater-unit dl)))))
               ;; TODO Implement via RDATE with changing DURATION
-              (warn "Not yet implemented: \
+              (org-display-warning "Not yet implemented: \
 different repeaters on SCHEDULED and DEADLINE. Skipping.")
              ;; DEADLINE has repeater but SCHEDULED doesn't
              ((and dl-repeat-p (and sc (not sc-repeat-p)))
               ;; TODO SCHEDULED should only apply to first instance;
               ;; use RDATE with custom DURATION to implement that
-              (warn "Not yet implemented: \
+              (org-display-warning "Not yet implemented: \
 repeater on DEADLINE but not SCHEDULED. Skipping.")
              ((or sc-repeat-p dl-repeat-p)
diff --git a/testing/lisp/test-ox-icalendar.el b/testing/lisp/test-ox-icalendar.el
index 6a0c961d7..e631b2119 100644
--- a/testing/lisp/test-ox-icalendar.el
+++ b/testing/lisp/test-ox-icalendar.el
@@ -114,5 +114,19 @@ (ert-deftest test-ox-icalendar/todo-repeater-until-utc ()
             (should (re-search-forward "RRULE:FREQ=DAILY;INTERVAL=3;UNTIL=2023050.T..0000Z"))))
       (when (file-exists-p tmp-ics) (delete-file tmp-ics)))))
+(ert-deftest test-ox-icalendar/warn-unsupported-repeater ()
+  "Test warning is emitted for unsupported repeater type."
+  (let ((org-icalendar-include-todo 'all))
+    (should
+     (member
+      "Repeater-type restart not currently supported by iCalendar export"
+      (org-test-capture-warnings
+       (let ((tmp-ics (org-test-with-temp-text-in-file
+                       "* TODO Unsupported restart repeater
+SCHEDULED: <2023-03-26 Sun .+1m>"
+                       (expand-file-name (org-icalendar-export-to-ics)))))
+         (when (file-exists-p tmp-ics)
+           (delete-file tmp-ics))))))))
 (provide 'test-ox-icalendar)
 ;;; test-ox-icalendar.el ends here

>From 94f1c01273878e2a7403c1d47ebabe40595de23d Mon Sep 17 00:00:00 2001
From: Jack Kamm <jackk...@gmail.com>
Date: Sat, 17 Jun 2023 09:59:18 -0700
Subject: [PATCH 3/3] ox-icalendar: Links in docs for

 doc/org-manual.org   | 6 ++++--
 lisp/ox-icalendar.el | 5 +++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/doc/org-manual.org b/doc/org-manual.org
index c11694849..89589e32a 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -16054,14 +16054,16 @@ standard iCalendar format.
 #+vindex: org-icalendar-include-todo
 #+vindex: org-icalendar-use-deadline
 #+vindex: org-icalendar-use-scheduled
+#+vindex: org-icalendar-todo-unscheduled-start
 The iCalendar export backend can also incorporate TODO entries based
 on the configuration of the ~org-icalendar-include-todo~ variable.
 The backend exports plain timestamps as =VEVENT=, TODO items as
 =VTODO=, and also create events from deadlines that are in non-TODO
 items.  The backend uses the deadlines and scheduling dates in Org
 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.
+entry.  Consult the ~org-icalendar-use-deadline~,
+~org-icalendar-use-scheduled~, and
+~org-icalendar-todo-unscheduled-start~ variables for more details.
 #+vindex: org-icalendar-categories
 #+vindex: org-icalendar-alarm-time
diff --git a/lisp/ox-icalendar.el b/lisp/ox-icalendar.el
index 0dbc623b4..55ada8e60 100644
--- a/lisp/ox-icalendar.el
+++ b/lisp/ox-icalendar.el
@@ -168,8 +168,9 @@ (defcustom org-icalendar-use-scheduled '(todo-start)
-  Scheduling time stamps in TODO entries become start date.  Some
-  calendar applications show TODO entries only after that date."
+  Scheduling time stamps in TODO entries become start date.  (See
+  also `org-icalendar-todo-unscheduled-start', which controls the
+  start date for TODO entries without a scheduling time stamp)"
   :group 'org-export-icalendar
   '(set :greedy t

Reply via email to