diff options
| author | Ulf Jasper | 2014-08-10 19:48:51 +0200 |
|---|---|---|
| committer | Ulf Jasper | 2014-08-10 19:48:51 +0200 |
| commit | d4ed7004f510237849d080000930889c4a54e73d (patch) | |
| tree | 6d060006fa99393b865f685fbe3a7e37ac77e3ba /lisp | |
| parent | 643a0303965c233b66d7ebfd5b2c045253dea3be (diff) | |
| download | emacs-d4ed7004f510237849d080000930889c4a54e73d.tar.gz emacs-d4ed7004f510237849d080000930889c4a54e73d.zip | |
iCalendar export: Enumerate evaluated sexp diary entries (Bug#7911).
2014-08-10 Ulf Jasper <ulf.jasper@web.de>
Enumerate evaluated sexp diary entries (Bug#7911).
* calendar/icalendar.el (icalendar-export-sexp-enumerate-all)
(icalendar-export-sexp-enumeration-days): New
(icalendar-export-region): `icalendar--convert-to-ical' now
returns a cons cell or a list of cons cells.
(icalendar--convert-to-ical): Take care of
`icalendar-export-sexp-enumerate-all'. Return (a list of) cons
cells.
(icalendar--convert-ordinary-to-ical),
(icalendar--convert-weekly-to-ical),
(icalendar--convert-yearly-to-ical),
(icalendar--convert-block-to-ical),
(icalendar--convert-block-to-ical),
(icalendar--convert-float-to-ical),
(icalendar--convert-cyclic-to-ical),
(icalendar--convert-anniversary-to-ical): Return cons cell.
(icalendar--convert-sexp-to-ical): Enumerate evaluated sexp
entries. Return (list of) cons cells.
2014-08-10 Ulf Jasper <ulf.jasper@web.de>
Enumerate evaluated sexp diary entries (Bug#7911).
* automated/icalendar-tests.el
(icalendar--convert-anniversary-to-ical),
(icalendar--convert-cyclic-to-ical),
(icalendar--convert-block-to-ical),
(icalendar--convert-yearly-to-ical),
(icalendar--convert-weekly-to-ical),
(icalendar--convert-ordinary-to-ical): Returns cons cell now.
(icalendar--convert-to-ical),
(icalendar--convert-sexp-to-ical): New tests.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 22 | ||||
| -rw-r--r-- | lisp/calendar/icalendar.el | 179 |
2 files changed, 144 insertions, 57 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index b0a0e0c95a0..8cf5e0f54c9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,25 @@ | |||
| 1 | 2014-08-10 Ulf Jasper <ulf.jasper@web.de> | ||
| 2 | |||
| 3 | Enumerate evaluated sexp diary entries (Bug#7911). | ||
| 4 | |||
| 5 | * calendar/icalendar.el (icalendar-export-sexp-enumerate-all) | ||
| 6 | (icalendar-export-sexp-enumeration-days): New | ||
| 7 | (icalendar-export-region): `icalendar--convert-to-ical' now | ||
| 8 | returns a cons cell or a list of cons cells. | ||
| 9 | (icalendar--convert-to-ical): Take care of | ||
| 10 | `icalendar-export-sexp-enumerate-all'. Return (a list of) cons | ||
| 11 | cells. | ||
| 12 | (icalendar--convert-ordinary-to-ical), | ||
| 13 | (icalendar--convert-weekly-to-ical), | ||
| 14 | (icalendar--convert-yearly-to-ical), | ||
| 15 | (icalendar--convert-block-to-ical), | ||
| 16 | (icalendar--convert-block-to-ical), | ||
| 17 | (icalendar--convert-float-to-ical), | ||
| 18 | (icalendar--convert-cyclic-to-ical), | ||
| 19 | (icalendar--convert-anniversary-to-ical): Return cons cell. | ||
| 20 | (icalendar--convert-sexp-to-ical): Enumerate evaluated sexp | ||
| 21 | entries. Return (list of) cons cells. | ||
| 22 | |||
| 1 | 2014-08-09 Juri Linkov <juri@jurta.org> | 23 | 2014-08-09 Juri Linkov <juri@jurta.org> |
| 2 | 24 | ||
| 3 | * vc/vc-annotate.el (vc-annotate-background-mode): Add :set | 25 | * vc/vc-annotate.el (vc-annotate-background-mode): Add :set |
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el index ba4ff1c1fa8..8881796c94b 100644 --- a/lisp/calendar/icalendar.el +++ b/lisp/calendar/icalendar.el | |||
| @@ -240,6 +240,31 @@ code for the event, and your personal domain name." | |||
| 240 | :type 'string | 240 | :type 'string |
| 241 | :group 'icalendar) | 241 | :group 'icalendar) |
| 242 | 242 | ||
| 243 | (defcustom icalendar-export-sexp-enumeration-days | ||
| 244 | 14 | ||
| 245 | "Number of days over which a sexp diary entry is enumerated. | ||
| 246 | In general sexp entries cannot be translated to icalendar format. | ||
| 247 | They are therefore enumerated, i.e. explicitly evaluated for a | ||
| 248 | certain number of days, and then exported. The enumeration starts | ||
| 249 | on the current day and continues for the number of days given here. | ||
| 250 | |||
| 251 | See `icalendar-export-sexp-enumerate-all' for a list of sexp | ||
| 252 | entries which by default are NOT enumerated." | ||
| 253 | :type 'integer | ||
| 254 | :group 'icalendar) | ||
| 255 | |||
| 256 | (defcustom icalendar-export-sexp-enumerate-all | ||
| 257 | nil | ||
| 258 | "Determines whether ALL sexp diary entries are enumerated. | ||
| 259 | If non-nil all sexp diary entries are enumerated for | ||
| 260 | `icalendar-export-sexp-enumeration-days' days instead of | ||
| 261 | translating into an icalendar equivalent. This affects the | ||
| 262 | following sexp diary entries: `diary-anniversary', | ||
| 263 | `diary-cyclic', `diary-date', `diary-float',`diary-block'. All | ||
| 264 | other sexp entries are enumerated in any case." | ||
| 265 | :type 'boolean | ||
| 266 | :group 'icalendar) | ||
| 267 | |||
| 243 | (defvar icalendar-debug nil | 268 | (defvar icalendar-debug nil |
| 244 | "Enable icalendar debug messages.") | 269 | "Enable icalendar debug messages.") |
| 245 | 270 | ||
| @@ -1027,40 +1052,48 @@ FExport diary data into iCalendar file: ") | |||
| 1027 | 1052 | ||
| 1028 | (condition-case error-val | 1053 | (condition-case error-val |
| 1029 | (progn | 1054 | (progn |
| 1030 | (setq contents-n-summary | 1055 | (setq cns-cons-or-list |
| 1031 | (icalendar--convert-to-ical nonmarker entry-main)) | 1056 | (icalendar--convert-to-ical nonmarker entry-main)) |
| 1032 | (setq other-elements (icalendar--parse-summary-and-rest | 1057 | (setq other-elements (icalendar--parse-summary-and-rest |
| 1033 | entry-full)) | 1058 | entry-full)) |
| 1034 | (setq contents (concat (car contents-n-summary) | 1059 | (mapc (lambda (contents-n-summary) |
| 1035 | "\nSUMMARY:" (cadr contents-n-summary))) | 1060 | (setq contents (concat (car contents-n-summary) |
| 1036 | (let ((cla (cdr (assoc 'cla other-elements))) | 1061 | "\nSUMMARY:" |
| 1037 | (des (cdr (assoc 'des other-elements))) | 1062 | (cdr contents-n-summary))) |
| 1038 | (loc (cdr (assoc 'loc other-elements))) | 1063 | (let ((cla (cdr (assoc 'cla other-elements))) |
| 1039 | (org (cdr (assoc 'org other-elements))) | 1064 | (des (cdr (assoc 'des other-elements))) |
| 1040 | (sta (cdr (assoc 'sta other-elements))) | 1065 | (loc (cdr (assoc 'loc other-elements))) |
| 1041 | (sum (cdr (assoc 'sum other-elements))) | 1066 | (org (cdr (assoc 'org other-elements))) |
| 1042 | (url (cdr (assoc 'url other-elements))) | 1067 | (sta (cdr (assoc 'sta other-elements))) |
| 1043 | (uid (cdr (assoc 'uid other-elements)))) | 1068 | (sum (cdr (assoc 'sum other-elements))) |
| 1044 | (if cla | 1069 | (url (cdr (assoc 'url other-elements))) |
| 1045 | (setq contents (concat contents "\nCLASS:" cla))) | 1070 | (uid (cdr (assoc 'uid other-elements)))) |
| 1046 | (if des | 1071 | (if cla |
| 1047 | (setq contents (concat contents "\nDESCRIPTION:" des))) | 1072 | (setq contents (concat contents "\nCLASS:" cla))) |
| 1048 | (if loc | 1073 | (if des |
| 1049 | (setq contents (concat contents "\nLOCATION:" loc))) | 1074 | (setq contents (concat contents "\nDESCRIPTION:" |
| 1050 | (if org | 1075 | des))) |
| 1051 | (setq contents (concat contents "\nORGANIZER:" org))) | 1076 | (if loc |
| 1052 | (if sta | 1077 | (setq contents (concat contents "\nLOCATION:" loc))) |
| 1053 | (setq contents (concat contents "\nSTATUS:" sta))) | 1078 | (if org |
| 1054 | ;;(if sum | 1079 | (setq contents (concat contents "\nORGANIZER:" |
| 1055 | ;; (setq contents (concat contents "\nSUMMARY:" sum))) | 1080 | org))) |
| 1056 | (if url | 1081 | (if sta |
| 1057 | (setq contents (concat contents "\nURL:" url))) | 1082 | (setq contents (concat contents "\nSTATUS:" sta))) |
| 1058 | 1083 | ;;(if sum | |
| 1059 | (setq header (concat "\nBEGIN:VEVENT\nUID:" | 1084 | ;; (setq contents (concat contents "\nSUMMARY:" sum))) |
| 1060 | (or uid | 1085 | (if url |
| 1061 | (icalendar--create-uid entry-full | 1086 | (setq contents (concat contents "\nURL:" url))) |
| 1062 | contents))))) | 1087 | |
| 1063 | (setq result (concat result header contents "\nEND:VEVENT"))) | 1088 | (setq header (concat "\nBEGIN:VEVENT\nUID:" |
| 1089 | (or uid | ||
| 1090 | (icalendar--create-uid | ||
| 1091 | entry-full contents))))) | ||
| 1092 | (setq result (concat result header contents | ||
| 1093 | "\nEND:VEVENT"))) | ||
| 1094 | (if (consp cns-cons-or-list) | ||
| 1095 | (list cns-cons-or-list) | ||
| 1096 | cns-cons-or-list))) | ||
| 1064 | ;; handle errors | 1097 | ;; handle errors |
| 1065 | (error | 1098 | (error |
| 1066 | (setq found-error t) | 1099 | (setq found-error t) |
| @@ -1092,16 +1125,18 @@ FExport diary data into iCalendar file: ") | |||
| 1092 | NONMARKER is a regular expression matching the start of non-marking | 1125 | NONMARKER is a regular expression matching the start of non-marking |
| 1093 | entries. ENTRY-MAIN is the first line of the diary entry." | 1126 | entries. ENTRY-MAIN is the first line of the diary entry." |
| 1094 | (or | 1127 | (or |
| 1095 | ;; anniversaries -- %%(diary-anniversary ...) | 1128 | (unless icalendar-export-sexp-enumerate-all |
| 1096 | (icalendar--convert-anniversary-to-ical nonmarker entry-main) | 1129 | (or |
| 1097 | ;; cyclic events -- %%(diary-cyclic ...) | 1130 | ;; anniversaries -- %%(diary-anniversary ...) |
| 1098 | (icalendar--convert-cyclic-to-ical nonmarker entry-main) | 1131 | (icalendar--convert-anniversary-to-ical nonmarker entry-main) |
| 1099 | ;; diary-date -- %%(diary-date ...) | 1132 | ;; cyclic events -- %%(diary-cyclic ...) |
| 1100 | (icalendar--convert-date-to-ical nonmarker entry-main) | 1133 | (icalendar--convert-cyclic-to-ical nonmarker entry-main) |
| 1101 | ;; float events -- %%(diary-float ...) | 1134 | ;; diary-date -- %%(diary-date ...) |
| 1102 | (icalendar--convert-float-to-ical nonmarker entry-main) | 1135 | (icalendar--convert-date-to-ical nonmarker entry-main) |
| 1103 | ;; block events -- %%(diary-block ...) | 1136 | ;; float events -- %%(diary-float ...) |
| 1104 | (icalendar--convert-block-to-ical nonmarker entry-main) | 1137 | (icalendar--convert-float-to-ical nonmarker entry-main) |
| 1138 | ;; block events -- %%(diary-block ...) | ||
| 1139 | (icalendar--convert-block-to-ical nonmarker entry-main))) | ||
| 1105 | ;; other sexp diary entries | 1140 | ;; other sexp diary entries |
| 1106 | (icalendar--convert-sexp-to-ical nonmarker entry-main) | 1141 | (icalendar--convert-sexp-to-ical nonmarker entry-main) |
| 1107 | ;; weekly by day -- Monday 8:30 Team meeting | 1142 | ;; weekly by day -- Monday 8:30 Team meeting |
| @@ -1300,7 +1335,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1300 | (- time 230000))) | 1335 | (- time 230000))) |
| 1301 | (setq endisostring1 endisostring)) ))) | 1336 | (setq endisostring1 endisostring)) ))) |
| 1302 | 1337 | ||
| 1303 | (list (concat "\nDTSTART;" | 1338 | (cons (concat "\nDTSTART;" |
| 1304 | (if starttimestring "VALUE=DATE-TIME:" | 1339 | (if starttimestring "VALUE=DATE-TIME:" |
| 1305 | "VALUE=DATE:") | 1340 | "VALUE=DATE:") |
| 1306 | startisostring | 1341 | startisostring |
| @@ -1381,7 +1416,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1381 | starttimestring)))) | 1416 | starttimestring)))) |
| 1382 | (setq endtimestring (format "T%06d" | 1417 | (setq endtimestring (format "T%06d" |
| 1383 | (+ 10000 time)))))) | 1418 | (+ 10000 time)))))) |
| 1384 | (list (concat "\nDTSTART;" | 1419 | (cons (concat "\nDTSTART;" |
| 1385 | (if starttimestring | 1420 | (if starttimestring |
| 1386 | "VALUE=DATE-TIME:" | 1421 | "VALUE=DATE-TIME:" |
| 1387 | "VALUE=DATE:") | 1422 | "VALUE=DATE:") |
| @@ -1468,7 +1503,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1468 | starttimestring)))) | 1503 | starttimestring)))) |
| 1469 | (setq endtimestring (format "T%06d" | 1504 | (setq endtimestring (format "T%06d" |
| 1470 | (+ 10000 time)))))) | 1505 | (+ 10000 time)))))) |
| 1471 | (list (concat "\nDTSTART;" | 1506 | (cons (concat "\nDTSTART;" |
| 1472 | (if starttimestring "VALUE=DATE-TIME:" | 1507 | (if starttimestring "VALUE=DATE-TIME:" |
| 1473 | "VALUE=DATE:") | 1508 | "VALUE=DATE:") |
| 1474 | (format "1900%02d%02d" month day) | 1509 | (format "1900%02d%02d" month day) |
| @@ -1489,13 +1524,16 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1489 | ;; no match | 1524 | ;; no match |
| 1490 | nil)) | 1525 | nil)) |
| 1491 | 1526 | ||
| 1492 | (defun icalendar--convert-sexp-to-ical (nonmarker entry-main) | 1527 | (defun icalendar--convert-sexp-to-ical (nonmarker entry-main &optional start) |
| 1493 | "Convert complex sexp diary entry to iCalendar format -- unsupported! | 1528 | "Convert sexp diary entry to iCalendar format. |
| 1529 | Enumerate the evaluated sexp entry for the next | ||
| 1530 | `icalendar-export-sexp-enumeration-days' days. NONMARKER is a | ||
| 1531 | regular expression matching the start of non-marking entries. | ||
| 1532 | ENTRY-MAIN is the first line of the diary entry. | ||
| 1494 | 1533 | ||
| 1495 | FIXME! | 1534 | Optional argument START determines the first day of the |
| 1496 | 1535 | enumeration, given as a time value, in same format as returned by | |
| 1497 | NONMARKER is a regular expression matching the start of non-marking | 1536 | `current-time' -- used for test purposes." |
| 1498 | entries. ENTRY-MAIN is the first line of the diary entry." | ||
| 1499 | (cond ((string-match (concat nonmarker | 1537 | (cond ((string-match (concat nonmarker |
| 1500 | "%%(and \\(([^)]+)\\))\\(\\s-*.*?\\) ?$") | 1538 | "%%(and \\(([^)]+)\\))\\(\\s-*.*?\\) ?$") |
| 1501 | entry-main) | 1539 | entry-main) |
| @@ -1508,10 +1546,37 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1508 | (substring entry-main (match-beginning 1) (match-end 1)) | 1546 | (substring entry-main (match-beginning 1) (match-end 1)) |
| 1509 | (substring entry-main (match-beginning 2) (match-end 2))))) | 1547 | (substring entry-main (match-beginning 2) (match-end 2))))) |
| 1510 | ((string-match (concat nonmarker | 1548 | ((string-match (concat nonmarker |
| 1511 | "%%([^)]+)\\s-*.*") | 1549 | "%%\\(([^)]+)\\)\\s-*\\(.*\\)") |
| 1512 | entry-main) | 1550 | entry-main) |
| 1551 | ;; regular sexp entry | ||
| 1513 | (icalendar--dmsg "diary-sexp %s" entry-main) | 1552 | (icalendar--dmsg "diary-sexp %s" entry-main) |
| 1514 | (error "Sexp-entries are not supported yet")) | 1553 | (let ((p1 (substring entry-main (match-beginning 1) (match-end 1))) |
| 1554 | (p2 (substring entry-main (match-beginning 2) (match-end 2))) | ||
| 1555 | (now (or start (current-time)))) | ||
| 1556 | (delete nil | ||
| 1557 | (mapcar | ||
| 1558 | (lambda (offset) | ||
| 1559 | (let* ((day (decode-time (time-add now | ||
| 1560 | (seconds-to-time | ||
| 1561 | (* offset 60 60 24))))) | ||
| 1562 | (d (nth 3 day)) | ||
| 1563 | (m (nth 4 day)) | ||
| 1564 | (y (nth 5 day)) | ||
| 1565 | (se (diary-sexp-entry p1 p2 (list m d y))) | ||
| 1566 | (see (cond ((stringp se) se) | ||
| 1567 | ((consp se) (cdr se)) | ||
| 1568 | (t nil)))) | ||
| 1569 | (cond ((null see) | ||
| 1570 | nil) | ||
| 1571 | ((stringp see) | ||
| 1572 | (let ((calendar-date-style 'iso)) | ||
| 1573 | (icalendar--convert-ordinary-to-ical | ||
| 1574 | nonmarker (format "%4d/%02d/%02d %s" y m d see)))) | ||
| 1575 | (;TODO: | ||
| 1576 | (error (format "Unsopported Sexp-entry: %s" | ||
| 1577 | entry-main)))))) | ||
| 1578 | (number-sequence | ||
| 1579 | 0 (- icalendar-export-sexp-enumeration-days 1)))))) | ||
| 1515 | (t | 1580 | (t |
| 1516 | ;; no match | 1581 | ;; no match |
| 1517 | nil))) | 1582 | nil))) |
| @@ -1576,7 +1641,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1576 | (+ 10000 time)))))) | 1641 | (+ 10000 time)))))) |
| 1577 | (if starttimestring | 1642 | (if starttimestring |
| 1578 | ;; with time -> write rrule | 1643 | ;; with time -> write rrule |
| 1579 | (list (concat "\nDTSTART;VALUE=DATE-TIME:" | 1644 | (cons (concat "\nDTSTART;VALUE=DATE-TIME:" |
| 1580 | startisostring | 1645 | startisostring |
| 1581 | starttimestring | 1646 | starttimestring |
| 1582 | "\nDTEND;VALUE=DATE-TIME:" | 1647 | "\nDTEND;VALUE=DATE-TIME:" |
| @@ -1586,7 +1651,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1586 | endisostring) | 1651 | endisostring) |
| 1587 | summary) | 1652 | summary) |
| 1588 | ;; no time -> write long event | 1653 | ;; no time -> write long event |
| 1589 | (list (concat "\nDTSTART;VALUE=DATE:" startisostring | 1654 | (cons (concat "\nDTSTART;VALUE=DATE:" startisostring |
| 1590 | "\nDTEND;VALUE=DATE:" endisostring+1) | 1655 | "\nDTEND;VALUE=DATE:" endisostring+1) |
| 1591 | summary))) | 1656 | summary))) |
| 1592 | ;; no match | 1657 | ;; no match |
| @@ -1622,7 +1687,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1622 | (icalendar--dmsg "diary-float %s" entry-main) | 1687 | (icalendar--dmsg "diary-float %s" entry-main) |
| 1623 | (error "Don't know if or how to implement day in `diary-float'"))) | 1688 | (error "Don't know if or how to implement day in `diary-float'"))) |
| 1624 | 1689 | ||
| 1625 | (list (concat | 1690 | (cons (concat |
| 1626 | ;;Start today (yes this is an arbitrary choice): | 1691 | ;;Start today (yes this is an arbitrary choice): |
| 1627 | "\nDTSTART;VALUE=DATE:" | 1692 | "\nDTSTART;VALUE=DATE:" |
| 1628 | (format-time-string "%Y%m%d" (current-time)) | 1693 | (format-time-string "%Y%m%d" (current-time)) |
| @@ -1727,7 +1792,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1727 | starttimestring)))) | 1792 | starttimestring)))) |
| 1728 | (setq endtimestring (format "T%06d" | 1793 | (setq endtimestring (format "T%06d" |
| 1729 | (+ 10000 time)))))) | 1794 | (+ 10000 time)))))) |
| 1730 | (list (concat "\nDTSTART;" | 1795 | (cons (concat "\nDTSTART;" |
| 1731 | (if starttimestring "VALUE=DATE-TIME:" | 1796 | (if starttimestring "VALUE=DATE-TIME:" |
| 1732 | "VALUE=DATE:") | 1797 | "VALUE=DATE:") |
| 1733 | startisostring | 1798 | startisostring |
| @@ -1796,7 +1861,7 @@ entries. ENTRY-MAIN is the first line of the diary entry." | |||
| 1796 | starttimestring)))) | 1861 | starttimestring)))) |
| 1797 | (setq endtimestring (format "T%06d" | 1862 | (setq endtimestring (format "T%06d" |
| 1798 | (+ 10000 time)))))) | 1863 | (+ 10000 time)))))) |
| 1799 | (list (concat "\nDTSTART;" | 1864 | (cons (concat "\nDTSTART;" |
| 1800 | (if starttimestring "VALUE=DATE-TIME:" | 1865 | (if starttimestring "VALUE=DATE-TIME:" |
| 1801 | "VALUE=DATE:") | 1866 | "VALUE=DATE:") |
| 1802 | startisostring | 1867 | startisostring |