emacs-wiki-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[emacs-wiki-discuss] planner appointments exported to icalendar events


From: Edgar Gonçalves
Subject: [emacs-wiki-discuss] planner appointments exported to icalendar events
Date: Sun, 26 Mar 2006 21:19:24 +0100
User-agent: Gnus/5.110004 (No Gnus v0.4)

Hi,

after managing to keep all my personal information in Emacs (hooray to
planner, muse, gnus, and bbdb!), I came to the conclusion that the outside
world still uses other tools, and they often ask me for some portions of
information. One of such is my schedule. So I promised to give them an
iCalendar .ics file, and dug into Emacs to code some elisp to make it
work. First, I found icalendar.el, and then planner-ical. Both wouldn't work
for me:
1)  icalendar.el provides a simple API, directed to diary<->icalendar
    migration. It doesn't merge information :(
2) planner-ical.el is a work in progress, I suppose. It only converts tasks
   into VTODO, and only from one page at a time.

So I thought about what I needed:
o export all my future appointments into VEVENTs. This includes cyclic events,
  and tasks with time informations (both handled with planner-appt).
o import a full icalendar into planner. deal with VEVENT, VTODO, VJOURNAL, and
  create, respectively, schedule entries, tasks and notes. add the appointments
  retrieved from the VALARMS.


The code I made today fulfills, although not wonderfully, my first
requirement. I'm using it specially to communicate my availability to my
co-workers. So I added a regexp argument to filter each entry by its planner
category! The only thing I can't seem to manage is to get planner-appt to tell
me the category of a task-appointment. So right now I export all of the tasks!
Anyone knows how I can get this behavior?

Here's the code to export to a ics file:


;; iCalendar export of appointments:
(require 'icalendar)
;; TODO: Each VEVENT and VTODO will have a VALARM if it has an associated
;; appointment."

(defun planner-export-ical (category-regexp n ical-output-file)
  "Write ICAL-OUTPUT-FILE with iCalendar format. CATEGORY_REGEXP will
limit category marked entries, enabling filtering of the exported
data (up until N days from now).
The iCalendar exported data are all the planner task appointments and
all the cyclic diary entries (in `planner-cyclic-diary-file').
They are exported as VEVENTs."
  (interactive)
  ;; Get the appointments until end-date:
  (let ((appts (planner-appt-forthcoming-get-appts n (planner-today))))

    ;; And now add the cyclic appointments from the appropriate file:
    (with-temp-buffer
      (let ((cyclic-appts nil))
        (with-temp-buffer
          (find-file planner-cyclic-diary-file)
          (dolist (line (split-string (buffer-string) "[\n\r]"))
            (unless (or (string= line "")
                        (string-match "^!" line))
              (push line cyclic-appts)))
          (kill-buffer (current-buffer)))
        (dolist (appt-desc cyclic-appts)
          (let ((appt-category (when (string-match "\\(.*\\)[ \t]*(\\(.*\\))$" 
appt-desc)
                                 (match-string 2 appt-desc)))
                (appt-text (match-string 1 appt-desc)))
            ;; Now filter by categories regexp:
            (when (string-match category-regexp appt-category)
              (when (string-match "\\(.*\\) @\\([0-2]?[0-9]:[0-5]?[0-9]\\)[ 
\t]*[-|][ \t]*\\([0-2]?[0-9]:[0-5]?[0-9]\\)[ \t]*|?[ \t]*\\(.*\\)$" appt-text)
                (let ((day        (match-string 1 appt-text))
                      (start-time (match-string 2 appt-text))
                      (end-time   (match-string 3 appt-text))
                      (text       (match-string 4 appt-text)))
                  (setq appt-text (format "%s %s-%s %s\n" day start-time 
end-time text))
                  (message "Adding cyclic appt to temp diary:::: %s" appt-text)
                  (insert appt-text)))))))      
      (dolist (appt appts)
        (let* ((appt-date (first appt))
               (appt-desc (second appt))
               (appt-category (when (string-match "\\(.*\\)(\\(.*\\))$" 
appt-desc)
                                (match-string 2 appt-desc)))
               (appt-text (when (string-match "\\(.*\\)\\((.*)\\)?$" appt-desc)
                                (match-string 1 appt-desc))))
          ;; Filter task appointments only:
          (when (and appt-text
                     (string-match "address@hidden(.*\\)[       ]*|?[   ]#[     
 ]*[-|]?\\(.*\\)$" appt-text))
            ;; Now filter by categories regexp:
            (if (or (null appt-category)
                    (string-match category-regexp appt-category))

                ;; Extract time and text strings:
                (let ((appt-time (match-string 1 appt-text))
                      (appt-text (match-string 2 appt-text)))
                  
                  (setq appt-time (replace-in-string appt-time "|" ""))
                  (setq appt-time (replace-in-string appt-time " [ ]*" " "))
                  (setq appt-time (replace-in-string appt-time " $" ""))
                  (setq appt-time (replace-in-string appt-time " " "-"))
                  (setq appt-date (apply #'format "%s/%s/%s" 
(planner-filename-to-calendar-date appt-date)))
                  (message "Adding task to temp diary:::: %s %s %s" appt-date 
appt-time appt-text)
                  (insert (format "%s %s %s\n" appt-date appt-time appt-text)))
                (message "NOT adding task to temp diary:::: %s" appt-desc)))))
      (icalendar-export-region (point-min)
                               (point-max)
                               ical-output-file))))

;; icalendar fix (this function wouldn't work properly under my Windows + GNU
;; Emacs configuration, so I just removed a silly comparison:
(defalias 'icalendar--rris 'replace-regexp-in-string)

;; Usage example (export ical for the next 31 days):
;;  (planner-export-ical "." 31 "~/exported-planner-appts.ics")


-- 
Edgar Gonçalves
Software Engineering Group @ INESC-ID
IST/Technical University of Lisbon
Rua Alves Redol, 9, Room 635              
1000-029 Lisboa, Portugal                 
mailto:edgar[DOT]goncalves[AT]inesc[DASH]id[DOT]pt
http://www.esw.inesc-id.pt/~eemg





reply via email to

[Prev in Thread] Current Thread [Next in Thread]