5 |
;; Author: Carsten Dominik <dominik at science dot uva dot nl> |
;; Author: Carsten Dominik <dominik at science dot uva dot nl> |
6 |
;; Keywords: outlines, hypermedia, calendar |
;; Keywords: outlines, hypermedia, calendar |
7 |
;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/ |
;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/ |
8 |
;; Version: 3.17 |
;; Version: 3.18 |
9 |
;; |
;; |
10 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
11 |
;; |
;; |
80 |
;; |
;; |
81 |
;; Changes: |
;; Changes: |
82 |
;; ------- |
;; ------- |
83 |
|
;; Version 3.18 |
84 |
|
;; - Export of calendar information in the standard iCalendar format. |
85 |
|
;; - Some bug fixes. |
86 |
|
;; |
87 |
;; Version 3.17 |
;; Version 3.17 |
88 |
;; - HTML export specifies character set depending on coding-system. |
;; - HTML export specifies character set depending on coding-system. |
89 |
;; |
;; |
217 |
|
|
218 |
;;; Customization variables |
;;; Customization variables |
219 |
|
|
220 |
(defvar org-version "3.17" |
(defvar org-version "3.18" |
221 |
"The version number of the file org.el.") |
"The version number of the file org.el.") |
222 |
(defun org-version () |
(defun org-version () |
223 |
(interactive) |
(interactive) |
1494 |
:group 'org-export |
:group 'org-export |
1495 |
:type 'boolean) |
:type 'boolean) |
1496 |
|
|
1497 |
|
(defcustom org-combined-agenda-icalendar-file "~/org.ics" |
1498 |
|
"The file name for the iCalendar file covering all agenda files. |
1499 |
|
This file is created with the command \\[org-export-icalendar-all-agenda-files]." |
1500 |
|
:group 'org-export |
1501 |
|
:type 'file) |
1502 |
|
|
1503 |
|
(defcustom org-icalendar-include-todo nil |
1504 |
|
"Non-nil means, export to iCalendar files should also cover TODO items." |
1505 |
|
:group 'org-export |
1506 |
|
:type 'boolean) |
1507 |
|
|
1508 |
|
;; FIXME: not yet used. |
1509 |
|
(defcustom org-icalendar-combined-name "OrgMode" |
1510 |
|
"Calendar name for the combined iCalendar representing all agenda files." |
1511 |
|
:group 'org-export |
1512 |
|
:type 'string) |
1513 |
|
|
1514 |
(defgroup org-faces nil |
(defgroup org-faces nil |
1515 |
"Faces for highlighting in Org-mode." |
"Faces for highlighting in Org-mode." |
1516 |
:tag "Org Faces" |
:tag "Org Faces" |
3200 |
;; Copied (with modifications) from planner.el by John Wiegley |
;; Copied (with modifications) from planner.el by John Wiegley |
3201 |
(save-excursion |
(save-excursion |
3202 |
(save-window-excursion |
(save-window-excursion |
3203 |
(calendar) |
(let ((view-diary-entries-initially nil)) |
3204 |
|
(calendar)) |
3205 |
(calendar-forward-day (- (time-to-days default-time) |
(calendar-forward-day (- (time-to-days default-time) |
3206 |
(calendar-absolute-from-gregorian |
(calendar-absolute-from-gregorian |
3207 |
(calendar-current-date)))) |
(calendar-current-date)))) |
3545 |
(d2 (time-to-days |
(d2 (time-to-days |
3546 |
(org-time-string-to-time (match-string 1))))) |
(org-time-string-to-time (match-string 1))))) |
3547 |
(setq diff (- d2 d1)))) |
(setq diff (- d2 d1)))) |
3548 |
(calendar) |
(let ((view-diary-entries-initially nil)) |
3549 |
|
(calendar)) |
3550 |
(calendar-goto-today) |
(calendar-goto-today) |
3551 |
(if (and diff (not arg)) (calendar-forward-day diff)))) |
(if (and diff (not arg)) (calendar-forward-day diff)))) |
3552 |
|
|
3651 |
(define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down) |
(define-key org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down) |
3652 |
(define-key org-agenda-mode-map [(right)] 'org-agenda-later) |
(define-key org-agenda-mode-map [(right)] 'org-agenda-later) |
3653 |
(define-key org-agenda-mode-map [(left)] 'org-agenda-earlier) |
(define-key org-agenda-mode-map [(left)] 'org-agenda-earlier) |
3654 |
|
(define-key org-agenda-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files) |
3655 |
(defvar org-agenda-keymap (copy-keymap org-agenda-mode-map) |
(defvar org-agenda-keymap (copy-keymap org-agenda-mode-map) |
3656 |
"Local keymap for agenda entries from Org-mode.") |
"Local keymap for agenda entries from Org-mode.") |
3657 |
|
|
3704 |
["Sunrise/Sunset" org-agenda-sunrise-sunset t] |
["Sunrise/Sunset" org-agenda-sunrise-sunset t] |
3705 |
["Holidays" org-agenda-holidays t] |
["Holidays" org-agenda-holidays t] |
3706 |
["Convert" org-agenda-convert-date t]) |
["Convert" org-agenda-convert-date t]) |
3707 |
|
["Create iCalendar file" org-export-icalendar-combine-agenda-files t] |
3708 |
"--" |
"--" |
3709 |
["Quit" org-agenda-quit t] |
["Quit" org-agenda-quit t] |
3710 |
["Exit and Release Buffers" org-agenda-exit t] |
["Exit and Release Buffers" org-agenda-exit t] |
4277 |
|
|
4278 |
(defun org-file-menu-entry (file) |
(defun org-file-menu-entry (file) |
4279 |
(vector file (list 'find-file file) t)) |
(vector file (list 'find-file file) t)) |
4280 |
|
;; FIXME: Maybe removed a buffer visited through the menu from |
4281 |
|
;; org-agenda-new-buffers, so that the buffer will not be removed |
4282 |
|
;; when exiting the agenda???? |
4283 |
|
|
4284 |
(defun org-get-all-dates (beg end &optional no-ranges force-today) |
(defun org-get-all-dates (beg end &optional no-ranges force-today) |
4285 |
"Return a list of all relevant day numbers from BEG to END buffer positions. |
"Return a list of all relevant day numbers from BEG to END buffer positions. |
5249 |
(let* ((day (or (get-text-property (point) 'day) |
(let* ((day (or (get-text-property (point) 'day) |
5250 |
(error "Don't know which date to open in calendar"))) |
(error "Don't know which date to open in calendar"))) |
5251 |
(date (calendar-gregorian-from-absolute day))) |
(date (calendar-gregorian-from-absolute day))) |
5252 |
(calendar) |
(let ((view-diary-entries-initially nil)) |
5253 |
|
(calendar)) |
5254 |
(calendar-goto-date date))) |
(calendar-goto-date date))) |
5255 |
|
|
5256 |
(defun org-calendar-goto-agenda () |
(defun org-calendar-goto-agenda () |
8059 |
"--" |
"--" |
8060 |
["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"]) |
["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"]) |
8061 |
("Rectangle" |
("Rectangle" |
8062 |
["Copy Rectangle" org-copy-special :active (org-at-table-p) :keys "C-c C-x M-w"] |
["Copy Rectangle" org-copy-special :active (org-at-table-p)] |
8063 |
["Cut Rectangle" org-cut-special :active (org-at-table-p) :keys "C-c C-x C-w"] |
["Cut Rectangle" org-cut-special :active (org-at-table-p)] |
8064 |
["Paste Rectangle" org-paste-special :active (org-at-table-p) :keys "C-c C-x C-y"] |
["Paste Rectangle" org-paste-special :active (org-at-table-p)] |
8065 |
["Fill Rectangle" org-table-wrap-region :active (org-at-table-p) :keys "C-c C-q"]) |
["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)]) |
8066 |
"--" |
"--" |
8067 |
["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="] |
["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="] |
8068 |
["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="] |
["Set Named Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="] |
8862 |
(coding-system (and (fboundp 'coding-system-get) |
(coding-system (and (fboundp 'coding-system-get) |
8863 |
(boundp 'buffer-file-coding-system) |
(boundp 'buffer-file-coding-system) |
8864 |
buffer-file-coding-system)) |
buffer-file-coding-system)) |
8865 |
|
(coding-system-for-write (or coding-system coding-system-for-write)) |
8866 |
|
(save-buffer-coding-system (or coding-system save-buffer-coding-system)) |
8867 |
(charset (and coding-system |
(charset (and coding-system |
8868 |
(coding-system-get coding-system 'mime-charset))) |
(coding-system-get coding-system 'mime-charset))) |
8869 |
table-open type |
table-open type |
9096 |
(if org-export-html-with-timestamp |
(if org-export-html-with-timestamp |
9097 |
(insert org-export-html-html-helper-timestamp)) |
(insert org-export-html-html-helper-timestamp)) |
9098 |
(insert "</body>\n</html>\n") |
(insert "</body>\n</html>\n") |
9099 |
|
(debug) |
9100 |
(normal-mode) |
(normal-mode) |
9101 |
(save-buffer) |
(save-buffer) |
9102 |
(goto-char (point-min))))) |
(goto-char (point-min))))) |
9440 |
string)) |
string)) |
9441 |
|
|
9442 |
|
|
9443 |
|
|
9444 |
|
|
9445 |
|
|
9446 |
|
(defun org-export-icalendar-this-file () |
9447 |
|
"Export current file as an iCalendar file. |
9448 |
|
The iCalendar file will be located in the same directory as the Org-mode |
9449 |
|
file, but with extension `.ics'." |
9450 |
|
(interactive) |
9451 |
|
(org-export-icalendar nil (buffer-file-name))) |
9452 |
|
|
9453 |
|
;;;###autoload |
9454 |
|
(defun org-export-icalendar-all-agenda-files () |
9455 |
|
"Export all files in `org-agenda-files' to iCalendar .ics files. |
9456 |
|
Each iCalendar file will be located in the same directory as the Org-mode |
9457 |
|
file, but with extension `.ics'." |
9458 |
|
(interactive) |
9459 |
|
(apply 'org-export-icalendar nil org-agenda-files)) |
9460 |
|
|
9461 |
|
;;;###autoload |
9462 |
|
(defun org-export-icalendar-combine-agenda-files () |
9463 |
|
"Export all files in `org-agenda-files' to a single combined iCalendar file. |
9464 |
|
The file is stored under the name `org-combined-agenda-icalendar-file'." |
9465 |
|
(interactive) |
9466 |
|
(apply 'org-export-icalendar t org-agenda-files)) |
9467 |
|
|
9468 |
|
(defun org-export-icalendar (combine &rest files) |
9469 |
|
"Create iCalendar files for all elements of FILES. |
9470 |
|
If COMBINE is non-nil, combine all calendar entries into a single large |
9471 |
|
file and store it under the name `org-combined-agenda-icalendar-file'." |
9472 |
|
(save-excursion |
9473 |
|
(let* (file ical-file ical-buffer category started org-agenda-new-buffers) |
9474 |
|
(when combine |
9475 |
|
(setq ical-file org-combined-agenda-icalendar-file |
9476 |
|
ical-buffer (org-get-agenda-file-buffer ical-file)) |
9477 |
|
(set-buffer ical-buffer) (erase-buffer)) |
9478 |
|
(while (setq file (pop files)) |
9479 |
|
(catch 'nextfile |
9480 |
|
(org-check-agenda-file file) |
9481 |
|
(unless combine |
9482 |
|
(setq ical-file (concat (file-name-sans-extension file) ".ics")) |
9483 |
|
(setq ical-buffer (org-get-agenda-file-buffer ical-file)) |
9484 |
|
(set-buffer ical-buffer) (erase-buffer)) |
9485 |
|
(set-buffer (org-get-agenda-file-buffer file)) |
9486 |
|
(setq category (or org-category |
9487 |
|
(file-name-sans-extension |
9488 |
|
(file-name-nondirectory (buffer-file-name))))) |
9489 |
|
(if (symbolp category) (setq category (symbol-name category))) |
9490 |
|
(let ((standard-output ical-buffer)) |
9491 |
|
(if combine |
9492 |
|
(and (not started) (setq started t) |
9493 |
|
(org-start-icalendar-file "OrgMode")) |
9494 |
|
(org-start-icalendar-file category)) |
9495 |
|
(org-print-icalendar-entries combine category) |
9496 |
|
(when (or (and combine (not files)) (not combine)) |
9497 |
|
(org-finish-icalendar-file) |
9498 |
|
(set-buffer ical-buffer) |
9499 |
|
(save-buffer) |
9500 |
|
(run-hooks 'org-after-save-iCalendar-file-hook))))) |
9501 |
|
(org-release-buffers org-agenda-new-buffers)))) |
9502 |
|
|
9503 |
|
(defvar org-after-save-iCalendar-file-hook nil |
9504 |
|
"Hook run after an iCalendar file has been saved. |
9505 |
|
The iCalendar buffer is still current when this hook is run. |
9506 |
|
A good way to use this is to tell a desktop calenndar application to re-read |
9507 |
|
the iCalendar file.") |
9508 |
|
|
9509 |
|
(defun org-print-icalendar-entries (&optional combine category) |
9510 |
|
"Print iCalendar entries for the current Org-mode file to `standard-output'. |
9511 |
|
When COMBINE is non nil, add the category to each line." |
9512 |
|
(let ((re2 (concat "--?-?\\(" org-ts-regexp "\\)")) |
9513 |
|
(dts (org-ical-ts-to-string |
9514 |
|
(format-time-string (cdr org-time-stamp-formats) (current-time)) |
9515 |
|
"DTSTART")) |
9516 |
|
hd ts ts2 state (inc t) pos scheduledp deadlinep donep tmp pri) |
9517 |
|
(save-excursion |
9518 |
|
(goto-char (point-min)) |
9519 |
|
(while (re-search-forward org-ts-regexp nil t) |
9520 |
|
(setq pos (match-beginning 0) |
9521 |
|
ts (match-string 0) |
9522 |
|
inc t |
9523 |
|
hd (org-get-heading)) |
9524 |
|
(if (looking-at re2) |
9525 |
|
(progn |
9526 |
|
(goto-char (match-end 0)) |
9527 |
|
(setq ts2 (match-string 1) inc nil)) |
9528 |
|
(setq ts2 ts |
9529 |
|
tmp (buffer-substring (max (point-min) |
9530 |
|
(- pos org-ds-keyword-length)) |
9531 |
|
pos) |
9532 |
|
deadlinep (string-match org-deadline-regexp tmp) |
9533 |
|
scheduledp (string-match org-scheduled-regexp tmp) |
9534 |
|
donep (org-entry-is-done-p))) |
9535 |
|
(if (or (string-match org-tr-regexp hd) |
9536 |
|
(string-match org-ts-regexp hd)) |
9537 |
|
(setq hd (replace-match "" t t hd))) |
9538 |
|
(if combine |
9539 |
|
(setq hd (concat hd " (category " category ")"))) |
9540 |
|
(if deadlinep (setq hd (concat "DL: " hd " This is a deadline"))) |
9541 |
|
(if scheduledp (setq hd (concat "S: " hd " Scheduled for this date"))) |
9542 |
|
(princ (format "BEGIN:VEVENT |
9543 |
|
%s |
9544 |
|
%s |
9545 |
|
SUMMARY:%s |
9546 |
|
END:VEVENT\n" |
9547 |
|
(org-ical-ts-to-string ts "DTSTART") |
9548 |
|
(org-ical-ts-to-string ts2 "DTEND" inc) |
9549 |
|
hd))) |
9550 |
|
(when org-icalendar-include-todo |
9551 |
|
(goto-char (point-min)) |
9552 |
|
(while (re-search-forward org-todo-line-regexp nil t) |
9553 |
|
(setq state (match-string 1)) |
9554 |
|
(unless (equal state org-done-string) |
9555 |
|
(setq hd (match-string 3)) |
9556 |
|
(if (string-match org-priority-regexp hd) |
9557 |
|
(setq pri (string-to-char (match-string 2 hd)) |
9558 |
|
hd (concat (substring hd 0 (match-beginning 1)) |
9559 |
|
(substring hd (- (match-end 1))))) |
9560 |
|
(setq pri org-default-priority)) |
9561 |
|
(setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri)) |
9562 |
|
(- org-lowest-priority ?A)))))) |
9563 |
|
|
9564 |
|
(princ (format "BEGIN:VTODO |
9565 |
|
%s |
9566 |
|
SUMMARY:%s |
9567 |
|
SEQUENCE:1 |
9568 |
|
PRIORITY:%d |
9569 |
|
END:VTODO\n" |
9570 |
|
dts hd pri)))))))) |
9571 |
|
|
9572 |
|
(defun org-start-icalendar-file (name) |
9573 |
|
"Start an iCalendar file by inserting the header." |
9574 |
|
(let ((user user-full-name) |
9575 |
|
(calname "something") |
9576 |
|
(name (or name "unknown")) |
9577 |
|
(timezone "FIXME")) |
9578 |
|
(princ |
9579 |
|
(format "BEGIN:VCALENDAR |
9580 |
|
VERSION:2.0 |
9581 |
|
X-WR-CALNAME:%s |
9582 |
|
PRODID:-//%s//Emacs with Org-mode//EN |
9583 |
|
X-WR-TIMEZONE:Europe/Amsterdam |
9584 |
|
CALSCALE:GREGORIAN\n" name user timezone)))) |
9585 |
|
|
9586 |
|
(defun org-finish-icalendar-file () |
9587 |
|
"Finish an iCalendar file by inserting the END statement." |
9588 |
|
(princ "END:VCALENDAR\n")) |
9589 |
|
|
9590 |
|
(defun org-ical-ts-to-string (s keyword &optional inc) |
9591 |
|
"Take a time string S and convert it to iCalendar format. |
9592 |
|
KEYWORD is added in front, to make a complete line like DTSTART.... |
9593 |
|
When INC is non-nil, increase the hour by two (if time string contains |
9594 |
|
a time), or the day by one (if it does not contain a time)." |
9595 |
|
(let ((t1 (org-parse-time-string s 'nodefault)) |
9596 |
|
t2 fmt have-time time) |
9597 |
|
(if (and (car t1) (nth 1 t1) (nth 2 t1)) |
9598 |
|
(setq t2 t1 have-time t) |
9599 |
|
(setq t2 (org-parse-time-string s))) |
9600 |
|
(let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2)) |
9601 |
|
(d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2))) |
9602 |
|
(when inc |
9603 |
|
(if have-time (setq h (+ 2 h)) (setq d (1+ d)))) |
9604 |
|
(setq time (encode-time s mi h d m y))) |
9605 |
|
(setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d")) |
9606 |
|
(concat keyword (format-time-string fmt time)))) |
9607 |
|
|
9608 |
|
|
9609 |
;;; Key bindings |
;;; Key bindings |
9610 |
|
|
9611 |
;; - Bindings in Org-mode map are currently |
;; - Bindings in Org-mode map are currently |
9707 |
(define-key org-mode-map "\C-c\C-x\C-a" 'org-export-as-ascii) |
(define-key org-mode-map "\C-c\C-x\C-a" 'org-export-as-ascii) |
9708 |
(define-key org-mode-map "\C-c\C-xv" 'org-export-copy-visible) |
(define-key org-mode-map "\C-c\C-xv" 'org-export-copy-visible) |
9709 |
(define-key org-mode-map "\C-c\C-x\C-v" 'org-export-copy-visible) |
(define-key org-mode-map "\C-c\C-x\C-v" 'org-export-copy-visible) |
9710 |
;; OPML support is only planned |
;; OPML support is only an option for the future |
9711 |
;(define-key org-mode-map "\C-c\C-xo" 'org-export-as-opml) |
;(define-key org-mode-map "\C-c\C-xo" 'org-export-as-opml) |
9712 |
;(define-key org-mode-map "\C-c\C-x\C-o" 'org-export-as-opml) |
;(define-key org-mode-map "\C-c\C-x\C-o" 'org-export-as-opml) |
9713 |
|
(define-key org-mode-map "\C-c\C-xi" 'org-export-icalendar-this-file) |
9714 |
|
(define-key org-mode-map "\C-c\C-x\C-i" 'org-export-icalendar-all-agenda-files) |
9715 |
|
(define-key org-mode-map "\C-c\C-xc" 'org-export-icalendar-combine-agenda-files) |
9716 |
|
(define-key org-mode-map "\C-c\C-x\C-c" 'org-export-icalendar-combine-agenda-files) |
9717 |
(define-key org-mode-map "\C-c\C-xt" 'org-insert-export-options-template) |
(define-key org-mode-map "\C-c\C-xt" 'org-insert-export-options-template) |
9718 |
(define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section) |
(define-key org-mode-map "\C-c:" 'org-toggle-fixed-width-section) |
9719 |
(define-key org-mode-map "\C-c\C-xh" 'org-export-as-html) |
(define-key org-mode-map "\C-c\C-xh" 'org-export-as-html) |
10146 |
["HTML and Open" org-export-as-html-and-open t] |
["HTML and Open" org-export-as-html-and-open t] |
10147 |
; ["OPML" org-export-as-opml nil] |
; ["OPML" org-export-as-opml nil] |
10148 |
"--" |
"--" |
10149 |
|
["iCalendar this file" org-export-icalendar-this-file t] |
10150 |
|
["iCalendar all agenda files" org-export-icalendar-all-agenda-files |
10151 |
|
:active t :keys "C-c C-x C-i"] |
10152 |
|
["iCalendar combined" org-export-icalendar-combine-agenda-files t] |
10153 |
|
"--" |
10154 |
["Option Template" org-insert-export-options-template t] |
["Option Template" org-insert-export-options-template t] |
10155 |
["Toggle Fixed Width" org-toggle-fixed-width-section t]) |
["Toggle Fixed Width" org-toggle-fixed-width-section t]) |
10156 |
"--" |
"--" |