1 |
;;; icalendar.el --- iCalendar implementation |
;;; icalendar.el --- iCalendar implementation -*-coding: utf-8 -*- |
2 |
|
|
3 |
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: Ulf Jasper <ulf.jasper@web.de> |
;; Author: Ulf Jasper <ulf.jasper@web.de> |
6 |
;; Created: August 2002 |
;; Created: August 2002 |
7 |
;; Keywords: calendar |
;; Keywords: calendar |
8 |
;; Human-Keywords: calendar, diary, iCalendar, vCalendar |
;; Human-Keywords: calendar, diary, iCalendar, vCalendar |
9 |
|
|
10 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
31 |
|
|
32 |
;;; History: |
;;; History: |
33 |
|
|
34 |
;; 0.06 Bugfixes regarding icalendar-import-format-*. |
;; 0.07: Renamed commands! |
35 |
;; Fix in icalendar-convert-diary-to-ical -- thanks to Philipp Grau. |
;; icalendar-extract-ical-from-buffer -> icalendar-import-buffer |
36 |
|
;; icalendar-convert-diary-to-ical -> icalendar-export-file |
37 |
|
;; Naming scheme: icalendar-.* = user command; icalendar--.* = |
38 |
|
;; internal. |
39 |
|
;; Added icalendar-export-region. |
40 |
|
;; The import and export commands do not clear their target file, |
41 |
|
;; but append their results to the target file. |
42 |
|
|
43 |
|
;; 0.06: Bugfixes regarding icalendar-import-format-*. |
44 |
|
;; Fix in icalendar-convert-diary-to-ical -- thanks to Philipp |
45 |
|
;; Grau. |
46 |
|
|
47 |
;; 0.05: New import format scheme: Replaced icalendar-import-prefix-*, |
;; 0.05: New import format scheme: Replaced icalendar-import-prefix-*, |
48 |
;; icalendar-import-ignored-properties, and |
;; icalendar-import-ignored-properties, and |
71 |
;; ====================================================================== |
;; ====================================================================== |
72 |
;; To Do: |
;; To Do: |
73 |
|
|
74 |
;; * Import from ical: |
;; * Import from ical to diary: |
75 |
;; + Need more properties for icalendar-import-format |
;; + Need more properties for icalendar-import-format |
76 |
;; + check vcalendar version |
;; + check vcalendar version |
77 |
;; + check (unknown) elements |
;; + check (unknown) elements |
83 |
;; + error log is incomplete |
;; + error log is incomplete |
84 |
;; + nice to have: #include "webcal://foo.com/some-calendar.ics" |
;; + nice to have: #include "webcal://foo.com/some-calendar.ics" |
85 |
|
|
86 |
;; * Export into ical |
;; * Export from diary to ical |
87 |
;; + diary-date, diary-float, and self-made sexp entries are not |
;; + diary-date, diary-float, and self-made sexp entries are not |
88 |
;; understood |
;; understood |
89 |
;; + timezones, currently all times are local! |
;; + timezones, currently all times are local! |
90 |
|
|
91 |
;; * Other things |
;; * Other things |
|
;; + defcustom icalendar-import-ignored-properties does not work with |
|
|
;; XEmacs. |
|
92 |
;; + clean up all those date/time parsing functions |
;; + clean up all those date/time parsing functions |
93 |
;; + Handle todo items? |
;; + Handle todo items? |
94 |
;; + Check iso 8601 for datetime and period |
;; + Check iso 8601 for datetime and period |
95 |
;; + Which chars to (un)escape? |
;; + Which chars to (un)escape? |
|
;; + Time to find out how the profiler works? |
|
96 |
|
|
97 |
|
|
98 |
;;; Code: |
;;; Code: |
99 |
|
|
100 |
(defconst icalendar-version 0.06 |
(defconst icalendar-version 0.07 |
101 |
"Version number of icalendar.el.") |
"Version number of icalendar.el.") |
102 |
|
|
103 |
;; ====================================================================== |
;; ====================================================================== |
180 |
(defconst icalendar-monthnumber-table |
(defconst icalendar-monthnumber-table |
181 |
'(("^jan\\(uar\\)?y?$" . 1) |
'(("^jan\\(uar\\)?y?$" . 1) |
182 |
("^feb\\(ruar\\)?y?$" . 2) |
("^feb\\(ruar\\)?y?$" . 2) |
183 |
("^mar\\(ch\\)?\\|märz?$" . 3) |
("^mar\\(ch\\)?\\|märz$" . 3) |
184 |
("^apr\\(il\\)?$" . 4) |
("^apr\\(il\\)?$" . 4) |
185 |
("^ma[iy]$" . 5) |
("^ma[iy]$" . 5) |
186 |
("^jun[ie]?$" . 6) |
("^jun[ie]?$" . 6) |
202 |
(require 'appt) |
(require 'appt) |
203 |
|
|
204 |
;; ====================================================================== |
;; ====================================================================== |
205 |
|
;; misc |
206 |
|
;; ====================================================================== |
207 |
|
(defun icalendar--dmsg (&rest args) |
208 |
|
"Print message ARGS if `icalendar-debug' is non-nil." |
209 |
|
(if icalendar-debug |
210 |
|
(apply 'message args))) |
211 |
|
|
212 |
|
;; ====================================================================== |
213 |
;; Core functionality |
;; Core functionality |
214 |
;; Functions for parsing icalendars, importing and so on |
;; Functions for parsing icalendars, importing and so on |
215 |
;; ====================================================================== |
;; ====================================================================== |
216 |
|
|
217 |
(defun icalendar-get-unfolded-buffer (folded-ical-buffer) |
(defun icalendar--get-unfolded-buffer (folded-ical-buffer) |
218 |
"Return a new buffer containing the unfolded contents of a buffer. |
"Return a new buffer containing the unfolded contents of a buffer. |
219 |
Folding is the iCalendar way of wrapping long lines. In the |
Folding is the iCalendar way of wrapping long lines. In the |
220 |
created buffer all occurrences of CR LF BLANK are replaced by the |
created buffer all occurrences of CR LF BLANK are replaced by the |
226 |
(erase-buffer) |
(erase-buffer) |
227 |
(insert-buffer folded-ical-buffer) |
(insert-buffer folded-ical-buffer) |
228 |
(while (re-search-forward "\r?\n[ \t]" nil t) |
(while (re-search-forward "\r?\n[ \t]" nil t) |
229 |
(replace-match "" nil nil)) |
(replace-match "" nil nil))) |
|
) |
|
230 |
unfolded-buffer)) |
unfolded-buffer)) |
231 |
|
|
232 |
;; Replace regexp RE with RP in string ST and return the new string. |
(defsubst icalendar--rris (re rp st) |
233 |
;; This is here for compatibility with XEmacs. |
"Replace regexp RE with RP in string ST and return the new string. |
234 |
(defsubst icalendar-rris (re rp st) |
This is here for compatibility with XEmacs." |
235 |
;; XEmacs: |
;; XEmacs: |
236 |
(if (fboundp 'replace-in-string) |
(if (fboundp 'replace-in-string) |
237 |
(save-match-data ;; apparently XEmacs needs save-match-data |
(save-match-data ;; apparently XEmacs needs save-match-data |
239 |
;; Emacs: |
;; Emacs: |
240 |
(replace-regexp-in-string re rp st))) |
(replace-regexp-in-string re rp st))) |
241 |
|
|
242 |
(defun icalendar-read-element (invalue inparams) |
(defun icalendar--read-element (invalue inparams) |
243 |
"Recursively read the next iCalendar element in the current buffer. |
"Recursively read the next iCalendar element in the current buffer. |
244 |
INVALUE gives the current iCalendar element we are reading. |
INVALUE gives the current iCalendar element we are reading. |
245 |
INPARAMS gives the current parameters..... |
INPARAMS gives the current parameters..... |
247 |
it finds" |
it finds" |
248 |
(let (element children line name params param param-name param-value |
(let (element children line name params param param-name param-value |
249 |
value |
value |
250 |
(continue t)) |
(continue t)) |
251 |
(setq children '()) |
(setq children '()) |
252 |
(while (and continue |
(while (and continue |
253 |
(re-search-forward "^\\([A-Za-z0-9-]+\\)[;:]" nil t)) |
(re-search-forward "^\\([A-Za-z0-9-]+\\)[;:]" nil t)) |
275 |
(error "Oops")) |
(error "Oops")) |
276 |
(forward-char 1) |
(forward-char 1) |
277 |
(re-search-forward "\\(.*\\)\\(\r?\n[ \t].*\\)*" nil t) |
(re-search-forward "\\(.*\\)\\(\r?\n[ \t].*\\)*" nil t) |
278 |
(setq value (icalendar-rris "\r?\n[ \t]" "" (match-string 0))) |
(setq value (icalendar--rris "\r?\n[ \t]" "" (match-string 0))) |
279 |
(setq line (list name params value)) |
(setq line (list name params value)) |
280 |
(cond ((eq name 'BEGIN) |
(cond ((eq name 'BEGIN) |
281 |
(setq children |
(setq children |
282 |
(append children |
(append children |
283 |
(list (icalendar-read-element (intern value) |
(list (icalendar--read-element (intern value) |
284 |
params))))) |
params))))) |
285 |
((eq name 'END) |
((eq name 'END) |
286 |
(setq continue nil)) |
(setq continue nil)) |
287 |
(t |
(t |
294 |
;; helper functions for examining events |
;; helper functions for examining events |
295 |
;; ====================================================================== |
;; ====================================================================== |
296 |
|
|
297 |
(defsubst icalendar-get-all-event-properties (event) |
;;(defsubst icalendar--get-all-event-properties (event) |
298 |
"Return the list of properties in this EVENT." |
;; "Return the list of properties in this EVENT." |
299 |
(car (cddr event))) |
;; (car (cddr event))) |
300 |
|
|
301 |
(defun icalendar-get-event-property (event prop) |
(defun icalendar--get-event-property (event prop) |
302 |
"For the given EVENT return the value of the property PROP." |
"For the given EVENT return the value of the property PROP." |
303 |
(catch 'found |
(catch 'found |
304 |
(let ((props (car (cddr event))) pp) |
(let ((props (car (cddr event))) pp) |
309 |
(setq props (cdr props)))) |
(setq props (cdr props)))) |
310 |
nil)) |
nil)) |
311 |
|
|
312 |
(defun icalendar-set-event-property (event prop new-value) |
;; (defun icalendar--set-event-property (event prop new-value) |
313 |
"For the given EVENT set the property PROP to the value NEW-VALUE." |
;; "For the given EVENT set the property PROP to the value NEW-VALUE." |
314 |
(catch 'found |
;; (catch 'found |
315 |
(let ((props (car (cddr event))) pp) |
;; (let ((props (car (cddr event))) pp) |
316 |
(while props |
;; (while props |
317 |
(setq pp (car props)) |
;; (setq pp (car props)) |
318 |
(when (eq (car pp) prop) |
;; (when (eq (car pp) prop) |
319 |
(setcdr (cdr pp) new-value) |
;; (setcdr (cdr pp) new-value) |
320 |
(throw 'found (car (cddr pp)))) |
;; (throw 'found (car (cddr pp)))) |
321 |
(setq props (cdr props))) |
;; (setq props (cdr props))) |
322 |
(setq props (car (cddr event))) |
;; (setq props (car (cddr event))) |
323 |
(setcar (cddr event) |
;; (setcar (cddr event) |
324 |
(append props (list (list prop nil new-value))))))) |
;; (append props (list (list prop nil new-value))))))) |
325 |
|
|
326 |
(defun icalendar-get-children (node name) |
(defun icalendar--get-children (node name) |
327 |
"Return all children of the given NODE which have a name NAME. |
"Return all children of the given NODE which have a name NAME. |
328 |
For instance the VCALENDAR node can have VEVENT children as well as VTODO |
For instance the VCALENDAR node can have VEVENT children as well as VTODO |
329 |
children." |
children." |
335 |
(when children |
(when children |
336 |
(let ((subresult |
(let ((subresult |
337 |
(delq nil |
(delq nil |
338 |
(mapcar (lambda (n) |
(mapcar (lambda (n) |
339 |
(icalendar-get-children n name)) |
(icalendar--get-children n name)) |
340 |
children)))) |
children)))) |
341 |
(if subresult |
(if subresult |
342 |
(if result |
(if result |
343 |
(setq result (append result subresult)) |
(setq result (append result subresult)) |
344 |
(setq result subresult))))) |
(setq result subresult))))) |
345 |
result)) |
result)) |
346 |
|
|
347 |
; private |
; private |
348 |
(defun icalendar-all-events (icalendar) |
(defun icalendar--all-events (icalendar) |
349 |
"Return the list of all existing events in the given ICALENDAR." |
"Return the list of all existing events in the given ICALENDAR." |
350 |
(interactive "") |
(icalendar--get-children (car icalendar) 'VEVENT)) |
|
(icalendar-get-children (car icalendar) 'VEVENT)) |
|
351 |
|
|
352 |
(defun icalendar-split-value (value-string) |
(defun icalendar--split-value (value-string) |
353 |
"Splits VALUE-STRING at ';='." |
"Splits VALUE-STRING at ';='." |
354 |
(let ((result '()) |
(let ((result '()) |
355 |
param-name param-value) |
param-name param-value) |
361 |
(insert value-string) |
(insert value-string) |
362 |
(goto-char (point-min)) |
(goto-char (point-min)) |
363 |
(while |
(while |
364 |
(re-search-forward |
(re-search-forward |
365 |
"\\([A-Za-z0-9-]+\\)=\\(\\([^;,:]+\\)\\|\"\\([^\"]+\\)\"\\);?" |
"\\([A-Za-z0-9-]+\\)=\\(\\([^;,:]+\\)\\|\"\\([^\"]+\\)\"\\);?" |
366 |
nil t) |
nil t) |
367 |
(setq param-name (intern (match-string 1))) |
(setq param-name (intern (match-string 1))) |
368 |
(setq param-value (match-string 2)) |
(setq param-value (match-string 2)) |
369 |
(setq result |
(setq result |
370 |
(append result (list (list param-name param-value))))))) |
(append result (list (list param-name param-value))))))) |
371 |
result)) |
result)) |
372 |
|
|
373 |
(defun icalendar-decode-isodatetime (isodatetimestring) |
(defun icalendar--decode-isodatetime (isodatetimestring) |
374 |
"Return ISODATETIMESTRING in format like `decode-time'. |
"Return ISODATETIMESTRING in format like `decode-time'. |
375 |
Converts from ISO-8601 to Emacs representation. If ISODATETIMESTRING |
Converts from ISO-8601 to Emacs representation. If ISODATETIMESTRING |
376 |
specifies UTC time (trailing letter Z) the decoded time is given in |
specifies UTC time (trailing letter Z) the decoded time is given in |
377 |
the local time zone! FIXME: TZID-attributes are ignored....! FIXME: |
the local time zone! FIXME: TZID-attributes are ignored....! FIXME: |
378 |
multiple comma-separated values should be allowed!" |
multiple comma-separated values should be allowed!" |
379 |
(icalendar-dmsg isodatetimestring) |
(icalendar--dmsg isodatetimestring) |
380 |
(if isodatetimestring |
(if isodatetimestring |
381 |
;; day/month/year must be present |
;; day/month/year must be present |
382 |
(let ((year (read (substring isodatetimestring 0 4))) |
(let ((year (read (substring isodatetimestring 0 4))) |
386 |
(minute 0) |
(minute 0) |
387 |
(second 0)) |
(second 0)) |
388 |
(when (> (length isodatetimestring) 12) |
(when (> (length isodatetimestring) 12) |
389 |
;; hour/minute present |
;; hour/minute present |
390 |
(setq hour (read (substring isodatetimestring 9 11))) |
(setq hour (read (substring isodatetimestring 9 11))) |
391 |
(setq minute (read (substring isodatetimestring 11 13)))) |
(setq minute (read (substring isodatetimestring 11 13)))) |
392 |
(when (> (length isodatetimestring) 14) |
(when (> (length isodatetimestring) 14) |
393 |
;; seconds present |
;; seconds present |
394 |
(setq second (read (substring isodatetimestring 13 15)))) |
(setq second (read (substring isodatetimestring 13 15)))) |
395 |
(when (and (> (length isodatetimestring) 15) |
(when (and (> (length isodatetimestring) 15) |
396 |
;; UTC specifier present |
;; UTC specifier present |
397 |
(char-equal ?Z (aref isodatetimestring 15))) |
(char-equal ?Z (aref isodatetimestring 15))) |
398 |
;; if not UTC add current-time-zone offset |
;; if not UTC add current-time-zone offset |
399 |
(setq second (+ (car (current-time-zone)) second))) |
(setq second (+ (car (current-time-zone)) second))) |
408 |
;; isodatetimestring == nil |
;; isodatetimestring == nil |
409 |
nil)) |
nil)) |
410 |
|
|
411 |
(defun icalendar-decode-isoduration (isodurationstring) |
(defun icalendar--decode-isoduration (isodurationstring) |
412 |
"Return ISODURATIONSTRING in format like `decode-time'. |
"Return ISODURATIONSTRING in format like `decode-time'. |
413 |
Converts from ISO-8601 to Emacs representation. If ISODURATIONSTRING |
Converts from ISO-8601 to Emacs representation. If ISODURATIONSTRING |
414 |
specifies UTC time (trailing letter Z) the decoded time is given in |
specifies UTC time (trailing letter Z) the decoded time is given in |
422 |
"\\(\\([0-9]+\\)D\\)" ; days only |
"\\(\\([0-9]+\\)D\\)" ; days only |
423 |
"\\|" |
"\\|" |
424 |
"\\(\\(\\([0-9]+\\)D\\)?T\\(\\([0-9]+\\)H\\)?" ; opt days |
"\\(\\(\\([0-9]+\\)D\\)?T\\(\\([0-9]+\\)H\\)?" ; opt days |
425 |
"\\(\\([0-9]+\\)M\\)?\\(\\([0-9]+\\)S\\)?\\)" ; mand. time |
"\\(\\([0-9]+\\)M\\)?\\(\\([0-9]+\\)S\\)?\\)" ; mand. time |
426 |
"\\|" |
"\\|" |
427 |
"\\(\\([0-9]+\\)W\\)" ; weeks only |
"\\(\\([0-9]+\\)W\\)" ; weeks only |
428 |
"\\)$") isodurationstring) |
"\\)$") isodurationstring) |
432 |
(days 0) |
(days 0) |
433 |
(months 0) |
(months 0) |
434 |
(years 0)) |
(years 0)) |
435 |
(cond |
(cond |
436 |
((match-beginning 2) ;days only |
((match-beginning 2) ;days only |
437 |
(setq days (read (substring isodurationstring |
(setq days (read (substring isodurationstring |
438 |
(match-beginning 3) |
(match-beginning 3) |
439 |
(match-end 3)))) |
(match-end 3)))) |
440 |
(when icalendar-duration-correction |
(when icalendar-duration-correction |
441 |
(setq days (1- days)))) |
(setq days (1- days)))) |
442 |
((match-beginning 4) ;days and time |
((match-beginning 4) ;days and time |
443 |
(if (match-beginning 5) |
(if (match-beginning 5) |
444 |
(setq days (* 7 (read (substring isodurationstring |
(setq days (* 7 (read (substring isodurationstring |
445 |
(match-beginning 6) |
(match-beginning 6) |
446 |
(match-end 6)))))) |
(match-end 6)))))) |
447 |
(if (match-beginning 7) |
(if (match-beginning 7) |
448 |
(setq hours (read (substring isodurationstring |
(setq hours (read (substring isodurationstring |
449 |
(match-beginning 8) |
(match-beginning 8) |
450 |
(match-end 8))))) |
(match-end 8))))) |
451 |
(if (match-beginning 9) |
(if (match-beginning 9) |
452 |
(setq minutes (read (substring isodurationstring |
(setq minutes (read (substring isodurationstring |
453 |
(match-beginning 10) |
(match-beginning 10) |
454 |
(match-end 10))))) |
(match-end 10))))) |
455 |
(if (match-beginning 11) |
(if (match-beginning 11) |
456 |
(setq seconds (read (substring isodurationstring |
(setq seconds (read (substring isodurationstring |
457 |
(match-beginning 12) |
(match-beginning 12) |
458 |
(match-end 12))))) |
(match-end 12))))) |
459 |
) |
) |
460 |
((match-beginning 13) ;weeks only |
((match-beginning 13) ;weeks only |
461 |
(setq days (* 7 (read (substring isodurationstring |
(setq days (* 7 (read (substring isodurationstring |
462 |
(match-beginning 14) |
(match-beginning 14) |
463 |
(match-end 14)))))) |
(match-end 14)))))) |
464 |
) |
) |
465 |
(list seconds minutes hours days months years))) |
(list seconds minutes hours days months years))) |
466 |
;; isodatetimestring == nil |
;; isodatetimestring == nil |
467 |
nil)) |
nil)) |
468 |
|
|
469 |
(defun icalendar-add-decoded-times (time1 time2) |
(defun icalendar--add-decoded-times (time1 time2) |
470 |
"Add TIME1 to TIME2. |
"Add TIME1 to TIME2. |
471 |
Both times must be given in decoded form. One of these times must be |
Both times must be given in decoded form. One of these times must be |
472 |
valid (year > 1900 or something)." |
valid (year > 1900 or something)." |
483 |
;;(or (nth 6 time1) (nth 6 time2)) ;; FIXME? |
;;(or (nth 6 time1) (nth 6 time2)) ;; FIXME? |
484 |
))) |
))) |
485 |
|
|
486 |
(defun icalendar-datetime-to-noneuropean-date (datetime) |
(defun icalendar--datetime-to-noneuropean-date (datetime) |
487 |
"Convert the decoded DATETIME to non-european-style format. |
"Convert the decoded DATETIME to non-european-style format. |
488 |
Non-European format: (month day year)." |
Non-European format: (month day year)." |
489 |
(if datetime |
(if datetime |
490 |
(list (nth 4 datetime) ;month |
(list (nth 4 datetime) ;month |
491 |
(nth 3 datetime) ;day |
(nth 3 datetime) ;day |
492 |
(nth 5 datetime));year |
(nth 5 datetime)) ;year |
493 |
;; datetime == nil |
;; datetime == nil |
494 |
nil)) |
nil)) |
495 |
|
|
496 |
(defun icalendar-datetime-to-european-date (datetime) |
(defun icalendar--datetime-to-european-date (datetime) |
497 |
"Convert the decoded DATETIME to European format. |
"Convert the decoded DATETIME to European format. |
498 |
European format: (day month year). |
European format: (day month year). |
499 |
FIXME" |
FIXME" |
500 |
(if datetime |
(if datetime |
501 |
(format "%d %d %d" (nth 3 datetime); day |
(format "%d %d %d" (nth 3 datetime) ; day |
502 |
(nth 4 datetime) ;month |
(nth 4 datetime) ;month |
503 |
(nth 5 datetime));year |
(nth 5 datetime)) ;year |
504 |
;; datetime == nil |
;; datetime == nil |
505 |
nil)) |
nil)) |
506 |
|
|
507 |
(defun icalendar-datetime-to-colontime (datetime) |
(defun icalendar--datetime-to-colontime (datetime) |
508 |
"Extract the time part of a decoded DATETIME into 24-hour format. |
"Extract the time part of a decoded DATETIME into 24-hour format. |
509 |
Note that this silently ignores seconds." |
Note that this silently ignores seconds." |
510 |
(format "%02d:%02d" (nth 2 datetime) (nth 1 datetime))) |
(format "%02d:%02d" (nth 2 datetime) (nth 1 datetime))) |
511 |
|
|
512 |
(defun icalendar-get-month-number (monthname) |
(defun icalendar--get-month-number (monthname) |
513 |
"Return the month number for the given MONTHNAME." |
"Return the month number for the given MONTHNAME." |
514 |
(save-match-data |
(save-match-data |
515 |
(let ((case-fold-search t)) |
(let ((case-fold-search t)) |
516 |
(assoc-default monthname icalendar-monthnumber-table |
(assoc-default monthname icalendar-monthnumber-table |
517 |
'string-match)))) |
'string-match)))) |
518 |
|
|
519 |
(defun icalendar-get-weekday-abbrev (weekday) |
(defun icalendar--get-weekday-abbrev (weekday) |
520 |
"Return the abbreviated WEEKDAY." |
"Return the abbreviated WEEKDAY." |
521 |
;;FIXME: ISO-like(?). |
;;FIXME: ISO-like(?). |
522 |
(save-match-data |
(save-match-data |
524 |
(assoc-default weekday icalendar-weekdayabbrev-table |
(assoc-default weekday icalendar-weekdayabbrev-table |
525 |
'string-match)))) |
'string-match)))) |
526 |
|
|
527 |
(defun icalendar-datestring-to-isodate (datestring &optional day-shift) |
(defun icalendar--datestring-to-isodate (datestring &optional day-shift) |
528 |
"Convert diary-style DATESTRING to iso-style date. |
"Convert diary-style DATESTRING to iso-style date. |
529 |
If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days |
If DAY-SHIFT is non-nil, the result is shifted by DAY-SHIFT days |
530 |
-- DAY-SHIFT must be either nil or an integer. This function |
-- DAY-SHIFT must be either nil or an integer. This function |
531 |
takes care of european-style." |
takes care of european-style." |
532 |
(let ((day -1) month year) |
(let ((day -1) month year) |
533 |
(save-match-data |
(save-match-data |
534 |
(cond (;; numeric date |
(cond ( ;; numeric date |
535 |
(string-match (concat "\\s-*" |
(string-match (concat "\\s-*" |
536 |
"0?\\([1-9][0-9]?\\)[ \t/]\\s-*" |
"0?\\([1-9][0-9]?\\)[ \t/]\\s-*" |
537 |
"0?\\([1-9][0-9]?\\),?[ \t/]\\s-*" |
"0?\\([1-9][0-9]?\\),?[ \t/]\\s-*" |
538 |
"\\([0-9]\\{4\\}\\)") |
"\\([0-9]\\{4\\}\\)") |
539 |
datestring) |
datestring) |
540 |
(setq day (read (substring datestring (match-beginning 1) |
(setq day (read (substring datestring (match-beginning 1) |
541 |
(match-end 1)))) |
(match-end 1)))) |
542 |
(setq month (read (substring datestring (match-beginning 2) |
(setq month (read (substring datestring (match-beginning 2) |
543 |
(match-end 2)))) |
(match-end 2)))) |
544 |
(setq year (read (substring datestring (match-beginning 3) |
(setq year (read (substring datestring (match-beginning 3) |
545 |
(match-end 3)))) |
(match-end 3)))) |
546 |
(unless european-calendar-style |
(unless european-calendar-style |
547 |
(let ((x month)) |
(let ((x month)) |
548 |
(setq month day) |
(setq month day) |
549 |
(setq day x)))) |
(setq day x)))) |
550 |
(;; date contains month names -- european-style |
( ;; date contains month names -- european-style |
551 |
(and european-calendar-style |
(and european-calendar-style |
552 |
(string-match (concat "\\s-*" |
(string-match (concat "\\s-*" |
553 |
"0?\\([123]?[0-9]\\)[ \t/]\\s-*" |
"0?\\([123]?[0-9]\\)[ \t/]\\s-*" |
554 |
"\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
"\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
555 |
"\\([0-9]\\{4\\}\\)") |
"\\([0-9]\\{4\\}\\)") |
556 |
datestring)) |
datestring)) |
557 |
(setq day (read (substring datestring (match-beginning 1) |
(setq day (read (substring datestring (match-beginning 1) |
558 |
(match-end 1)))) |
(match-end 1)))) |
559 |
(setq month (icalendar-get-month-number |
(setq month (icalendar--get-month-number |
560 |
(substring datestring (match-beginning 2) |
(substring datestring (match-beginning 2) |
561 |
(match-end 2)))) |
(match-end 2)))) |
562 |
(setq year (read (substring datestring (match-beginning 3) |
(setq year (read (substring datestring (match-beginning 3) |
563 |
(match-end 3))))) |
(match-end 3))))) |
564 |
(;; date contains month names -- non-european-style |
( ;; date contains month names -- non-european-style |
565 |
(and (not european-calendar-style) |
(and (not european-calendar-style) |
566 |
(string-match (concat "\\s-*" |
(string-match (concat "\\s-*" |
567 |
"\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
"\\([A-Za-z][^ ]+\\)[ \t/]\\s-*" |
568 |
"0?\\([123]?[0-9]\\),?[ \t/]\\s-*" |
"0?\\([123]?[0-9]\\),?[ \t/]\\s-*" |
569 |
"\\([0-9]\\{4\\}\\)") |
"\\([0-9]\\{4\\}\\)") |
570 |
datestring)) |
datestring)) |
571 |
(setq day (read (substring datestring (match-beginning 2) |
(setq day (read (substring datestring (match-beginning 2) |
572 |
(match-end 2)))) |
(match-end 2)))) |
573 |
(setq month (icalendar-get-month-number |
(setq month (icalendar--get-month-number |
574 |
(substring datestring (match-beginning 1) |
(substring datestring (match-beginning 1) |
575 |
(match-end 1)))) |
(match-end 1)))) |
576 |
(setq year (read (substring datestring (match-beginning 3) |
(setq year (read (substring datestring (match-beginning 3) |
577 |
(match-end 3))))) |
(match-end 3))))) |
578 |
(t |
(t |
579 |
nil))) |
nil))) |
580 |
(if (> day 0) |
(if (> day 0) |
581 |
(let ((mdy (calendar-gregorian-from-absolute |
(let ((mdy (calendar-gregorian-from-absolute |
582 |
(+ (calendar-absolute-from-gregorian (list month day year)) |
(+ (calendar-absolute-from-gregorian (list month day |
583 |
(or day-shift 0))))) |
year)) |
584 |
(format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) |
(or day-shift 0))))) |
585 |
|
(format "%04d%02d%02d" (nth 2 mdy) (nth 0 mdy) (nth 1 mdy))) |
586 |
nil))) |
nil))) |
587 |
|
|
588 |
(defun icalendar-dmsg (&rest args) |
(defun icalendar--diarytime-to-isotime (timestring ampmstring) |
|
"Print message ARGS if `icalendar-debug' is non-nil." |
|
|
(if icalendar-debug |
|
|
(apply 'message args))) |
|
|
|
|
|
(defun icalendar-diarytime-to-isotime (timestring ampmstring) |
|
589 |
"Convert a a time like 9:30pm to an iso-conform string like T213000. |
"Convert a a time like 9:30pm to an iso-conform string like T213000. |
590 |
In this example the TIMESTRING would be \"9:30\" and the AMPMSTRING |
In this example the TIMESTRING would be \"9:30\" and the AMPMSTRING |
591 |
would be \"pm\"." |
would be \"pm\"." |
592 |
(if timestring |
(if timestring |
593 |
(let ((starttimenum (read (icalendar-rris ":" "" timestring)))) |
(let ((starttimenum (read (icalendar--rris ":" "" timestring)))) |
594 |
;; take care of am/pm style |
;; take care of am/pm style |
595 |
(if (and ampmstring (string= "pm" ampmstring)) |
(if (and ampmstring (string= "pm" ampmstring)) |
596 |
(setq starttimenum (+ starttimenum 1200))) |
(setq starttimenum (+ starttimenum 1200))) |
597 |
(format "T%04d00" starttimenum)) |
(format "T%04d00" starttimenum)) |
598 |
nil)) |
nil)) |
599 |
|
|
600 |
(defun icalendar-convert-string-for-export (s) |
(defun icalendar--convert-string-for-export (s) |
601 |
"Escape comma and other critical characters in string S." |
"Escape comma and other critical characters in string S." |
602 |
(icalendar-rris "," "\\\\," s)) |
(icalendar--rris "," "\\\\," s)) |
603 |
|
|
604 |
(defun icalendar-convert-for-import (string) |
(defun icalendar--convert-string-for-import (string) |
605 |
"Remove escape chars for comma, semicolon etc. from STRING." |
"Remove escape chars for comma, semicolon etc. from STRING." |
606 |
(icalendar-rris |
(icalendar--rris |
607 |
"\\\\n" "\n " (icalendar-rris |
"\\\\n" "\n " (icalendar--rris |
608 |
"\\\\\"" "\"" (icalendar-rris |
"\\\\\"" "\"" (icalendar--rris |
609 |
"\\\\;" ";" (icalendar-rris |
"\\\\;" ";" (icalendar--rris |
610 |
"\\\\," "," string))))) |
"\\\\," "," string))))) |
611 |
|
|
612 |
;; ====================================================================== |
;; ====================================================================== |
613 |
;; export -- convert emacs-diary to icalendar |
;; Export -- convert emacs-diary to icalendar |
614 |
;; ====================================================================== |
;; ====================================================================== |
615 |
|
|
616 |
(defun icalendar-convert-diary-to-ical (diary-filename ical-filename |
;; User function |
617 |
&optional do-not-clear-diary-file) |
(defun icalendar-export-file (diary-filename ical-filename) |
618 |
"Export diary file to iCalendar format -- erases ical-filename!!!. |
"Export diary file to iCalendar format. |
619 |
Argument DIARY-FILENAME is the input `diary-file'. |
All diary entries in the file DIARY-FILENAME are converted to iCalendar |
620 |
Argument ICAL-FILENAME is the output iCalendar file. |
format. The result is appended to the file ICAL-FILENAME." |
|
If DO-NOT-CLEAR-DIARY-FILE is not nil the target iCalendar file |
|
|
is not erased." |
|
621 |
(interactive "FExport diary data from file: |
(interactive "FExport diary data from file: |
622 |
Finto iCalendar file: ") |
Finto iCalendar file: ") |
623 |
|
(save-current-buffer |
624 |
|
(set-buffer (find-file diary-filename)) |
625 |
|
(icalendar-export-region (point-min) (point-max) ical-filename))) |
626 |
|
|
627 |
|
(defalias 'icalendar-convert-diary-to-ical 'icalendar-export-file) |
628 |
|
(make-obsolete 'icalendar-convert-diary-to-ical 'icalendar-export-file |
629 |
|
"icalendar 0.07") |
630 |
|
|
631 |
|
;; User function |
632 |
|
(defun icalendar-export-region (min max ical-filename) |
633 |
|
"Export region in diary file to iCalendar format. |
634 |
|
All diary entries in the region from MIN to MAX in the current buffer are |
635 |
|
converted to iCalendar format. The result is appended to the file |
636 |
|
ICAL-FILENAME." |
637 |
|
(interactive "r |
638 |
|
FExport diary data into iCalendar file: ") |
639 |
(let ((result "") |
(let ((result "") |
640 |
(start 0) |
(start 0) |
641 |
(entry-main "") |
(entry-main "") |
644 |
(contents) |
(contents) |
645 |
(oops nil) |
(oops nil) |
646 |
(nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol) |
(nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol) |
647 |
"?"))) |
"?"))) |
648 |
(save-current-buffer |
(save-excursion |
649 |
(set-buffer (find-file diary-filename)) |
(goto-char min) |
|
(goto-char (point-min)) |
|
650 |
(while (re-search-forward |
(while (re-search-forward |
651 |
"^\\([^ \t\n].*\\)\\(\n[ \t].*\\)*" nil t) |
"^\\([^ \t\n].*\\)\\(\n[ \t].*\\)*" max t) |
652 |
(setq entry-main (match-string 1)) |
(setq entry-main (match-string 1)) |
653 |
(if (match-beginning 2) |
(if (match-beginning 2) |
654 |
(setq entry-rest (match-string 2)) |
(setq entry-rest (match-string 2)) |
664 |
(concat nonmarker |
(concat nonmarker |
665 |
"%%(diary-anniversary \\([^)]+\\))\\s-*\\(.*\\)") |
"%%(diary-anniversary \\([^)]+\\))\\s-*\\(.*\\)") |
666 |
entry-main) |
entry-main) |
667 |
(icalendar-dmsg "diary-anniversary %s" entry-main) |
(icalendar--dmsg "diary-anniversary %s" entry-main) |
668 |
(let* ((datetime (substring entry-main (match-beginning 1) |
(let* ((datetime (substring entry-main (match-beginning 1) |
669 |
(match-end 1))) |
(match-end 1))) |
670 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
671 |
(substring entry-main (match-beginning 2) |
(substring entry-main (match-beginning 2) |
672 |
(match-end 2)))) |
(match-end 2)))) |
673 |
(startisostring (icalendar-datestring-to-isodate |
(startisostring (icalendar--datestring-to-isodate |
674 |
datetime)) |
datetime)) |
675 |
(endisostring (icalendar-datestring-to-isodate |
(endisostring (icalendar--datestring-to-isodate |
676 |
datetime 1))) |
datetime 1))) |
677 |
(setq contents |
(setq contents |
678 |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
679 |
"\nDTEND;VALUE=DATE:" endisostring |
"\nDTEND;VALUE=DATE:" endisostring |
688 |
))) |
))) |
689 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
690 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
691 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
692 |
entry-rest))))) |
entry-rest))))) |
693 |
;; cyclic events |
;; cyclic events |
694 |
;; %%(diary-cyclic ) |
;; %%(diary-cyclic ) |
697 |
"%%(diary-cyclic \\([^ ]+\\) +" |
"%%(diary-cyclic \\([^ ]+\\) +" |
698 |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") |
699 |
entry-main) |
entry-main) |
700 |
(icalendar-dmsg "diary-cyclic %s" entry-main) |
(icalendar--dmsg "diary-cyclic %s" entry-main) |
701 |
(let* ((frequency (substring entry-main (match-beginning 1) |
(let* ((frequency (substring entry-main (match-beginning 1) |
702 |
(match-end 1))) |
(match-end 1))) |
703 |
(datetime (substring entry-main (match-beginning 2) |
(datetime (substring entry-main (match-beginning 2) |
704 |
(match-end 2))) |
(match-end 2))) |
705 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
706 |
(substring entry-main (match-beginning 3) |
(substring entry-main (match-beginning 3) |
707 |
(match-end 3)))) |
(match-end 3)))) |
708 |
(startisostring (icalendar-datestring-to-isodate |
(startisostring (icalendar--datestring-to-isodate |
709 |
datetime)) |
datetime)) |
710 |
(endisostring (icalendar-datestring-to-isodate |
(endisostring (icalendar--datestring-to-isodate |
711 |
datetime 1))) |
datetime 1))) |
712 |
(setq contents |
(setq contents |
713 |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
714 |
"\nDTEND;VALUE=DATE:" endisostring |
"\nDTEND;VALUE=DATE:" endisostring |
719 |
))) |
))) |
720 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
721 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
722 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
723 |
entry-rest))))) |
entry-rest))))) |
724 |
;; diary-date -- FIXME |
;; diary-date -- FIXME |
725 |
((string-match |
((string-match |
726 |
(concat nonmarker |
(concat nonmarker |
727 |
"%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)") |
"%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)") |
728 |
entry-main) |
entry-main) |
729 |
(icalendar-dmsg "diary-date %s" entry-main) |
(icalendar--dmsg "diary-date %s" entry-main) |
730 |
(setq oops t)) |
(setq oops t)) |
731 |
;; float events -- FIXME |
;; float events -- FIXME |
732 |
((string-match |
((string-match |
733 |
(concat nonmarker |
(concat nonmarker |
734 |
"%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)") |
"%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)") |
735 |
entry-main) |
entry-main) |
736 |
(icalendar-dmsg "diary-float %s" entry-main) |
(icalendar--dmsg "diary-float %s" entry-main) |
737 |
(setq oops t)) |
(setq oops t)) |
738 |
;; block events |
;; block events |
739 |
((string-match |
((string-match |
741 |
"%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\) +" |
"%%(diary-block \\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\) +" |
742 |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\))\\s-*\\(.*\\)") |
743 |
entry-main) |
entry-main) |
744 |
(icalendar-dmsg "diary-block %s" entry-main) |
(icalendar--dmsg "diary-block %s" entry-main) |
745 |
(let* ((startstring (substring entry-main (match-beginning 1) |
(let* ((startstring (substring entry-main (match-beginning 1) |
746 |
(match-end 1))) |
(match-end 1))) |
747 |
(endstring (substring entry-main (match-beginning 2) |
(endstring (substring entry-main (match-beginning 2) |
748 |
(match-end 2))) |
(match-end 2))) |
749 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
750 |
(substring entry-main (match-beginning 3) |
(substring entry-main (match-beginning 3) |
751 |
(match-end 3)))) |
(match-end 3)))) |
752 |
(startisostring (icalendar-datestring-to-isodate |
(startisostring (icalendar--datestring-to-isodate |
753 |
startstring)) |
startstring)) |
754 |
(endisostring (icalendar-datestring-to-isodate |
(endisostring (icalendar--datestring-to-isodate |
755 |
endstring 1))) |
endstring 1))) |
756 |
(setq contents |
(setq contents |
757 |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
(concat "\nDTSTART;VALUE=DATE:" startisostring |
758 |
"\nDTEND;VALUE=DATE:" endisostring |
"\nDTEND;VALUE=DATE:" endisostring |
760 |
)) |
)) |
761 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
762 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
763 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
764 |
entry-rest)))))) |
entry-rest)))))) |
765 |
;; other sexp diary entries -- FIXME |
;; other sexp diary entries -- FIXME |
766 |
((string-match |
((string-match |
767 |
(concat nonmarker |
(concat nonmarker |
768 |
"%%(\\([^)]+\\))\\s-*\\(.*\\)") |
"%%(\\([^)]+\\))\\s-*\\(.*\\)") |
769 |
entry-main) |
entry-main) |
770 |
(icalendar-dmsg "diary-sexp %s" entry-main) |
(icalendar--dmsg "diary-sexp %s" entry-main) |
771 |
(setq oops t)) |
(setq oops t)) |
772 |
;; weekly by day |
;; weekly by day |
773 |
;; Monday 8:30 Team meeting |
;; Monday 8:30 Team meeting |
780 |
"\\)?" |
"\\)?" |
781 |
"\\s-*\\(.*\\)$") |
"\\s-*\\(.*\\)$") |
782 |
entry-main) |
entry-main) |
783 |
(icalendar-get-weekday-abbrev |
(icalendar--get-weekday-abbrev |
784 |
(substring entry-main (match-beginning 1) (match-end 1)))) |
(substring entry-main (match-beginning 1) (match-end 1)))) |
785 |
(icalendar-dmsg "weekly %s" entry-main) |
(icalendar--dmsg "weekly %s" entry-main) |
786 |
(let* ((day (icalendar-get-weekday-abbrev |
(let* ((day (icalendar--get-weekday-abbrev |
787 |
(substring entry-main (match-beginning 1) |
(substring entry-main (match-beginning 1) |
788 |
(match-end 1)))) |
(match-end 1)))) |
789 |
(starttimestring (icalendar-diarytime-to-isotime |
(starttimestring (icalendar--diarytime-to-isotime |
790 |
(if (match-beginning 3) |
(if (match-beginning 3) |
791 |
(substring entry-main |
(substring entry-main |
792 |
(match-beginning 3) |
(match-beginning 3) |
797 |
(match-beginning 4) |
(match-beginning 4) |
798 |
(match-end 4)) |
(match-end 4)) |
799 |
nil))) |
nil))) |
800 |
(endtimestring (icalendar-diarytime-to-isotime |
(endtimestring (icalendar--diarytime-to-isotime |
801 |
(if (match-beginning 6) |
(if (match-beginning 6) |
802 |
(substring entry-main |
(substring entry-main |
803 |
(match-beginning 6) |
(match-beginning 6) |
804 |
(match-end 6)) |
(match-end 6)) |
805 |
nil) |
nil) |
806 |
(if (match-beginning 7) |
(if (match-beginning 7) |
807 |
(substring entry-main |
(substring entry-main |
808 |
(match-beginning 7) |
(match-beginning 7) |
809 |
(match-end 7)) |
(match-end 7)) |
810 |
nil))) |
nil))) |
811 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
812 |
(substring entry-main (match-beginning 8) |
(substring entry-main (match-beginning 8) |
813 |
(match-end 8))))) |
(match-end 8))))) |
814 |
(when starttimestring |
(when starttimestring |
815 |
(unless endtimestring |
(unless endtimestring |
816 |
(let ((time (read (icalendar-rris "^T0?" "" |
(let ((time (read (icalendar--rris "^T0?" "" |
817 |
starttimestring)))) |
starttimestring)))) |
818 |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
819 |
(setq contents |
(setq contents |
820 |
(concat "\nDTSTART" |
(concat "\nDTSTART" |
831 |
))) |
))) |
832 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
833 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
834 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
835 |
entry-rest))))) |
entry-rest))))) |
836 |
;; yearly by day |
;; yearly by day |
837 |
;; 1 May Tag der Arbeit |
;; 1 May Tag der Arbeit |
843 |
"\\*?\\s-*" |
"\\*?\\s-*" |
844 |
"\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" |
"\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" |
845 |
"\\(" |
"\\(" |
846 |
"-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" |
"-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" |
847 |
"\\)?" |
"\\)?" |
848 |
"\\s-*\\([^0-9]+.*\\)$"; must not match years |
"\\s-*\\([^0-9]+.*\\)$" ; must not match years |
849 |
) |
) |
850 |
entry-main) |
entry-main) |
851 |
(icalendar-dmsg "yearly %s" entry-main) |
(icalendar--dmsg "yearly %s" entry-main) |
852 |
(let* ((daypos (if european-calendar-style 1 2)) |
(let* ((daypos (if european-calendar-style 1 2)) |
853 |
(monpos (if european-calendar-style 2 1)) |
(monpos (if european-calendar-style 2 1)) |
854 |
(day (read (substring entry-main (match-beginning daypos) |
(day (read (substring entry-main (match-beginning daypos) |
855 |
(match-end daypos)))) |
(match-end daypos)))) |
856 |
(month (icalendar-get-month-number |
(month (icalendar--get-month-number |
857 |
(substring entry-main (match-beginning monpos) |
(substring entry-main (match-beginning monpos) |
858 |
(match-end monpos)))) |
(match-end monpos)))) |
859 |
(starttimestring (icalendar-diarytime-to-isotime |
(starttimestring (icalendar--diarytime-to-isotime |
860 |
(if (match-beginning 4) |
(if (match-beginning 4) |
861 |
(substring entry-main |
(substring entry-main |
862 |
(match-beginning 4) |
(match-beginning 4) |
867 |
(match-beginning 5) |
(match-beginning 5) |
868 |
(match-end 5)) |
(match-end 5)) |
869 |
nil))) |
nil))) |
870 |
(endtimestring (icalendar-diarytime-to-isotime |
(endtimestring (icalendar--diarytime-to-isotime |
871 |
(if (match-beginning 7) |
(if (match-beginning 7) |
872 |
(substring entry-main |
(substring entry-main |
873 |
(match-beginning 7) |
(match-beginning 7) |
874 |
(match-end 7)) |
(match-end 7)) |
875 |
nil) |
nil) |
876 |
(if (match-beginning 8) |
(if (match-beginning 8) |
877 |
(substring entry-main |
(substring entry-main |
878 |
(match-beginning 8) |
(match-beginning 8) |
879 |
(match-end 8)) |
(match-end 8)) |
880 |
nil))) |
nil))) |
881 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
882 |
(substring entry-main (match-beginning 9) |
(substring entry-main (match-beginning 9) |
883 |
(match-end 9))))) |
(match-end 9))))) |
884 |
(when starttimestring |
(when starttimestring |
885 |
(unless endtimestring |
(unless endtimestring |
886 |
(let ((time (read (icalendar-rris "^T0?" "" |
(let ((time (read (icalendar--rris "^T0?" "" |
887 |
starttimestring)))) |
starttimestring)))) |
888 |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
889 |
(setq contents |
(setq contents |
890 |
(concat "\nDTSTART" |
(concat "\nDTSTART" |
903 |
))) |
))) |
904 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
905 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
906 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
907 |
entry-rest))))) |
entry-rest))))) |
908 |
;; "ordinary" events, start and end time given |
;; "ordinary" events, start and end time given |
909 |
;; 1 Feb 2003 Hs Hochzeitsfeier, Dreieich |
;; 1 Feb 2003 Hs Hochzeitsfeier, Dreieich |
912 |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-+" |
"\\([^ /]+[ /]+[^ /]+[ /]+[^ ]+\\)\\s-+" |
913 |
"\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" |
"\\(0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?" |
914 |
"\\(" |
"\\(" |
915 |
"-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" |
"-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?" |
916 |
"\\)?" |
"\\)?" |
917 |
"\\s-*\\(.*\\)") |
"\\s-*\\(.*\\)") |
918 |
entry-main) |
entry-main) |
919 |
(icalendar-dmsg "ordinary %s" entry-main) |
(icalendar--dmsg "ordinary %s" entry-main) |
920 |
(let* ((datestring (icalendar-datestring-to-isodate |
(let* ((datestring (icalendar--datestring-to-isodate |
921 |
(substring entry-main (match-beginning 1) |
(substring entry-main (match-beginning 1) |
922 |
(match-end 1)))) |
(match-end 1)))) |
923 |
(starttimestring (icalendar-diarytime-to-isotime |
(starttimestring (icalendar--diarytime-to-isotime |
924 |
(if (match-beginning 3) |
(if (match-beginning 3) |
925 |
(substring entry-main |
(substring entry-main |
926 |
(match-beginning 3) |
(match-beginning 3) |
931 |
(match-beginning 4) |
(match-beginning 4) |
932 |
(match-end 4)) |
(match-end 4)) |
933 |
nil))) |
nil))) |
934 |
(endtimestring (icalendar-diarytime-to-isotime |
(endtimestring (icalendar--diarytime-to-isotime |
935 |
(if (match-beginning 6) |
(if (match-beginning 6) |
936 |
(substring entry-main |
(substring entry-main |
937 |
(match-beginning 6) |
(match-beginning 6) |
938 |
(match-end 6)) |
(match-end 6)) |
939 |
nil) |
nil) |
940 |
(if (match-beginning 7) |
(if (match-beginning 7) |
941 |
(substring entry-main |
(substring entry-main |
942 |
(match-beginning 7) |
(match-beginning 7) |
943 |
(match-end 7)) |
(match-end 7)) |
944 |
nil))) |
nil))) |
945 |
(summary (icalendar-convert-string-for-export |
(summary (icalendar--convert-string-for-export |
946 |
(substring entry-main (match-beginning 8) |
(substring entry-main (match-beginning 8) |
947 |
(match-end 8))))) |
(match-end 8))))) |
948 |
(when starttimestring |
(when starttimestring |
949 |
(unless endtimestring |
(unless endtimestring |
950 |
(let ((time (read (icalendar-rris "^T0?" "" |
(let ((time (read (icalendar--rris "^T0?" "" |
951 |
starttimestring)))) |
starttimestring)))) |
952 |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
(setq endtimestring (format "T%06d" (+ 10000 time)))))) |
953 |
(setq contents (format |
(setq contents (format |
954 |
"\nDTSTART%s:%s%s\nDTEND%s:%s%s\nSUMMARY:%s" |
"\nDTSTART%s:%s%s\nDTEND%s:%s%s\nSUMMARY:%s" |
955 |
(if starttimestring "" ";VALUE=DATE") |
(if starttimestring "" ";VALUE=DATE") |
956 |
datestring |
datestring |
957 |
(or starttimestring "") |
(or starttimestring "") |
958 |
(if endtimestring "" |
(if endtimestring "" |
959 |
";VALUE=DATE") |
";VALUE=DATE") |
960 |
datestring |
datestring |
961 |
(or endtimestring "") |
(or endtimestring "") |
962 |
summary)) |
summary)) |
963 |
(unless (string= entry-rest "") |
(unless (string= entry-rest "") |
964 |
(setq contents (concat contents "\nDESCRIPTION:" |
(setq contents (concat contents "\nDESCRIPTION:" |
965 |
(icalendar-convert-string-for-export |
(icalendar--convert-string-for-export |
966 |
entry-rest)))))) |
entry-rest)))))) |
967 |
;; everything else |
;; everything else |
968 |
(t |
(t |
970 |
(setq oops t))) |
(setq oops t))) |
971 |
(if oops |
(if oops |
972 |
(message "Cannot export entry on line %d" |
(message "Cannot export entry on line %d" |
973 |
(count-lines (point-min) (point))) |
(count-lines (point-min) (point))) |
974 |
(setq result (concat result header contents "\nEND:VEVENT")))) |
(setq result (concat result header contents "\nEND:VEVENT")))) |
975 |
;; we're done, insert everything into the file |
;; we're done, insert everything into the file |
976 |
(let ((coding-system-for-write 'utf8)) |
(let ((coding-system-for-write 'utf8)) |
977 |
(set-buffer (find-file ical-filename)) |
(set-buffer (find-file ical-filename)) |
978 |
(unless do-not-clear-diary-file |
(goto-char (point-max)) |
979 |
(erase-buffer)) |
(insert "BEGIN:VCALENDAR") |
980 |
(insert |
(insert "\nPRODID:-//Emacs//NONSGML icalendar.el//EN") |
|
"BEGIN:VCALENDAR\nPRODID:-//Emacs//NONSGML icalendar.el//EN") |
|
981 |
(insert "\nVERSION:2.0") |
(insert "\nVERSION:2.0") |
982 |
(insert result) |
(insert result) |
983 |
(insert "\nEND:VCALENDAR\n"))))) |
(insert "\nEND:VCALENDAR\n"))))) |
984 |
|
|
|
|
|
985 |
;; ====================================================================== |
;; ====================================================================== |
986 |
;; import -- convert icalendar to emacs-diary |
;; Import -- convert icalendar to emacs-diary |
987 |
;; ====================================================================== |
;; ====================================================================== |
988 |
|
|
989 |
;; user function |
;; User function |
990 |
(defun icalendar-import-file (ical-filename diary-filename |
(defun icalendar-import-file (ical-filename diary-filename |
991 |
&optional non-marking |
&optional non-marking) |
992 |
do-not-clear-diary-file) |
"Import a iCalendar file and append to a diary file. |
|
"Import a iCalendar file and save to a diary file -- erases diary-file! |
|
993 |
Argument ICAL-FILENAME output iCalendar file. |
Argument ICAL-FILENAME output iCalendar file. |
994 |
Argument DIARY-FILENAME input `diary-file'. |
Argument DIARY-FILENAME input `diary-file'. |
995 |
Optional argument NON-MARKING determines whether events are created as |
Optional argument NON-MARKING determines whether events are created as |
996 |
non-marking or not. |
non-marking or not." |
|
If DO-NOT-CLEAR-DIARY-FILE is not nil the target diary file is |
|
|
not erased." |
|
997 |
(interactive "fImport iCalendar data from file: |
(interactive "fImport iCalendar data from file: |
998 |
Finto diary file (will be erased!): |
Finto diary file: |
999 |
p") |
p") |
1000 |
;; clean up the diary file |
;; clean up the diary file |
1001 |
(save-current-buffer |
(save-current-buffer |
|
(unless do-not-clear-diary-file |
|
|
;; clear the target diary file |
|
|
(set-buffer (find-file diary-filename)) |
|
|
(erase-buffer)) |
|
1002 |
;; now load and convert from the ical file |
;; now load and convert from the ical file |
1003 |
(set-buffer (find-file ical-filename)) |
(set-buffer (find-file ical-filename)) |
1004 |
(icalendar-extract-ical-from-buffer diary-filename t non-marking))) |
(icalendar-import-buffer diary-filename t non-marking))) |
1005 |
|
|
1006 |
; user function |
;; User function |
1007 |
(defun icalendar-extract-ical-from-buffer (&optional |
(defun icalendar-import-buffer (&optional diary-file do-not-ask |
1008 |
diary-file do-not-ask |
non-marking) |
|
non-marking) |
|
1009 |
"Extract iCalendar events from current buffer. |
"Extract iCalendar events from current buffer. |
1010 |
|
|
1011 |
This function searches the current buffer for the first iCalendar |
This function searches the current buffer for the first iCalendar |
1025 |
(save-current-buffer |
(save-current-buffer |
1026 |
;; prepare ical |
;; prepare ical |
1027 |
(message "Preparing icalendar...") |
(message "Preparing icalendar...") |
1028 |
(set-buffer (icalendar-get-unfolded-buffer (current-buffer))) |
(set-buffer (icalendar--get-unfolded-buffer (current-buffer))) |
1029 |
(goto-char (point-min)) |
(goto-char (point-min)) |
1030 |
(message "Preparing icalendar...done") |
(message "Preparing icalendar...done") |
1031 |
(if (re-search-forward "^BEGIN:VCALENDAR\\s-*$" nil t) |
(if (re-search-forward "^BEGIN:VCALENDAR\\s-*$" nil t) |
1033 |
;; read ical |
;; read ical |
1034 |
(message "Reading icalendar...") |
(message "Reading icalendar...") |
1035 |
(beginning-of-line) |
(beginning-of-line) |
1036 |
(setq ical-contents (icalendar-read-element nil nil)) |
(setq ical-contents (icalendar--read-element nil nil)) |
1037 |
(message "Reading icalendar...done") |
(message "Reading icalendar...done") |
1038 |
;; convert ical |
;; convert ical |
1039 |
(message "Converting icalendar...") |
(message "Converting icalendar...") |
1040 |
(setq ical-errors (icalendar-convert-ical-to-diary |
(setq ical-errors (icalendar--convert-ical-to-diary |
1041 |
ical-contents |
ical-contents |
1042 |
diary-file do-not-ask non-marking)) |
diary-file do-not-ask non-marking)) |
1043 |
(when diary-file |
(when diary-file |
1047 |
(save-buffer))) |
(save-buffer))) |
1048 |
(message "Converting icalendar...done") |
(message "Converting icalendar...done") |
1049 |
(if (and ical-errors (y-or-n-p |
(if (and ical-errors (y-or-n-p |
1050 |
(concat "Something went wrong -- " |
(concat "Something went wrong -- " |
1051 |
"do you want to see the " |
"do you want to see the " |
1052 |
"error log? "))) |
"error log? "))) |
1053 |
(switch-to-buffer " *icalendar-errors*"))) |
(switch-to-buffer " *icalendar-errors*"))) |
1054 |
(message |
(message |
1055 |
"Current buffer does not contain icalendar contents!")))) |
"Current buffer does not contain icalendar contents!")))) |
1056 |
|
|
1057 |
;; ---------------------------------------------------------------------- |
(defalias 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer) |
1058 |
|
|
1059 |
|
(make-obsolete 'icalendar-extract-ical-from-buffer 'icalendar-import-buffer |
1060 |
|
"icalendar 0.07") |
1061 |
|
|
1062 |
|
;; ====================================================================== |
1063 |
;; private area |
;; private area |
1064 |
;; ---------------------------------------------------------------------- |
;; ====================================================================== |
1065 |
(defun icalendar-format-ical-event (event) |
|
1066 |
|
(defun icalendar--format-ical-event (event) |
1067 |
"Create a string representation of an iCalendar EVENT." |
"Create a string representation of an iCalendar EVENT." |
1068 |
(let ((string icalendar-import-format) |
(let ((string icalendar-import-format) |
1069 |
(conversion-list |
(conversion-list |
1076 |
(let* ((spec (car i)) |
(let* ((spec (car i)) |
1077 |
(prop (cadr i)) |
(prop (cadr i)) |
1078 |
(format (car (cddr i))) |
(format (car (cddr i))) |
1079 |
(contents (icalendar-get-event-property event prop)) |
(contents (icalendar--get-event-property event prop)) |
1080 |
(formatted-contents "")) |
(formatted-contents "")) |
|
;;(message "%s" event) |
|
|
;;(message "contents%s = %s" prop contents) |
|
1081 |
(when (and contents (> (length contents) 0)) |
(when (and contents (> (length contents) 0)) |
1082 |
(setq formatted-contents |
(setq formatted-contents |
1083 |
(icalendar-rris "%s" |
(icalendar--rris "%s" |
1084 |
(icalendar-convert-for-import |
(icalendar--convert-string-for-import |
1085 |
contents) |
contents) |
1086 |
(symbol-value format)))) |
(symbol-value format)))) |
1087 |
(setq string (icalendar-rris spec |
(setq string (icalendar--rris spec |
1088 |
formatted-contents |
formatted-contents |
1089 |
string)))) |
string)))) |
1090 |
conversion-list) |
conversion-list) |
1091 |
string)) |
string)) |
1092 |
|
|
1093 |
(defun icalendar-convert-ical-to-diary (ical-list diary-file |
(defun icalendar--convert-ical-to-diary (ical-list diary-file |
1094 |
&optional do-not-ask |
&optional do-not-ask |
1095 |
non-marking) |
non-marking) |
1096 |
"Convert an iCalendar file to an Emacs diary file. |
"Convert an iCalendar file to an Emacs diary file. |
1097 |
Import VEVENTS from the iCalendar object ICAL-LIST and saves them to a |
Import VEVENTS from the iCalendar object ICAL-LIST and saves them to a |
1098 |
DIARY-FILE. If DO-NOT-ASK is nil the user is asked for each event |
DIARY-FILE. If DO-NOT-ASK is nil the user is asked for each event |
1101 |
This function attempts to return t if something goes wrong. In this |
This function attempts to return t if something goes wrong. In this |
1102 |
case an error string which describes all the errors and problems is |
case an error string which describes all the errors and problems is |
1103 |
written into the buffer ` *icalendar-errors*'." |
written into the buffer ` *icalendar-errors*'." |
1104 |
(let* ((ev (icalendar-all-events ical-list)) |
(let* ((ev (icalendar--all-events ical-list)) |
1105 |
(error-string "") |
(error-string "") |
1106 |
(event-ok t) |
(event-ok t) |
1107 |
(found-error nil) |
(found-error nil) |
1112 |
(setq ev (cdr ev)) |
(setq ev (cdr ev)) |
1113 |
(setq event-ok nil) |
(setq event-ok nil) |
1114 |
(condition-case error-val |
(condition-case error-val |
1115 |
(let* ((dtstart (icalendar-decode-isodatetime |
(let* ((dtstart (icalendar--decode-isodatetime |
1116 |
(icalendar-get-event-property e 'DTSTART))) |
(icalendar--get-event-property e 'DTSTART))) |
1117 |
(start-d (calendar-date-string |
(start-d (calendar-date-string |
1118 |
(icalendar-datetime-to-noneuropean-date |
(icalendar--datetime-to-noneuropean-date |
1119 |
dtstart) |
dtstart) |
1120 |
t t)) |
t t)) |
1121 |
(start-t (icalendar-datetime-to-colontime dtstart)) |
(start-t (icalendar--datetime-to-colontime dtstart)) |
1122 |
(dtend (icalendar-decode-isodatetime |
(dtend (icalendar--decode-isodatetime |
1123 |
(icalendar-get-event-property e 'DTEND))) |
(icalendar--get-event-property e 'DTEND))) |
1124 |
end-d |
end-d |
1125 |
end-t |
end-t |
1126 |
(subject (icalendar-convert-for-import |
(subject (icalendar--convert-string-for-import |
1127 |
(or (icalendar-get-event-property e 'SUMMARY) |
(or (icalendar--get-event-property e 'SUMMARY) |
1128 |
"No Subject"))) |
"No Subject"))) |
1129 |
(rrule (icalendar-get-event-property e 'RRULE)) |
(rrule (icalendar--get-event-property e 'RRULE)) |
1130 |
(rdate (icalendar-get-event-property e 'RDATE)) |
(rdate (icalendar--get-event-property e 'RDATE)) |
1131 |
(duration (icalendar-get-event-property e 'DURATION))) |
(duration (icalendar--get-event-property e 'DURATION))) |
1132 |
(icalendar-dmsg "%s: %s" start-d subject) |
(icalendar--dmsg "%s: %s" start-d subject) |
1133 |
(when duration |
(when duration |
1134 |
(let ((dtend2 (icalendar-add-decoded-times |
(let ((dtend2 (icalendar--add-decoded-times |
1135 |
dtstart |
dtstart |
1136 |
(icalendar-decode-isoduration duration)))) |
(icalendar--decode-isoduration duration)))) |
1137 |
(if (and dtend (not (eq dtend dtend2))) |
(if (and dtend (not (eq dtend dtend2))) |
1138 |
(message "Inconsistent endtime and duration for %s" |
(message "Inconsistent endtime and duration for %s" |
1139 |
subject)) |
subject)) |
1140 |
(setq dtend dtend2))) |
(setq dtend dtend2))) |
1141 |
(setq end-d (if dtend |
(setq end-d (if dtend |
1142 |
(calendar-date-string |
(calendar-date-string |
1143 |
(icalendar-datetime-to-noneuropean-date |
(icalendar--datetime-to-noneuropean-date |
1144 |
dtend) |
dtend) |
1145 |
t t) |
t t) |
1146 |
start-d)) |
start-d)) |
1147 |
(setq end-t (if dtend |
(setq end-t (if dtend |
1148 |
(icalendar-datetime-to-colontime dtend) |
(icalendar--datetime-to-colontime dtend) |
1149 |
start-t)) |
start-t)) |
1150 |
(icalendar-dmsg "start-d: %s, end-d: %s" start-d end-d) |
(icalendar--dmsg "start-d: %s, end-d: %s" start-d end-d) |
1151 |
(cond |
(cond |
1152 |
;; recurring event |
;; recurring event |
1153 |
(rrule |
(rrule |
1154 |
(icalendar-dmsg "recurring event") |
(icalendar--dmsg "recurring event") |
1155 |
(let* ((rrule-props (icalendar-split-value rrule)) |
(let* ((rrule-props (icalendar--split-value rrule)) |
1156 |
(frequency (car (cdr (assoc 'FREQ rrule-props)))) |
(frequency (car (cdr (assoc 'FREQ rrule-props)))) |
1157 |
(until (car (cdr (assoc 'UNTIL rrule-props)))) |
(until (car (cdr (assoc 'UNTIL rrule-props)))) |
1158 |
(interval (read (car (cdr (assoc 'INTERVAL |
(interval (read (car (cdr (assoc 'INTERVAL |
1159 |
rrule-props)))))) |
rrule-props)))))) |
1160 |
(cond ((string-equal frequency "WEEKLY") |
(cond ((string-equal frequency "WEEKLY") |
1161 |
(if (not start-t) |
(if (not start-t) |
1162 |
(progn |
(progn |
1163 |
;; weekly and all-day |
;; weekly and all-day |
1164 |
(icalendar-dmsg "weekly all-day") |
(icalendar--dmsg "weekly all-day") |
1165 |
(setq diary-string |
(setq diary-string |
1166 |
(format |
(format |
1167 |
"%%%%(diary-cyclic %d %s)" |
"%%%%(diary-cyclic %d %s)" |
1168 |
(* interval 7) |
(* interval 7) |
1169 |
(icalendar-datetime-to-european-date |
(icalendar--datetime-to-european-date |
1170 |
dtstart)))) |
dtstart)))) |
1171 |
;; weekly and not all-day |
;; weekly and not all-day |
1172 |
(let* ((byday (cadr (assoc 'BYDAY rrule-props))) |
(let* ((byday (cadr (assoc 'BYDAY rrule-props))) |
1173 |
(weekday |
(weekday |
1174 |
(cdr (rassoc |
(cdr (rassoc |
1175 |
byday |
byday |
1176 |
icalendar-weekdayabbrev-table)))) |
icalendar-weekdayabbrev-table)))) |
1177 |
(icalendar-dmsg "weekly not-all-day") |
(icalendar--dmsg "weekly not-all-day") |
1178 |
(if weekday |
(if weekday |
1179 |
(setq diary-string |
(setq diary-string |
1180 |
(format "%s %s%s%s" weekday |
(format "%s %s%s%s" weekday |
1185 |
;; DTEND;VALUE=DATE-TIME:20030919T113000 |
;; DTEND;VALUE=DATE-TIME:20030919T113000 |
1186 |
(setq diary-string |
(setq diary-string |
1187 |
(format |
(format |
1188 |
"%%%%(diary-cyclic %s %s) %s%s%s" |
"%%%%(diary-cyclic %s %s) %s%s%s" |
1189 |
(* interval 7) |
(* interval 7) |
1190 |
(icalendar-datetime-to-european-date |
(icalendar--datetime-to-european-date |
1191 |
dtstart) |
dtstart) |
1192 |
start-t (if end-t "-" "") (or end-t "")))) |
start-t (if end-t "-" "") (or end-t "")))) |
1193 |
(setq event-ok t)))) |
(setq event-ok t)))) |
1194 |
;; yearly |
;; yearly |
1195 |
((string-equal frequency "YEARLY") |
((string-equal frequency "YEARLY") |
1196 |
(icalendar-dmsg "yearly") |
(icalendar--dmsg "yearly") |
1197 |
(setq diary-string |
(setq diary-string |
1198 |
(format |
(format |
1199 |
"%%%%(diary-anniversary %s)" |
"%%%%(diary-anniversary %s)" |
1200 |
(icalendar-datetime-to-european-date dtstart))) |
(icalendar--datetime-to-european-date dtstart))) |
1201 |
(setq event-ok t)) |
(setq event-ok t)) |
1202 |
;; FIXME: war auskommentiert: |
;; FIXME: war auskommentiert: |
1203 |
((and (string-equal frequency "DAILY") |
((and (string-equal frequency "DAILY") |
1205 |
;;(not start-t) |
;;(not start-t) |
1206 |
;;(not end-t) |
;;(not end-t) |
1207 |
) |
) |
1208 |
(let ((ds (icalendar-datetime-to-noneuropean-date |
(let ((ds (icalendar--datetime-to-noneuropean-date |
1209 |
(icalendar-decode-isodatetime |
(icalendar--decode-isodatetime |
1210 |
(icalendar-get-event-property e |
(icalendar--get-event-property e |
1211 |
'DTSTART)))) |
'DTSTART)))) |
1212 |
(de (icalendar-datetime-to-noneuropean-date |
(de (icalendar--datetime-to-noneuropean-date |
1213 |
(icalendar-decode-isodatetime |
(icalendar--decode-isodatetime |
1214 |
until)))) |
until)))) |
1215 |
(setq diary-string |
(setq diary-string |
1216 |
(format |
(format |
1217 |
"%%%%(diary-block %d %d %d %d %d %d)" |
"%%%%(diary-block %d %d %d %d %d %d)" |
1218 |
(nth 1 ds) (nth 0 ds) (nth 2 ds) |
(nth 1 ds) (nth 0 ds) (nth 2 ds) |
1219 |
(nth 1 de) (nth 0 de) (nth 2 de)))) |
(nth 1 de) (nth 0 de) (nth 2 de)))) |
1220 |
(setq event-ok t))) |
(setq event-ok t))) |
1221 |
)) |
)) |
1222 |
(rdate |
(rdate |
1223 |
(icalendar-dmsg "rdate event") |
(icalendar--dmsg "rdate event") |
1224 |
(setq diary-string "") |
(setq diary-string "") |
1225 |
(mapcar (lambda (datestring) |
(mapcar (lambda (datestring) |
1226 |
(setq diary-string |
(setq diary-string |
1227 |
(concat diary-string |
(concat diary-string |
1228 |
(format "......")))) |
(format "......")))) |
1229 |
(icalendar-split-value rdate))) |
(icalendar--split-value rdate))) |
1230 |
;; non-recurring event |
;; non-recurring event |
1231 |
;; long event |
;; long event |
1232 |
((not (string= start-d end-d)) |
((not (string= start-d end-d)) |
1233 |
(icalendar-dmsg "non-recurring event") |
(icalendar--dmsg "non-recurring event") |
1234 |
(let ((ds (icalendar-datetime-to-noneuropean-date dtstart)) |
(let ((ds (icalendar--datetime-to-noneuropean-date dtstart)) |
1235 |
(de (icalendar-datetime-to-noneuropean-date dtend))) |
(de (icalendar--datetime-to-noneuropean-date dtend))) |
1236 |
(setq diary-string |
(setq diary-string |
1237 |
(format "%%%%(diary-block %d %d %d %d %d %d)" |
(format "%%%%(diary-block %d %d %d %d %d %d)" |
1238 |
(nth 1 ds) (nth 0 ds) (nth 2 ds) |
(nth 1 ds) (nth 0 ds) (nth 2 ds) |
1241 |
;; not all-day |
;; not all-day |
1242 |
((and start-t (or (not end-t) |
((and start-t (or (not end-t) |
1243 |
(not (string= start-t end-t)))) |
(not (string= start-t end-t)))) |
1244 |
(icalendar-dmsg "not all day event") |
(icalendar--dmsg "not all day event") |
1245 |
(cond (end-t |
(cond (end-t |
1246 |
(setq diary-string (format "%s %s-%s" start-d |
(setq diary-string (format "%s %s-%s" start-d |
1247 |
start-t end-t))) |
start-t end-t))) |
1248 |
(t |
(t |
1249 |
(setq diary-string (format "%s %s" start-d |
(setq diary-string (format "%s %s" start-d |
1250 |
start-t)))) |
start-t)))) |
1251 |
(setq event-ok t)) |
(setq event-ok t)) |
1252 |
;; all-day event |
;; all-day event |
1253 |
(t |
(t |
1254 |
(icalendar-dmsg "all day event") |
(icalendar--dmsg "all day event") |
1255 |
(setq diary-string start-d) |
(setq diary-string start-d) |
1256 |
(setq event-ok t))) |
(setq event-ok t))) |
1257 |
;; add all other elements unless the user doesn't want to have |
;; add all other elements unless the user doesn't want to have |
1259 |
(if event-ok |
(if event-ok |
1260 |
(progn |
(progn |
1261 |
(setq diary-string |
(setq diary-string |
1262 |
(concat diary-string " " |
(concat diary-string " " |
1263 |
(icalendar-format-ical-event e))) |
(icalendar--format-ical-event e))) |
1264 |
(if do-not-ask (setq subject nil)) |
(if do-not-ask (setq subject nil)) |
1265 |
(icalendar-add-diary-entry diary-string diary-file |
(icalendar--add-diary-entry diary-string diary-file |
1266 |
non-marking subject)) |
non-marking subject)) |
1267 |
;; event was not ok |
;; event was not ok |
1268 |
(setq found-error t) |
(setq found-error t) |
1269 |
(setq error-string |
(setq error-string |
1270 |
(format "%s\nCannot handle this event:%s" |
(format "%s\nCannot handle this event:%s" |
1271 |
error-string e)))) |
error-string e)))) |
1272 |
;; handle errors |
;; handle errors |
1273 |
(error |
(error |
1274 |
(message "Ignoring event \"%s\"" e) |
(message "Ignoring event \"%s\"" e) |
1283 |
(message "Converting icalendar...done") |
(message "Converting icalendar...done") |
1284 |
found-error)) |
found-error)) |
1285 |
|
|
1286 |
(defun icalendar-add-diary-entry (string diary-file non-marking |
(defun icalendar--add-diary-entry (string diary-file non-marking |
1287 |
&optional subject) |
&optional subject) |
1288 |
"Add STRING to the diary file DIARY-FILE. |
"Add STRING to the diary file DIARY-FILE. |
1289 |
STRING must be a properly formatted valid diary entry. NON-MARKING |
STRING must be a properly formatted valid diary entry. NON-MARKING |
1290 |
determines whether diary events are created as non-marking. If |
determines whether diary events are created as non-marking. If |
1291 |
SUBJECT is not nil it must be a string that gives the subject of the |
SUBJECT is not nil it must be a string that gives the subject of the |
1292 |
entry. In this case the user will be asked whether he wants to insert |
entry. In this case the user will be asked whether he wants to insert |
1293 |
the entry." |
the entry." |
1294 |
(when (or (not subject) ; |
(when (or (not subject) ; |
1295 |
(y-or-n-p (format "Add appointment for `%s' to diary? " |
(y-or-n-p (format "Add appointment for `%s' to diary? " |
1296 |
subject))) |
subject))) |
1297 |
(when subject |
(when subject |
1298 |
(setq non-marking |
(setq non-marking |
1299 |
(y-or-n-p (format "Make appointment non-marking? ")))) |
(y-or-n-p (format "Make appointment non-marking? ")))) |
1303 |
(read-file-name "Add appointment to this diary file: "))) |
(read-file-name "Add appointment to this diary file: "))) |
1304 |
(make-diary-entry string non-marking diary-file)))) |
(make-diary-entry string non-marking diary-file)))) |
1305 |
|
|
|
;; ====================================================================== |
|
|
;; (add-hook 'list-diary-entries-hook 'include-icalendar-files) |
|
|
;; ====================================================================== |
|
|
(defun include-icalendar-files () |
|
|
"Not yet implemented.") |
|
|
|
|
1306 |
(provide 'icalendar) |
(provide 'icalendar) |
1307 |
|
|
1308 |
;; arch-tag: 74fdbe8e-0451-4e38-bb61-4416e822f4fc |
;; arch-tag: 74fdbe8e-0451-4e38-bb61-4416e822f4fc |