Jelajahi Sumber

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 tahun lalu
induk
melakukan
cdb872efb9
3 mengubah file dengan 91 tambahan dan 19 penghapusan
  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>
 
 	* 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.
 
-
-
-	
 2005-01-11  Carsten Dominik  <dominik@science.uva.nl>
 
 	* org.el (org-show-following-heading): New option.
@@ -2755,8 +2764,8 @@ Release of 3.04 -------------------------------------------------------------
 	* org.el (orgtbl-optimized): New option
 	(orgtbl-mode): New command, a minor mode.
 	(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.
 
 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.
 Depending on the extension of the file name, plain text (.txt),
 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
 `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,
@@ -20426,6 +20429,13 @@ higher priority settings."
 	  ((string-match "\\.ps\\'" file)
 	   (ps-print-buffer-with-faces 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
 	   (let ((bs (buffer-string)))
 	     (find-file file)
@@ -20435,6 +20445,43 @@ higher priority settings."
 	     (message "Plain text written to %s" file))))))
     (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)
   "Inhibit read-only for 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
 			     org-export-publishing-directory)))
 	   file ical-file ical-buffer category started org-agenda-new-buffers)
-
       (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
       (when combine
 	(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)
 	(catch :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)
 		ts (match-string 0)
 		inc t
@@ -26837,6 +26888,11 @@ END:VEVENT\n"
 	(while (re-search-forward org-todo-line-regexp nil t)
 	  (catch :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 status (if (member state org-done-keywords)
 			     "COMPLETED" "NEEDS-ACTION"))
@@ -28884,6 +28940,7 @@ Still experimental, may disappear in the future."
     ;; make tree, check each match with the callback
     (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
 
+
 ;;;; Finish up
 
 (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
 printed version of some agenda views to carry around.  Org-mode can
 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
 @kindex C-x C-w
@@ -5898,10 +5898,12 @@ to do this only occasionally, use the command
 @cindex agenda views, exporting
 Write the agenda view to a file.  Depending on the extension of the
 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
 (setq org-agenda-exporter-settings
       '((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
 @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
-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
 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,
 or absolute.
 
@@ -5937,7 +5939,7 @@ or absolute.
           (tags-todo "work")
           (tags "office"))
          nil
-         ("~/views/office.ps"))))
+         ("~/views/office.ps" "~/calendars/office.ics"))))
 @end group
 @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
 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
-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
-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
 @kindex 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.
 @end table