Quellcode durchsuchen

New contributed modules org-mac-iCal.el by Christopher Suckling

Carsten Dominik vor 15 Jahren
Ursprung
Commit
a2f787a643
4 geänderte Dateien mit 251 neuen und 1 gelöschten Zeilen
  1. 2 0
      contrib/README
  2. 1 1
      contrib/lisp/org-jira.el
  3. 246 0
      contrib/lisp/org-mac-iCal.el
  4. 2 0
      lisp/org.el

+ 2 - 0
contrib/README

@@ -26,7 +26,9 @@ org-exp-bibtex.el        --- Export citations to LaTeX and HTML
 org-exp-blocks.el        --- Pre-process blocks when exporting org files
 org-indent.el            --- Dynamic outline indentation (does not really work)
 org-interactive-query.el --- Interactive modification of tags query
+org-jira.el              --- Add a jira:ticket protocol to Org
 org-mairix.el 	         --- Hook mairix search into Org for different MUAs
+org-mac-iCal.el          --- Imports events from iCal.app to the Emacs diary
 org-man.el 	         --- Support for links to manpages in Org-mode
 org-mtags.el 	         --- Support for some Muse-like tags in Org-mode
 org-panel.el 	         --- Simple routines for us with bad memory

+ 1 - 1
contrib/lisp/org-jira.el

@@ -1,4 +1,4 @@
-;;; org-jira.el --- add a jira:ticket protocol to org.
+;;; org-jira.el --- add a jira:ticket protocol to Org
 (defconst org-jira-version "0.1")
 ;; Copyright (c)2008 Jonathan Arkell. (by)(nc)(sa)  Some rights reserved.
 ;; Author: Jonathan Arkell <jonnay@jonnay.net>

+ 246 - 0
contrib/lisp/org-mac-iCal.el

@@ -0,0 +1,246 @@
+;;; org-mac-iCal.el --- Imports events from iCal.app to the Emacs diary
+
+;; Copyright (C) 2009 Christopher Suckling
+
+;; Author: Christopher Suckling <suckling at gmail dot com>
+
+;; This file is Free Software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; It is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Version: 0.1057.104
+;; Keywords: outlines, calendar
+
+;;; Commentary:
+;;
+;; This file provides the import of events from Mac OS X 10.5 iCal.app
+;; into the Emacs diary (it is not compatible with OS X < 10.5). The
+;; function org-mac-iCal will import events in all checked iCal.app
+;; calendars for the date range org-mac-iCal-range months, centered
+;; around the current date.
+;;
+;; CAVEAT: This function is destructive; it will overwrite the current
+;; contents of the Emacs diary.
+;;
+;; Installation: add (require 'org-mac-iCal) to your .emacs.
+;;
+;; If you view Emacs diary entries in org-agenda, the following hook
+;; will ensure that all-day events are not orphaned below TODO items
+;; and that any supplementary fields to events (e.g. Location) are
+;; grouped with their parent event
+;;
+;; (add-hook 'org-agenda-cleanup-fancy-diary-hook
+;; 	  (lambda ()
+;; 	    (goto-char (point-min))
+;; 	    (save-excursion
+;; 	      (while (re-search-forward "^[a-z]" nil t)
+;; 		(goto-char (match-beginning 0))
+;; 		(insert "0:00-24:00 ")))
+;; 	    (while (re-search-forward "^ [a-z]" nil t)
+;; 	      (goto-char (match-beginning 0))
+;; 	      (save-excursion
+;; 		(re-search-backward "^[0-9]+:[0-9]+-[0-9]+:[0-9]+ " nil t))
+;; 	      (insert (match-string 0)))))
+
+;;; Code:
+
+(defcustom org-mac-iCal-range 2
+  "The range in months to import iCal.app entries into the Emacs
+diary. The import is centered around today's date; thus a value
+of 2 imports entries for one month before and one month after
+today's date"
+  :group 'org-time
+  :type 'integer)
+
+(defun org-mac-iCal ()
+  "Selects checked calendars in iCal.app and imports them into
+the the Emacs diary"
+  (interactive)
+
+  ;; kill diary buffers then empty diary files to avoid duplicates
+  (setq currentBuffer (buffer-name))
+  (setq openBuffers (mapcar (function buffer-name) (buffer-list)))
+  (omi-kill-diary-buffer openBuffers)
+  (with-temp-buffer
+    (insert-file-contents diary-file)
+    (delete-region (point-min) (point-max))
+    (write-region (point-min) (point-max) diary-file))
+
+  ;; determine available calendars
+  (setq caldav-folders (directory-files "~/Library/Calendars" 1 ".*caldav$"))
+  (setq caldav-calendars nil)
+  (mapc
+     (lambda (x)
+       (setq caldav-calendars (nconc caldav-calendars (directory-files x 1 ".*calendar$"))))
+     caldav-folders)
+
+  (setq local-calendars nil)
+  (setq local-calendars (directory-files "~/Library/Calendars" 1 ".*calendar$"))
+
+  (setq all-calendars (append caldav-calendars local-calendars))
+
+  ;; parse each calendar's Info.plist to see if calendar is checked in iCal
+  (setq all-calendars (delq 'nil (mapcar
+				    (lambda (x)
+				      (omi-checked x))
+				    all-calendars)))
+
+  ;; for each caledar, concatenate individual events into a single ics file
+  (with-temp-buffer
+    (shell-command "sw_vers" " *temp*")
+    (when (re-search-backward "10.5" nil t)
+      (omi-concat-leopard-ics all-calendars)))
+  
+  ;; move any caldav ics files to the same place as local ics files
+  (mapc
+   (lambda (x)
+     (when (directory-files x 1 ".*ics$")
+       (rename-file (car (directory-files x 1 ".*ics$")) (concat "~/Library/Calendars/" (car (directory-files x nil ".*ics$"))))))
+   caldav-folders)
+  
+  ;; check calendar has contents and import
+  (setq import-calendars (directory-files "~/Library/Calendars" 1 ".*ics$"))
+  (mapc
+   (lambda (x)
+     (when (/= (nth 7 (file-attributes x 'string)) 0)
+       (omi-import-ics x)))
+   import-calendars)
+
+  ;; tidy up intermediate files and buffers
+  (setq usedCalendarsBuffers (mapcar (function buffer-name) (buffer-list)))
+  (omi-kill-ics-buffer usedCalendarsBuffers)
+  (setq usedCalendarsFiles (directory-files "~/Library/Calendars" 1 ".*ics$"))
+  (omi-delete-ics-file usedCalendarsFiles)
+
+  (switch-to-buffer currentBuffer))
+
+(defun omi-concat-leopard-ics (list)
+  "Leopard stores each iCal.app event in a separate ics file.
+Whilst useful for Spotlight indexing, this is less helpful for
+icalendar-import-file. omi-concat-leopard-ics concatenates these
+individual event files into a single ics file"
+  (mapc
+   (lambda (x)
+     (setq omi-leopard-events (directory-files (concat x "/Events") 1 ".*ics$"))
+     (with-temp-buffer
+       (mapc
+	(lambda (y)
+	  (insert-file-contents (expand-file-name y)))
+	omi-leopard-events)
+       (write-region (point-min) (point-max) (concat (expand-file-name x) ".ics"))))
+   list))
+
+(defun omi-import-ics (string)
+  "Imports an ics file into the Emacs diary. First tidies up the
+ics file so that it is suitable for import and selects a sensible
+date range so that Emacs calendar view doesn't grind to a halt"
+  (with-temp-buffer
+    (insert-file-contents string)
+    (goto-char (point-min))
+    (while
+	(re-search-forward "^BEGIN:VCALENDAR$" nil t)
+      (setq startEntry (match-beginning 0))
+      (re-search-forward "^END:VCALENDAR$" nil t)
+      (setq endEntry (match-end 0))
+      (save-restriction
+	(narrow-to-region startEntry endEntry)
+	(goto-char (point-min))
+	(re-search-forward "\\(^DTSTART;.*:\\)\\([0-9][0-9][0-9][0-9]\\)\\([0-9][0-9]\\)" nil t)
+	(if (or (eq (match-string 2) nil) (eq (match-string 3) nil))
+	    (progn
+	      (setq yearEntry 0)
+	      (setq monthEntry 0))
+	  (setq yearEntry (string-to-number (match-string 2)))
+	  (setq monthEntry (string-to-number (match-string 3))))
+	(setq year (string-to-number (format-time-string "%Y")))
+	(setq month (string-to-number (format-time-string "%m")))
+	(when (or
+	       (and
+		(= yearEntry year)
+		(or (< monthEntry (- month (/ org-mac-iCal-range 2))) (> monthEntry (+ month (/ org-mac-iCal-range 2)))))
+	       (< yearEntry (- year 1))
+	       (> yearEntry (+ year 1))
+	       (and
+		(= yearEntry (- year 1)) (/= monthEntry 12))
+	       (and
+		(= yearEntry (+ year 1)) (/= monthEntry 1)))
+	  (delete-region startEntry endEntry))))
+    (while 
+	(re-search-forward "^END:VEVENT$" nil t)
+      (delete-blank-lines))
+    (goto-line 1)
+    (insert "BEGIN:VCALENDAR\n\n")
+    (goto-line 2)
+    (while
+	(re-search-forward "^BEGIN:VCALENDAR$" nil t)
+      (replace-match "\n"))
+    (goto-line 2)
+    (while
+	(re-search-forward "^END:VCALENDAR$" nil t)
+      (replace-match "\n"))
+    (insert "END:VCALENDAR")
+    (goto-line 1)
+    (delete-blank-lines)
+    (while
+	(re-search-forward "^END:VEVENT$" nil t)
+      (delete-blank-lines))
+    (goto-line 1)
+    (while
+	(re-search-forward "^ORG.*" nil t)
+      (replace-match "\n"))
+    (goto-line 1)
+    (write-region (point-min) (point-max) string))
+
+  (icalendar-import-file string (expand-file-name "~/.emacs.d/diary")))
+
+(defun omi-kill-diary-buffer (list)
+  (mapc
+   (lambda (x)
+     (if (string-match "^diary" x)
+	 (kill-buffer x)))
+   list))
+
+(defun omi-kill-ics-buffer (list)
+  (mapc
+   (lambda (x)
+     (if (string-match "ics$" x)
+	 (kill-buffer x)))
+   list))
+
+(defun omi-delete-ics-file (list)
+  (mapc
+   (lambda (x)
+     (delete-file x))
+   list))
+
+(defun omi-checked (directory)
+  "Parse Info.plist in iCal.app calendar folder and determine
+whether Checked key is 1. If Checked key is not 1, remove
+calendar from list of calendars for import"
+  (let* ((root (xml-parse-file (car (directory-files directory 1 "Info.plist"))))
+	 (plist (car root))
+	 (dict (car (xml-get-children plist 'dict)))
+	 (keys (cdr (xml-node-children dict)))
+	 (keys (mapcar
+		(lambda (x)
+		  (cond ((listp x)
+			 x)))
+		keys))
+	 (keys (delq 'nil keys)))
+    (when (equal "1" (car (cddr (lax-plist-get keys '(key nil "Checked")))))
+      directory)))
+
+(provide 'org-mac-iCal)
+
+;;; org-mac-iCal.el ends here

+ 2 - 0
lisp/org.el

@@ -193,7 +193,9 @@ to add the symbol `xyz', and the package must have a call to
 	(const :tag "C  exp-bibtex:        Export citations using BibTeX" org-exp-bibtex)
 	(const :tag "C  exp-blocks:        Pre-process blocks for export" org-exp-blocks)
 	(const :tag "C  interactive-query: Interactive modification of tags query (PARTIALLY OBSOLETE, see secondary filtering)" org-interactive-query)
+	(const :tag "C  jira               Add a jira:ticket protocol to Org" org-jira)
 	(const :tag "C  mairix:            Hook mairix search into Org for different MUAs" org-mairix)
+	(const :tag "C  mac-iCal           Imports events from iCal.app to the Emacs diary" org-mac-iCal)
 	(const :tag "C  man:               Support for links to manpages in Org-mode" org-man)
 	(const :tag "C  mtags:             Support for muse-like tags" org-mtags)
 	(const :tag "C  panel:             Simple routines for us with bad memory" org-panel)