Explorar o código

Implement proper UIDs for iCalendar export.

This works now fine except for sexp entries which don't
get reusable UIDs, but fresh ones each time they are exported......
Carsten Dominik %!s(int64=17) %!d(string=hai) anos
pai
achega
24fd4650de
Modificáronse 4 ficheiros con 82 adicións e 19 borrados
  1. 27 0
      ORGWEBPAGE/Changes.org
  2. 14 2
      doc/org.texi
  3. 6 0
      lisp/ChangeLog
  4. 35 17
      lisp/org-exp.el

+ 27 - 0
ORGWEBPAGE/Changes.org

@@ -8,6 +8,33 @@
 #+LINK_UP: index.html
 #+LINK_HOME: http://orgmode.org
 
+* Version 6.04
+
+** Details
+
+*** iCalendar now defines proper UIDs for entries
+
+This is necessary for synchronization services.  The UIDs are
+created using the the org-id.el module.  If you set the variable 
+
+: (setq org-icalendar-store-UID t)
+
+then all created UIDs will be stored in the entry as an =:ID:=
+property.  You should definitely do this if you plan to use
+synchronization.
+
+Diary sexp entries do not yet receive proper persistent UIDs,
+because they are transformed to iCalendar format by icalendar.el
+which creates fresh UIDs each time, based on the current time.
+
+A single entry can give rise to multiple iCalendar entries (as a
+timestamp, a deadline, a scheduled item, and as a TODO
+item). Therefore, Org adds prefixes "TS-", "DL-" "CS-", and "TD-"
+to the UID during iCalendar export, depending on what triggered
+the inclusion of the entry.  In this way the UID remains unique,
+but a synchronization program can still figure out from which
+entry all the different instances originate.
+
 * Version 6.03
   :PROPERTIES:
   :VISIBILITY: content

+ 14 - 2
doc/org.texi

@@ -3984,8 +3984,10 @@ capture, you can use 3 values:
 @example
 local     @r{use the tree in which the capture block is located}
 global    @r{make a global view, including all headings in the file}
-"label"   @r{call column view in the tree that has and @code{:ID:}}
-          @r{property with the value @i{label}}
+"label"   @r{call column view in the tree that has an @code{:ID:}}
+          @r{property with the value @i{label}.  You can use}
+          @r{@kbd{M-x org-id-copy} to create a globally unique ID for}
+          @r{the current entry and copy it to the kill-ring.}
 @end example
 @item :hlines
 When @code{t}, insert a hline after every line.  When a number N, insert
@@ -7426,6 +7428,16 @@ application.  Org mode can export calendar information in the standard
 iCalendar format.  If you also want to have TODO entries included in the
 export, configure the variable @code{org-icalendar-include-todo}.
 
+The iCalendar standard requires each entry to have a globally unique
+identifier (UID).  Org creates these identifiers during export.  If you set
+the variable @code{org-icalendar-store-UID}, the UID will be stored in the
+@code{:ID:} property of the entry and re-used next time you report this
+entry.  Since a single entry can give rise to multiple iCalendar entries (as
+a timestamp, a deadline, a scheduled item, and as a TODO item), Org adds
+prefixes to the UID, depending on what triggered the inclusion of the entry.
+In this way the UID remains unique, but a synchronization program can still
+figure out from which entry all the different instances originate.
+
 @table @kbd
 @kindex C-c C-e i
 @item C-c C-e i

+ 6 - 0
lisp/ChangeLog

@@ -1,3 +1,9 @@
+2008-05-19  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org-exp.el (org-icalendar-store-UID): New option.
+	(org-icalendar-force-UID): Option removed.
+	(org-print-icalendar-entries): IMplement UIDs.
+
 2008-05-18  Carsten Dominik  <dominik@science.uva.nl>
 
 	* org-mhe.el (org-mhe-follow-link): Fix bug in mhe searches.

+ 35 - 17
lisp/org-exp.el

@@ -634,9 +634,17 @@ The text will be inserted into the DESCRIPTION field."
   :group 'org-export-icalendar
   :type 'string)
 
-(defcustom org-icalendar-force-UID nil
-  "Non-nil means, each exported entry must have a UID.
-If not present, that UID will be created."
+(defcustom org-icalendar-store-UID nil
+  "Non-nil means, store any created UIDs in properties.
+The iCalendar standard requires that all entries have a unique identifyer.
+Org will create these identifiers as needed.  When this variable is non-nil,
+the created UIDs will be stored in the ID property of the entry.  Then the
+next time this entry is exported, it will be exported with the same UID,
+superceeding the previous form of it.  This is essential for
+synchronization services.
+This variable is not turned on by default because we want to avoid creating
+a property drawer in every entry if people are only playing with this feature,
+or if they are only using it locally."
   :group 'org-export-icalendar
   :type 'boolean)
 
@@ -3696,7 +3704,8 @@ When COMBINE is non nil, add the category to each line."
 	      (format-time-string (cdr org-time-stamp-formats) (current-time))
 	      "DTSTART"))
 	hd ts ts2 state status (inc t) pos b sexp rrule
-	scheduledp deadlinep tmp pri category entry location summary desc uid
+	scheduledp deadlinep prefix
+	tmp pri category entry location summary desc uid
 	(sexp-buffer (get-buffer-create "*ical-tmp*")))
     (org-refresh-category-properties)
     (save-excursion
@@ -3724,10 +3733,11 @@ When COMBINE is non nil, add the category to each line."
 		      t org-icalendar-include-body)
 		location (org-icalendar-cleanup-string
 			  (org-entry-get nil "LOCATION"))
-		uid (if org-icalendar-force-UID
+		uid (if org-icalendar-store-UID
 			(org-id-get-create)
-		      (org-id-get))
-		category (org-get-category))
+		      (or (org-id-get) (org-id-new)))
+		category (org-get-category)
+		deadlinep nil scheduledp nil)
 	  (if (looking-at re2)
 	      (progn
 		(goto-char (match-end 0))
@@ -3745,6 +3755,7 @@ When COMBINE is non nil, add the category to each line."
 		  scheduledp (string-match org-scheduled-regexp tmp)
 		  ;; donep (org-entry-is-done-p)
 		  ))
+	  (setq prefix (if deadlinep "DL-" (if scheduledp "SC-" "TS-")))
 	  (if (or (string-match org-tr-regexp hd)
 		  (string-match org-ts-regexp hd))
 	      (setq hd (replace-match "" t t hd)))
@@ -3762,19 +3773,21 @@ When COMBINE is non nil, add the category to each line."
 	      (setq summary
 		    (replace-match (if (match-end 3)
 				       (match-string 3 summary)
-					(match-string 1 summary))
-				      t t summary)))
+				     (match-string 1 summary))
+				   t t summary)))
 	  (if deadlinep (setq summary (concat "DL: " summary)))
 	  (if scheduledp (setq summary (concat "S: " summary)))
 	  (if (string-match "\\`<%%" ts)
 	      (with-current-buffer sexp-buffer
 		(insert (substring ts 1 -1) " " summary "\n"))
 	    (princ (format "BEGIN:VEVENT
+UID: %s
 %s
 %s%s
 SUMMARY:%s%s%s
-CATEGORIES:%s%s
+CATEGORIES:%s
 END:VEVENT\n"
+			   (concat prefix uid)
 			   (org-ical-ts-to-string ts "DTSTART")
 			   (org-ical-ts-to-string ts2 "DTEND" inc)
 			   rrule summary
@@ -3782,8 +3795,7 @@ END:VEVENT\n"
 			       (concat "\nDESCRIPTION: " desc) "")
 			   (if (and location (string-match "\\S-" location))
 			       (concat "\nLOCATION: " location) "")
-			   category
-			   (if uid (concat "\nUID: " uid) ""))))))
+			   category)))))
       (when (and org-icalendar-include-sexps
 		 (condition-case nil (require 'icalendar) (error nil))
 		 (fboundp 'icalendar-export-region))
@@ -3800,8 +3812,9 @@ END:VEVENT\n"
 	    (with-current-buffer sexp-buffer
 	      (insert sexp "\n"))
 	    (princ (org-diary-to-ical-string sexp-buffer)))))
-
+      
       (when org-icalendar-include-todo
+	(setq prefix "TODO-")
 	(goto-char (point-min))
 	(while (re-search-forward org-todo-line-regexp nil t)
 	  (catch :skip
@@ -3827,7 +3840,10 @@ END:VEVENT\n"
 			      (and org-icalendar-include-body (org-get-entry)))
 			  t org-icalendar-include-body)
 		    location (org-icalendar-cleanup-string
-			      (org-entry-get nil "LOCATION")))
+			      (org-entry-get nil "LOCATION"))
+		    uid (if org-icalendar-store-UID
+			    (org-id-get-create)
+			  (or (org-id-get) (orgg-id-new))))
 	      (if (string-match org-bracket-link-regexp hd)
 		  (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
 					    (match-string 1 hd))
@@ -3841,20 +3857,23 @@ END:VEVENT\n"
 					    (- org-lowest-priority org-highest-priority))))))
 
 	      (princ (format "BEGIN:VTODO
+UID: %s
 %s
 SUMMARY:%s%s%s
-CATEGORIES:%s
+CATEGORIES:%s%s
 SEQUENCE:1
 PRIORITY:%d
 STATUS:%s
 END:VTODO\n"
+			     (concat prefix uid)
 			     dts
 			     (or summary hd)
 			     (if (and location (string-match "\\S-" location))
 				 (concat "\nLOCATION: " location) "")
 			     (if (and desc (string-match "\\S-" desc))
 				 (concat "\nDESCRIPTION: " desc) "")
-			     category pri status)))))))))
+			     category
+			     pri status)))))))))
 
 (defun org-icalendar-cleanup-string (s &optional is-body maxlength)
   "Take out stuff and quote what needs to be quoted.
@@ -4022,4 +4041,3 @@ The XOXO buffer is named *xoxo-<source buffer name>*"
 
 ;;; org-exp.el ends here
 
-