Browse Source

Implement filtered iCalendar export.

This patch implements a way to limit the iCalendar export to
the entries listed in any agenda view.  It is implemented as a way to
export an agenda view (using C-x C-w) in the agenda, but internally
it really is a limited iCalendar export.
Carsten Dominik 17 years ago
parent
commit
cdb872efb9
3 changed files with 91 additions and 19 deletions
  1. 14 5
      ChangeLog
  2. 58 1
      org.el
  3. 19 13
      org.texi

+ 14 - 5
ChangeLog

@@ -1,3 +1,15 @@
+2008-03-09  Carsten Dominik  <dominik@science.uva.nl>
+
+	* org.texi (Exporting Agenda Views): Document agenda export to
+	iCalendar.
+
+	* org.el (org-write-agenda): New output type ".ics" files.
+	(org-write-agenda): Call `org-icalendar-verify-function', both for
+	time stamps and for TODO entries.
+	(org-agenda-collect-markers, org-create-marker-find-array)
+	(org-check-agenda-marker-table): New functions.
+	(org-agenda-marker-table): New variable.
+
 2008-03-07  Bastien Guerry  <bzg@altern.org>
 2008-03-07  Bastien Guerry  <bzg@altern.org>
 
 
 	* org-export-latex.el (org-export-as-latex): Revert the change
 	* org-export-latex.el (org-export-as-latex): Revert the change
@@ -2742,9 +2754,6 @@ Release of 3.04 -------------------------------------------------------------
 
 
 	* org.el (org-version): Prefix arg removed, was not needed.
 	* org.el (org-version): Prefix arg removed, was not needed.
 
 
-
-
-	
 2005-01-11  Carsten Dominik  <dominik@science.uva.nl>
 2005-01-11  Carsten Dominik  <dominik@science.uva.nl>
 
 
 	* org.el (org-show-following-heading): New option.
 	* org.el (org-show-following-heading): New option.
@@ -2755,8 +2764,8 @@ Release of 3.04 -------------------------------------------------------------
 	* org.el (orgtbl-optimized): New option
 	* org.el (orgtbl-optimized): New option
 	(orgtbl-mode): New command, a minor mode.
 	(orgtbl-mode): New command, a minor mode.
 	(orgtbl-mode-map): New variable.
 	(orgtbl-mode-map): New variable.
-	(turn-on-orgtbl, orgtbl-mode, orgtbl-make-binding) 
-	(orgtbl-error, orgtbl-self-insert-command) 
+	(turn-on-orgtbl, orgtbl-mode, orgtbl-make-binding)
+	(orgtbl-error, orgtbl-self-insert-command)
 	(orgtbl-delete-backward-char, orgtbl-delete-char): New functions.
 	(orgtbl-delete-backward-char, orgtbl-delete-char): New functions.
 
 
 2004-12-22  Carsten Dominik  <dominik@science.uva.nl>
 2004-12-22  Carsten Dominik  <dominik@science.uva.nl>

+ 58 - 1
org.el

@@ -20396,6 +20396,9 @@ so the export commands can easily use it."
   "Write the current buffer (an agenda view) as a file.
   "Write the current buffer (an agenda view) as a file.
 Depending on the extension of the file name, plain text (.txt),
 Depending on the extension of the file name, plain text (.txt),
 HTML (.html or .htm) or Postscript (.ps) is produced.
 HTML (.html or .htm) or Postscript (.ps) is produced.
+If the extension is .ics, run icalendar export over all files used
+to construct the agenda and limit the export to entries listed in the
+agenda now.
 If NOSETTINGS is given, do not scope the settings of
 If NOSETTINGS is given, do not scope the settings of
 `org-agenda-exporter-settings' into the export commands.  This is used when
 `org-agenda-exporter-settings' into the export commands.  This is used when
 the settings have already been scoped and we do not wish to overrule other,
 the settings have already been scoped and we do not wish to overrule other,
@@ -20426,6 +20429,13 @@ higher priority settings."
 	  ((string-match "\\.ps\\'" file)
 	  ((string-match "\\.ps\\'" file)
 	   (ps-print-buffer-with-faces file)
 	   (ps-print-buffer-with-faces file)
 	   (message "Postscript written to %s" file))
 	   (message "Postscript written to %s" file))
+	  ((string-match "\\.ics\\'" file)
+	   (let ((org-agenda-marker-table
+		  (org-create-marker-find-array
+		   (org-agenda-collect-markers)))
+		 (org-icalendar-verify-function 'org-check-agenda-marker-table)
+		 (org-combined-agenda-icalendar-file file))
+	     (apply 'org-export-icalendar 'combine (org-agenda-files))))
 	  (t
 	  (t
 	   (let ((bs (buffer-string)))
 	   (let ((bs (buffer-string)))
 	     (find-file file)
 	     (find-file file)
@@ -20435,6 +20445,43 @@ higher priority settings."
 	     (message "Plain text written to %s" file))))))
 	     (message "Plain text written to %s" file))))))
     (set-buffer org-agenda-buffer-name)))
     (set-buffer org-agenda-buffer-name)))
 
 
+(defun org-agenda-collect-markers ()
+  "Collect the markers pointing to entries in the agenda buffer."
+  (let (m markers)
+    (save-excursion
+      (goto-char (point-min))
+      (while (not (eobp))
+	(when (setq m (or (get-text-property (point) 'org-hd-marker)
+			  (get-text-property (point) 'org-marker)))
+	  (push m markers))
+	(beginning-of-line 2)))
+    (nreverse markers)))
+
+(defun org-create-marker-find-array (marker-list)
+  "Create a alist of files names with all marker positions in that file."
+  (let (f tbl m a p)
+    (while (setq m (pop marker-list))
+      (setq p (marker-position m)
+	    f (buffer-file-name (or (buffer-base-buffer
+				     (marker-buffer m))
+				    (marker-buffer m))))
+      (if (setq a (assoc f tbl))
+	  (push (marker-position m) (cdr a))
+	(push (list f p) tbl)))
+    (mapcar (lambda (x) (setcdr x (sort (copy-sequence (cdr x)) '<)) x)
+	    tbl)))
+
+(defvar org-agenda-marker-table nil) ; dyamically scoped parameter
+(defun org-check-agenda-marker-table ()
+  "Check of the current entry is on the marker list."
+  (let ((file (buffer-file-name (or (buffer-base-buffer) (current-buffer))))
+	a)
+    (and (setq a (assoc file org-agenda-marker-table))
+	 (save-match-data
+	   (save-excursion
+	     (org-back-to-heading t)
+	     (member (point) (cdr a)))))))
+
 (defmacro org-no-read-only (&rest body)
 (defmacro org-no-read-only (&rest body)
   "Inhibit read-only for BODY."
   "Inhibit read-only for BODY."
   `(let ((inhibit-read-only t)) ,@body))
   `(let ((inhibit-read-only t)) ,@body))
@@ -26687,7 +26734,6 @@ file and store it under the name `org-combined-agenda-icalendar-file'."
 		 :ical (list :publishing-directory
 		 :ical (list :publishing-directory
 			     org-export-publishing-directory)))
 			     org-export-publishing-directory)))
 	   file ical-file ical-buffer category started org-agenda-new-buffers)
 	   file ical-file ical-buffer category started org-agenda-new-buffers)
-
       (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
       (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
       (when combine
       (when combine
 	(setq ical-file
 	(setq ical-file
@@ -26747,6 +26793,11 @@ When COMBINE is non nil, add the category to each line."
       (while (re-search-forward re1 nil t)
       (while (re-search-forward re1 nil t)
 	(catch :skip
 	(catch :skip
 	  (org-agenda-skip)
 	  (org-agenda-skip)
+	  (when (boundp 'org-icalendar-verify-function)
+	    (unless (funcall org-icalendar-verify-function)
+	      (outline-next-heading)
+	      (backward-char 1)
+	      (throw :skip nil)))
 	  (setq pos (match-beginning 0)
 	  (setq pos (match-beginning 0)
 		ts (match-string 0)
 		ts (match-string 0)
 		inc t
 		inc t
@@ -26837,6 +26888,11 @@ END:VEVENT\n"
 	(while (re-search-forward org-todo-line-regexp nil t)
 	(while (re-search-forward org-todo-line-regexp nil t)
 	  (catch :skip
 	  (catch :skip
 	    (org-agenda-skip)
 	    (org-agenda-skip)
+	    (when (boundp 'org-icalendar-verify-function)
+	      (unless (funcall org-icalendar-verify-function)
+		(outline-next-heading)
+		(backward-char 1)
+		(throw :skip nil)))
 	    (setq state (match-string 2))
 	    (setq state (match-string 2))
 	    (setq status (if (member state org-done-keywords)
 	    (setq status (if (member state org-done-keywords)
 			     "COMPLETED" "NEEDS-ACTION"))
 			     "COMPLETED" "NEEDS-ACTION"))
@@ -28884,6 +28940,7 @@ Still experimental, may disappear in the future."
     ;; make tree, check each match with the callback
     ;; make tree, check each match with the callback
     (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
     (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
 
 
+
 ;;;; Finish up
 ;;;; Finish up
 
 
 (provide 'org)
 (provide 'org)

+ 19 - 13
org.texi

@@ -5888,8 +5888,8 @@ yourself.
 If you are away from your computer, it can be very useful to have a
 If you are away from your computer, it can be very useful to have a
 printed version of some agenda views to carry around.  Org-mode can
 printed version of some agenda views to carry around.  Org-mode can
 export custom agenda views as plain text, HTML@footnote{You need to
 export custom agenda views as plain text, HTML@footnote{You need to
-install Hrvoje Niksic' @file{htmlize.el}.} and postscript.  If you want
-to do this only occasionally, use the command
+install Hrvoje Niksic' @file{htmlize.el}.} postscript, and iCalendar
+files.  If you want to do this only occasionally, use the command
 
 
 @table @kbd
 @table @kbd
 @kindex C-x C-w
 @kindex C-x C-w
@@ -5898,10 +5898,12 @@ to do this only occasionally, use the command
 @cindex agenda views, exporting
 @cindex agenda views, exporting
 Write the agenda view to a file.  Depending on the extension of the
 Write the agenda view to a file.  Depending on the extension of the
 selected file name, the view will be exported as HTML (extension
 selected file name, the view will be exported as HTML (extension
-@file{.html} or @file{.htm}), Postscript (extension @file{.ps}), or
-plain text (any other extension).  Use the variable
-@code{org-agenda-exporter-settings} to set options for @file{ps-print}
-and for @file{htmlize} to be used during export, for example
+@file{.html} or @file{.htm}), Postscript (extension @file{.ps}),
+iCalendar (extension @file{.ics}), or plain text (any other extension).
+Use the variable @code{org-agenda-exporter-settings} to
+set options for @file{ps-print} and for @file{htmlize} to be used during
+export, for example
+
 @lisp
 @lisp
 (setq org-agenda-exporter-settings
 (setq org-agenda-exporter-settings
       '((ps-number-of-columns 2)
       '((ps-number-of-columns 2)
@@ -5914,10 +5916,10 @@ If you need to export certain agenda views frequently, you can associate
 any custom agenda command with a list of output file names
 any custom agenda command with a list of output file names
 @footnote{If you want to store standard views like the weekly agenda
 @footnote{If you want to store standard views like the weekly agenda
 or the global TODO list as well, you need to define custom commands for
 or the global TODO list as well, you need to define custom commands for
-them in order to be able to specify filenames.}.  Here is an example
+them in order to be able to specify file names.}.  Here is an example
 that first does define custom commands for the agenda and the global
 that first does define custom commands for the agenda and the global
 todo list, together with a number of files to which to export them.
 todo list, together with a number of files to which to export them.
-Then we define two block agenda commands and specify filenames for them
+Then we define two block agenda commands and specify file names for them
 as well.  File names can be relative to the current working directory,
 as well.  File names can be relative to the current working directory,
 or absolute.
 or absolute.
 
 
@@ -5937,7 +5939,7 @@ or absolute.
           (tags-todo "work")
           (tags-todo "work")
           (tags "office"))
           (tags "office"))
          nil
          nil
-         ("~/views/office.ps"))))
+         ("~/views/office.ps" "~/calendars/office.ics"))))
 @end group
 @end group
 @end lisp
 @end lisp
 
 
@@ -5945,16 +5947,20 @@ The extension of the file name determines the type of export.  If it is
 @file{.html}, Org-mode will use the @file{htmlize.el} package to convert
 @file{.html}, Org-mode will use the @file{htmlize.el} package to convert
 the buffer to HTML and save it to this file name.  If the extension is
 the buffer to HTML and save it to this file name.  If the extension is
 @file{.ps}, @code{ps-print-buffer-with-faces} is used to produce
 @file{.ps}, @code{ps-print-buffer-with-faces} is used to produce
-postscript output.  Any other extension produces a plain ASCII file.
+postscript output.  If the extension is @file{.ics}, iCalendar export is
+run export over all files that were used to construct the agenda, and
+limit the export to entries listed in the agenda now.  Any other
+extension produces a plain ASCII file.
 
 
 The export files are @emph{not} created when you use one of those
 The export files are @emph{not} created when you use one of those
-commands interactively.  Instead, there is a special command to produce
-@emph{all} specified files in one step:
+commands interactively because this might use too much overhead.
+Instead, there is a special command to produce @emph{all} specified
+files in one step:
 
 
 @table @kbd
 @table @kbd
 @kindex C-c a e
 @kindex C-c a e
 @item C-c a e
 @item C-c a e
-Export all agenda views that have export filenames associated with
+Export all agenda views that have export file names associated with
 them.
 them.
 @end table
 @end table