/[emacs]/emacs/lisp/calendar/icalendar.el
ViewVC logotype

Diff of /emacs/lisp/calendar/icalendar.el

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.13 by deego, Sun Sep 18 12:41:38 2005 UTC revision 1.14 by gm, Mon Oct 24 07:27:39 2005 UTC
# Line 97  Line 97 
97    
98  ;;; Code:  ;;; Code:
99    
100  (defconst icalendar-version 0.12  (defconst icalendar-version "0.13"
101    "Version number of icalendar.el.")    "Version number of icalendar.el.")
102    
103  ;; ======================================================================  ;; ======================================================================
# Line 113  Line 113 
113    "Format string for importing events from iCalendar into Emacs diary.    "Format string for importing events from iCalendar into Emacs diary.
114  This string defines how iCalendar events are inserted into diary  This string defines how iCalendar events are inserted into diary
115  file.  Meaning of the specifiers:  file.  Meaning of the specifiers:
116    %c Class, see `icalendar-import-format-class'
117  %d Description, see `icalendar-import-format-description'  %d Description, see `icalendar-import-format-description'
118  %l Location, see `icalendar-import-format-location'  %l Location, see `icalendar-import-format-location'
119  %o Organizer, see `icalendar-import-format-organizer'  %o Organizer, see `icalendar-import-format-organizer'
120  %s Subject, see `icalendar-import-format-subject'"  %s Summary, see `icalendar-import-format-summary'
121    %t Status, see `icalendar-import-format-status'
122    %u URL, see `icalendar-import-format-url'"
123    :type 'string    :type 'string
124    :group 'icalendar)    :group 'icalendar)
125    
126  (defcustom icalendar-import-format-subject  (defcustom icalendar-import-format-summary
127    "%s"    "%s"
128    "Format string defining how the subject element is formatted.    "Format string defining how the summary element is formatted.
129  This applies only if the subject is not empty! `%s' is replaced  This applies only if the summary is not empty! `%s' is replaced
130  by the subject."  by the summary."
131    :type 'string    :type 'string
132    :group 'icalendar)    :group 'icalendar)
133    
# Line 152  replaced by the organizer." Line 155  replaced by the organizer."
155    :type 'string    :type 'string
156    :group 'icalendar)    :group 'icalendar)
157    
158    (defcustom icalendar-import-format-url
159      "\n URL: %s"
160      "Format string defining how the URL element is formatted.
161    This applies only if the URL is not empty! `%s' is replaced by
162    the URL."
163      :type 'string
164      :group 'icalendar)
165    
166    (defcustom icalendar-import-format-status
167      "\n Status: %s"
168      "Format string defining how the status element is formatted.
169    This applies only if the status is not empty! `%s' is replaced by
170    the status."
171      :type 'string
172      :group 'icalendar)
173    
174    (defcustom icalendar-import-format-class
175      "\n Class: %s"
176      "Format string defining how the class element is formatted.
177    This applies only if the class is not empty! `%s' is replaced by
178    the class."
179      :type 'string
180      :group 'icalendar)
181    
182  (defvar icalendar-debug nil  (defvar icalendar-debug nil
183    "Enable icalendar debug messages.")    "Enable icalendar debug messages.")
184    
# Line 195  buffer." Line 222  buffer."
222          (replace-match "" nil nil)))          (replace-match "" nil nil)))
223      unfolded-buffer))      unfolded-buffer))
224    
225  (defsubst icalendar--rris (re rp st)  (defsubst icalendar--rris (&rest args)
226    "Replace regexp RE with RP in string ST and return the new string.    "Replace regular expression in string.
227  This is here for compatibility with XEmacs."  Pass ARGS to `replace-regexp-in-string' (Emacs) or to
228    `replace-in-string' (XEmacs)."
229    ;; XEmacs:    ;; XEmacs:
230    (if (fboundp 'replace-in-string)    (if (fboundp 'replace-in-string)
231        (save-match-data ;; apparently XEmacs needs save-match-data        (save-match-data ;; apparently XEmacs needs save-match-data
232          (replace-in-string st re rp))          (apply 'replace-in-string args))
233      ;; Emacs:      ;; Emacs:
234      (replace-regexp-in-string re rp st)))      (apply 'replace-regexp-in-string args)))
235    
236  (defun icalendar--read-element (invalue inparams)  (defun icalendar--read-element (invalue inparams)
237    "Recursively read the next iCalendar element in the current buffer.    "Recursively read the next iCalendar element in the current buffer.
# Line 609  takes care of european-style." Line 637  takes care of european-style."
637                   (setq month day)                   (setq month day)
638                   (setq day x))))                   (setq day x))))
639              ( ;; date contains month names -- european-style              ( ;; date contains month names -- european-style
640               (and european-calendar-style               (string-match (concat "\\s-*"
641                    (string-match (concat "\\s-*"                                     "0?\\([123]?[0-9]\\)[ \t/]\\s-*"
642                                          "0?\\([123]?[0-9]\\)[ \t/]\\s-*"                                     "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*"
643                                          "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*"                                     "\\([0-9]\\{4\\}\\)")
644                                          "\\([0-9]\\{4\\}\\)")                             datestring)
                                 datestring))  
645               (setq day (read (substring datestring (match-beginning 1)               (setq day (read (substring datestring (match-beginning 1)
646                                          (match-end 1))))                                          (match-end 1))))
647               (setq month (icalendar--get-month-number               (setq month (icalendar--get-month-number
# Line 623  takes care of european-style." Line 650  takes care of european-style."
650               (setq year (read (substring datestring (match-beginning 3)               (setq year (read (substring datestring (match-beginning 3)
651                                           (match-end 3)))))                                           (match-end 3)))))
652              ( ;; date contains month names -- non-european-style              ( ;; date contains month names -- non-european-style
653               (and (not european-calendar-style)               (string-match (concat "\\s-*"
654                    (string-match (concat "\\s-*"                                     "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*"
655                                          "\\([A-Za-z][^ ]+\\)[ \t/]\\s-*"                                     "0?\\([123]?[0-9]\\),?[ \t/]\\s-*"
656                                          "0?\\([123]?[0-9]\\),?[ \t/]\\s-*"                                     "\\([0-9]\\{4\\}\\)")
657                                          "\\([0-9]\\{4\\}\\)")                             datestring)
                                 datestring))  
658               (setq day (read (substring datestring (match-beginning 2)               (setq day (read (substring datestring (match-beginning 2)
659                                          (match-end 2))))                                          (match-end 2))))
660               (setq month (icalendar--get-month-number               (setq month (icalendar--get-month-number
# Line 704  FExport diary data into iCalendar file: Line 730  FExport diary data into iCalendar file:
730          (entry-main "")          (entry-main "")
731          (entry-rest "")          (entry-rest "")
732          (header "")          (header "")
733            (contents-n-summary)
734          (contents)          (contents)
735          (found-error nil)          (found-error nil)
736          (nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol)          (nonmarker (concat "^" (regexp-quote diary-nonmarking-symbol)
737                             "?")))                             "?"))
738            (other-elements nil))
739      ;; prepare buffer with error messages      ;; prepare buffer with error messages
740      (save-current-buffer      (save-current-buffer
741        (set-buffer (get-buffer-create "*icalendar-errors*"))        (set-buffer (get-buffer-create "*icalendar-errors*"))
# Line 728  FExport diary data into iCalendar file: Line 756  FExport diary data into iCalendar file:
756                               (car (cddr (current-time)))))                               (car (cddr (current-time)))))
757          (condition-case error-val          (condition-case error-val
758              (progn              (progn
759                (setq contents                (setq contents-n-summary
760                      (or                      (icalendar--convert-to-ical nonmarker entry-main))
761                       ;; anniversaries -- %%(diary-anniversary ...)                (setq other-elements (icalendar--parse-summary-and-rest
762                       (icalendar--convert-anniversary-to-ical nonmarker                                      (concat entry-main entry-rest)))
763                                                               entry-main)                (setq contents (concat (car contents-n-summary)
764                       ;; cyclic events -- %%(diary-cyclic ...)                                       "\nSUMMARY:" (cadr contents-n-summary)))
765                       (icalendar--convert-cyclic-to-ical nonmarker entry-main)                (let ((cla (cdr (assoc 'cla other-elements)))
766                       ;; diary-date -- %%(diary-date ...)                      (des (cdr (assoc 'des other-elements)))
767                       (icalendar--convert-date-to-ical nonmarker entry-main)                      (loc (cdr (assoc 'loc other-elements)))
768                       ;; float events -- %%(diary-float ...)                      (org (cdr (assoc 'org other-elements)))
769                       (icalendar--convert-float-to-ical nonmarker entry-main)                      (sta (cdr (assoc 'sta other-elements)))
770                       ;; block events -- %%(diary-block ...)                      (sum (cdr (assoc 'sum other-elements)))
771                       (icalendar--convert-block-to-ical nonmarker entry-main)                      (url (cdr (assoc 'url other-elements))))
772                       ;; other sexp diary entries                  (if cla
773                       (icalendar--convert-sexp-to-ical nonmarker entry-main)                      (setq contents (concat contents "\nCLASS:" cla)))
774                       ;; weekly by day -- Monday 8:30 Team meeting                  (if des
775                       (icalendar--convert-weekly-to-ical nonmarker entry-main)                      (setq contents (concat contents "\nDESCRIPTION:" des)))
776                       ;; yearly by day -- 1 May Tag der Arbeit                  (if loc
777                       (icalendar--convert-yearly-to-ical nonmarker entry-main)                      (setq contents (concat contents "\nLOCATION:" loc)))
778                       ;; "ordinary" events, start and end time given                  (if org
779                       ;; 1 Feb 2003 blah                      (setq contents (concat contents "\nORGANIZER:" org)))
780                       (icalendar--convert-ordinary-to-ical nonmarker entry-main)                  (if sta
781                       ;; everything else                      (setq contents (concat contents "\nSTATUS:" sta)))
782                       ;; Oops! what's that?                  ;;(if sum
783                       (error "Could not parse entry")))                  ;;    (setq contents (concat contents "\nSUMMARY:" sum)))
784                (unless (string= entry-rest "")                  (if url
785                  (setq contents                      (setq contents (concat contents "\nURL:" url))))
                       (concat contents "\nDESCRIPTION:"  
                               (icalendar--convert-string-for-export  
                                entry-rest))))  
786                (setq result (concat result header contents "\nEND:VEVENT")))                (setq result (concat result header contents "\nEND:VEVENT")))
787            ;; handle errors            ;; handle errors
788            (error            (error
# Line 780  FExport diary data into iCalendar file: Line 805  FExport diary data into iCalendar file:
805            (insert result)            (insert result)
806            (insert "\nEND:VCALENDAR\n")            (insert "\nEND:VCALENDAR\n")
807            ;; save the diary file            ;; save the diary file
808            (save-buffer))))            (save-buffer)
809              (unless found-error
810                (bury-buffer)))))
811      found-error))      found-error))
812    
813  ;; subroutines  (defun icalendar--convert-to-ical (nonmarker entry-main)
814      "Convert a diary entry to icalendar format.
815    NONMARKER is a regular expression matching the start of non-marking
816    entries.  ENTRY-MAIN is the first line of the diary entry."
817      (or
818       ;; anniversaries -- %%(diary-anniversary ...)
819       (icalendar--convert-anniversary-to-ical nonmarker entry-main)
820       ;; cyclic events -- %%(diary-cyclic ...)
821       (icalendar--convert-cyclic-to-ical nonmarker entry-main)
822       ;; diary-date -- %%(diary-date ...)
823       (icalendar--convert-date-to-ical nonmarker entry-main)
824       ;; float events -- %%(diary-float ...)
825       (icalendar--convert-float-to-ical nonmarker entry-main)
826       ;; block events -- %%(diary-block ...)
827       (icalendar--convert-block-to-ical nonmarker entry-main)
828       ;; other sexp diary entries
829       (icalendar--convert-sexp-to-ical nonmarker entry-main)
830       ;; weekly by day -- Monday 8:30 Team meeting
831       (icalendar--convert-weekly-to-ical nonmarker entry-main)
832       ;; yearly by day -- 1 May Tag der Arbeit
833       (icalendar--convert-yearly-to-ical nonmarker entry-main)
834       ;; "ordinary" events, start and end time given
835       ;; 1 Feb 2003 blah
836       (icalendar--convert-ordinary-to-ical nonmarker entry-main)
837       ;; everything else
838       ;; Oops! what's that?
839       (error "Could not parse entry")))
840    
841    (defun icalendar--parse-summary-and-rest (summary-and-rest)
842      "Parse SUMMARY-AND-REST from a diary to fill iCalendar properties."
843      (save-match-data
844        (let* ((s icalendar-import-format)
845               (p-cla (or (string-match "%c" icalendar-import-format) -1))
846               (p-des (or (string-match "%d" icalendar-import-format) -1))
847               (p-loc (or (string-match "%l" icalendar-import-format) -1))
848               (p-org (or (string-match "%o" icalendar-import-format) -1))
849               (p-sum (or (string-match "%s" icalendar-import-format) -1))
850               (p-sta (or (string-match "%t" icalendar-import-format) -1))
851               (p-url (or (string-match "%u" icalendar-import-format) -1))
852               (p-list (sort (list p-cla p-des p-loc p-org p-sta p-sum p-url) '<))
853               pos-cla pos-des pos-loc pos-org pos-sta pos-sum pos-url)
854          (dotimes (i (length p-list))
855            (cond ((and (>= p-cla 0) (= (nth i p-list) p-cla))
856                   (setq pos-cla (+ 2 (* 2 i))))
857                  ((and (>= p-des 0) (= (nth i p-list) p-des))
858                   (setq pos-des (+ 2 (* 2 i))))
859                  ((and (>= p-loc 0) (= (nth i p-list) p-loc))
860                   (setq pos-loc (+ 2 (* 2 i))))
861                  ((and (>= p-org 0) (= (nth i p-list) p-org))
862                   (setq pos-org (+ 2 (* 2 i))))
863                  ((and (>= p-sta 0) (= (nth i p-list) p-sta))
864                   (setq pos-sta (+ 2 (* 2 i))))
865                  ((and (>= p-sum 0) (= (nth i p-list) p-sum))
866                   (setq pos-sum (+ 2 (* 2 i))))
867                  ((and (>= p-url 0) (= (nth i p-list) p-url))
868                   (setq pos-url (+ 2 (* 2 i))))))
869          (mapc (lambda (ij)
870                  (setq s (icalendar--rris (car ij) (cadr ij) s t t)))
871                (list
872                 ;; summary must be first! because of %s
873                 (list "%s"
874                       (concat "\\(" icalendar-import-format-summary "\\)?"))
875                 (list "%c"
876                       (concat "\\(" icalendar-import-format-class "\\)?"))
877                 (list "%d"
878                       (concat "\\(" icalendar-import-format-description "\\)?"))
879                 (list "%l"
880                       (concat "\\(" icalendar-import-format-location "\\)?"))
881                 (list "%o"
882                       (concat "\\(" icalendar-import-format-organizer "\\)?"))
883                 (list "%t"
884                       (concat "\\(" icalendar-import-format-status "\\)?"))
885                 (list "%u"
886                       (concat "\\(" icalendar-import-format-url "\\)?"))))
887          (setq s (concat (icalendar--rris "%s" "\\(.*\\)" s nil t) " "))
888          (if (string-match s summary-and-rest)
889              (let (cla des loc org sta sum url)
890                (if (and pos-sum (match-beginning pos-sum))
891                    (setq sum (substring summary-and-rest
892                                         (match-beginning pos-sum)
893                                         (match-end pos-sum))))
894                (if (and pos-cla (match-beginning pos-cla))
895                    (setq cla (substring summary-and-rest
896                                         (match-beginning pos-cla)
897                                         (match-end pos-cla))))
898                (if (and pos-des (match-beginning pos-des))
899                    (setq des (substring summary-and-rest
900                                         (match-beginning pos-des)
901                                         (match-end pos-des))))
902                (if (and pos-loc (match-beginning pos-loc))
903                    (setq loc (substring summary-and-rest
904                                         (match-beginning pos-loc)
905                                         (match-end pos-loc))))
906                (if (and pos-org (match-beginning pos-org))
907                    (setq org (substring summary-and-rest
908                                         (match-beginning pos-org)
909                                         (match-end pos-org))))
910                (if (and pos-sta (match-beginning pos-sta))
911                    (setq sta (substring summary-and-rest
912                                         (match-beginning pos-sta)
913                                         (match-end pos-sta))))
914                (if (and pos-url (match-beginning pos-url))
915                    (setq url (substring summary-and-rest
916                                         (match-beginning pos-url)
917                                         (match-end pos-url))))
918                (list (if cla (cons 'cla cla) nil)
919                      (if des (cons 'des des) nil)
920                      (if loc (cons 'loc loc) nil)
921                      (if org (cons 'org org) nil)
922                      (if sta (cons 'sta sta) nil)
923                      ;;(if sum (cons 'sum sum) nil)
924                      (if url (cons 'url url) nil)))))))
925    
926    ;; subroutines for icalendar-export-region
927  (defun icalendar--convert-ordinary-to-ical (nonmarker entry-main)  (defun icalendar--convert-ordinary-to-ical (nonmarker entry-main)
928    "Convert \"ordinary\" diary entry to icalendar format.    "Convert \"ordinary\" diary entry to icalendar format.
   
929  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
930  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
931    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
# Line 795  entries.  ENTRY-MAIN is the first line o Line 934  entries.  ENTRY-MAIN is the first line o
934                              "\\("                              "\\("
935                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
936                              "\\)?"                              "\\)?"
937                              "\\s-*\\(.*\\)")                              "\\s-*\\(.*?\\) ?$")
938                      entry-main)                      entry-main)
939        (let* ((datetime (substring entry-main (match-beginning 1)        (let* ((datetime (substring entry-main (match-beginning 1)
940                                    (match-end 1)))                                    (match-end 1)))
# Line 839  entries.  ENTRY-MAIN is the first line o Line 978  entries.  ENTRY-MAIN is the first line o
978                                            starttimestring))))                                            starttimestring))))
979                (setq endtimestring (format "T%06d"                (setq endtimestring (format "T%06d"
980                                            (+ 10000 time))))))                                            (+ 10000 time))))))
981          (concat "\nDTSTART;"          (list (concat "\nDTSTART;"
982                  (if starttimestring "VALUE=DATE-TIME:"                        (if starttimestring "VALUE=DATE-TIME:"
983                    "VALUE=DATE:")                          "VALUE=DATE:")
984                  startisostring                        startisostring
985                  (or starttimestring "")                        (or starttimestring "")
986                  "\nDTEND;"                        "\nDTEND;"
987                  (if endtimestring "VALUE=DATE-TIME:"                        (if endtimestring "VALUE=DATE-TIME:"
988                    "VALUE=DATE:")                          "VALUE=DATE:")
989                  (if starttimestring                        (if starttimestring
990                      startisostring                            startisostring
991                    endisostring)                          endisostring)
992                  (or endtimestring "")                        (or endtimestring ""))
993                  "\nSUMMARY:"                summary))
                 summary))  
994      ;; no match      ;; no match
995      nil))      nil))
996    
997  (defun icalendar--convert-weekly-to-ical (nonmarker entry-main)  (defun icalendar--convert-weekly-to-ical (nonmarker entry-main)
998    "Convert weekly diary entry to icalendar format.    "Convert weekly diary entry to icalendar format.
   
999  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1000  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1001    (if (and (string-match (concat nonmarker    (if (and (string-match (concat nonmarker
# Line 869  entries.  ENTRY-MAIN is the first line o Line 1006  entries.  ENTRY-MAIN is the first line o
1006                                   "\\([1-9][0-9]?:[0-9][0-9]\\)"                                   "\\([1-9][0-9]?:[0-9][0-9]\\)"
1007                                   "\\([ap]m\\)?\\)?"                                   "\\([ap]m\\)?\\)?"
1008                                   "\\)?"                                   "\\)?"
1009                                   "\\s-*\\(.*\\)$")                                   "\\s-*\\(.*?\\) ?$")
1010                           entry-main)                           entry-main)
1011             (icalendar--get-weekday-abbrev             (icalendar--get-weekday-abbrev
1012              (substring entry-main (match-beginning 1)              (substring entry-main (match-beginning 1)
# Line 911  entries.  ENTRY-MAIN is the first line o Line 1048  entries.  ENTRY-MAIN is the first line o
1048                                            starttimestring))))                                            starttimestring))))
1049                (setq endtimestring (format "T%06d"                (setq endtimestring (format "T%06d"
1050                                            (+ 10000 time))))))                                            (+ 10000 time))))))
1051          (concat "\nDTSTART;"          (list (concat "\nDTSTART;"
1052                  (if starttimestring                        (if starttimestring
1053                      "VALUE=DATE-TIME:"                            "VALUE=DATE-TIME:"
1054                    "VALUE=DATE:")                          "VALUE=DATE:")
1055                  ;; find the correct week day,                        ;; find the correct week day,
1056                  ;; 1st january 2000 was a saturday                        ;; 1st january 2000 was a saturday
1057                  (format                        (format
1058                   "200001%02d"                         "200001%02d"
1059                   (+ (icalendar--get-weekday-number day) 2))                         (+ (icalendar--get-weekday-number day) 2))
1060                  (or starttimestring "")                        (or starttimestring "")
1061                  "\nDTEND;"                        "\nDTEND;"
1062                  (if endtimestring                        (if endtimestring
1063                      "VALUE=DATE-TIME:"                            "VALUE=DATE-TIME:"
1064                    "VALUE=DATE:")                          "VALUE=DATE:")
1065                  (format                        (format
1066                   "200001%02d"                         "200001%02d"
1067                   ;; end is non-inclusive!                         ;; end is non-inclusive!
1068                   (+ (icalendar--get-weekday-number day)                         (+ (icalendar--get-weekday-number day)
1069                      (if endtimestring 2 3)))                            (if endtimestring 2 3)))
1070                  (or endtimestring "")                        (or endtimestring "")
1071                  "\nSUMMARY:" summary                        "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY="
1072                  "\nRRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY="                        day)
1073                  day))                summary))
1074      ;; no match      ;; no match
1075      nil))      nil))
1076    
1077  (defun icalendar--convert-yearly-to-ical (nonmarker entry-main)  (defun icalendar--convert-yearly-to-ical (nonmarker entry-main)
1078    "Convert yearly diary entry to icalendar format.    "Convert yearly diary entry to icalendar format.
   
1079  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1080  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1081    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
# Line 951  entries.  ENTRY-MAIN is the first line o Line 1087  entries.  ENTRY-MAIN is the first line o
1087                              "\\("                              "\\("
1088                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
1089                              "\\)?"                              "\\)?"
1090                              "\\s-*\\([^0-9]+.*\\)$" ; must not match years                              "\\s-*\\([^0-9]+.*?\\) ?$" ; must not match years
1091                              )                              )
1092                      entry-main)                      entry-main)
1093        (let* ((daypos (if european-calendar-style 1 2))        (let* ((daypos (if european-calendar-style 1 2))
# Line 997  entries.  ENTRY-MAIN is the first line o Line 1133  entries.  ENTRY-MAIN is the first line o
1133                                            starttimestring))))                                            starttimestring))))
1134                (setq endtimestring (format "T%06d"                (setq endtimestring (format "T%06d"
1135                                            (+ 10000 time))))))                                            (+ 10000 time))))))
1136          (concat "\nDTSTART;"          (list (concat "\nDTSTART;"
1137                  (if starttimestring "VALUE=DATE-TIME:"                        (if starttimestring "VALUE=DATE-TIME:"
1138                    "VALUE=DATE:")                          "VALUE=DATE:")
1139                  (format "1900%02d%02d" month day)                        (format "1900%02d%02d" month day)
1140                  (or starttimestring "")                        (or starttimestring "")
1141                  "\nDTEND;"                        "\nDTEND;"
1142                  (if endtimestring "VALUE=DATE-TIME:"                        (if endtimestring "VALUE=DATE-TIME:"
1143                    "VALUE=DATE:")                          "VALUE=DATE:")
1144                  ;; end is not included! shift by one day                        ;; end is not included! shift by one day
1145                  (icalendar--date-to-isodate                        (icalendar--date-to-isodate
1146                   (list month day 1900)                         (list month day 1900)
1147                   (if endtimestring 0 1))                         (if endtimestring 0 1))
1148                  (or endtimestring "")                        (or endtimestring "")
1149                  "\nSUMMARY:"                        "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH="
1150                  summary                        (format "%2d" month)
1151                  "\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH="                        ";BYMONTHDAY="
1152                  (format "%2d" month)                        (format "%2d" day))
1153                  ";BYMONTHDAY="                summary))
                 (format "%2d" day)))  
1154      ;; no match      ;; no match
1155      nil))      nil))
1156    
# Line 1026  FIXME! Line 1161  FIXME!
1161    
1162  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1163  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1164    (if (string-match (concat nonmarker    (cond ((string-match (concat nonmarker
1165                              "%%(\\([^)]+\\))\\s-*\\(.*\\)")                                 "%%(and \\(([^)]+)\\))\\(\\s-*.*?\\) ?$")
1166                      entry-main)                         entry-main)
1167        (progn           ;; simple sexp entry as generated by icalendar.el: strip off the
1168          (icalendar--dmsg "diary-sexp %s" entry-main)           ;; unnecessary (and)
1169          (error "Sexp-entries are not supported yet"))           (icalendar--dmsg "diary-sexp from icalendar.el %s" entry-main)
1170      ;; no match           (icalendar--convert-to-ical
1171      nil))            nonmarker
1172              (concat "%%"
1173                      (substring entry-main (match-beginning 1) (match-end 1))
1174                      (substring entry-main (match-beginning 2) (match-end 2)))))
1175            ((string-match (concat nonmarker
1176                                   "%%([^)]+)\\s-*.*")
1177                           entry-main)
1178             (icalendar--dmsg "diary-sexp %s" entry-main)
1179             (error "Sexp-entries are not supported yet"))
1180            (t
1181             ;; no match
1182             nil)))
1183    
1184  (defun icalendar--convert-block-to-ical (nonmarker entry-main)  (defun icalendar--convert-block-to-ical (nonmarker entry-main)
1185    "Convert block diary entry to icalendar format.    "Convert block diary entry to icalendar format.
   
1186  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1187  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1188    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
# Line 1047  entries.  ENTRY-MAIN is the first line o Line 1192  entries.  ENTRY-MAIN is the first line o
1192                              "\\("                              "\\("
1193                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
1194                              "\\)?"                              "\\)?"
1195                              "\\s-*\\(.*\\)")                              "\\s-*\\(.*?\\) ?$")
1196                      entry-main)                      entry-main)
1197        (let* ((startstring (substring entry-main        (let* ((startstring (substring entry-main
1198                                       (match-beginning 1)                                       (match-beginning 1)
# Line 1096  entries.  ENTRY-MAIN is the first line o Line 1241  entries.  ENTRY-MAIN is the first line o
1241                                            (+ 10000 time))))))                                            (+ 10000 time))))))
1242          (if starttimestring          (if starttimestring
1243              ;; with time -> write rrule              ;; with time -> write rrule
1244              (concat "\nDTSTART;VALUE=DATE-TIME:"              (list (concat "\nDTSTART;VALUE=DATE-TIME:"
1245                      startisostring                            startisostring
1246                      starttimestring                            starttimestring
1247                      "\nDTEND;VALUE=DATE-TIME:"                            "\nDTEND;VALUE=DATE-TIME:"
1248                      startisostring                            startisostring
1249                      endtimestring                            endtimestring
1250                      "\nSUMMARY:"                            "\nRRULE:FREQ=DAILY;INTERVAL=1;UNTIL="
1251                      summary                            endisostring)
1252                      "\nRRULE:FREQ=DAILY;INTERVAL=1;UNTIL="                    summary)
                     endisostring)  
1253            ;; no time -> write long event            ;; no time -> write long event
1254            (concat "\nDTSTART;VALUE=DATE:" startisostring            (list (concat "\nDTSTART;VALUE=DATE:" startisostring
1255                    "\nDTEND;VALUE=DATE:" endisostring+1                          "\nDTEND;VALUE=DATE:" endisostring+1)
1256                    "\nSUMMARY:" summary)))                  summary)))
1257      ;; no match      ;; no match
1258      nil))      nil))
1259    
# Line 1121  FIXME! Line 1265  FIXME!
1265  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1266  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1267    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
1268                              "%%(diary-float \\([^)]+\\))\\s-*\\(.*\\)")                              "%%(diary-float \\([^)]+\\))\\s-*\\(.*?\\) ?$")
1269                      entry-main)                      entry-main)
1270        (progn        (progn
1271          (icalendar--dmsg "diary-float %s" entry-main)          (icalendar--dmsg "diary-float %s" entry-main)
# Line 1137  FIXME! Line 1281  FIXME!
1281  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1282  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1283    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
1284                              "%%(diary-date \\([^)]+\\))\\s-*\\(.*\\)")                              "%%(diary-date \\([^)]+\\))\\s-*\\(.*?\\) ?$")
1285                      entry-main)                      entry-main)
1286        (progn        (progn
1287          (icalendar--dmsg "diary-date %s" entry-main)          (icalendar--dmsg "diary-date %s" entry-main)
# Line 1147  entries.  ENTRY-MAIN is the first line o Line 1291  entries.  ENTRY-MAIN is the first line o
1291    
1292  (defun icalendar--convert-cyclic-to-ical (nonmarker entry-main)  (defun icalendar--convert-cyclic-to-ical (nonmarker entry-main)
1293    "Convert `diary-cyclic' diary entry to icalendar format.    "Convert `diary-cyclic' diary entry to icalendar format.
   
1294  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1295  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1296    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
# Line 1157  entries.  ENTRY-MAIN is the first line o Line 1300  entries.  ENTRY-MAIN is the first line o
1300                              "\\("                              "\\("
1301                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
1302                              "\\)?"                              "\\)?"
1303                              "\\s-*\\(.*\\)")                              "\\s-*\\(.*?\\) ?$")
1304                      entry-main)                      entry-main)
1305        (let* ((frequency (substring entry-main (match-beginning 1)        (let* ((frequency (substring entry-main (match-beginning 1)
1306                                     (match-end 1)))                                     (match-end 1)))
# Line 1202  entries.  ENTRY-MAIN is the first line o Line 1345  entries.  ENTRY-MAIN is the first line o
1345                                            starttimestring))))                                            starttimestring))))
1346                (setq endtimestring (format "T%06d"                (setq endtimestring (format "T%06d"
1347                                            (+ 10000 time))))))                                            (+ 10000 time))))))
1348          (concat "\nDTSTART;"          (list (concat "\nDTSTART;"
1349                  (if starttimestring "VALUE=DATE-TIME:"                        (if starttimestring "VALUE=DATE-TIME:"
1350                    "VALUE=DATE:")                          "VALUE=DATE:")
1351                  startisostring                        startisostring
1352                  (or starttimestring "")                        (or starttimestring "")
1353                  "\nDTEND;"                        "\nDTEND;"
1354                  (if endtimestring "VALUE=DATE-TIME:"                        (if endtimestring "VALUE=DATE-TIME:"
1355                    "VALUE=DATE:")                          "VALUE=DATE:")
1356                  (if endtimestring endisostring endisostring+1)                        (if endtimestring endisostring endisostring+1)
1357                  (or endtimestring "")                        (or endtimestring "")
1358                  "\nSUMMARY:" summary                        "\nRRULE:FREQ=DAILY;INTERVAL=" frequency
1359                  "\nRRULE:FREQ=DAILY;INTERVAL=" frequency                        ;; strange: korganizer does not expect
1360                  ;; strange: korganizer does not expect                        ;; BYSOMETHING here...
1361                  ;; BYSOMETHING here...                        )
1362                  ))                summary))
1363      ;; no match      ;; no match
1364      nil))      nil))
1365    
1366  (defun icalendar--convert-anniversary-to-ical (nonmarker entry-main)  (defun icalendar--convert-anniversary-to-ical (nonmarker entry-main)
1367    "Convert `diary-anniversary' diary entry to icalendar format.    "Convert `diary-anniversary' diary entry to icalendar format.
   
1368  NONMARKER is a regular expression matching the start of non-marking  NONMARKER is a regular expression matching the start of non-marking
1369  entries.  ENTRY-MAIN is the first line of the diary entry."  entries.  ENTRY-MAIN is the first line of the diary entry."
1370    (if (string-match (concat nonmarker    (if (string-match (concat nonmarker
# Line 1231  entries.  ENTRY-MAIN is the first line o Line 1373  entries.  ENTRY-MAIN is the first line o
1373                              "\\("                              "\\("
1374                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"                              "-0?\\([1-9][0-9]?:[0-9][0-9]\\)\\([ap]m\\)?\\)?"
1375                              "\\)?"                              "\\)?"
1376                              "\\s-*\\(.*\\)")                              "\\s-*\\(.*?\\) ?$")
1377                      entry-main)                      entry-main)
1378        (let* ((datetime (substring entry-main (match-beginning 1)        (let* ((datetime (substring entry-main (match-beginning 1)
1379                                    (match-end 1)))                                    (match-end 1)))
# Line 1272  entries.  ENTRY-MAIN is the first line o Line 1414  entries.  ENTRY-MAIN is the first line o
1414                                            starttimestring))))                                            starttimestring))))
1415                (setq endtimestring (format "T%06d"                (setq endtimestring (format "T%06d"
1416                                            (+ 10000 time))))))                                            (+ 10000 time))))))
1417          (concat "\nDTSTART;"          (list (concat "\nDTSTART;"
1418                  (if starttimestring "VALUE=DATE-TIME:"                        (if starttimestring "VALUE=DATE-TIME:"
1419                    "VALUE=DATE:")                          "VALUE=DATE:")
1420                  startisostring                        startisostring
1421                  (or starttimestring "")                        (or starttimestring "")
1422                  "\nDTEND;"                        "\nDTEND;"
1423                  (if endtimestring "VALUE=DATE-TIME:"                        (if endtimestring "VALUE=DATE-TIME:"
1424                    "VALUE=DATE:")                          "VALUE=DATE:")
1425                  endisostring                        endisostring
1426                  (or endtimestring "")                        (or endtimestring "")
1427                  "\nSUMMARY:" summary                        "\nRRULE:FREQ=YEARLY;INTERVAL=1"
1428                  "\nRRULE:FREQ=YEARLY;INTERVAL=1"                        ;; the following is redundant,
1429                  ;; the following is redundant,                        ;; but korganizer seems to expect this... ;(
1430                  ;; but korganizer seems to expect this... ;(                        ;; and evolution doesn't understand it... :(
1431                  ;; and evolution doesn't understand it... :(                        ;; so... who is wrong?!
1432                  ;; so... who is wrong?!                        ";BYMONTH="
1433                  ";BYMONTH="                        (substring startisostring 4 6)
1434                  (substring startisostring 4 6)                        ";BYMONTHDAY="
1435                  ";BYMONTHDAY="                        (substring startisostring 6 8))
1436                  (substring startisostring 6 8)))                summary))
1437      ;; no match      ;; no match
1438      nil))      nil))
1439    
# Line 1302  entries.  ENTRY-MAIN is the first line o Line 1444  entries.  ENTRY-MAIN is the first line o
1444  ;;;###autoload  ;;;###autoload
1445  (defun icalendar-import-file (ical-filename diary-filename  (defun icalendar-import-file (ical-filename diary-filename
1446                                              &optional non-marking)                                              &optional non-marking)
1447    "Import a iCalendar file and append to a diary file.    "Import an iCalendar file and append to a diary file.
1448  Argument ICAL-FILENAME output iCalendar file.  Argument ICAL-FILENAME output iCalendar file.
1449  Argument DIARY-FILENAME input `diary-file'.  Argument DIARY-FILENAME input `diary-file'.
1450  Optional argument NON-MARKING determines whether events are created as  Optional argument NON-MARKING determines whether events are created as
# Line 1376  buffer `*icalendar-errors*'." Line 1518  buffer `*icalendar-errors*'."
1518    "Create a string representation of an iCalendar EVENT."    "Create a string representation of an iCalendar EVENT."
1519    (let ((string icalendar-import-format)    (let ((string icalendar-import-format)
1520          (conversion-list          (conversion-list
1521           '(("%d" DESCRIPTION icalendar-import-format-description)           '(("%c" CLASS       icalendar-import-format-class)
1522             ("%s" SUMMARY     icalendar-import-format-subject)             ("%d" DESCRIPTION icalendar-import-format-description)
1523             ("%l" LOCATION    icalendar-import-format-location)             ("%l" LOCATION    icalendar-import-format-location)
1524             ("%o" ORGANIZER   icalendar-import-format-organizer))))             ("%o" ORGANIZER   icalendar-import-format-organizer)
1525               ("%s" SUMMARY     icalendar-import-format-summary)
1526               ("%t" STATUS      icalendar-import-format-status)
1527               ("%u" URL         icalendar-import-format-url))))
1528      ;; convert the specifiers in the format string      ;; convert the specifiers in the format string
1529      (mapcar (lambda (i)      (mapcar (lambda (i)
1530                (let* ((spec (car i))                (let* ((spec (car i))
# Line 1392  buffer `*icalendar-errors*'." Line 1537  buffer `*icalendar-errors*'."
1537                          (icalendar--rris "%s"                          (icalendar--rris "%s"
1538                                           (icalendar--convert-string-for-import                                           (icalendar--convert-string-for-import
1539                                            contents)                                            contents)
1540                                           (symbol-value format))))                                           (symbol-value format)
1541                                             t t)))
1542                  (setq string (icalendar--rris spec                  (setq string (icalendar--rris spec
1543                                                formatted-contents                                                formatted-contents
1544                                                string))))                                                string
1545                                                  t t))))
1546              conversion-list)              conversion-list)
1547      string))      string))
1548    
1549  (defun icalendar--convert-ical-to-diary (ical-list diary-file  (defun icalendar--convert-ical-to-diary (ical-list diary-file
1550                                                     &optional do-not-ask                                                     &optional do-not-ask
1551                                                     non-marking)                                                     non-marking)
1552    "Convert an iCalendar file to an Emacs diary file.    "Convert Calendar data to an Emacs diary file.
1553  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
1554  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
1555  whether to actually import it.  NON-MARKING determines whether diary  whether to actually import it.  NON-MARKING determines whether diary
# Line 1432  written into the buffer `*icalendar-erro Line 1579  written into the buffer `*icalendar-erro
1579                   end-d                   end-d
1580                   end-1-d                   end-1-d
1581                   end-t                   end-t
1582                   (subject (icalendar--convert-string-for-import                   (summary (icalendar--convert-string-for-import
1583                             (or (icalendar--get-event-property e 'SUMMARY)                             (or (icalendar--get-event-property e 'SUMMARY)
1584                                 "No Subject")))                                 "No summary")))
1585                   (rrule (icalendar--get-event-property e 'RRULE))                   (rrule (icalendar--get-event-property e 'RRULE))
1586                   (rdate (icalendar--get-event-property e 'RDATE))                   (rdate (icalendar--get-event-property e 'RDATE))
1587                   (duration (icalendar--get-event-property e 'DURATION)))                   (duration (icalendar--get-event-property e 'DURATION)))
1588              (icalendar--dmsg "%s: `%s'" start-d subject)              (icalendar--dmsg "%s: `%s'" start-d summary)
1589              ;; check whether start-time is missing              ;; check whether start-time is missing
1590              (if  (and dtstart              (if  (and dtstart
1591                        (string=                        (string=
# Line 1456  written into the buffer `*icalendar-erro Line 1603  written into the buffer `*icalendar-erro
1603                                                                     t))))                                                                     t))))
1604                  (if (and dtend-dec (not (eq dtend-dec dtend-dec-d)))                  (if (and dtend-dec (not (eq dtend-dec dtend-dec-d)))
1605                      (message "Inconsistent endtime and duration for %s"                      (message "Inconsistent endtime and duration for %s"
1606                               subject))                               summary))
1607                  (setq dtend-dec dtend-dec-d)                  (setq dtend-dec dtend-dec-d)
1608                  (setq dtend-1-dec dtend-1-dec-d)))                  (setq dtend-1-dec dtend-1-dec-d)))
1609              (setq end-d (if dtend-dec              (setq end-d (if dtend-dec
# Line 1517  written into the buffer `*icalendar-erro Line 1664  written into the buffer `*icalendar-erro
1664                    (setq diary-string                    (setq diary-string
1665                          (concat diary-string " "                          (concat diary-string " "
1666                                  (icalendar--format-ical-event e)))                                  (icalendar--format-ical-event e)))
1667                    (if do-not-ask (setq subject nil))                    (if do-not-ask (setq summary nil))
1668                    (icalendar--add-diary-entry diary-string diary-file                    (icalendar--add-diary-entry diary-string diary-file
1669                                                non-marking subject))                                                non-marking summary))
1670                ;; event was not ok                ;; event was not ok
1671                (setq found-error t)                (setq found-error t)
1672                (setq error-string                (setq error-string
# Line 1570  END-T is the event's end time in diary f Line 1717  END-T is the event's end time in diary f
1717          (let ((until-1 0))          (let ((until-1 0))
1718            (cond ((string-equal frequency "DAILY")            (cond ((string-equal frequency "DAILY")
1719                   (setq until (icalendar--add-decoded-times                   (setq until (icalendar--add-decoded-times
1720                                dtstart-dec                                dtstart-dec
1721                                (list 0 0 0 (* (read count) interval) 0 0)))                                (list 0 0 0 (* (read count) interval) 0 0)))
1722                   (setq until-1 (icalendar--add-decoded-times                   (setq until-1 (icalendar--add-decoded-times
1723                                  dtstart-dec                                  dtstart-dec
# Line 1767  END-T is the event's end time in diary f Line 1914  END-T is the event's end time in diary f
1914                   start-t))))                   start-t))))
1915    
1916  (defun icalendar--add-diary-entry (string diary-file non-marking  (defun icalendar--add-diary-entry (string diary-file non-marking
1917                                            &optional subject)                                            &optional summary)
1918    "Add STRING to the diary file DIARY-FILE.    "Add STRING to the diary file DIARY-FILE.
1919  STRING must be a properly formatted valid diary entry.  NON-MARKING  STRING must be a properly formatted valid diary entry.  NON-MARKING
1920  determines whether diary events are created as non-marking.  If  determines whether diary events are created as non-marking.  If
1921  SUBJECT is not nil it must be a string that gives the subject of the  SUMMARY is not nil it must be a string that gives the summary of the
1922  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
1923  the entry."  the entry."
1924    (when (or (not subject)    (when (or (not summary)
1925              (y-or-n-p (format "Add appointment for `%s' to diary? "              (y-or-n-p (format "Add appointment for `%s' to diary? "
1926                                subject)))                                summary)))
1927      (when subject      (when summary
1928        (setq non-marking        (setq non-marking
1929              (y-or-n-p (format "Make appointment non-marking? "))))              (y-or-n-p (format "Make appointment non-marking? "))))
1930      (save-window-excursion      (save-window-excursion
1931        (unless diary-file        (unless diary-file
1932          (setq diary-file          (setq diary-file
1933                (read-file-name "Add appointment to this diary file: ")))                (read-file-name "Add appointment to this diary file: ")))
1934          ;; Note: make-diary-entry will add a trailing blank char.... :(
1935        (make-diary-entry string non-marking diary-file))))        (make-diary-entry string non-marking diary-file))))
1936    
1937  (provide 'icalendar)  (provide 'icalendar)

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26