diff options
Diffstat (limited to 'lisp/org')
-rw-r--r-- | lisp/org/ChangeLog | 480 | ||||
-rw-r--r-- | lisp/org/org-agenda.el | 156 | ||||
-rw-r--r-- | lisp/org/org-archive.el | 37 | ||||
-rw-r--r-- | lisp/org/org-bbdb.el | 125 | ||||
-rw-r--r-- | lisp/org/org-bibtex.el | 3 | ||||
-rw-r--r-- | lisp/org/org-clock.el | 150 | ||||
-rw-r--r-- | lisp/org/org-colview.el | 136 | ||||
-rw-r--r-- | lisp/org/org-compat.el | 4 | ||||
-rw-r--r-- | lisp/org/org-exp.el | 1165 | ||||
-rw-r--r-- | lisp/org/org-export-latex.el | 37 | ||||
-rw-r--r-- | lisp/org/org-faces.el | 39 | ||||
-rw-r--r-- | lisp/org/org-gnus.el | 3 | ||||
-rw-r--r-- | lisp/org/org-info.el | 3 | ||||
-rw-r--r-- | lisp/org/org-irc.el | 3 | ||||
-rw-r--r-- | lisp/org/org-jsinfo.el | 5 | ||||
-rw-r--r-- | lisp/org/org-mac-message.el | 3 | ||||
-rw-r--r-- | lisp/org/org-macs.el | 7 | ||||
-rw-r--r-- | lisp/org/org-mew.el | 3 | ||||
-rw-r--r-- | lisp/org/org-mhe.el | 17 | ||||
-rw-r--r-- | lisp/org/org-mouse.el | 4 | ||||
-rw-r--r-- | lisp/org/org-publish.el | 88 | ||||
-rw-r--r-- | lisp/org/org-remember.el | 253 | ||||
-rw-r--r-- | lisp/org/org-rmail.el | 3 | ||||
-rw-r--r-- | lisp/org/org-table.el | 119 | ||||
-rw-r--r-- | lisp/org/org-vm.el | 3 | ||||
-rw-r--r-- | lisp/org/org-wl.el | 3 | ||||
-rw-r--r-- | lisp/org/org.el | 1241 |
27 files changed, 3213 insertions, 877 deletions
diff --git a/lisp/org/ChangeLog b/lisp/org/ChangeLog new file mode 100644 index 00000000000..a2c5e7044d4 --- /dev/null +++ b/lisp/org/ChangeLog @@ -0,0 +1,480 @@ +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-colview.el (org-columns-next-allowed-value): Bug fix. + + * org-colview-xemacs.el (org-columns-next-allowed-value): Bug fix. + + * org-agenda.el (org-agenda-get-closed): Get the end time into the + agenda prefix as well. + + * org-publish.el (org-publish-org-index): Make a properly indented + list. + + * org.el (org-calendar-agenda-action-key): New option. + (org-get-cursor-date): New function. + (org-mark-entry-for-agenda-action): New command. + (org-overriding-default-time): New variable. + (org-read-date): Respect `org-overriding-default-time'. + + * org-remember.el (org-remember-apply-template): Respect the + ovverriding default time. + + * org-agenda.el (org-agenda-action-marker): New variable. + (org-agenda-action): New command. + (org-agenda-do-action): New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-schedule, org-deadline): Protect scheduled and + deadline tasks against changes that accidently remove the + repeater. Also show a message with the new date when done. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-beginning-of-line): Cater for the case when there + are tags but no headline text. + (org-align-tags-here): Convert to tabs only when indent-tabs-mode + it set. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-mhe.el (org-mhe-get-message-folder-from-index): Make sure + the return value is nil instead of "nil" when there is no match. + + * org-exp.el (org-insert-centered): Use fill-column instead of + 80. + (org-export-as-ascii): Use string-width to measure the width of + the heading. + + * org.el (org-diary-to-ical-string): No longer kill buffer + FROMBUF, this is now done by the caller. + + * org-exp.el (org-print-icalendar-entries): Move the call to + `org-diary-to-ical-string' out of the loop, and kill the buffer + afterwords. + + * org-remember.el (org-remember-visit-immediately): Position + cursor after moving to the note. + (org-remember-apply-template): Use a text property to record the + cursor position. + (org-remember-handler): Align tags after pasting the note. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-bbdb.el (org-bbdb-follow-anniversary-link): New function. + + * org-agenda.el (org-agenda-open-link): If there is an + org-bbdb-name property in the current line, jump to that bbdb + entry. + + * org-bbdb.el (org-bbdb-anniversaries): Add the bbdb-name as a + text property, so that the agenda knows where this entry comes + from. + + * org-agenda.el (org-agenda-clock-in): Fixed bug in the + interaction between clocking-in from the agenda, and automatic + task state switching. + + * org-macs.el (org-with-point-at): Bug fix in macro defintion. + + * org.el (org-beginning-of-line, org-end-of-line): Make sure the + zmacs-region stays after this command in XEmacs. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-scan-tags): Allow new values for ACTION parameter. + + * org-remember.el (org-remember-templates): Fix bug in + customization type definition. + + * org.el (org-map-entries): New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-agenda.el (org-agenda-skip-comment-trees): New option. + (org-agenda-skip): Respect `org-agenda-skip-comment-trees'. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-remember.el (org-jump-to-target-location): New variable. + (org-remember-apply-template): Set + `org-remember-apply-template' if requested by template. + (org-remember-handler): Start an idle timer to jump to + remember location. + + * org-exp.el (org-get-current-options): Add the FILETAGS setting. + + * org.el (org-set-regexps-and-options): Fix bug with parsing of + file tags. + (org-get-tags-at): Add the content of `org-file-tags'. + + * org-exp.el (org-export-handle-comments): Fix bug with several + comment lines after each other. + (org-number-to-roman, org-number-to-counter): New functions. + (org-export-section-number-format): New option. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-exp.el (org-export-protect-examples): Catch the case of a + missing end_example line. + + * org.el (org-set-regexps-and-options): Set `org-file-properties' and + `org-file-tags' to nil. + + * org-colview.el (org-columns-next-allowed-value): Handle next + argument NTH to directly select a value. + + * org-colview-xemacs.el (org-columns-next-allowed-value): Handle next + argument NTH to directly select a value. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-agenda.el (org-agenda-scheduled-leaders): Fix docstring. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-columns-ellipses): New option. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-colview.el (org-columns-add-ellipses): New function. + (org-columns-compact-links): New function. + (org-columns-cleanup-item): Call `org-columns-compact-links'. + (org-columns-display-here): Call `org-agenda-columns-cleanup-item' + when in agenda. + (org-columns-edit-value): Fixed bug with editing values from + agenda column view. + (org-columns-redo): Also redo the agenda itself. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-agenda.el (org-agenda-columns-remove-prefix-from-item): New + option. + + * org-colview.el (org-agenda-columns-cleanup-item): New function. + + * org-exp.el (org-export-ascii-preprocess): Renamed from + `org-export-ascii-clean-string'. + (org-export-kill-licensed-text) + (org-export-define-heading-targets) + (org-export-handle-invisible-targets) + (org-export-target-internal-links) + (org-export-remove-or-extract-drawers) + (org-export-remove-archived-trees) + (org-export-protect-quoted-subtrees) + (org-export-protect-verbatim, org-export-protect-examples) + (org-export-select-backend-specific-text) + (org-export-mark-blockquote-and-verse) + (org-export-remove-comment-blocks-and-subtrees) + (org-export-handle-comments, org-export-mark-radio-links) + (org-export-remove-special-table-lines) + (org-export-normalize-links) + (org-export-concatenate-multiline-links) + (org-export-concatenate-multiline-emphasis): New functions, + obtained from spliiting the export preprocessor. + + * org-table.el (org-table-recalculate): Improve error message if + the row number is invalid. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-archive.el (org-archive-save-context-info): Fix bugs in + customization setup and docstring. + + * org-exp.el (org-export-html-style): Changed the size of in the + <pre> element to 90%. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-find-src-example-start): Function removed. + (org-edit-src-find-region-and-lang): New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-edit-src-exit): New function. + (org-exit-edit-mode): New minor mode. + + * org-exp.el (org-export-preprocess-string): Fix bug with removing + comment-like lines from protected examples. + + * org.el (org-edit-src-example, org-find-src-example-start) + (org-protect-source-example, org-edit-special): New functions. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-publish.el (org-publish-project-alist): Fix typo in + docstring. + (org-publish-project-alist): Handle :index-title property. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-export-latex.el (org-export-as-latex): Make sure region + bounds are correct. Parse subtree properties relating to export. + + * org-exp.el (org-export-add-options-to-plist): New function. + (org-infile-export-plist): Use `org-export-add-options-to-plist'. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-default-properties): Add EXPORT_FILE_NAME and + EXPORT_TITLE. + + * org-exp.el (org-export-get-title-from-subtree) + (org-export-as-ascii, org-export-as-html): Make sure the original + region-beginning and region-end are used, even after moving + point. + (org-export-get-title-from-subtree): Also try the EXPORT_TITLE + property. + + * org-remember.el (org-remember-last-stored-marker): New variable. + (org-remember-goto-last-stored): Use `org-goto-marker-or-bmk'. + (org-remember-handler): Also use marker to remember + last-stored position. + + * org.el (org-goto-marker-or-bmk): New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-file-properties): Renamed from `org-local-properties'. + (org-scan-tags): Take file tags into account. + (org-tags-match-list-sublevels): Default changed to t. + + * org-exp.el (org-export-as-html): Close paragraph after a + footnote. + + * org.el (org-update-parent-todo-statistics): New function. + + * org-exp.el (org-icalendar-store-UID): New option. + (org-icalendar-force-UID): Option removed. + (org-print-icalendar-entries): IMplement UIDs. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-mhe.el (org-mhe-follow-link): Fix bug in mhe searches. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-faces.el (org-column): Document how this face is being used + and why sometimes the background faces shine through. + + * org-mhe.el (org-mhe-follow-link): Improve handling of searches. + + * org-publish.el (org-publish-attachment): Create publishing + directory if it does not yet exist. + + * org-table.el (org-calc-default-modes): Change default number + format to (float 8). + + * org.el (org-olpath-completing-read): New function. + (org-time-clocksum-format): New option. + (org-minutes-to-hh:mm-string): Use `org-time-clocksum-format'. + + * org-clock.el (org-clock-display, org-clock-out) + (org-update-mode-line): Use `org-time-clocksum-format'. + + * org-colview-xemacs.el (org-columns-number-to-string): Use + `org-time-clocksum-format'. + + * org-colview.el (org-columns-number-to-string): Use + `org-time-clocksum-format'. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-id.el: New file, move from contrib to core. + + * org-exp.el (org-icalendar-force-UID): New option. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-exp.el (org-print-icalendar-entries): Make sure DTEND is + shifted by one day if theere is a date range without an end + time. + + * org.el (org-try-structure-completion): New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-set-font-lock-defaults): Improve fontification of + description lists. + (org-insert-item): Handle description lists. + (org-adaptive-fill-function): Improve auto indentation in + description lists. + + * org-exp.el (org-export-as-html, org-export-preprocess-string): + Implement VERSE environment. + (org-export-preprocess-string): Implement the COMMENT + environment. + + * org-export-latex.el (org-export-latex-preprocess): Implement + VERSE environment. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-jsinfo.el (org-infojs-opts-table): Add entry for FIXED_TOC + option. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-table.el (orgtbl-to-tsv, orgtbl-to-csv): New functions. + + * org.el (org-quote-csv-field): New functions. + + * org-table.el (org-table-export-default-format): Remove :splice + from default format, we get the same effect by not specifying + :tstart and :tend. + (org-table-export): Improve setup, distinguish better between + interactive and non-interactive use, allow specifying the format + on the fly, better protection against wrong file names. + (orgtbl-to-generic): Fix documentation. Do not require :tstart + and :tend when :splice is omitted. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-clock.el (org-clock-select-task): Make sure the selection + letters are 1-9 and A-Z, no special characters. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-exp.el (org-export-htmlize): New group. + (org-export-htmlize-output-type) + (org-export-htmlize-css-font-prefix): New options. + (org-export-htmlize-region-for-paste): New function. + (org-export-htmlize-generate-css): New command. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-set-visibility-according-to-property): New function. + (org-ctrl-c-ctrl-c): Do not restart org-mode, just get the options + and compute the regular expressions, and update font-lock. + (org-property-re): Allow a dash in property names. + + * org-archive.el (org-extract-archive-file): Insert the file name + without the path into the format, to allow the location format to + contain a subdirectory. + + * org-agenda.el (org-agenda-post-command-hook): If point is at end + of buffer, and the `org-agenda-type' property undefined, use the + value from the character before. + + * org.el (org-add-planning-info): Don't let indentation for + would-be timestamp become extra whitespace at the end of headline. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-remove-double-quotes, org-file-contents): New + functions. + + * org-exp.el (org-infile-export-plist): Also parse the + contents of #+SETUPFILE files, recursively. + + * org.el (org-set-regexps-and-options): Also parse the + contents of #+SETUPFILE files, recursively. + + * org-exp.el (org-export-handle-include-files): New function. + (org-export-preprocess-string): Call + `org-export-handle-include-files'. + + * org.el (org-delete-property-globally) + (org-delete-property, org-set-property): Ignore case during + completion. + (org-set-property): Use `org-completing-read' instead of + `completing-read'. + + * org.el (org-complete-expand-structure-template): New, + experimental function. + (org-structure-template-alist): New, experimental option. + (org-complete): Call `org-complete-expand-structure-template'. + +2008-06-17 Bastien Guerry <bzg@altern.org> + + * org-export-latex.el (org-export-latex-preprocess): Added + support for blockquotes. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-read-date-analyze): Catch the case where only a + weekday is given. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-set-font-lock-defaults): Make the description + tag bold. + + * org-exp.el (org-export-as-html, org-close-li): Implement + description lists. + +2008-06-17 Jason Riedy <jason@acm.org> + + * org-table.el (*orgtbl-default-fmt*): New variable. + (orgtbl-format-line): Use the value of *orgtbl-default-fmt* + when there is no other fmt available. + + (orgtbl-to-generic): Allow an explicitly nil :tstart or + :tend to suppress the appropriate string. + + (orgtbl-to-orgtbl): New function for translating to another orgtbl + table. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org.el (org-read-date-analyze): "." as an alias for "+0" in + read date. + + * org-clock.el (org-clock-save-markers-for-cut-and-paste): + New function. + + * org-agenda.el (org-agenda-save-markers-for-cut-and-paste): + New function. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-clock.el (org-clock-find-position): Don't include notes + into clock drawer. + + * org-archive.el (org-archive-subtree): No longer remove an + extra line after cutting the subtree. `org-cut-subtree' already + takes care of this. + + * org-remember.el (org-remember-handler): Only kill the target + buffer if it does not contain the running clock. + + * org.el (org-markers-to-move): New variable. + (org-save-markers-in-region, org-check-and-save-marker) + (org-reinstall-markers-in-region): New function. + (org-move-subtree-down, org-copy-subtree): Remember relative + marker positions before cutting. + (org-move-subtree-down, org-paste-subtree): Restore relative + marker positions after pasting. + + * org-remember.el (org-remember-clock-out-on-exit): New option. + (org-remember-finalize): Clock out only if the setting in + `org-remember-clock-out-on-exit' requires it. + (org-remember-handler): Do the cleanup in the buffer, to make sure + that the clock marker remains in tact. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-clock.el (org-clock-goto): Widen buffer if necessary. + (org-clock-in): Make sure that also tasks outside the narrowed + region will be clocked in correctly. + (org-clock-insert-selection-line): Widen the buffer so that we can + find the correct task heading. + + * org.el (org-base-buffer): New function. + + * org-exp.el (org-icalendar-cleanup-string): Make sure '," + and ";" are escaped. + (org-print-icalendar-entries): Also apply + `org-icalendar-cleanup-string' to the headline, not only to the + summary property. + +2008-06-17 Carsten Dominik <dominik@science.uva.nl> + + * org-exp.el (org-export-preprocess-hook): New hook. + (org-export-preprocess-string): Call + `org-export-preprocess-hook'. + + * org.el (org-font-lock-hook): New variable. + (org-font-lock-hook): New function. + (org-set-font-lock-defaults): Call `org-font-lock-hook'. + diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index 0f8fcf5a377..32efe5d8413 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -1,4 +1,4 @@ -;;; org-agenda.el --- The table editor for Org-mode +;;; org-agenda.el --- Dynamic task and appointment lists for Org ;; Copyright (C) 2004, 2005, 2006, 2007, 2008 ;; Free Software Foundation, Inc. @@ -6,7 +6,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -34,7 +34,7 @@ (eval-when-compile (require 'calendar)) -(declare-function add-to-diary-list "diary-lib" +(declare-function diary-add-to-list "diary-lib" (date string specifier &optional marker globcolor literal)) (declare-function calendar-absolute-from-iso "cal-iso" (date)) (declare-function calendar-astro-date-string "cal-julian" (&optional date)) @@ -392,6 +392,12 @@ or `C-c a #' to produce the list." :tag "Org Agenda Skip" :group 'org-agenda) +(defcustom org-agenda-skip-comment-trees t + "Non-nil means, skip trees that start with teh COMMENT keyword. +When nil, these trees are also scand by agenda commands." + :group 'org-agenda-skip + :type 'boolean) + (defcustom org-agenda-todo-list-sublevels t "Non-nil means, check also the sublevels of a TODO entry for TODO entries. When nil, the sublevels of a TODO entry are not checked, resulting in @@ -464,7 +470,6 @@ N days, just insert a special line indicating the size of the gap." (const :tag "All" t) (number :tag "at most"))) - (defgroup org-agenda-startup nil "Options concerning initial settings in the Agenda in Org Mode." :tag "Org Agenda Startup" @@ -676,7 +681,7 @@ symbols specifying conditions when the grid should be displayed: today show grid on current date, independent of daily/weekly display require-timed show grid only if at least one item has a time specification -The second item is a string which will be places behing the grid time. +The second item is a string which will be placed behind the grid time. The third item is a list of integers, indicating the times that should have a grid line." @@ -849,8 +854,10 @@ to occupy a fixed space in the agenda display." "Text preceeding scheduled items in the agenda view. This is a list with two strings. The first applies when the item is scheduled on the current day. The second applies when it has been scheduled -previously, it may contain a %d to capture how many days ago the item was -scheduled." +previously, it may contain a %d indicating that this is the nth time that +this item is scheduled, due to automatic rescheduling of unfinished items +for the following day. So this number is one larger than the number of days +that passed since this item was scheduled first." :group 'org-agenda-line-format :type '(list (string :tag "Scheduled today ") @@ -946,6 +953,16 @@ a names face, or a list like `(:background \"Red\")'." :group 'org-agenda-column-view :type 'boolean) +(defcustom org-agenda-columns-remove-prefix-from-item t + "Non-nil means, remove the prefix from a headline for agenda column view. +The special ITEM field in the columns format contains the current line, with +all information shown in other columns (like the TODO state or a tag). +When this variable is non-nil, also the agenda prefix will be removed from +the content of the ITEM field, to make sure as much as possible of the +headline can be shown in the limited width of the field." + :group 'org-agenda + :type 'boolean) + (defcustom org-agenda-columns-compute-summary-properties t "Non-nil means, recompute all summary properties before column view. When column view in the agenda is listing properties that have a summary @@ -1071,6 +1088,8 @@ The following commands are available: (org-defkey org-agenda-mode-map "y" 'org-agenda-year-view) (org-defkey org-agenda-mode-map "\C-c\C-z" 'org-agenda-add-note) (org-defkey org-agenda-mode-map "z" 'org-agenda-add-note) +(org-defkey org-agenda-mode-map "k" 'org-agenda-action) +(org-defkey org-agenda-mode-map "\C-c\C-x\C-k" 'org-agenda-action) (org-defkey org-agenda-mode-map [(shift right)] 'org-agenda-date-later) (org-defkey org-agenda-mode-map [(shift left)] 'org-agenda-date-earlier) (org-defkey org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later) @@ -1177,6 +1196,11 @@ The following commands are available: ["Schedule" org-agenda-schedule t] ["Set Deadline" org-agenda-deadline t] "--" + ["Mark item" org-agenda-action :active t :keys "k m"] + ["Show mark item" org-agenda-action :active t :keys "k v"] + ["Schedule marked item" org-agenda-action :active t :keys "k s"] + ["Set Deadline for marked item" org-agenda-action :active t :keys "k d"] + "--" ["Change Date +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)] ["Change Date -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)] ["Change Date to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)]) @@ -2012,7 +2036,8 @@ continue from there." (get-text-property p :org-archived) (org-end-of-subtree t) (throw :skip t)) - (and (get-text-property p :org-comment) + (and org-agenda-skip-comment-trees + (get-text-property p :org-comment) (org-end-of-subtree t) (throw :skip t)) (if (equal (char-after p) ?#) (throw :skip t)) @@ -2045,6 +2070,11 @@ no longer in use." (while org-agenda-markers (move-marker (pop org-agenda-markers) nil))) +(defun org-agenda-save-markers-for-cut-and-paste (beg end) + "Save relative positions of markers in region." + (mapc (lambda (m) (org-check-and-save-marker m beg end)) + org-agenda-markers)) + ;;; Agenda timeline (defvar org-agenda-only-exact-dates nil) ; dynamically scoped @@ -2425,6 +2455,7 @@ in `org-agenda-text-search-extra-files'." 'done-face 'org-done 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'mouse-face 'highlight 'keymap org-agenda-keymap 'help-echo (format "mouse-2 or RET jump to location"))) @@ -2539,6 +2570,7 @@ in `org-agenda-text-search-extra-files'." (org-add-props txt props 'org-marker marker 'org-hd-marker marker 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'priority 1000 'org-category category 'type "search") (push txt ee) @@ -3065,6 +3097,7 @@ the documentation of `org-diary'." 'done-face 'org-done 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'mouse-face 'highlight 'keymap org-agenda-keymap 'help-echo @@ -3123,6 +3156,7 @@ the documentation of `org-diary'." (let* ((props (list 'face nil 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'mouse-face 'highlight 'keymap org-agenda-keymap 'help-echo @@ -3255,6 +3289,7 @@ the documentation of `org-diary'." (let* ((props (list 'mouse-face 'highlight 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'keymap org-agenda-keymap 'help-echo (format "mouse-2 or RET jump to org file %s" @@ -3269,7 +3304,7 @@ the documentation of `org-diary'." (list 0 0 0 (nth 1 date) (car date) (nth 2 date)))) 1 11)))) marker hdmarker priority category tags closedp - ee txt timestr) + ee txt timestr rest) (goto-char (point-min)) (while (re-search-forward regexp nil t) (catch :skip @@ -3280,9 +3315,15 @@ the documentation of `org-diary'." timestr (buffer-substring (match-beginning 0) (point-at-eol)) ;; donep (org-entry-is-done-p) ) - (if (string-match "\\]" timestr) - ;; substring should only run to end of time stamp - (setq timestr (substring timestr 0 (match-end 0)))) + (when (string-match "\\]" timestr) + ;; substring should only run to end of time stamp + (setq rest (substring timestr (match-end 0)) + timestr (substring timestr 0 (match-end 0))) + (if (and (not closedp) + (string-match "\\([0-9]\\{1,2\\}:[0-9]\\{2\\}\\)\\]" rest)) + (setq timestr (concat (substring timestr 0 -1) + "-" (match-string 1 rest) "]")))) + (save-excursion (if (re-search-backward "^\\*+ " nil t) (progn @@ -3309,6 +3350,7 @@ the documentation of `org-diary'." (let* ((props (list 'mouse-face 'highlight 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'keymap org-agenda-keymap 'help-echo (format "mouse-2 or RET jump to org file %s" @@ -3394,6 +3436,7 @@ FRACTION is what fraction of the head-warning time has passed." "Return the scheduled information for agenda display." (let* ((props (list 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'done-face 'org-done 'mouse-face 'highlight 'keymap org-agenda-keymap @@ -3469,6 +3512,7 @@ FRACTION is what fraction of the head-warning time has passed." (let* ((props (list 'face nil 'org-not-done-regexp org-not-done-regexp 'org-todo-regexp org-todo-regexp + 'org-complex-heading-regexp org-complex-heading-regexp 'mouse-face 'highlight 'keymap org-agenda-keymap 'help-echo @@ -4137,12 +4181,12 @@ written as 2-digit years." (setq org-agenda-ndays 7) (org-agenda-change-time-span 'week iso-week)) (defun org-agenda-month-view (&optional month) - "Switch to daily view for agenda. + "Switch to monthly view for agenda. With argument MONTH, switch to that month." (interactive "P") (org-agenda-change-time-span 'month month)) (defun org-agenda-year-view (&optional year) - "Switch to daily view for agenda. + "Switch to yearly view for agenda. With argument YEAR, switch to that year. If MONTH has more then 2 digits, only the last two encode the month. Any digits before this encode a year. So 200712 means @@ -4331,7 +4375,10 @@ so that the date SD will be in that range." (defun org-agenda-post-command-hook () (and (eolp) (not (bolp)) (backward-char 1)) - (setq org-agenda-type (get-text-property (point) 'org-agenda-type)) + (setq org-agenda-type + (or (get-text-property (point) 'org-agenda-type) + (get-text-property (max (point-min) (1- (point))) + 'org-agenda-type))) (if (and org-agenda-follow-mode (get-text-property (point) 'org-marker)) (org-agenda-show))) @@ -4890,6 +4937,69 @@ be used to request time specification in the time stamp." (org-agenda-show-new-time marker ts "S")) (message "Deadline for this item set to %s" ts))) +(defun org-agenda-action () + "Select entry for agenda action, or execute an agenda action. +This command prompts for another letter. Valid inputs are: + +m Mark the entry at point for an agenda action +s Schedule the marked entry to the date at the cursor +d Set the deadline of the marked entry to the date at the cursor +r Call `org-remember' with cursor date as the default date +SPC Show marked entry in other window +TAB Visit marked entry in other window + +The cursor may be at a date in the calendar, or in the Org agenda." + (interactive) + (let (pos ans) + (message "Select action: [m]ark | [s]chedule [d]eadline [r]emember [ ]show") + (setq ans (read-char-exclusive)) + (cond + ((equal ans ?m) + ;; Mark this entry + (if (eq major-mode 'org-agenda-mode) + (let ((m (or (get-text-property (point) 'org-hd-marker) + (get-text-property (point) 'org-marker)))) + (if m + (progn + (move-marker org-agenda-action-marker + (marker-position m) (marker-buffer m)) + (message "Entry marked for action; press `k' at desired date in agenda or calendar")) + (error "Don't know which entry to mark"))) + (error "This command works only in the agenda"))) + ((equal ans ?s) + (org-agenda-do-action '(org-schedule nil org-overriding-default-time))) + ((equal ans ?d) + (org-agenda-do-action '(org-deadline nil org-overriding-default-time))) + ((equal ans ?r) + (org-agenda-do-action '(org-remember) t)) + ((equal ans ?\ ) + (let ((cw (selected-window))) + (org-switch-to-buffer-other-window + (marker-buffer org-agenda-action-marker)) + (goto-char org-agenda-action-marker) + (org-show-context 'agenda) + (select-window cw))) + ((equal ans ?\C-i) + (org-switch-to-buffer-other-window + (marker-buffer org-agenda-action-marker)) + (goto-char org-agenda-action-marker) + (org-show-context 'agenda)) + (t (error "Invalid agenda action %c" ans))))) + +(defun org-agenda-do-action (form &optional current-buffer) + "Evaluate FORM at the entry pointed to by `org-agenda-action-marker'." + (let ((org-overriding-default-time (org-get-cursor-date))) + (if current-buffer + (eval form) + (if (not (marker-buffer org-agenda-action-marker)) + (error "No entry has bee selected for agenda action") + (with-current-buffer (marker-buffer org-agenda-action-marker) + (save-excursion + (save-restriction + (widen) + (goto-char org-agenda-action-marker) + (eval form)))))))) + (defun org-agenda-clock-in (&optional arg) "Start the clock on the currently selected item." (interactive "P") @@ -4898,12 +5008,20 @@ be used to request time specification in the time stamp." (org-clock-in arg) (let* ((marker (or (get-text-property (point) 'org-marker) (org-agenda-error))) - (pos (marker-position marker))) + (hdmarker (or (get-text-property (point) 'org-hd-marker) + marker)) + (pos (marker-position marker)) + newhead) (org-with-remote-undo (marker-buffer marker) (with-current-buffer (marker-buffer marker) (widen) (goto-char pos) - (org-clock-in arg)))))) + (org-show-context 'agenda) + (org-show-entry) + (org-cycle-hide-drawers 'children) + (org-clock-in arg) + (setq newhead (org-get-heading))) + (org-agenda-change-all-lines newhead hdmarker t))))) (defun org-agenda-clock-out (&optional arg) "Stop the currently running clock." @@ -5141,6 +5259,8 @@ belonging to the \"Work\" category." (provide 'org-agenda) +;; arch-tag: 77f7565d-7c4b-44af-a2df-9f6f7070cff1 + ;;; org-agenda.el ends here -;; arch-tag: 77f7565d-7c4b-44af-a2df-9f6f7070cff1 + diff --git a/lisp/org/org-archive.el b/lisp/org/org-archive.el index 9f8e57d6898..3d7d06f3453 100644 --- a/lisp/org/org-archive.el +++ b/lisp/org/org-archive.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -64,8 +64,8 @@ This variable can be a list of any of the following symbols: time The time of archiving. file The file where the entry originates. -itags The local tags, in the headline of the subtree. -ltags The tags the subtree inherits from further up the hierarchy. +ltags The local tags, in the headline of the subtree. +itags The tags the subtree inherits from further up the hierarchy. todo The pre-archive TODO state. category The category, taken from file name or #+CATEGORY lines. olpath The outline path to the item. These are all headlines above @@ -80,7 +80,7 @@ information." (const :tag "File" file) (const :tag "Category" category) (const :tag "TODO state" todo) - (const :tag "TODO state" priority) + (const :tag "Priority" priority) (const :tag "Inherited tags" itags) (const :tag "Outline path" olpath) (const :tag "Local tags" ltags))) @@ -135,14 +135,19 @@ archive file is." files)) (defun org-extract-archive-file (&optional location) + "Extract and expand the file name from archive LOCATION. +if LOCATION is not given, the value of `org-archive-location' is used." (setq location (or location org-archive-location)) (if (string-match "\\(.*\\)::\\(.*\\)" location) (if (= (match-beginning 1) (match-end 1)) (buffer-file-name) (expand-file-name - (format (match-string 1 location) buffer-file-name))))) + (format (match-string 1 location) + (file-name-nondirectory buffer-file-name)))))) (defun org-extract-archive-heading (&optional location) + "Extract the heading from archive LOCATION. +if LOCATION is not given, the value of `org-archive-location' is used." (setq location (or location org-archive-location)) (if (string-match "\\(.*\\)::\\(.*\\)" location) (match-string 2 location))) @@ -180,7 +185,7 @@ this heading." (current-time))) category todo priority ltags itags ;; end of variables that will be used for saving context - location afile heading buffer level newfile-p) + location afile heading buffer level newfile-p visiting) ;; Find the local archive location (setq location (org-get-local-archive-location) @@ -191,7 +196,8 @@ this heading." (if (> (length afile) 0) (setq newfile-p (not (file-exists-p afile)) - buffer (find-file-noselect afile)) + visiting (find-buffer-visiting afile) + buffer (or visiting (find-file-noselect afile))) (setq buffer (current-buffer))) (unless buffer (error "Cannot access file \"%s\"" afile)) @@ -213,9 +219,9 @@ this heading." (setq ltags (mapconcat 'identity ltags " ") itags (mapconcat 'identity itags " ")) ;; We first only copy, in case something goes wrong - ;; we need to protect this-command, to avoid kill-region sets it, + ;; we need to protect `this-command', to avoid kill-region sets it, ;; which would lead to duplication of subtrees - (let (this-command) (org-copy-subtree)) + (let (this-command) (org-copy-subtree 1 nil t)) (set-buffer buffer) ;; Enforce org-mode for the archive buffer (if (not (org-mode-p)) @@ -283,12 +289,18 @@ this heading." (org-entry-put (point) n v))))) ;; Save and kill the buffer, if it is not the same buffer. - (if (not (eq this-buffer buffer)) - (progn (save-buffer) (kill-buffer buffer))))) + (when (not (eq this-buffer buffer)) + (save-buffer) + ;; Check if it is OK to kill the buffer + (unless + (or visiting + (equal (marker-buffer org-clock-marker) (current-buffer))) + (kill-buffer buffer))) + )) ;; Here we are back in the original buffer. Everything seems to have ;; worked. So now cut the tree and finish up. (let (this-command) (org-cut-subtree)) - (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line)) + (setq org-markers-to-move nil) (message "Subtree archived %s" (if (eq this-buffer buffer) (concat "under heading: " heading) @@ -404,4 +416,5 @@ the children that do not contain any open TODO items." (provide 'org-archive) ;; arch-tag: 0837f601-9699-43c3-8b90-631572ae6c85 + ;;; org-archive.el ends here diff --git a/lisp/org/org-bbdb.el b/lisp/org/org-bbdb.el index b32899e5727..4dd6b2332c4 100644 --- a/lisp/org/org-bbdb.el +++ b/lisp/org/org-bbdb.el @@ -6,7 +6,7 @@ ;; Thomas Baumann <thomas dot baumann at ch dot tum dot de> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -30,7 +30,6 @@ ;; Org-mode loads this module by default - if this is not what you want, ;; configure the variable `org-modules'. - ;; It also implements an interface (based on Ivar Rummelhoff's ;; bbdb-anniv.el) for those org-mode users, who do not use the diary ;; but who do want to include the anniversaries stored in the BBDB @@ -77,7 +76,10 @@ ;; 1973-06-22 ;; 20??-??-?? wedding ;; 1998-03-12 %s created bbdb-anniv.el %d years ago - +;; +;; From Org's agenda, you can use `C-c C-o' to jump to the BBDB +;; link from which the entry at point originates. +;; ;;; Code: (require 'org) @@ -100,7 +102,7 @@ (declare-function calendar-leap-year-p "calendar" (year)) (declare-function diary-ordinal-suffix "diary-lib" (n)) -(defvar date) +(defvar date) ;; dynamically scoped from Org ;; Customization @@ -115,8 +117,16 @@ :require 'bbdb) (defcustom org-bbdb-anniversary-format-alist - '( ("birthday" . "Birthday: %s (%d%s)") - ("wedding" . "%s's %d%s wedding anniversary") ) + '(("birthday" lambda + (name years suffix) + (concat "Birthday: [[bbdb:" name "][" name " (" + (number-to-string years) + suffix ")]]")) + ("wedding" lambda + (name years suffix) + (concat "[[bbdb:" name "][" name "'s " + (number-to-string years) + suffix " wedding anniversary]]"))) "How different types of anniversaries should be formatted. An alist of elements (STRING . FORMAT) where STRING is the name of an anniversary class and format is either: @@ -227,17 +237,19 @@ Argument STR is the anniversary field in BBDB." (bbdb-string-trim (substring str pos))) (list str nil)))) +(defvar org-bbdb-anniv-hash nil + "A hash holding anniversaries extracted from BBDB. +The hash table is created on first use.") -;;;###autoload -(defun org-bbdb-anniversaries () - "Extract anniversaries from BBDB for display in the agenda." - (require 'diary-lib) - (let ((dates (list (cons (cons (car date) ; month - (nth 1 date)) ; day - (nth 2 date)))) ; year - (text ()) - annivs date years - split class form) +(defvar org-bbdb-updated-p t + "This is non-nil if BBDB has been updated since we last built the hash.") + +(defun org-bbdb-make-anniv-hash () + "Create a hash with anniversaries extracted from BBDB, for fast access. +The anniversaries are assumed to be stored `org-bbdb-anniversary-field'." + + (let (split tmp annivs) + (clrhash org-bbdb-anniv-hash) (dolist (rec (bbdb-records)) (when (setq annivs (bbdb-record-getprop rec org-bbdb-anniversary-field)) @@ -246,33 +258,70 @@ Argument STR is the anniversary field in BBDB." (setq split (org-bbdb-anniv-split (pop annivs))) (multiple-value-bind (m d y) (funcall org-bbdb-extract-date-fun (car split)) + (setq tmp (gethash (list m d) org-bbdb-anniv-hash)) + (puthash (list m d) (cons (list y + (bbdb-record-name rec) + (cadr split)) + tmp) + org-bbdb-anniv-hash)))))) + (setq org-bbdb-updated-p nil)) + +(defun org-bbdb-updated (rec) + "Record the fact that BBDB has been updated. +This is used by Org to re-create the anniversary hash table." + (setq org-bbdb-updated-p t)) - (when (and (or (setq date (assoc (cons m d) dates)) - (and (= d 29) - (= m 2) - (setq date (assoc '(3 . 1) dates)) - (not (calendar-leap-year-p (cdr date))))) - (< 0 (setq years (- (cdr date) y)))) - (let* ((class (or (cadr split) - org-bbdb-default-anniversary-format)) - (form (or (cdr (assoc class - org-bbdb-anniversary-format-alist)) - class)) ; (as format string) - (name (bbdb-record-name rec)) - (suffix (diary-ordinal-suffix years)) - (tmp (cond - ((functionp form) - (funcall form name years suffix)) - ((listp form) (eval form)) - (t (format form name years suffix))))) - (if text - (setq text (append text (list tmp))) - (setq text (list tmp)))) - ))))) +(add-hook 'bbdb-after-change-hook 'org-bbdb-updated) + +;;;###autoload +(defun org-bbdb-anniversaries() + "Extract anniversaries from BBDB for display in the agenda." + (require 'diary-lib) + (unless (hash-table-p org-bbdb-anniv-hash) + (setq org-bbdb-anniv-hash + (make-hash-table :test 'equal :size 366))) + + (when (or org-bbdb-updated-p + (= 0 (hash-table-count org-bbdb-anniv-hash))) + (org-bbdb-make-anniv-hash)) + + (let* ((m (car date)) ; month + (d (nth 1 date)) ; day + (y (nth 2 date)) ; year + (annivs (gethash (list m d) org-bbdb-anniv-hash)) + (text ()) + split class form rec) + + ;; we don't want to miss people born on Feb. 29th + (when (and (= m 3) (= d 1) (not (calendar-leap-year-p y))) + (setq annivs (cons annivs (gethash (list 2 29) org-bbdb-anniv-hash)))) + + (when annivs + (while (setq rec (pop annivs)) + (when rec + (let* ((class (or (nth 2 rec) + org-bbdb-default-anniversary-format)) + (form (or (cdr (assoc class + org-bbdb-anniversary-format-alist)) + class)) ; (as format string) + (name (nth 1 rec)) + (years (- y (car rec))) + (suffix (diary-ordinal-suffix years)) + (tmp (cond + ((functionp form) + (funcall form name years suffix)) + ((listp form) (eval form)) + (t (format form name years suffix))))) + (org-add-props tmp nil 'org-bbdb-name name) + (if text + (setq text (append text (list tmp))) + (setq text (list tmp))))) + )) (when text (mapconcat 'identity text "; ")))) (provide 'org-bbdb) ;; arch-tag: 9e4f275d-d080-48c1-b040-62247f66b5c2 + ;;; org-bbdb.el ends here diff --git a/lisp/org/org-bibtex.el b/lisp/org/org-bibtex.el index e0de2579f32..e314f452e9f 100644 --- a/lisp/org/org-bibtex.el +++ b/lisp/org/org-bibtex.el @@ -5,7 +5,7 @@ ;; Author: Bastien Guerry <bzg at altern dot org> ;; Carsten Dominik <carsten dot dominik at gmail dot com> ;; Keywords: org, wp, remember -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -200,4 +200,5 @@ (provide 'org-bibtex) ;; arch-tag: 83987d5a-01b8-41c7-85bc-77700f1285f5 + ;;; org-bibtex.el ends here diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index ca0f50591ff..99be3907cd7 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -97,11 +97,7 @@ The function is called with point at the beginning of the headline." (defvar org-clock-start-time "") (defvar org-clock-history nil - "Marker pointing to the previous task teking clock time. -This is used to find back to the previous task after interrupting work. -When clocking into a task and the clock is currently running, this marker -is moved to the position of the currently running task and continues -to point there even after the task is clocked out.") + "List of marker pointing to recent clocked tasks.") (defvar org-clock-default-task (make-marker) "Marker pointing to the default task that should clock time. @@ -109,12 +105,11 @@ The clock can be made to switch to this task after clocking out of a different task.") (defvar org-clock-interrupted-task (make-marker) - "Marker pointing to the default task that should clock time. -The clock can be made to switch to this task after clocking out -of a different task.") + "Marker pointing to the task that has been interrupted by the current clock.") (defun org-clock-history-push (&optional pos buffer) "Push a marker to the clock history." + (setq org-clock-history-length (max 1 (min 35 org-clock-history-length))) (let ((m (move-marker (make-marker) (or pos (point)) buffer)) n l) (while (setq n (member m org-clock-history)) (move-marker (car n) nil)) @@ -129,6 +124,14 @@ of a different task.") (nreverse org-clock-history))))) (push m org-clock-history))) +(defun org-clock-save-markers-for-cut-and-paste (beg end) + "Save relative positions of markers in region." + (org-check-and-save-marker org-clock-marker beg end) + (org-check-and-save-marker org-clock-default-task beg end) + (org-check-and-save-marker org-clock-interrupted-task beg end) + (mapc (lambda (m) (org-check-and-save-marker m beg end)) + org-clock-history)) + (defun org-clock-select-task (&optional prompt) "Select a task that recently was associated with clocking." (interactive) @@ -155,10 +158,14 @@ of a different task.") (when (marker-buffer m) (setq i (1+ i) s (org-clock-insert-selection-line - (string-to-char (number-to-string i)) m)) + (if (< i 10) + (+ i ?0) + (+ i (- ?A 10))) m)) (push s sel-list))) org-clock-history) - (shrink-window-if-larger-than-buffer) + (if (fboundp 'fit-window-to-buffer) + (fit-window-to-buffer) + (shrink-window-if-larger-than-buffer)) (message (or prompt "Select task for clocking:")) (setq rpl (read-char-exclusive)) (cond @@ -170,14 +177,16 @@ of a different task.") (defun org-clock-insert-selection-line (i marker) (when (marker-buffer marker) (let (file cat task) - (with-current-buffer (marker-buffer marker) + (with-current-buffer (org-base-buffer (marker-buffer marker)) (save-excursion - (goto-char marker) - (setq file (buffer-file-name (marker-buffer marker)) - cat (or (org-get-category) - (progn (org-refresh-category-properties) - (org-get-category))) - task (org-get-heading 'notags)))) + (save-restriction + (widen) + (goto-char marker) + (setq file (buffer-file-name (marker-buffer marker)) + cat (or (org-get-category) + (progn (org-refresh-category-properties) + (org-get-category))) + task (org-get-heading 'notags))))) (when (and cat task) (insert (format "[%c] %-15s %s\n" i cat task)) (cons i marker))))) @@ -188,7 +197,7 @@ of a different task.") (h (floor delta 3600)) (m (floor (- delta (* 3600 h)) 60))) (setq org-mode-line-string - (propertize (format "-[%d:%02d (%s)]" h m org-clock-heading) + (propertize (format (concat "-[" org-time-clocksum-format " (%s)]") h m org-clock-heading) 'help-echo "Org-mode clock is running")) (force-mode-line-update))) @@ -204,60 +213,69 @@ is as the default task, a special task that will always be offered in the clocking selection, associated with the letter `d'." (interactive "P") (let ((interrupting (marker-buffer org-clock-marker)) - ts selected-task) + ts selected-task target-pos) (when (equal select '(4)) (setq selected-task (org-clock-select-task "Clock-in on task: ")) (if selected-task (setq selected-task (copy-marker selected-task)) (error "Abort"))) - ;; Are we interrupting the clocking of a differnt task? - (if interrupting - (progn - (move-marker org-clock-interrupted-task - (marker-position org-clock-marker) - (marker-buffer org-clock-marker)) - (org-clock-out t))) + (when interrupting + ;; We are interrupting the clocking of a differnt task. + ;; Save a marker to this task, so that we can go back. + (move-marker org-clock-interrupted-task + (marker-position org-clock-marker) + (marker-buffer org-clock-marker)) + (org-clock-out t)) (when (equal select '(16)) + ;; Mark as default clocking task (save-excursion (org-back-to-heading t) (move-marker org-clock-default-task (point)))) + (setq target-pos (point)) ;; we want to clock in at this location (save-excursion - (org-back-to-heading t) (when (and selected-task (marker-buffer selected-task)) - (set-buffer (marker-buffer selected-task)) - (goto-char selected-task) + ;; There is a selected task, move to the correct buffer + ;; and set the new target position. + (set-buffer (org-base-buffer (marker-buffer selected-task))) + (setq target-pos (marker-position selected-task)) (move-marker selected-task nil)) - (or interrupting (move-marker org-clock-interrupted-task nil)) - (org-clock-history-push) - (when (and org-clock-in-switch-to-state - (not (looking-at (concat outline-regexp "[ \t]*" - org-clock-in-switch-to-state - "\\>")))) - (org-todo org-clock-in-switch-to-state)) - (if (and org-clock-heading-function - (functionp org-clock-heading-function)) - (setq org-clock-heading (funcall org-clock-heading-function)) - (if (looking-at org-complex-heading-regexp) - (setq org-clock-heading (match-string 4)) - (setq org-clock-heading "???"))) - (setq org-clock-heading (propertize org-clock-heading 'face nil)) - (org-clock-find-position) - - (insert "\n") (backward-char 1) - (indent-relative) - (insert org-clock-string " ") - (setq org-clock-start-time (current-time)) - (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive)) - (move-marker org-clock-marker (point) (buffer-base-buffer)) - (or global-mode-string (setq global-mode-string '(""))) - (or (memq 'org-mode-line-string global-mode-string) - (setq global-mode-string - (append global-mode-string '(org-mode-line-string)))) - (org-update-mode-line) - (setq org-mode-line-timer (run-with-timer 60 60 'org-update-mode-line)) - (message "Clock started at %s" ts)))) + (save-excursion + (save-restriction + (widen) + (goto-char target-pos) + (org-back-to-heading t) + (or interrupting (move-marker org-clock-interrupted-task nil)) + (org-clock-history-push) + (when (and org-clock-in-switch-to-state + (not (looking-at (concat outline-regexp "[ \t]*" + org-clock-in-switch-to-state + "\\>")))) + (org-todo org-clock-in-switch-to-state)) + (if (and org-clock-heading-function + (functionp org-clock-heading-function)) + (setq org-clock-heading (funcall org-clock-heading-function)) + (if (looking-at org-complex-heading-regexp) + (setq org-clock-heading (match-string 4)) + (setq org-clock-heading "???"))) + (setq org-clock-heading (propertize org-clock-heading 'face nil)) + (org-clock-find-position) + + (insert "\n") (backward-char 1) + (indent-relative) + (insert org-clock-string " ") + (setq org-clock-start-time (current-time)) + (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive)) + (move-marker org-clock-marker (point) (buffer-base-buffer)) + (or global-mode-string (setq global-mode-string '(""))) + (or (memq 'org-mode-line-string global-mode-string) + (setq global-mode-string + (append global-mode-string '(org-mode-line-string)))) + (org-update-mode-line) + (setq org-mode-line-timer + (run-with-timer 60 60 'org-update-mode-line)) + (message "Clock started at %s" ts)))))) (defun org-clock-find-position () "Find the location where the next clock line should be inserted." @@ -288,7 +306,6 @@ the clocking selection, associated with the letter `d'." ;; Wrap current entries into a new drawer (goto-char last) (beginning-of-line 2) - (if (org-at-item-p) (org-end-of-item)) (insert ":END:\n") (beginning-of-line 0) (org-indent-line-function) @@ -358,7 +375,7 @@ If there is no running clock, throw an error, unless FAIL-QUIETLY is set." (setq global-mode-string (delq 'org-mode-line-string global-mode-string)) (force-mode-line-update) - (message "Clock stopped at %s after HH:MM = %d:%02d%s" te h m + (message (concat "Clock stopped at %s after HH:MM = " org-time-clocksum-format "%s") te h m (if remove " => LINE REMOVED" ""))))))) (defun org-clock-cancel () @@ -387,6 +404,7 @@ With prefix arg SELECT, offer recently clocked tasks." (error "No task selected") (error "No active clock"))) (switch-to-buffer (marker-buffer m)) + (if (or (< m (point-min)) (> m (point-max))) (widen)) (goto-char m) (org-show-entry) (org-back-to-heading) @@ -469,7 +487,7 @@ in the echo area." (when org-remove-highlights-with-change (org-add-hook 'before-change-functions 'org-remove-clock-overlays nil 'local)))) - (message "Total file time: %d:%02d (%d hours and %d minutes)" h m h m))) + (message (concat "Total file time: " org-time-clocksum-format " (%d hours and %d minutes)") h m h m))) (defvar org-clock-overlays nil) (make-variable-buffer-local 'org-clock-overlays) @@ -481,6 +499,7 @@ This creates a new overlay and stores it in `org-clock-overlays', so that it will be easy to remove." (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h))) (l (if level (org-get-valid-level level 0) 0)) + (fmt (concat "%s " org-time-clocksum-format "%s")) (off 0) ov tx) (org-move-to-column c) @@ -489,7 +508,7 @@ will be easy to remove." (setq ov (org-make-overlay (1- (point)) (point-at-eol)) tx (concat (buffer-substring (1- (point)) (point)) (make-string (+ off (max 0 (- c (current-column)))) ?.) - (org-add-props (format "%s %2d:%02d%s" + (org-add-props (format fmt (make-string l ?*) h m (make-string (- 16 l) ?\ )) '(face secondary-selection)) @@ -920,7 +939,6 @@ the currently selected interval size." (provide 'org-clock) -;;; org-clock.el ends here - - ;; arch-tag: 7b42c5d4-9b36-48be-97c0-66a869daed4c + +;;; org-clock.el ends here diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el index 9c4cfbad322..95a5aa3fccf 100644 --- a/lisp/org/org-colview.el +++ b/lisp/org/org-colview.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -32,6 +32,8 @@ (eval-when-compile (require 'cl)) (require 'org) +(declare-function org-agenda-redo "org-agenda" ()) + ;;; Column View (defvar org-columns-overlays nil @@ -90,6 +92,10 @@ This is the compiled version of the format.") (org-defkey org-columns-map [(meta left)] 'org-columns-move-left) (org-defkey org-columns-map [(shift meta right)] 'org-columns-new) (org-defkey org-columns-map [(shift meta left)] 'org-columns-delete) +(dotimes (i 10) + (org-defkey org-columns-map (number-to-string i) + `(lambda () (interactive) + (org-columns-next-allowed-value nil ,i)))) (easy-menu-define org-columns-menu org-columns-map "Org Column Menu" '("Column" @@ -137,12 +143,11 @@ This is the compiled version of the format.") (and (eq major-mode 'org-agenda-mode) (get-text-property (point-at-bol) 'face)) 'default)) - (color (list :foreground - (face-attribute ref-face :foreground) - :weight 'normal :strike-through nil - :underline nil)) - (face (list color 'org-column level-face)) - pom property ass width f string ov column val modval) + (color (list :foreground (face-attribute ref-face :foreground))) + (face (list color 'org-column ref-face)) + (pl (or (get-text-property (point-at-bol) 'prefix-length) 0)) + (cphr (get-text-property (point-at-bol) 'org-complex-heading-regexp)) + pom property ass width f string ov column val modval s1 s2) ;; Check if the entry is in another buffer. (unless props (if (eq major-mode 'org-agenda-mode) @@ -167,8 +172,13 @@ This is the compiled version of the format.") f (format "%%-%d.%ds | " width width) val (or (cdr ass) "") modval (if (equal property "ITEM") - (org-columns-cleanup-item val org-columns-current-fmt-compiled)) - string (format f (or modval val))) + (if (org-mode-p) + (org-columns-cleanup-item + val org-columns-current-fmt-compiled) + (org-agenda-columns-cleanup-item + val pl cphr org-columns-current-fmt-compiled)))) + (setq s2 (org-columns-add-ellipses (or modval val) width)) + (setq string (format f s2)) ;; Create the overlay (org-unmodified (setq ov (org-columns-new-overlay @@ -200,6 +210,15 @@ This is the compiled version of the format.") (min (point-max) (1+ (point-at-eol))) 'read-only "Type `e' to edit property"))))) +(defun org-columns-add-ellipses (string width) + "Truncate STRING with WIDTH characters, with ellipses." + (cond + ((<= (length string) width) string) + ((<= width (length org-columns-ellipses)) + (substring org-columns-ellipses 0 width)) + (t (concat (substring string 0 (- width (length org-columns-ellipses))) + org-columns-ellipses)))) + (defvar org-columns-full-header-line-format nil "Fthe full header line format, will be shifted by horizontal scrolling." ) (defvar org-previous-header-line-format nil @@ -275,13 +294,40 @@ for the duration of the command.") (if (not org-complex-heading-regexp) item (when (string-match org-complex-heading-regexp item) - (concat - (org-add-props (concat (match-string 1 item) " ") nil - 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1)))))) - (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " (match-string 2 item))) - (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " (match-string 3 item))) - " " (match-string 4 item) - (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " (match-string 5 item))))))) + (setq item + (concat + (org-add-props (match-string 1 item) nil + 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1)))))) + (and (match-end 2) (not (assoc "TODO" fmt)) (concat " " (match-string 2 item))) + (and (match-end 3) (not (assoc "PRIORITY" fmt)) (concat " " (match-string 3 item))) + " " (save-match-data (org-columns-compact-links (match-string 4 item))) + (and (match-end 5) (not (assoc "TAGS" fmt)) (concat " " (match-string 5 item))))) + (add-text-properties + 0 (1+ (match-end 1)) + (list 'org-whitespace (* 2 (1- (org-reduced-level (- (match-end 1) (match-beginning 1)))))) + item) + item))) + +(defun org-columns-compact-links (s) + "Replace [[link][desc]] with [desc] or [link]." + (while (string-match org-bracket-link-regexp s) + (setq s (replace-match + (concat "[" (match-string (if (match-end 3) 3 1) s) "]") + t t s))) + s) + +(defvar org-agenda-columns-remove-prefix-from-item) +(defun org-agenda-columns-cleanup-item (item pl cphr fmt) + "Cleanup the tiem property for agenda column view. +See also the variable `org-agenda-columns-remove-prefix-from-item'." + (let* ((org-complex-heading-regexp cphr) + (prefix (substring item 0 pl)) + (rest (substring item pl)) + (fake (concat "* " rest)) + (cleaned (org-trim (substring (org-columns-cleanup-item fake fmt) 1)))) + (if org-agenda-columns-remove-prefix-from-item + cleaned + (concat prefix cleaned)))) (defun org-columns-show-value () "Show the full value of the property." @@ -381,7 +427,7 @@ Where possible, use the standard interface for changing this line." (cond ((equal major-mode 'org-agenda-mode) - (org-columns-eval '(org-entry-put pom key nval)) + (org-columns-eval eval) ;; The following let preserves the current format, and makes sure ;; that in only a single file things need to be upated. (let* ((org-agenda-overriding-columns-format org-columns-current-fmt) @@ -411,7 +457,8 @@ Where possible, use the standard interface for changing this line." "Edit the current headline, the part without TODO keyword, TAGS." (org-back-to-heading) (when (looking-at org-todo-line-regexp) - (let ((pre (buffer-substring (match-beginning 0) (match-beginning 3))) + (let ((pos (point)) + (pre (buffer-substring (match-beginning 0) (match-beginning 3))) (txt (match-string 3)) (post "") txt2) @@ -420,7 +467,7 @@ Where possible, use the standard interface for changing this line." txt (substring txt 0 (match-beginning 0)))) (setq txt2 (read-string "Edit: " txt)) (when (not (equal txt txt2)) - (beginning-of-line 1) + (goto-char pos) (insert pre txt2 post) (delete-region (point) (point-at-eol)) (org-set-tags nil t))))) @@ -461,8 +508,10 @@ Where possible, use the standard interface for changing this line." (interactive) (org-columns-next-allowed-value t)) -(defun org-columns-next-allowed-value (&optional previous) - "Switch to the next allowed value for this column." +(defun org-columns-next-allowed-value (&optional previous nth) + "Switch to the next allowed value for this column. +When PREVIOUS is set, go to the previous value. When NTH is +an integer, select that value." (interactive) (org-columns-check-computed) (let* ((col (current-column)) @@ -484,6 +533,9 @@ Where possible, use the standard interface for changing this line." '(checkbox checkbox-n-of-m checkbox-percent)) '("[ ]" "[X]")))) nval) + (when (integerp nth) + (setq nth (1- nth)) + (if (= nth -1) (setq nth 9))) (when (equal key "ITEM") (error "Cannot edit item headline from here")) (unless (or allowed (member key '("SCHEDULED" "DEADLINE"))) @@ -491,11 +543,18 @@ Where possible, use the standard interface for changing this line." (if (member key '("SCHEDULED" "DEADLINE")) (setq nval (if previous 'earlier 'later)) (if previous (setq allowed (reverse allowed))) - (if (member value allowed) - (setq nval (car (cdr (member value allowed))))) - (setq nval (or nval (car allowed))) - (if (equal nval value) - (error "Only one allowed value for this property"))) + (cond + (nth + (setq nval (nth nth allowed)) + (if (not nval) + (error "There are only %d allowed values for property `%s'" + (length allowed) key))) + ((member value allowed) + (setq nval (or (car (cdr (member value allowed))) + (car allowed))) + (if (equal nval value) + (error "Only one allowed value for this property"))) + (t (setq nval (car allowed))))) (cond ((equal major-mode 'org-agenda-mode) (org-columns-eval '(org-entry-put pom key nval)) @@ -812,13 +871,18 @@ Don't set this, this is meant for dynamic scoping.") "Construct the column display again." (interactive) (message "Recomputing columns...") - (save-excursion - (if (marker-position org-columns-begin-marker) - (goto-char org-columns-begin-marker)) - (org-columns-remove-overlays) - (if (org-mode-p) - (call-interactively 'org-columns) - (call-interactively 'org-agenda-columns))) + (let ((line (org-current-line)) + (col (current-column))) + (save-excursion + (if (marker-position org-columns-begin-marker) + (goto-char org-columns-begin-marker)) + (org-columns-remove-overlays) + (if (org-mode-p) + (call-interactively 'org-columns) + (org-agenda-redo) + (call-interactively 'org-agenda-columns))) + (goto-line line) + (move-to-column col)) (message "Recomputing columns...done")) (defun org-columns-not-in-agenda () @@ -840,7 +904,7 @@ Don't set this, this is meant for dynamic scoping.") (cond ((eq fmt 'add_times) (let* ((h (floor n)) (m (floor (+ 0.5 (* 60 (- n h)))))) - (format "%d:%02d" h m))) + (format org-time-clocksum-format h m))) ((eq fmt 'checkbox) (cond ((= n (floor n)) "[X]") ((> n 1.) "[-]") @@ -1212,6 +1276,6 @@ This will add overlays to the date lines, to show the summary for each day." (provide 'org-colview) -;;; org-colview.el ends here - ;; arch-tag: 61f5128d-747c-4983-9479-e3871fa3d73c + +;;; org-colview.el ends here diff --git a/lisp/org/org-compat.el b/lisp/org/org-compat.el index e4fe1f2a36d..bc21429cb37 100644 --- a/lisp/org/org-compat.el +++ b/lisp/org/org-compat.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -246,8 +246,8 @@ that can be added." (cadr ext-inv-spec)))) (move-to-column column force))) - (provide 'org-compat) ;; arch-tag: a0a0579f-e68c-4bdf-9e55-93768b846bbe + ;;; org-compat.el ends here diff --git a/lisp/org/org-exp.el b/lisp/org/org-exp.el index c401226a83d..0ebcdbbfb89 100644 --- a/lisp/org/org-exp.el +++ b/lisp/org/org-exp.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -33,6 +33,8 @@ (declare-function org-export-latex-preprocess "org-export-latex" ()) (declare-function org-agenda-skip "org-agenda" ()) (declare-function org-infojs-options-inbuffer-template "org-jsinfo" ()) +(declare-function htmlize-region "ext:htmlize" (beg end)) +(defvar htmlize-buffer-places) ; from htmlize.el (defgroup org-export nil "Options for exporting org-listings." @@ -86,7 +88,9 @@ This option can also be set with the +OPTIONS line, e.g. \"-:nil\"." ("fr" "Auteur" "Date" "Table des mati\xe8res") ("it" "Autore" "Data" "Indice") ("nl" "Auteur" "Datum" "Inhoudsopgave") - ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk) + ("no" "Forfatter" "Dato" "Innhold") + ("nb" "Forfatter" "Dato" "Innhold") ;; nb = Norsk (bokm.l) + ("nn" "Forfattar" "Dato" "Innhald") ;; nn = Norsk (nynorsk) ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll")) "Terms used in export text, translated to different languages. Use the variable `org-export-default-language' to set the language, @@ -105,7 +109,7 @@ This should have an association in `org-export-language-setup'." :group 'org-export-general :type 'string) -(defcustom org-export-skip-text-before-1st-heading t +(defcustom org-export-skip-text-before-1st-heading nil "Non-nil means, skip all text before the first headline when exporting. When nil, that text is exported as well." :group 'org-export-general @@ -128,6 +132,26 @@ This option can also be set with the +OPTIONS line, e.g. \"num:t\"." :group 'org-export-general :type 'boolean) +(defcustom org-export-section-number-format '((("1" ".")) . "") + "Format of section numbers for export. +The variable has two components. +1. A list of lists, each indicating a counter type and a separator. + The counter type can be any of \"1\", \"A\", \"a\", \"I\", or \"a\". + It causes causes numeric, alphabetic, or roman counters, respectively. + The separator is only used if another counter for a subsection is being + added. + If there are more numbered section levels than entries in this lists, + then the last entry will be reused. +2. A terminator string that will be added after the entire + section number." + :group 'org-export-general + :type '(cons + (repeat + (list + (string :tag "Counter Type") + (string :tag "Separator "))) + (string :tag "Terminator"))) + (defcustom org-export-with-toc t "Non-nil means, create a table of contents in exported files. The TOC contains headlines with levels up to`org-export-headline-levels'. @@ -227,6 +251,10 @@ drawer names to export." (repeat :tag "Selected drawers" (string :tag "Drawer name")))) +(defvar org-export-preprocess-hook nil + "Hook for preprocessing an export buffer. +Pretty much the first thing when exporting is running this hook.") + (defgroup org-export-translation nil "Options for translating special ascii sequences for the export backends." :tag "Org Export Translation" @@ -456,12 +484,14 @@ Org-mode file." background-color: #F3F5F7; padding: 5pt; font-family: courier, monospace; + font-size: 90%; } table { border-collapse: collapse; } td, th { vertical-align: top; <!--border: 1pt solid #ADB9CC;--> } + dt { font-weight: bold; } </style>" "The default style specification for exported HTML files. Since there are different ways of setting style information, this variable @@ -564,6 +594,25 @@ to a file." :group 'org-export-html :type 'string) +(defgroup org-export-htmlize nil + "Options for processing examples with htmlize.el." + :tag "Org Export Htmlize" + :group 'org-export-html) + +(defcustom org-export-htmlize-output-type 'inline-css + "Output type to be used by htmlize when formatting code snippets. +Normally this is `inline-css', but if you have defined to appropriate +classes in your css style file, setting this to `css' means that the +fontification will use the class names. +See also the function `org-export-htmlize-generate-css'." + :group 'org-export-htmlize + :type '(choice (const css) (const inline-css))) + +(defcustom org-export-htmlize-css-font-prefix "org-" + "The prefix for CSS class names for htmlize font specifications." + :group 'org-export-htmlize + :type 'string) + (defgroup org-export-icalendar nil "Options specific for iCalendar export of Org-mode files." :tag "Org Export iCalendar" @@ -606,6 +655,20 @@ The text will be inserted into the DESCRIPTION field." :group 'org-export-icalendar :type 'string) +(defcustom org-icalendar-store-UID nil + "Non-nil means, store any created UIDs in properties. +The iCalendar standard requires that all entries have a unique identifyer. +Org will create these identifiers as needed. When this variable is non-nil, +the created UIDs will be stored in the ID property of the entry. Then the +next time this entry is exported, it will be exported with the same UID, +superceeding the previous form of it. This is essential for +synchronization services. +This variable is not turned on by default because we want to avoid creating +a property drawer in every entry if people are only playing with this feature, +or if they are only using it locally." + :group 'org-export-icalendar + :type 'boolean) + ;;;; Exporting ;;; Variables, constants, and parameter plists @@ -630,6 +693,7 @@ The text will be inserted into the DESCRIPTION field." (:customtime . org-display-custom-times) (:headline-levels . org-export-headline-levels) (:section-numbers . org-export-with-section-numbers) + (:section-number-format . org-export-section-number-format) (:table-of-contents . org-export-with-toc) (:preserve-breaks . org-export-preserve-breaks) (:archived-trees . org-export-with-archived-trees) @@ -694,16 +758,21 @@ modified) list.") (save-excursion (save-restriction (widen) - (goto-char 0) + (goto-char (point-min)) (let ((re (org-make-options-regexp (append '("TITLE" "AUTHOR" "DATE" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE" - "LINK_UP" "LINK_HOME") + "LINK_UP" "LINK_HOME" "SETUPFILE") (mapcar 'car org-export-inbuffer-options-extra)))) - p key val text options js-up js-main js-css js-opt a pr) - (while (re-search-forward re nil t) - (setq key (org-match-string-no-properties 1) - val (org-match-string-no-properties 2)) + p key val text options js-up js-main js-css js-opt a pr + ext-setup-or-nil setup-contents (start 0)) + (while (or (and ext-setup-or-nil + (string-match re ext-setup-or-nil start) + (setq start (match-end 0))) + (and (setq ext-setup-or-nil nil start 0) + (re-search-forward re nil t))) + (setq key (upcase (org-match-string-no-properties 1 ext-setup-or-nil)) + val (org-match-string-no-properties 2 ext-setup-or-nil)) (cond ((setq a (assoc key org-export-inbuffer-options-extra)) (setq pr (nth 1 a)) @@ -716,41 +785,75 @@ modified) list.") ((string-equal key "TEXT") (setq text (if text (concat text "\n" val) val))) ((string-equal key "OPTIONS") - (setq options (concat options " " val))) + (setq options (concat val " " options))) ((string-equal key "LINK_UP") (setq p (plist-put p :link-up val))) ((string-equal key "LINK_HOME") - (setq p (plist-put p :link-home val))))) + (setq p (plist-put p :link-home val))) + ((equal key "SETUPFILE") + (setq setup-contents (org-file-contents + (expand-file-name + (org-remove-double-quotes + (org-trim val))) + 'noerror)) + (if (not ext-setup-or-nil) + (setq ext-setup-or-nil setup-contents start 0) + (setq ext-setup-or-nil + (concat (substring ext-setup-or-nil 0 start) + "\n" setup-contents "\n" + (substring ext-setup-or-nil start))))))) (setq p (plist-put p :text text)) (when options - (let ((op '(("H" . :headline-levels) - ("num" . :section-numbers) - ("toc" . :table-of-contents) - ("\\n" . :preserve-breaks) - ("@" . :expand-quoted-html) - (":" . :fixed-width) - ("|" . :tables) - ("^" . :sub-superscript) - ("-" . :special-strings) - ("f" . :footnotes) - ("d" . :drawers) - ("tags" . :tags) - ("*" . :emphasize) - ("TeX" . :TeX-macros) - ("LaTeX" . :LaTeX-fragments) - ("skip" . :skip-before-1st-heading) - ("author" . :author-info) - ("timestamp" . :time-stamp-file))) - o) - (while (setq o (pop op)) - (if (string-match (concat (regexp-quote (car o)) - ":\\([^ \t\n\r;,.]*\\)") - options) - (setq p (plist-put p (cdr o) - (car (read-from-string - (match-string 1 options))))))))) + (setq p (org-export-add-options-to-plist p options))) p)))) +(defun org-export-add-options-to-plist (p options) + "Parse an OPTONS line and set values in the property list P." + (let (o) + (when options + (let ((op '(("H" . :headline-levels) + ("num" . :section-numbers) + ("toc" . :table-of-contents) + ("\\n" . :preserve-breaks) + ("@" . :expand-quoted-html) + (":" . :fixed-width) + ("|" . :tables) + ("^" . :sub-superscript) + ("-" . :special-strings) + ("f" . :footnotes) + ("d" . :drawers) + ("tags" . :tags) + ("*" . :emphasize) + ("TeX" . :TeX-macros) + ("LaTeX" . :LaTeX-fragments) + ("skip" . :skip-before-1st-heading) + ("author" . :author-info) + ("timestamp" . :time-stamp-file))) + o) + (while (setq o (pop op)) + (if (string-match (concat (regexp-quote (car o)) + ":\\([^ \t\n\r;,.]*\\)") + options) + (setq p (plist-put p (cdr o) + (car (read-from-string + (match-string 1 options)))))))))) + p) + +(defun org-export-add-subtree-options (p pos) + "Add options in subtree at position POS to property list P." + (save-excursion + (goto-char pos) + (when (org-at-heading-p) + (let (a) + ;; This is actually read in `org-export-get-title-from-subtree' + ;; (when (setq a (org-entry-get pos "EXPORT_TITLE")) + ;; (setq p (plist-put p :title a))) + (when (setq a (org-entry-get pos "EXPORT_TEXT")) + (setq p (plist-put p :text a))) + (when (setq a (org-entry-get pos "EXPORT_OPTIONS")) + (setq p (org-export-add-options-to-plist p a))))) + p)) + (defun org-export-directory (type plist) (let* ((val (plist-get plist :publishing-directory)) (dir (if (listp val) @@ -758,6 +861,12 @@ modified) list.") val))) dir)) +(defun org-export-process-option-filters (plist) + (let ((functions org-export-options-filters) f) + (while (setq f (pop functions)) + (setq plist (funcall f plist)))) + plist) + ;;;###autoload (defun org-export (&optional arg) "Export dispatcher for Org-mode. @@ -1151,51 +1260,41 @@ to export. It then creates a temporary buffer where it does its job. The result is then again returned as a string, and the exporter works on this string to produce the exported version." (interactive) - (let* ((re-radio (and org-target-link-regexp - (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)"))) - (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re)) - (re-angle-link (concat "\\([^[]\\)" org-angle-link-re)) - (re-archive (concat ":" org-archive-tag ":")) - (re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>")) - (re-commented (concat "^\\*+[ \t]+" org-comment-string "\\>")) - (htmlp (plist-get parameters :for-html)) + (let* ((htmlp (plist-get parameters :for-html)) (asciip (plist-get parameters :for-ascii)) (latexp (plist-get parameters :for-LaTeX)) - (commentsp (plist-get parameters :comments)) (archived-trees (plist-get parameters :archived-trees)) (inhibit-read-only t) (drawers org-drawers) - (exp-drawers (plist-get parameters :drawers)) (outline-regexp "\\*+ ") - target-alist tmp target level - a b xx rtn p) + target-alist rtn) (with-current-buffer (get-buffer-create " org-mode-tmp") (erase-buffer) (insert string) + (setq case-fold-search t) + ;; Call the hook + (run-hooks 'org-export-preprocess-hook) + ;; Remove license-to-kill stuff ;; The caller markes some stuff fo killing, stuff that has been ;; used to create the page title, for example. - (while (setq p (text-property-any (point-min) (point-max) - :org-license-to-kill t)) - (delete-region p (next-single-property-change p :org-license-to-kill))) - + (org-export-kill-licensed-text) + (let ((org-inhibit-startup t)) (org-mode)) + (setq case-fold-search t) (untabify (point-min) (point-max)) - + + ;; Handle incude files + (org-export-handle-include-files) + + ;; Handle source code snippets + (org-export-replace-src-segments) + ;; Get rid of drawers - (unless (eq t exp-drawers) - (goto-char (point-min)) - (let ((re (concat "^[ \t]*:\\(" - (mapconcat - 'identity - (org-delete-all exp-drawers - (copy-sequence drawers)) - "\\|") - "\\):[ \t]*\n\\([^@]*?\n\\)?[ \t]*:END:[ \t]*\n"))) - (while (re-search-forward re nil t) - (replace-match "")))) - + (org-export-remove-or-extract-drawers drawers + (plist-get parameters :drawers)) + ;; Get the correct stuff before the first headline (when (plist-get parameters :skip-before-1st-heading) (goto-char (point-min)) @@ -1206,247 +1305,390 @@ on this string to produce the exported version." (when (plist-get parameters :add-text) (goto-char (point-min)) (insert (plist-get parameters :add-text) "\n")) - + ;; Get rid of archived trees - (when (not (eq archived-trees t)) - (goto-char (point-min)) - (while (re-search-forward re-archive nil t) - (if (not (org-on-heading-p t)) - (org-end-of-subtree t) - (beginning-of-line 1) - (setq a (if archived-trees - (1+ (point-at-eol)) (point)) - b (org-end-of-subtree t)) - (if (> b a) (delete-region a b))))) - + (org-export-remove-archived-trees archived-trees) + ;; Find all headings and compute the targets for them - (goto-char (point-min)) - (org-init-section-numbers) - (let ((re (concat "^" org-outline-regexp))) - (while (re-search-forward re nil t) - (setq level (org-reduced-level - (save-excursion (goto-char (point-at-bol)) - (org-outline-level)))) - (setq target (org-solidify-link-text - (format "sec-%s" (org-section-number level)))) - (push (cons target target) target-alist) - (add-text-properties - (point-at-bol) (point-at-eol) - (list 'target target)))) + (setq target-alist (org-export-define-heading-targets target-alist)) ;; Find targets in comments and move them out of comments, ;; but mark them as targets that should be invisible - (goto-char (point-min)) - (while (re-search-forward "^#.*?\\(<<<?\\([^>\r\n]+\\)>>>?\\).*" nil t) - ;; Check if the line before or after is a headline with a target - (if (setq target (or (get-text-property (point-at-bol 0) 'target) - (get-text-property (point-at-bol 2) 'target))) - (progn - ;; use the existing target in a neighboring line - (setq tmp (match-string 2)) - (replace-match "") - (and (looking-at "\n") (delete-char 1)) - (push (cons (org-solidify-link-text tmp) target) - target-alist)) - ;; Make an invisible target - (replace-match "\\1(INVISIBLE)"))) + (setq target-alist (org-export-handle-invisible-targets target-alist)) + + ;; Protect examples + (org-export-protect-examples) ;; Protect backend specific stuff, throw away the others. - (let ((formatters - `((,htmlp "HTML" "BEGIN_HTML" "END_HTML") - (,asciip "ASCII" "BEGIN_ASCII" "END_ASCII") - (,latexp "LaTeX" "BEGIN_LaTeX" "END_LaTeX"))) - fmt) - (goto-char (point-min)) - (while (re-search-forward "^#\\+BEGIN_EXAMPLE[ \t]*\n" nil t) - (goto-char (match-end 0)) - (while (not (looking-at "#\\+END_EXAMPLE")) - (insert ": ") - (beginning-of-line 2))) - (goto-char (point-min)) - (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t) - (add-text-properties (match-beginning 0) (match-end 0) - '(org-protected t))) - (while formatters - (setq fmt (pop formatters)) - (when (car fmt) - (goto-char (point-min)) - (while (re-search-forward (concat "^#\\+" (cadr fmt) - ":[ \t]*\\(.*\\)") nil t) - (replace-match "\\1" t) - (add-text-properties - (point-at-bol) (min (1+ (point-at-eol)) (point-max)) - '(org-protected t)))) - (goto-char (point-min)) - (while (re-search-forward - (concat "^#\\+" - (caddr fmt) "\\>.*\\(\\(\n.*\\)*?\n\\)#\\+" - (cadddr fmt) "\\>.*\n?") nil t) - (if (car fmt) - (add-text-properties (match-beginning 1) (1+ (match-end 1)) - '(org-protected t)) - (delete-region (match-beginning 0) (match-end 0)))))) + (org-export-select-backend-specific-text + (cond (htmlp 'html) (latexp 'latex) (asciip 'ascii))) ;; Protect quoted subtrees - (goto-char (point-min)) - (while (re-search-forward re-quote nil t) - (goto-char (match-beginning 0)) - (end-of-line 1) - (add-text-properties (point) (org-end-of-subtree t) - '(org-protected t))) + (org-export-protect-quoted-subtrees) ;; Protect verbatim elements - (goto-char (point-min)) - (while (re-search-forward org-verbatim-re nil t) - (add-text-properties (match-beginning 4) (match-end 4) - '(org-protected t)) - (goto-char (1+ (match-end 4)))) + (org-export-protect-verbatim) - ;; Remove subtrees that are commented - (goto-char (point-min)) - (while (re-search-forward re-commented nil t) - (goto-char (match-beginning 0)) - (delete-region (point) (org-end-of-subtree t))) + ;; Blockquotes and verse + (org-export-mark-blockquote-and-verse) + + ;; Remove comment environment and comment subtrees + (org-export-remove-comment-blocks-and-subtrees) ;; Remove special table lines (when org-export-table-remove-special-lines - (goto-char (point-min)) - (while (re-search-forward "^[ \t]*|" nil t) - (beginning-of-line 1) - (if (or (looking-at "[ \t]*| *[!_^] *|") - (and (looking-at ".*?| *<[0-9]+> *|") - (not (looking-at ".*?| *[^ <|]")))) - (delete-region (max (point-min) (1- (point-at-bol))) - (point-at-eol)) - (end-of-line 1)))) + (org-export-remove-special-table-lines)) ;; Specific LaTeX stuff (when latexp (require 'org-export-latex nil) (org-export-latex-preprocess)) + ;; Specific ASCII stuff (when asciip - (org-export-ascii-clean-string)) + (org-export-ascii-preprocess)) ;; Specific HTML stuff (when htmlp - ;; Convert LaTeX fragments to images - (when (plist-get parameters :LaTeX-fragments) - (org-format-latex - (concat "ltxpng/" (file-name-sans-extension - (file-name-nondirectory - org-current-export-file))) - org-current-export-dir nil "Creating LaTeX image %s")) - (message "Exporting...")) + (org-export-html-preprocess parameters)) ;; Remove or replace comments - (goto-char (point-min)) - (while (re-search-forward "^#\\(.*\n?\\)" nil t) - (if commentsp - (progn (add-text-properties - (match-beginning 0) (match-end 0) '(org-protected t)) - (replace-match (format commentsp (match-string 1)) t t)) - (replace-match ""))) + (org-export-handle-comments (plist-get parameters :comments)) ;; Find matches for radio targets and turn them into internal links - (goto-char (point-min)) - (when re-radio - (while (re-search-forward re-radio nil t) - (org-if-unprotected - (replace-match "\\1[[\\2]]")))) + (org-export-mark-radio-links) ;; Find all links that contain a newline and put them into a single line - (goto-char (point-min)) - (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t) - (org-if-unprotected - (replace-match "\\1 \\3") - (goto-char (match-beginning 0)))) + (org-export-concatenate-multiline-links) ;; Find all internal links. If they have a fuzzy match (i.e. not ;; a *dedicated* target match, let the link point to the - ;; correspinding section. - - (goto-char (point-min)) - (while (re-search-forward org-bracket-link-regexp nil t) - (org-if-unprotected - (let* ((md (match-data)) - (desc (match-end 2)) - (link (org-link-unescape (match-string 1))) - (slink (org-solidify-link-text link)) - found props pos - (target - (or (cdr (assoc slink target-alist)) - (save-excursion - (unless (string-match org-link-types-re link) - (setq found (condition-case nil (org-link-search link) - (error nil))) - (when (and found - (or (org-on-heading-p) - (not (eq found 'dedicated)))) - (or (get-text-property (point) 'target) - (get-text-property - (max (point-min) - (1- (previous-single-property-change - (point) 'target))) - 'target)))))))) - (when target - (set-match-data md) - (goto-char (match-beginning 1)) - (setq props (text-properties-at (point))) - (delete-region (match-beginning 1) (match-end 1)) - (setq pos (point)) - (insert target) - (unless desc (insert "][" link)) - (add-text-properties pos (point) props))))) + ;; corresponding section. + (org-export-target-internal-links target-alist) ;; Normalize links: Convert angle and plain links into bracket links - ;; Expand link abbreviations - (goto-char (point-min)) - (while (re-search-forward re-plain-link nil t) - (goto-char (1- (match-end 0))) - (org-if-unprotected - (let* ((s (concat (match-string 1) "[[" (match-string 2) - ":" (match-string 3) "]]"))) - ;; added 'org-link face to links - (put-text-property 0 (length s) 'face 'org-link s) - (replace-match s t t)))) - (goto-char (point-min)) - (while (re-search-forward re-angle-link nil t) - (goto-char (1- (match-end 0))) - (org-if-unprotected - (let* ((s (concat (match-string 1) "[[" (match-string 2) - ":" (match-string 3) "]]"))) - (put-text-property 0 (length s) 'face 'org-link s) - (replace-match s t t)))) - (goto-char (point-min)) - (while (re-search-forward org-bracket-link-regexp nil t) - (org-if-unprotected - (let* ((s (concat "[[" (setq xx (save-match-data - (org-link-expand-abbrev (match-string 1)))) - "]" - (if (match-end 3) - (match-string 2) - (concat "[" xx "]")) - "]"))) - (put-text-property 0 (length s) 'face 'org-link s) - (replace-match s t t)))) + ;; and expand link abbreviations + (org-export-normalize-links) ;; Find multiline emphasis and put them into single line - (when (plist-get parameters :emph-multiline) - (goto-char (point-min)) - (while (re-search-forward org-emph-re nil t) - (if (not (= (char-after (match-beginning 3)) - (char-after (match-beginning 4)))) - (org-if-unprotected - (subst-char-in-region (match-beginning 0) (match-end 0) - ?\n ?\ t) - (goto-char (1- (match-end 0)))) - (goto-char (1+ (match-beginning 0)))))) + (when (plist-get parameters :emph-multiline) + (org-export-concatenate-multiline-emphasis)) (setq rtn (buffer-string))) (kill-buffer " org-mode-tmp") rtn)) +(defun org-export-kill-licensed-text () + "Remove all text that is marked with a :org-license-to-kill property." + (let (p) + (while (setq p (text-property-any (point-min) (point-max) + :org-license-to-kill t)) + (delete-region p (next-single-property-change p :org-license-to-kill))))) + +(defun org-export-define-heading-targets (target-alist) + "Find all headings and define the targets for them. +The new targets are added to TARGET-ALIST, which is also returned." + (goto-char (point-min)) + (org-init-section-numbers) + (let ((re (concat "^" org-outline-regexp)) + level target) + (while (re-search-forward re nil t) + (setq level (org-reduced-level + (save-excursion (goto-char (point-at-bol)) + (org-outline-level)))) + (setq target (org-solidify-link-text + (format "sec-%s" (org-section-number level)))) + (push (cons target target) target-alist) + (add-text-properties + (point-at-bol) (point-at-eol) + (list 'target target)))) + target-alist) + +(defun org-export-handle-invisible-targets (target-alist) + "Find targets in comments and move them out of comments. +Mark them as invisible targets." + (let (target tmp) + (goto-char (point-min)) + (while (re-search-forward "^#.*?\\(<<<?\\([^>\r\n]+\\)>>>?\\).*" nil t) + ;; Check if the line before or after is a headline with a target + (if (setq target (or (get-text-property (point-at-bol 0) 'target) + (get-text-property (point-at-bol 2) 'target))) + (progn + ;; use the existing target in a neighboring line + (setq tmp (match-string 2)) + (replace-match "") + (and (looking-at "\n") (delete-char 1)) + (push (cons (org-solidify-link-text tmp) target) + target-alist)) + ;; Make an invisible target + (replace-match "\\1(INVISIBLE)")))) + target-alist) + +(defun org-export-target-internal-links (target-alist) + "Find all internal links and assign target to them. +If a link has a fuzzy match (i.e. not a *dedicated* target match), +let the link point to the corresponding section." + (goto-char (point-min)) + (while (re-search-forward org-bracket-link-regexp nil t) + (org-if-unprotected + (let* ((md (match-data)) + (desc (match-end 2)) + (link (org-link-unescape (match-string 1))) + (slink (org-solidify-link-text link)) + found props pos + (target + (or (cdr (assoc slink target-alist)) + (save-excursion + (unless (string-match org-link-types-re link) + (setq found (condition-case nil (org-link-search link) + (error nil))) + (when (and found + (or (org-on-heading-p) + (not (eq found 'dedicated)))) + (or (get-text-property (point) 'target) + (get-text-property + (max (point-min) + (1- (previous-single-property-change + (point) 'target))) + 'target)))))))) + (when target + (set-match-data md) + (goto-char (match-beginning 1)) + (setq props (text-properties-at (point))) + (delete-region (match-beginning 1) (match-end 1)) + (setq pos (point)) + (insert target) + (unless desc (insert "][" link)) + (add-text-properties pos (point) props)))))) + +(defun org-export-remove-or-extract-drawers (all-drawers exp-drawers) + "Remove drawers, or extract the content. +ALL-DRAWERS is a list of all drawer names valid in the current buffer. +EXP-DRAWERS can be t to keep all drawer contents, or a list of drawers +whose content to keep." + (unless (eq t exp-drawers) + (goto-char (point-min)) + (let ((re (concat "^[ \t]*:\\(" + (mapconcat + 'identity + (org-delete-all exp-drawers + (copy-sequence all-drawers)) + "\\|") + "\\):[ \t]*\n\\([^@]*?\n\\)?[ \t]*:END:[ \t]*\n"))) + (while (re-search-forward re nil t) + (replace-match ""))))) + +(defun org-export-remove-archived-trees (export-archived-trees) + "Remove archived trees. +When EXPORT-ARCHIVED-TREES is `headline;, only the headline will be exported. +When it is t, the entire archived tree will be exported. +When it is nil the entire tree including the headline will be removed +from the buffer." + (let ((re-archive (concat ":" org-archive-tag ":")) + a b) + (when (not (eq export-archived-trees t)) + (goto-char (point-min)) + (while (re-search-forward re-archive nil t) + (if (not (org-on-heading-p t)) + (org-end-of-subtree t) + (beginning-of-line 1) + (setq a (if export-archived-trees + (1+ (point-at-eol)) (point)) + b (org-end-of-subtree t)) + (if (> b a) (delete-region a b))))))) + +(defun org-export-protect-quoted-subtrees () + "Mark quoted subtrees with the protection property." + (let ((re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>"))) + (goto-char (point-min)) + (while (re-search-forward re-quote nil t) + (goto-char (match-beginning 0)) + (end-of-line 1) + (add-text-properties (point) (org-end-of-subtree t) + '(org-protected t))))) + +(defun org-export-protect-verbatim () + "Mark verbatim snippets with the protection property." + (goto-char (point-min)) + (while (re-search-forward org-verbatim-re nil t) + (add-text-properties (match-beginning 4) (match-end 4) + '(org-protected t)) + (goto-char (1+ (match-end 4))))) + +(defun org-export-protect-examples () + "Protect code that should be exported as monospaced examples." + (goto-char (point-min)) + (while (re-search-forward "^#\\+BEGIN_EXAMPLE[ \t]*\n" nil t) + (goto-char (match-end 0)) + (while (and (not (looking-at "#\\+END_EXAMPLE")) (not (eobp))) + (insert ": ") + (beginning-of-line 2))) + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t) + (add-text-properties (match-beginning 0) (match-end 0) + '(org-protected t)))) + +(defun org-export-select-backend-specific-text (backend) + (let ((formatters + '((html "HTML" "BEGIN_HTML" "END_HTML") + (ascii "ASCII" "BEGIN_ASCII" "END_ASCII") + (latex "LaTeX" "BEGIN_LaTeX" "END_LaTeX"))) + fmt) + + (while formatters + (setq fmt (pop formatters)) + (when (eq (car fmt) backend) + ;; This is selected code, put it into the file for real + (goto-char (point-min)) + (while (re-search-forward (concat "^#\\+" (cadr fmt) + ":[ \t]*\\(.*\\)") nil t) + (replace-match "\\1" t) + (add-text-properties + (point-at-bol) (min (1+ (point-at-eol)) (point-max)) + '(org-protected t)))) + (goto-char (point-min)) + (while (re-search-forward + (concat "^#\\+" + (caddr fmt) "\\>.*\\(\\(\n.*\\)*?\n\\)#\\+" + (cadddr fmt) "\\>.*\n?") nil t) + (if (eq (car fmt) backend) + ;; yes, keep this + (add-text-properties (match-beginning 1) (1+ (match-end 1)) + '(org-protected t)) + ;; No, this is for a different backend, kill it + (delete-region (match-beginning 0) (match-end 0))))))) + +(defun org-export-mark-blockquote-and-verse () + "Mark block quote and verse environments with special cookies. +These special cookies will later be interpreted by the backend." + ;; Blockquotes + (goto-char (point-min)) + (while (re-search-forward "^#\\+\\(begin\\|end\\)_\\(block\\)?quote\\>.*" + nil t) + (replace-match (if (equal (downcase (match-string 1)) "end") + "ORG-BLOCKQUOTE-END" "ORG-BLOCKQUOTE-START") + t t)) + ;; Verse + (goto-char (point-min)) + (while (re-search-forward "^#\\+\\(begin\\|end\\)_verse\\>.*" nil t) + (replace-match (if (equal (downcase (match-string 1)) "end") + "ORG-VERSE-END" "ORG-VERSE-START") + t t))) + +(defun org-export-remove-comment-blocks-and-subtrees () + "Remove the comment environment, and also commented subtrees." + (let ((re-commented (concat "^\\*+[ \t]+" org-comment-string "\\>"))) + ;; Remove comment environment + (goto-char (point-min)) + (while (re-search-forward + "^#\\+BEGIN_COMMENT[ \t]*\n[^\000]*?^#\\+END_COMMENT\\>.*" nil t) + (replace-match "" t t)) + ;; Remove subtrees that are commented + (goto-char (point-min)) + (while (re-search-forward re-commented nil t) + (goto-char (match-beginning 0)) + (delete-region (point) (org-end-of-subtree t))))) + +(defun org-export-handle-comments (commentsp) + "Remove comments, or convert to backend-specific format. +COMMENTSP can be a format string for publishing comments. +When it is nil, all comments will be removed." + (let ((re "^#\\(.*\n?\\)") + pos) + (goto-char (point-min)) + (while (or (looking-at re) + (re-search-forward re nil t)) + (setq pos (match-beginning 0)) + (if commentsp + (progn (add-text-properties + (match-beginning 0) (match-end 0) '(org-protected t)) + (replace-match (format commentsp (match-string 1)) t t)) + (goto-char (1+ pos)) + (org-if-unprotected + (replace-match "") + (goto-char (max (point-min) (1- pos)))))))) + +(defun org-export-mark-radio-links () + "Find all matches for radio targets and turn them into internal links." + (let ((re-radio (and org-target-link-regexp + (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))) + (goto-char (point-min)) + (when re-radio + (while (re-search-forward re-radio nil t) + (org-if-unprotected + (replace-match "\\1[[\\2]]")))))) + +(defun org-export-remove-special-table-lines () + "Remove tables lines that are used for internal purposes." + (goto-char (point-min)) + (while (re-search-forward "^[ \t]*|" nil t) + (beginning-of-line 1) + (if (or (looking-at "[ \t]*| *[!_^] *|") + (and (looking-at ".*?| *<[0-9]+> *|") + (not (looking-at ".*?| *[^ <|]")))) + (delete-region (max (point-min) (1- (point-at-bol))) + (point-at-eol)) + (end-of-line 1)))) + +(defun org-export-normalize-links () + "Convert all links to bracket links, and expand link abbreviations." + (let ((re-plain-link (concat "\\([^[<]\\)" org-plain-link-re)) + (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))) + (goto-char (point-min)) + (while (re-search-forward re-plain-link nil t) + (goto-char (1- (match-end 0))) + (org-if-unprotected + (let* ((s (concat (match-string 1) "[[" (match-string 2) + ":" (match-string 3) "]]"))) + ;; added 'org-link face to links + (put-text-property 0 (length s) 'face 'org-link s) + (replace-match s t t)))) + (goto-char (point-min)) + (while (re-search-forward re-angle-link nil t) + (goto-char (1- (match-end 0))) + (org-if-unprotected + (let* ((s (concat (match-string 1) "[[" (match-string 2) + ":" (match-string 3) "]]"))) + (put-text-property 0 (length s) 'face 'org-link s) + (replace-match s t t)))) + (goto-char (point-min)) + (while (re-search-forward org-bracket-link-regexp nil t) + (org-if-unprotected + (let* ((xx (save-match-data + (org-link-expand-abbrev (match-string 1)))) + (s (concat + "[[" xx "]" + (if (match-end 3) + (match-string 2) + (concat "[" xx "]")) + "]"))) + (put-text-property 0 (length s) 'face 'org-link s) + (replace-match s t t)))))) + +(defun org-export-concatenate-multiline-links () + "Find multi-line links and put it all into a single line. +This is to make sure that the line-processing export backends +can work correctly." + (goto-char (point-min)) + (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t) + (org-if-unprotected + (replace-match "\\1 \\3") + (goto-char (match-beginning 0))))) + +(defun org-export-concatenate-multiline-emphasis () + "Find multi-line emphasis and put it all into a single line. +This is to make sure that the line-processing export backends +can work correctly." + (goto-char (point-min)) + (while (re-search-forward org-emph-re nil t) + (if (not (= (char-after (match-beginning 3)) + (char-after (match-beginning 4)))) + (org-if-unprotected + (subst-char-in-region (match-beginning 0) (match-end 0) + ?\n ?\ t) + (goto-char (1- (match-end 0)))) + (goto-char (1+ (match-beginning 0)))))) + (defun org-export-grab-title-from-buffer () "Get a title for the current document, from looking at the buffer." (let ((inhibit-read-only t)) @@ -1463,18 +1705,19 @@ on this string to produce the exported version." (defun org-export-get-title-from-subtree () "Return subtree title and exclude it from export." - (let (title (m (mark))) + (let (title (m (mark)) (rbeg (region-beginning)) (rend (region-end))) (save-excursion - (goto-char (region-beginning)) + (goto-char rbeg) (when (and (org-at-heading-p) - (>= (org-end-of-subtree t t) (region-end))) + (>= (org-end-of-subtree t t) rend)) ;; This is a subtree, we take the title from the first heading - (goto-char (region-beginning)) + (goto-char rbeg) (looking-at org-todo-line-regexp) (setq title (match-string 3)) (org-unmodified (add-text-properties (point) (1+ (point-at-eol)) - (list :org-license-to-kill t))))) + (list :org-license-to-kill t))) + (setq title (or (org-entry-get nil "EXPORT_TITLE") title)))) title)) (defun org-solidify-link-text (s &optional alist) @@ -1512,14 +1755,19 @@ on this string to produce the exported version." (if (string-match "\\`[A-Z]\\'" number-string) (aset org-section-numbers i (- (string-to-char number-string) ?A -1)) - (aset org-section-numbers i (string-to-number number-string))) + (aset org-section-numbers i (string-to-number number-string))) (pop numbers)) (setq i (1- i))))) (defun org-section-number (&optional level) "Return a string with the current section number. When LEVEL is non-nil, increase section numbers on that level." - (let* ((depth (1- (length org-section-numbers))) idx n (string "")) + (let* ((depth (1- (length org-section-numbers))) + (string "") + (fmts (car org-export-section-number-format)) + (term (cdr org-export-section-number-format)) + (sep "") + ctype fmt idx n) (when level (when (> level -1) (aset org-section-numbers @@ -1531,16 +1779,153 @@ When LEVEL is non-nil, increase section numbers on that level." (setq idx (1+ idx)))) (setq idx 0) (while (<= idx depth) - (setq n (aref org-section-numbers idx)) - (setq string (concat string (if (not (string= string "")) "." "") - (int-to-string n))) + (when (> (aref org-section-numbers idx) 0) + (setq fmt (or (pop fmts) fmt) + ctype (car fmt) + n (aref org-section-numbers idx) + string (if (> n 0) + (concat string sep (org-number-to-counter n ctype)) + (concat string ".0")) + sep (nth 1 fmt))) (setq idx (1+ idx))) (save-match-data (if (string-match "\\`\\([@0]\\.\\)+" string) (setq string (replace-match "" t nil string))) (if (string-match "\\(\\.0\\)+\\'" string) (setq string (replace-match "" t nil string)))) - string)) + (concat string term))) + +(defun org-number-to-counter (n type) + "Concert number N to a string counter, according to TYPE. +TYPE must be a string, any of: + 1 number + A A,B,.... + a a,b,.... + I uppper case roman numeral + i lower case roman numeral" + (cond + ((equal type "1") (number-to-string n)) + ((equal type "A") (char-to-string (+ ?A n -1))) + ((equal type "a") (char-to-string (+ ?a n -1))) + ((equal type "I") (org-number-to-roman n)) + ((equal type "i") (downcase (org-number-to-roman n))) + (t (error "Invalid counter type `%s'" type)))) + +(defun org-number-to-roman (n) + "Convert integer N into a roman numeral." + (let ((roman '((1000 . "M") (900 . "CM") (500 . "D") (400 . "CD") + ( 100 . "C") ( 90 . "XC") ( 50 . "L") ( 40 . "XL") + ( 10 . "X") ( 9 . "IX") ( 5 . "V") ( 4 . "IV") + ( 1 . "I"))) + (res "")) + (if (<= n 0) + (number-to-string n) + (while roman + (if (>= n (caar roman)) + (setq n (- n (caar roman)) + res (concat res (cdar roman))) + (pop roman))) + res))) + +(org-number-to-roman 1961) + + +;;; Include files + +(defun org-export-handle-include-files () + "Include the contents of include files, with proper formatting." + (let ((case-fold-search t) + params file markup lang start end) + (goto-char (point-min)) + (while (re-search-forward "^#\\+INCLUDE:?[ \t]+\\(.*\\)" nil t) + (setq params (read (concat "(" (match-string 1) ")")) + file (org-symname-or-string (pop params)) + markup (org-symname-or-string (pop params)) + lang (org-symname-or-string (pop params))) + (delete-region (match-beginning 0) (match-end 0)) + (if (or (not file) + (not (file-exists-p file)) + (not (file-readable-p file))) + (insert (format "CANNOT INCLUDE FILE %s" file)) + (when markup + (if (equal (downcase markup) "src") + (setq start (format "#+begin_src %s\n" (or lang "fundamental")) + end "#+end_src") + (setq start (format "#+begin_%s\n" markup) + end (format "#+end_%s" markup)))) + (insert (or start "")) + (forward-char (nth 1 (insert-file-contents (expand-file-name file)))) + (or (bolp) (newline)) + (insert (or end "")))))) + +(defun org-symname-or-string (s) + (if (symbolp s) + (if s (symbol-name s) s) + s)) + +;;; Fontification of code +;; Currently only for th HTML backend, but who knows.... +(defun org-export-replace-src-segments () + "Replace source code segments with special code for export." + (let ((case-fold-search t) + lang code trans) + (goto-char (point-min)) + (while (re-search-forward + "^#\\+BEGIN_SRC:?[ \t]+\\([^ \t\n]+\\)[ \t]*\n\\([^\000]+?\n\\)#\\+END_SRC.*" + nil t) + (setq lang (match-string 1) code (match-string 2) + trans (org-export-format-source-code lang code)) + (replace-match trans t t)))) + +(defvar htmlp) ;; dynamically scoped from org-exp.el + +(defun org-export-format-source-code (lang code) + "Format CODE from language LANG and return it formatted for export. +Currently, this only does something for HTML export, for all other +backends, it converts the segment into an EXAMPLE segment." + (save-match-data + (cond + (htmlp + ;; We are exporting to HTML + (condition-case nil (require 'htmlize) (nil t)) + (if (not (fboundp 'htmlize-region-for-paste)) + (progn + ;; we do not have htmlize.el, or an old version of it + (message + "htmlize.el 1.34 or later is needed for source code formatting") + (concat "#+BEGIN_EXAMPLE\n" code + (if (string-match "\n\\'" code) "" "\n") + "#+END_EXAMPLE\n")) + ;; ok, we are good to go + (let* ((mode (and lang (intern (concat lang "-mode")))) + (org-inhibit-startup t) + (org-startup-folded nil) + (htmltext + (with-temp-buffer + (insert code) + ;; Free up the protected stuff + (goto-char (point-min)) + (while (re-search-forward "^," nil t) + (replace-match "") + (end-of-line 1)) + (if (functionp mode) + (funcall mode) + (fundamental-mode)) + (font-lock-fontify-buffer) + (org-export-htmlize-region-for-paste + (point-min) (point-max))))) + (if (string-match "<pre\\([^>]*\\)>\n?" htmltext) + (setq htmltext (replace-match "<pre class=\"src\">" + t t htmltext))) + (concat "#+BEGIN_HTML\n" htmltext "\n#+END_HTML\n")))) + (t + ;; This is not HTML, so just make it an example. + (when (equal lang "org") + (while (string-match "^," code) + (setq code (replace-match "" t t code)))) + (concat "#+BEGIN_EXAMPLE\n" code + (if (string-match "\n\\'" code) "" "\n") + "#+END_EXAMPLE\n"))))) ;;; ASCII export @@ -1560,12 +1945,17 @@ underlined headlines. The default is 3." (let* ((opt-plist (org-combine-plists (org-default-export-plist) (org-infile-export-plist))) (region-p (org-region-active-p)) + (rbeg (and region-p (region-beginning))) + (rend (and region-p (region-end))) (subtree-p (when region-p (save-excursion - (goto-char (region-beginning)) + (goto-char rbeg) (and (org-at-heading-p) - (>= (org-end-of-subtree t t) (region-end)))))) + (>= (org-end-of-subtree t t) rend))))) + (opt-plist (if subtree-p + (org-export-add-subtree-options opt-plist rbeg) + opt-plist)) (custom-times org-display-custom-times) (org-ascii-current-indentation '(0 . 0)) (level 0) line txt @@ -1673,7 +2063,8 @@ underlined headlines. The default is 3." (if org-export-with-toc (progn (push (concat (nth 3 lang-words) "\n") thetoc) - (push (concat (make-string (length (nth 3 lang-words)) ?=) "\n") thetoc) + (push (concat (make-string (string-width (nth 3 lang-words)) ?=) + "\n") thetoc) (mapc '(lambda (line) (if (string-match org-todo-line-regexp line) @@ -1810,7 +2201,7 @@ underlined headlines. The default is 3." (goto-char beg))) (goto-char (point-min)))) -(defun org-export-ascii-clean-string () +(defun org-export-ascii-preprocess () "Do extra work for ASCII export" (goto-char (point-min)) (while (re-search-forward org-verbatim-re nil t) @@ -1847,7 +2238,7 @@ underlined headlines. The default is 3." (defun org-insert-centered (s &optional underline) "Insert the string S centered and underline it with character UNDERLINE." - (let ((ind (max (/ (- 80 (string-width s)) 2) 0))) + (let ((ind (max (/ (- fill-column (string-width s)) 2) 0))) (insert (make-string ind ?\ ) s "\n") (if underline (insert (make-string ind ?\ ) @@ -1984,6 +2375,7 @@ Does include HTML export options as well as TODO and CATEGORY stuff." #+DRAWERS: %s #+STARTUP: %s %s %s %s %s #+TAGS: %s +#+FILETAGS: %s #+ARCHIVE: %s #+LINK: %s " @@ -2006,7 +2398,7 @@ Does include HTML export options as well as TODO and CATEGORY stuff." org-export-skip-text-before-1st-heading org-export-with-drawers org-export-with-tags - (if (featurep 'org-infojs) (org-infojs-options-inbuffer-template) "") + (if (featurep 'org-jsinfo) (org-infojs-options-inbuffer-template) "") org-export-html-link-up org-export-html-link-home (file-name-nondirectory buffer-file-name) @@ -2029,10 +2421,21 @@ Does include HTML export options as well as TODO and CATEGORY stuff." ((cdr x) (format "%s(%c)" (car x) (cdr x))) (t (car x)))) (or org-tag-alist (org-get-buffer-tags)) " ") "") + (mapconcat 'identity org-file-tags " ") org-archive-location "org file:~/org/%s.org" )) +(defun org-export-html-preprocess (parameters) + ;; Convert LaTeX fragments to images + (when (plist-get parameters :LaTeX-fragments) + (org-format-latex + (concat "ltxpng/" (file-name-sans-extension + (file-name-nondirectory + org-current-export-file))) + org-current-export-dir nil "Creating LaTeX image %s")) + (message "Exporting...")) + ;;;###autoload (defun org-insert-export-options-template () "Insert into the buffer a template with information for exporting." @@ -2171,12 +2574,17 @@ PUB-DIR is set, use this as the publishing directory." valid thetoc have-headings first-heading-pos (odd org-odd-levels-only) (region-p (org-region-active-p)) + (rbeg (and region-p (region-beginning))) + (rend (and region-p (region-end))) (subtree-p (when region-p (save-excursion - (goto-char (region-beginning)) + (goto-char rbeg) (and (org-at-heading-p) - (>= (org-end-of-subtree t t) (region-end)))))) + (>= (org-end-of-subtree t t) rend))))) + (opt-plist (if subtree-p + (org-export-add-subtree-options opt-plist rbeg) + opt-plist)) ;; The following two are dynamically scoped into other ;; routines below. (org-current-export-dir @@ -2222,7 +2630,7 @@ PUB-DIR is set, use this as the publishing directory." (inquote nil) (infixed nil) (in-local-list nil) - (local-list-num nil) + (local-list-type nil) (local-list-indent nil) (llt org-plain-list-ordered-item-terminator) (email (plist-get opt-plist :email)) @@ -2262,9 +2670,9 @@ PUB-DIR is set, use this as the publishing directory." "[\r\n]")) table-open type table-buffer table-orig-buffer - ind start-is-num starter didclose + ind item-type starter didclose rpl path desc descp desc1 desc2 link - snumber fnc + snumber fnc item-tag ) (let ((inhibit-read-only t)) @@ -2435,9 +2843,9 @@ lang=\"%s\" xml:lang=\"%s\"> (setq infixed t) (insert "<pre>\n")) (insert (org-html-protect (match-string 1 line)) "\n") - (when (and lines - (not (string-match "^[ \t]*\\(:.*\\)" - (car lines)))) + (when (or (not lines) + (not (string-match "^[ \t]*\\(:.*\\)" + (car lines)))) (setq infixed nil) (insert "</pre>\n")) (throw 'nextline nil)) @@ -2451,6 +2859,7 @@ lang=\"%s\" xml:lang=\"%s\"> (replace-match "\\2\n")) (insert line "\n") (while (and lines + (not (string-match "^[ \t]*:" (car lines))) (or (= (length (car lines)) 0) (get-text-property 0 'org-protected (car lines)))) (insert (pop lines) "\n")) @@ -2462,6 +2871,20 @@ lang=\"%s\" xml:lang=\"%s\"> (insert "\n<hr/>\n") (throw 'nextline nil)) + ;; Blockquotes and verse + (when (equal "ORG-BLOCKQUOTE-START" line) + (insert "<blockquote>\n<p>\n") + (throw 'nextline nil)) + (when (equal "ORG-BLOCKQUOTE-END" line) + (insert "</p>\n</blockquote>\n") + (throw 'nextline nil)) + (when (equal "ORG-VERSE-START" line) + (insert "<verse>\n<p>\n") + (throw 'nextline nil)) + (when (equal "ORG-VERSE-END" line) + (insert "</p>\n</verse>\n") + (throw 'nextline nil)) + ;; make targets to anchors (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line) (cond @@ -2620,10 +3043,10 @@ lang=\"%s\" xml:lang=\"%s\"> (setq head-count (+ head-count 1))) (when in-local-list ;; Close any local lists before inserting a new header line - (while local-list-num - (org-close-li) - (insert (if (car local-list-num) "</ol>\n" "</ul>")) - (pop local-list-num)) + (while local-list-type + (org-close-li (car local-list-type)) + (insert (format "</%sl>\n" (car local-list-type))) + (pop local-list-type)) (setq local-list-indent nil in-local-list nil)) (setq first-heading-pos (or first-heading-pos (point))) @@ -2661,11 +3084,17 @@ lang=\"%s\" xml:lang=\"%s\"> (t (error "Invalid value of `org-plain-list-ordered-item-terminator'"))) line) (setq ind (org-get-string-indentation line) - start-is-num (match-beginning 4) + item-type (if (match-beginning 4) "o" "u") starter (if (match-beginning 2) (substring (match-string 2 line) 0 -1)) - line (substring line (match-beginning 5))) - (unless (string-match "[^ \t]" line) + line (substring line (match-beginning 5)) + item-tag nil) + (if (and starter (string-match "\\(.*?\\) ::[ \t]*" line)) + (setq item-type "d" + item-tag (match-string 1 line) + line (substring line (match-end 0)))) + (when (and (not (equal item-type "d")) + (not (string-match "[^ \t]" line))) ;; empty line. Pretend indentation is large. (setq ind (if org-empty-line-terminates-plain-lists 0 @@ -2676,9 +3105,9 @@ lang=\"%s\" xml:lang=\"%s\"> (not starter)) (< ind (car local-list-indent)))) (setq didclose t) - (org-close-li) - (insert (if (car local-list-num) "</ol>\n" "</ul>")) - (pop local-list-num) (pop local-list-indent) + (org-close-li (car local-list-type)) + (insert (format "</%sl>\n" (car local-list-type))) + (pop local-list-type) (pop local-list-indent) (setq in-local-list local-list-indent)) (cond ((and starter @@ -2686,14 +3115,21 @@ lang=\"%s\" xml:lang=\"%s\"> (> ind (car local-list-indent)))) ;; Start new (level of) list (org-close-par-maybe) - (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n")) - (push start-is-num local-list-num) + (insert (cond + ((equal item-type "u") "<ul>\n<li>\n") + ((equal item-type "o") "<ol>\n<li>\n") + ((equal item-type "d") + (format "<dl>\n<dt>%s</dt><dd>\n" item-tag)))) + (push item-type local-list-type) (push ind local-list-indent) (setq in-local-list t)) (starter ;; continue current list - (org-close-li) - (insert "<li>\n")) + (org-close-li (car local-list-type)) + (insert (cond + ((equal (car local-list-type) "d") + (format "<dt>%s</dt><dd>\n" (or item-tag "???"))) + (t "<li>\n")))) (didclose ;; we did close a list, normal text follows: need <p> (org-open-par))) @@ -2716,7 +3152,8 @@ lang=\"%s\" xml:lang=\"%s\"> (org-close-par-maybe) (let ((n (match-string 1 line))) (setq line (replace-match - (format "<p class=\"footnote\"><sup><a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a></sup>" n n n) t t line))))) + (format "<p class=\"footnote\"><sup><a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a></sup>" n n n) t t line)) + (setq line (concat line "</p>"))))) ;; Check if the line break needs to be conserved (cond @@ -2731,10 +3168,10 @@ lang=\"%s\" xml:lang=\"%s\"> (when inquote (insert "</pre>\n")) (when in-local-list ;; Close any local lists before inserting a new header line - (while local-list-num - (org-close-li) - (insert (if (car local-list-num) "</ol>\n" "</ul>\n")) - (pop local-list-num)) + (while local-list-type + (org-close-li (car local-list-type)) + (insert (format "</%sl>\n" (car local-list-type))) + (pop local-list-type)) (setq local-list-indent nil in-local-list nil)) (org-html-level-start 1 nil umax @@ -2762,6 +3199,8 @@ lang=\"%s\" xml:lang=\"%s\"> (insert "<p class=\"date\"> " (nth 2 lang-words) ": " date "</p>\n")) + (insert (format "<p>HTML generated by org-mode %s in emacs %s<\p>\n" + org-version emacs-major-version)) (insert "</div>")) (if org-export-html-with-timestamp @@ -3106,6 +3545,54 @@ But it has the disadvantage, that Org-mode's HTML conversions cannot be used." (setq r (concat r "@<br/>"))) r)))) +(defun org-export-htmlize-region-for-paste (beg end) + "Convert the region to HTML, using htmlize.el. +This is much like `htmlize-region-for-paste', only that it uses +the settings define in the org-... variables." + (let* ((htmlize-output-type org-export-htmlize-output-type) + (htmlize-css-name-prefix org-export-htmlize-css-font-prefix) + (htmlbuf (htmlize-region beg end))) + (unwind-protect + (with-current-buffer htmlbuf + (buffer-substring (plist-get htmlize-buffer-places 'content-start) + (plist-get htmlize-buffer-places 'content-end))) + (kill-buffer htmlbuf)))) + +;;;###autoload +(defun org-export-htmlize-generate-css () + "Create the CSS for all font definitions in the current Emacs session. +Use this to create face definitions in your CSS style file that can then +be used by code snippets transformed by htmlize. +This command just produces a buffer that contains class definitions for all +faces used in the current Emacs session. You can copy and paste the ones you +need into your CSS file. + +If you then set `org-export-htmlize-output-type' to `css', calls to +the function `org-export-htmlize-region-for-paste' will produce code +that uses these same face definitions." + (interactive) + (require 'htmlize) + (and (get-buffer "*html*") (kill-buffer "*html*")) + (with-temp-buffer + (let ((fl (face-list)) + (htmlize-css-name-prefix "org-") + (htmlize-output-type 'css) + f i) + (while (setq f (pop fl) + i (and f (face-attribute f :inherit))) + (when (and (symbolp f) (or (not i) (not (listp i)))) + (insert (org-add-props (copy-sequence "1") nil 'face f)))) + (htmlize-region (point-min) (point-max)))) + (switch-to-buffer "*html*") + (goto-char (point-min)) + (if (re-search-forward "<style" nil t) + (delete-region (point-min) (match-beginning 0))) + (if (re-search-forward "</style>" nil t) + (delete-region (1+ (match-end 0)) (point-max))) + (beginning-of-line 1) + (if (looking-at " +") (replace-match "")) + (goto-char (point-min))) + (defun org-html-protect (s) ;; convert & to &, < to < and > to > (let ((start 0)) @@ -3280,10 +3767,10 @@ stacked delimiters is N. Escaping delimiters is not possible." (when org-par-open (insert "</p>") (setq org-par-open nil))) -(defun org-close-li () +(defun org-close-li (&optional type) "Close <li> if necessary." (org-close-par-maybe) - (insert "</li>\n")) + (insert (if (equal type "d") "</dd>\n" "</li>\n"))) (defvar body-only) ; dynamically scoped into this. (defun org-html-level-start (level title umax with-toc head-count) @@ -3417,12 +3904,17 @@ file and store it under the name `org-combined-agenda-icalendar-file'." (when (or (and combine (not files)) (not combine)) (org-finish-icalendar-file) (set-buffer ical-buffer) + (run-hooks 'org-before-save-iCalendar-file-hook) (save-buffer) (run-hooks 'org-after-save-iCalendar-file-hook) (and (boundp 'org-wait) (numberp org-wait) (sit-for org-wait)) )))) (org-release-buffers org-agenda-new-buffers)))) +(defvar org-before-save-iCalendar-file-hook nil + "Hook run before an iCalendar file has been saved. +This can be used to modify the result of the export.") + (defvar org-after-save-iCalendar-file-hook nil "Hook run after an iCalendar file has been saved. The iCalendar buffer is still current when this hook is run. @@ -3440,7 +3932,8 @@ When COMBINE is non nil, add the category to each line." (format-time-string (cdr org-time-stamp-formats) (current-time)) "DTSTART")) hd ts ts2 state status (inc t) pos b sexp rrule - scheduledp deadlinep tmp pri category entry location summary desc + scheduledp deadlinep prefix + tmp pri category entry location summary desc uid (sexp-buffer (get-buffer-create "*ical-tmp*"))) (org-refresh-category-properties) (save-excursion @@ -3456,7 +3949,9 @@ When COMBINE is non nil, add the category to each line." (setq pos (match-beginning 0) ts (match-string 0) inc t - hd (condition-case nil (org-get-heading) + hd (condition-case nil + (org-icalendar-cleanup-string + (org-get-heading)) (error (throw :skip nil))) summary (org-icalendar-cleanup-string (org-entry-get nil "SUMMARY")) @@ -3466,11 +3961,16 @@ When COMBINE is non nil, add the category to each line." t org-icalendar-include-body) location (org-icalendar-cleanup-string (org-entry-get nil "LOCATION")) - category (org-get-category)) + uid (if org-icalendar-store-UID + (org-id-get-create) + (or (org-id-get) (org-id-new))) + category (org-get-category) + deadlinep nil scheduledp nil) (if (looking-at re2) (progn (goto-char (match-end 0)) - (setq ts2 (match-string 1) inc nil)) + (setq ts2 (match-string 1) + inc (not (string-match "[0-9]\\{1,2\\}:[0-9][0-9]" ts2)))) (setq tmp (buffer-substring (max (point-min) (- pos org-ds-keyword-length)) pos) @@ -3483,6 +3983,7 @@ When COMBINE is non nil, add the category to each line." scheduledp (string-match org-scheduled-regexp tmp) ;; donep (org-entry-is-done-p) )) + (setq prefix (if deadlinep "DL-" (if scheduledp "SC-" "TS-"))) (if (or (string-match org-tr-regexp hd) (string-match org-ts-regexp hd)) (setq hd (replace-match "" t t hd))) @@ -3500,19 +4001,21 @@ When COMBINE is non nil, add the category to each line." (setq summary (replace-match (if (match-end 3) (match-string 3 summary) - (match-string 1 summary)) - t t summary))) + (match-string 1 summary)) + t t summary))) (if deadlinep (setq summary (concat "DL: " summary))) (if scheduledp (setq summary (concat "S: " summary))) (if (string-match "\\`<%%" ts) (with-current-buffer sexp-buffer (insert (substring ts 1 -1) " " summary "\n")) (princ (format "BEGIN:VEVENT +UID: %s %s %s%s SUMMARY:%s%s%s CATEGORIES:%s END:VEVENT\n" + (concat prefix uid) (org-ical-ts-to-string ts "DTSTART") (org-ical-ts-to-string ts2 "DTEND" inc) rrule summary @@ -3521,7 +4024,6 @@ END:VEVENT\n" (if (and location (string-match "\\S-" location)) (concat "\nLOCATION: " location) "") category))))) - (when (and org-icalendar-include-sexps (condition-case nil (require 'icalendar) (error nil)) (fboundp 'icalendar-export-region)) @@ -3536,10 +4038,12 @@ END:VEVENT\n" (end-of-line 1) (setq sexp (buffer-substring b (point))) (with-current-buffer sexp-buffer - (insert sexp "\n")) - (princ (org-diary-to-ical-string sexp-buffer))))) - + (insert sexp "\n")))) + (princ (org-diary-to-ical-string sexp-buffer)) + (kill-buffer sexp-buffer)) + (when org-icalendar-include-todo + (setq prefix "TODO-") (goto-char (point-min)) (while (re-search-forward org-todo-line-regexp nil t) (catch :skip @@ -3565,7 +4069,10 @@ END:VEVENT\n" (and org-icalendar-include-body (org-get-entry))) t org-icalendar-include-body) location (org-icalendar-cleanup-string - (org-entry-get nil "LOCATION"))) + (org-entry-get nil "LOCATION")) + uid (if org-icalendar-store-UID + (org-id-get-create) + (or (org-id-get) (org-id-new)))) (if (string-match org-bracket-link-regexp hd) (setq hd (replace-match (if (match-end 3) (match-string 3 hd) (match-string 1 hd)) @@ -3579,6 +4086,7 @@ END:VEVENT\n" (- org-lowest-priority org-highest-priority)))))) (princ (format "BEGIN:VTODO +UID: %s %s SUMMARY:%s%s%s CATEGORIES:%s @@ -3586,13 +4094,15 @@ SEQUENCE:1 PRIORITY:%d STATUS:%s END:VTODO\n" + (concat prefix uid) dts (or summary hd) (if (and location (string-match "\\S-" location)) (concat "\nLOCATION: " location) "") (if (and desc (string-match "\\S-" desc)) (concat "\nDESCRIPTION: " desc) "") - category pri status))))))))) + category + pri status))))))))) (defun org-icalendar-cleanup-string (s &optional is-body maxlength) "Take out stuff and quote what needs to be quoted. @@ -3607,7 +4117,7 @@ characters." (while (string-match re s) (setq s (replace-match "" t t s))) (while (string-match re2 s) (setq s (replace-match "" t t s))))) (let ((start 0)) - (while (string-match "\\([,;\\]\\)" s start) + (while (string-match "\\([,;]\\)" s start) (setq start (+ (match-beginning 0) 2) s (replace-match "\\\\\\1" nil nil s)))) (when is-body @@ -3756,12 +4266,7 @@ The XOXO buffer is named *xoxo-<source buffer name>*" (provide 'org-exp) -;;; org-exp.el ends here +;; arch-tag: 65985fe9-095c-49c7-a7b6-cb4ee15c0a95 +;;; org-exp.el ends here -(defun org-export-process-option-filters (plist) - (let ((functions org-export-options-filters) f) - (while (setq f (pop functions)) - (setq plist (funcall f plist)))) - plist) -;; arch-tag: 65985fe9-095c-49c7-a7b6-cb4ee15c0a95 diff --git a/lisp/org/org-export-latex.el b/lisp/org/org-export-latex.el index 1c05e5fc913..11354fcd501 100644 --- a/lisp/org/org-export-latex.el +++ b/lisp/org/org-export-latex.el @@ -4,7 +4,7 @@ ;; ;; Emacs Lisp Archive Entry ;; Filename: org-export-latex.el -;; Version: 6.02b +;; Version: 6.05a ;; Author: Bastien Guerry <bzg AT altern DOT org> ;; Maintainer: Bastien Guerry <bzg AT altern DOT org> ;; Keywords: org, wp, tex @@ -361,12 +361,19 @@ when PUB-DIR is set, use this as the publishing directory." (let* ((wcf (current-window-configuration)) (opt-plist org-export-latex-options-plist) (region-p (org-region-active-p)) + (rbeg (and region-p (region-beginning))) + (rend (and region-p (region-end))) (subtree-p (when region-p (save-excursion - (goto-char (region-beginning)) + (goto-char rbeg) (and (org-at-heading-p) - (>= (org-end-of-subtree t t) (region-end)))))) + (>= (org-end-of-subtree t t) rend))))) + (opt-plist (if subtree-p + (org-export-add-subtree-options opt-plist rbeg) + opt-plist)) + ;; Make sure the variable contains the updated values. + (org-export-latex-options-plist opt-plist) (title (or (and subtree-p (org-export-get-title-from-subtree)) (plist-get opt-plist :title) (and (not @@ -378,8 +385,11 @@ when PUB-DIR is set, use this as the publishing directory." (or pub-dir (org-export-directory :LaTeX ext-plist))) (file-name-sans-extension - (file-name-nondirectory ;sans-extension - buffer-file-name)) ".tex")) + (or (and subtree-p + (org-entry-get rbeg "EXPORT_FILE_NAME" t)) + (file-name-nondirectory ;sans-extension + buffer-file-name))) + ".tex")) (filename (if (equal (file-truename filename) (file-truename buffer-file-name)) (concat filename ".tex") @@ -1094,6 +1104,22 @@ Regexps are those from `org-export-latex-special-string-regexps'." (replace-match (org-export-latex-protect-string (concat (match-string 1) "\\LaTeX{}")) t t))) + ;; Convert blockquotes + (goto-char (point-min)) + (while (re-search-forward "^#\\+BEGIN_QUOTE" nil t) + (replace-match "\\begin{quote}" t t)) + (goto-char (point-min)) + (while (re-search-forward "^#\\+END_QUOTE" nil t) + (replace-match "\\end{quote}" t t)) + + ;; Convert verse + (goto-char (point-min)) + (while (re-search-forward "^#\\+BEGIN_VERSE" nil t) + (replace-match "\\begin{verse}" t t)) + (goto-char (point-min)) + (while (re-search-forward "^#\\+END_VERSE" nil t) + (replace-match "\\end{verse}" t t)) + ;; Convert horizontal rules (goto-char (point-min)) (while (re-search-forward "^----+.$" nil t) @@ -1538,4 +1564,5 @@ Valid parameters are (provide 'org-export-latex) ;; arch-tag: 23c2b87d-da04-4c2d-ad2d-1eb6487bc3ad + ;;; org-export-latex.el ends here diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el index 8764fa5e319..102bec9db05 100644 --- a/lisp/org/org-faces.el +++ b/lisp/org/org-faces.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -148,13 +148,41 @@ color of the frame." (defface org-column (org-compatible-face nil '((((class color) (min-colors 16) (background light)) - (:background "grey90")) + (:background "grey90" :weight normal :slant normal :strike-through nil + :underline nil)) (((class color) (min-colors 16) (background dark)) - (:background "grey30")) + (:background "grey30" :weight normal :slant normal :strike-through nil + :underline nil)) (((class color) (min-colors 8)) - (:background "cyan" :foreground "black")) + (:background "cyan" :foreground "black" + :weight normal :slant normal :strike-through nil + :underline nil)) (t (:inverse-video t)))) - "Face for column display of entry properties." + "Face for column display of entry properties. +This is actually only part of the face definition for the text in column view. +The following faces apply, with this priority. + +1. The color of the reference face. This is normally the level fact that + is used in the outline. In agenda-mode, it will be the face of the + first character in the line. The color is explicitly retained to + make sure that the column line still looks a bit like the structure + line it is masking. + +2. The `org-column' face. + +3. The remaining properties of the reference face. + +Since column view works by putting overlays with a display property +over individual characters in the buffer, the face of the underlining +character (this might for example be the a TODO keyword) might still +shine through in some properties. So when your column view looks +funny, with \"random\" colors, weight, strike-through, try to explicitly +set the properties in the `org-column' face. For example, set +:underline to nil, or the :slant to `normal'. + +Under XEmacs, the rules are simpler, because the XEmacs version of +column view defines special faces for each outline level. See the file +`org-colview-xemacs.el' for details." :group 'org-faces) (defface org-column-title @@ -457,4 +485,5 @@ If it is less than 8, the level-1 face gets re-used for level N+1 etc." (provide 'org-faces) ;; arch-tag: 9dab5f91-c4b9-4d6f-bac3-1f6211ad0a04 + ;;; org-faces.el ends here diff --git a/lisp/org/org-gnus.el b/lisp/org/org-gnus.el index 280804a8cf0..e006f854e3d 100644 --- a/lisp/org/org-gnus.el +++ b/lisp/org/org-gnus.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -125,4 +125,5 @@ negates this setting for the duration of the command." (provide 'org-gnus) ;; arch-tag: 512e0840-58fa-45b3-b456-71e10fa2376d + ;;; org-gnus.el ends here diff --git a/lisp/org/org-info.el b/lisp/org/org-info.el index cdc0b579864..a81eaa793da 100644 --- a/lisp/org/org-info.el +++ b/lisp/org/org-info.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -78,4 +78,5 @@ (provide 'org-info) ;; arch-tag: 1e289f54-7176-487f-b575-dd4854bab15e + ;;; org-info.el ends here diff --git a/lisp/org/org-irc.el b/lisp/org/org-irc.el index 5704929ffbb..16a677c7ba2 100644 --- a/lisp/org/org-irc.el +++ b/lisp/org/org-irc.el @@ -4,7 +4,7 @@ ;; ;; Author: Philip Jackson <emacs@shellarchive.co.uk> ;; Keywords: erc, irc, link, org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -252,4 +252,5 @@ default." (provide 'org-irc) ;; arch-tag: 018d7dda-53b8-4a35-ba92-6670939e525a + ;;; org-irc.el ends here diff --git a/lisp/org/org-jsinfo.el b/lisp/org/org-jsinfo.el index 6eebf96d64a..337886c057c 100644 --- a/lisp/org/org-jsinfo.el +++ b/lisp/org/org-jsinfo.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -66,6 +66,7 @@ line in the buffer. See also the variable `org-infojs-options'." '((path PATH "http://orgmode.org/org-info.js") (view VIEW "info") (toc TOC :table-of-contents) + (ftoc FIXED_TOC "0") (tdepth TOC_DEPTH "max") (sdepth SECTION_DEPTH "max") (mouse MOUSE_HINT "underline") @@ -200,6 +201,8 @@ Option settings will replace the %MANAGER-OPTIONS cookie." (cdr (assoc 'path org-infojs-options)))) (provide 'org-infojs) +(provide 'org-jsinfo) ;; arch-tag: c71d1d85-3337-4817-a066-725e74ac9eac + ;;; org-jsinfo.el ends here diff --git a/lisp/org/org-mac-message.el b/lisp/org/org-mac-message.el index 758a345c82d..8f1607ffc47 100644 --- a/lisp/org/org-mac-message.el +++ b/lisp/org/org-mac-message.el @@ -3,7 +3,7 @@ ;; Copyright (C) 2008 Free Software Foundation, Inc. ;; Author: John Wiegley <johnw@gnu.org> -;; Version: 6.02b +;; Version: 6.05a ;; Keywords: outlines, hypermedia, calendar, wp ;; This file is part of GNU Emacs. @@ -79,4 +79,5 @@ end tell"))) (provide 'org-mac-message) ;; arch-tag: 3806d0c1-abe1-4db6-9c31-f3ed7d4a9b32 + ;;; org-mac-message.el ends here diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el index e9d0edb41c8..3434c57ec7b 100644 --- a/lisp/org/org-macs.el +++ b/lisp/org/org-macs.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -89,9 +89,9 @@ We use a macro so that the test can happen at compilation time." (defmacro org-with-point-at (pom &rest body) "Move to buffer and point of point-or-marker POM for the duration of BODY." `(save-excursion - (if (markerp pom) (set-buffer (marker-buffer pom))) + (if (markerp ,pom) (set-buffer (marker-buffer ,pom))) (save-excursion - (goto-char (or pom (point))) + (goto-char (or ,pom (point))) ,@body))) (defmacro org-no-warnings (&rest body) @@ -220,4 +220,5 @@ This is in contrast to merely setting it to 0." (provide 'org-macs) ;; arch-tag: 7e6a73ce-aac9-4fc0-9b30-ce6f89dc6668 + ;;; org-macs.el ends here diff --git a/lisp/org/org-mew.el b/lisp/org/org-mew.el index e3fba77d5e4..655e344e4ff 100644 --- a/lisp/org/org-mew.el +++ b/lisp/org/org-mew.el @@ -5,7 +5,7 @@ ;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; This file is part of GNU Emacs. @@ -123,4 +123,5 @@ (provide 'org-mew) ;; arch-tag: 07ccdca7-6020-4941-a593-588a1e51b870 + ;;; org-mew.el ends here diff --git a/lisp/org/org-mhe.el b/lisp/org/org-mhe.el index c29ea9d98c3..66f1bcc31a8 100644 --- a/lisp/org/org-mhe.el +++ b/lisp/org/org-mhe.el @@ -5,7 +5,7 @@ ;; Author: Thomas Baumann <thomas dot baumann at ch dot tum dot de> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -71,6 +71,7 @@ supported by MH-E." (defvar mh-show-folder-buffer) (defvar mh-index-folder) (defvar mh-searcher) +(defvar mh-search-regexp-builder) ;; Install the link type (org-add-link-type "mhe" 'org-mhe-open) @@ -137,11 +138,11 @@ So if you use sequences, it will now work." ))) (defun org-mhe-get-message-folder-from-index () - "Return the name of the message folder in a index folder buffer." + "Return the name of the message folder in an index folder buffer." (save-excursion (mh-index-previous-folder) - (re-search-forward "^\\(+.*\\)$" nil t) - (message "%s" (match-string 1)))) + (if (re-search-forward "^\\(+.*\\)$" nil t) + (message "%s" (match-string 1))))) (defun org-mhe-get-message-folder () "Return the name of the current message folder. @@ -194,16 +195,19 @@ folders." (mh-find-path) (if (not article) (mh-visit-folder (mh-normalize-folder-name folder)) - (setq article (org-add-angle-brackets article)) (mh-search-choose) (if (equal mh-searcher 'pick) (progn + (setq article (org-add-angle-brackets article)) (mh-search folder (list "--message-id" article)) (when (and org-mhe-search-all-folders (not (org-mhe-get-message-real-folder))) (kill-this-buffer) (mh-search "+" (list "--message-id" article)))) - (mh-search "+" article)) + (if mh-search-regexp-builder + (mh-search "+" (funcall mh-search-regexp-builder + (list (cons 'message-id article)))) + (mh-search "+" article))) (if (org-mhe-get-message-real-folder) (mh-show-msg 1) (kill-this-buffer) @@ -212,4 +216,5 @@ folders." (provide 'org-mhe) ;; arch-tag: dcb05484-8627-491d-a8c1-01dbd2bde4ae + ;;; org-mhe.el ends here diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el index 3be478b072e..623afac29fc 100644 --- a/lisp/org/org-mouse.el +++ b/lisp/org/org-mouse.el @@ -4,7 +4,7 @@ ;; ;; Author: Piotr Zielinski <piotr dot zielinski at gmail dot com> ;; Maintainer: Carsten Dominik <carsten at orgmode dot org> -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -1113,3 +1113,5 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" (provide 'org-mouse) ;; arch-tag: ff1ae557-3529-41a3-95c6-baaebdcc280f + +;;; org-mouse.el ends-here diff --git a/lisp/org/org-publish.el b/lisp/org/org-publish.el index 351b11e31a6..65c49e7b9c9 100644 --- a/lisp/org/org-publish.el +++ b/lisp/org/org-publish.el @@ -4,7 +4,7 @@ ;; Author: David O'Toole <dto@gnu.org> ;; Maintainer: Bastien Guerry <bzg AT altern DOT org> ;; Keywords: hypermedia, outlines, wp -;; Version: 6.02b +;; Version: 6.05a ;; This file is part of GNU Emacs. ;; @@ -149,15 +149,17 @@ (eval-when-compile (require 'cl)) +(require 'org) +(require 'org-exp) (eval-and-compile (unless (fboundp 'declare-function) (defmacro declare-function (fn file &optional arglist fileonly)))) (defgroup org-publish nil - "Options for publishing a set of Org-mode and related files." - :tag "Org Publishing" - :group 'org) + "Options for publishing a set of Org-mode and related files." + :tag "Org Publishing" + :group 'org) (defcustom org-publish-project-alist nil "Association list to control publishing behavior. @@ -195,8 +197,8 @@ being published. Its value may be a string or regexp matching file names you don't want to be published. The :include property may be used to include extra files. Its -value may be a list of filenames to include. The filenames are -considered relative to the publishing directory. +value may be a list of filenames to include. The filenames are +considered relative to the base directory. When both :include and :exclude properties are given values, the exclusion step happens first. @@ -219,6 +221,8 @@ certain makefile, to ensure published files are built up to date. :preparation-function Function to be called before publishing this project. + :completion-function Function to be called after publishing + this project. Some properties control details of the Org publishing process, and are equivalent to the corresponding user variables listed in @@ -449,6 +453,11 @@ matching filenames." ;; FIXME distinguish exclude regexp ;; for skip-file and skip-dir? exclude-regexp exclude-regexp) + (mapc (lambda (f) + (pushnew + (expand-file-name (concat base-dir f)) + org-publish-temp-files)) + include-list) org-publish-temp-files)) (defun org-publish-get-project-from-filename (filename) @@ -512,6 +521,8 @@ See `org-publish-org-to' to the list of arguments." (require 'eshell) (require 'esh-maint) (require 'em-unix)) + (unless (file-directory-p pub-dir) + (make-directory pub-dir t)) (eshell/cp filename pub-dir)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -559,19 +570,22 @@ See `org-publish-org-to' to the list of arguments." If :auto-index is set, publish the index too." (mapc (lambda (project) - (let* ((project-plist (cdr project)) - (exclude-regexp (plist-get project-plist :exclude)) - (index-p (plist-get project-plist :auto-index)) - (index-filename (or (plist-get project-plist :index-filename) - "index.org")) - (index-function (or (plist-get project-plist :index-function) - 'org-publish-org-index)) - (preparation-function (plist-get project-plist :preparation-function)) - (files (org-publish-get-base-files project exclude-regexp)) file) + (let* + ((project-plist (cdr project)) + (exclude-regexp (plist-get project-plist :exclude)) + (index-p (plist-get project-plist :auto-index)) + (index-filename (or (plist-get project-plist :index-filename) + "index.org")) + (index-function (or (plist-get project-plist :index-function) + 'org-publish-org-index)) + (preparation-function (plist-get project-plist :preparation-function)) + (completion-function (plist-get project-plist :completion-function)) + (files (org-publish-get-base-files project exclude-regexp)) file) (when preparation-function (funcall preparation-function)) (if index-p (funcall index-function project index-filename)) (while (setq file (pop files)) - (org-publish-file file project)))) + (org-publish-file file project)) + (when completion-function (funcall completion-function)))) (org-publish-expand-projects projects))) (defun org-publish-org-index (project &optional index-filename) @@ -581,9 +595,13 @@ Default for INDEX-FILENAME is 'index.org'." (let* ((project-plist (cdr project)) (dir (file-name-as-directory (plist-get project-plist :base-directory))) + (localdir (file-name-directory dir)) + (indent-str (make-string 2 ?\ )) (exclude-regexp (plist-get project-plist :exclude)) - (files (org-publish-get-base-files project exclude-regexp)) + (files (nreverse (org-publish-get-base-files project exclude-regexp))) (index-filename (concat dir (or index-filename "index.org"))) + (index-title (or (plist-get project-plist :index-title) + (concat "Index for project " (car project)))) (index-buffer (find-buffer-visiting index-filename)) (ifn (file-name-nondirectory index-filename)) file) @@ -591,16 +609,47 @@ Default for INDEX-FILENAME is 'index.org'." (if index-buffer (kill-buffer index-buffer)) (with-temp-buffer + (insert (concat index-title "\n\n")) (while (setq file (pop files)) - (let ((fn (file-name-nondirectory file))) + (let ((fn (file-name-nondirectory file)) + (link (file-relative-name file dir)) + (oldlocal localdir)) ;; index shouldn't index itself (unless (string= fn ifn) - (insert (concat " + [[file:" fn "][" + (setq localdir (concat (file-name-as-directory dir) + (file-name-directory link))) + (unless (string= localdir oldlocal) + (if (string= localdir dir) + (setq indent-str (make-string 2 ?\ )) + (let ((subdirs + (split-string + (directory-file-name + (file-name-directory + (file-relative-name localdir dir))) "/")) + (subdir "")) + (setq indent-str (make-string 2 ?\ )) + (dolist (d subdirs) + (setq subdir (concat subdir d "/")) + (insert (concat indent-str " + [[file:" subdir "][" d "/]]\n")) + (setq indent-str (make-string (+ (length indent-str) 2) ?\ )))))) + (insert (concat indent-str " + [[file:" link "][" (file-name-sans-extension fn) "]]\n"))))) (write-file index-filename) (kill-buffer (current-buffer))))) +(defun org-publish-find-title (file) + "Find the title of file in project." + (save-excursion + (set-buffer (find-file-noselect file)) + (let* ((opt-plist (org-combine-plists (org-default-export-plist) + (org-infile-export-plist)))) + (or (plist-get opt-plist :title) + (and (not + (plist-get opt-plist :skip-before-1st-heading)) + (org-export-grab-title-from-buffer)) + (file-name-sans-extension file))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Interactive publishing functions @@ -663,4 +712,5 @@ the project." ;; arch-tag: 72807f3c-8af0-4a6b-8dca-c3376eb25adb + ;;; org-publish.el ends here diff --git a/lisp/org/org-remember.el b/lisp/org/org-remember.el index 8a9bcecef66..a97fd647337 100644 --- a/lisp/org/org-remember.el +++ b/lisp/org/org-remember.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -50,9 +50,12 @@ :group 'org) (defcustom org-remember-store-without-prompt t - "Non-nil means, `C-c C-c' stores remember note without further promts. -In this case, you need `C-u C-c C-c' to get the prompts for -note file and headline. + "Non-nil means, `C-c C-c' stores remember note without further prompts. +It then uses the file and headline specified by the template or (if the +themplate does not specify them) by the variables `org-default-notes-file' +and `org-remember-default-headline'. To force prompting anyway, use +`C-u C-c C-c' to file the note. + When this variable is nil, `C-c C-c' gives you the prompts, and `C-u C-c C-c' triggers the fasttrack." :group 'org-remember @@ -99,13 +102,16 @@ it will be interpreted relative to `org-directory'. An optional fifth element can specify the headline in that file that should be offered first when the user is asked to file the entry. The default -headline is given in the variable `org-remember-default-headline'. +headline is given in the variable `org-remember-default-headline'. When +this element is `top' or `bottom', the note will be placed as a level-1 +entry at the beginning or end of the file, respectively. -An optional sixth element specifies the contexts in which the user can -select the template. This element can be either a list of major modes -or a function. `org-remember' will first check whether the function -returns `t' or if we are in any of the listed major modes, and select -the template accordingly. +An optional sixth element specifies the contexts in which the template +will be offered to the user. This element can be a list of major modes +or a function, and the template will only be offered if `org-remember' +is called from a mode in the list, or if the function returns t. +Templates that specify t or nil for the context will be always be added +to the list of selectable templates. The template specifies the structure of the remember buffer. It should have a first line starting with a star, to act as the org-mode headline. @@ -117,19 +123,23 @@ Furthermore, the following %-escapes will be replaced with content: %t time stamp, date only %T time stamp with date and time %u, %U like the above, but inactive time stamps - %^t like %t, but prompt for date. Similarly %^T, %^u, %^U - You may define a prompt like %^{Please specify birthday}t + %^t like %t, but prompt for date. Similarly %^T, %^u, %^U. + You may define a prompt like %^{Please specify birthday %n user name (taken from `user-full-name') %a annotation, normally the link created with org-store-link %i initial content, the region active. If %i is indented, the entire inserted text will be indented as well. - %c content of the clipboard, or current kill ring head + %c current kill ring head + %x content of the X clipboard + %^C Interactive selection of which kill or clip to use + %^L Like %^C, but insert as link %^g prompt for tags, with completion on tags in target file %^G prompt for tags, with completion all tags in all agenda files %:keyword specific information for certain link types, see below %[pathname] insert the contents of the file given by `pathname' %(sexp) evaluate elisp `(sexp)' and replace with the result %! Store this note immediately after filling the template + %& Visit note immediately after storing it %? After completing the template, position cursor here. @@ -164,19 +174,34 @@ calendar | %:type %:date" (string :tag "Name") (character :tag "Selection Key") (string :tag "Template") - (choice - (file :tag "Destination file") - (const :tag "Prompt for file" nil)) - (choice - (string :tag "Destination headline") - (const :tag "Selection interface for heading")) - (choice - (const :tag "Use by default" nil) + (choice :tag "Destination file" + (file :tag "Specify") + (const :tag "Use `org-default-notes-file'" nil)) + (choice :tag "Destin. headline" + (string :tag "Specify") + (const :tag "Use `org-remember-default-headline'" nil) + (const :tag "Level 1 at beginning of file" top) + (const :tag "Level 1 at end of file" bottom)) + (choice :tag "Context" + (const :tag "Use in all contexts" nil) (const :tag "Use in all contexts" t) (repeat :tag "Use only if in major mode" (symbol :tag "Major mode")) (function :tag "Perform a check against function"))))) +(defcustom org-remember-clock-out-on-exit 'query + "Non-nil means, stop the clock when exiting a clocking remember buffer. +This only applies if the clock is running in the remember buffer. If the +clock is not stopped, it continues to run in the storage location. +Instead of nil or t, this may also be the symbol `query' to prompt the +user each time a remember buffer with a running clock is filed away. " + :group 'org-remember + :type '(choice + (const :tag "Never" nil) + (const :tag "Always" t) + (const :tag "Query user" query))) + + (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode' (defvar initial) ; from remember.el, dynamically scoped in `remember-mode' @@ -203,6 +228,7 @@ RET on headline -> Store as sublevel entry to current headline RET at beg-of-buf -> Append to file as level 2 headline <left>/<right> -> before/after current headline, same headings level") +(defvar org-jump-to-target-location nil) (defvar org-remember-previous-location nil) (defvar org-force-remember-template-char) ;; dynamically scoped @@ -289,6 +315,7 @@ This function should be placed into `remember-mode-hook' and in fact requires to be run from that hook to function properly." (if org-remember-templates (let* ((entry (org-select-remember-template use-char)) + (ct (or org-overriding-default-time (org-current-time))) (tpl (car entry)) (plist-p (if org-store-link-plist t nil)) (file (if (and (nth 1 entry) (stringp (nth 1 entry)) @@ -300,8 +327,8 @@ to be run from that hook to function properly." (v-x (or (org-get-x-clipboard 'PRIMARY) (org-get-x-clipboard 'CLIPBOARD) (org-get-x-clipboard 'SECONDARY))) - (v-t (format-time-string (car org-time-stamp-formats) (org-current-time))) - (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time))) + (v-t (format-time-string (car org-time-stamp-formats) ct)) + (v-T (format-time-string (cdr org-time-stamp-formats) ct)) (v-u (concat "[" (substring v-t 1 -1) "]")) (v-U (concat "[" (substring v-T 1 -1) "]")) ;; `initial' and `annotation' are bound in `remember' @@ -394,11 +421,11 @@ to be run from that hook to function properly." (org-set-local 'org-finish-function 'org-remember-finalize) (if (and file (string-match "\\S-" file) (not (file-directory-p file))) (org-set-local 'org-default-notes-file file)) - (if (and headline (stringp headline) (string-match "\\S-" headline)) + (if headline (org-set-local 'org-remember-default-headline headline)) ;; Interactive template entries (goto-char (point-min)) - (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([gGuUtTCL]\\)?" nil t) + (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([gGtTuUCL]\\)?" nil t) (setq char (if (match-end 3) (match-string 3)) prompt (if (match-end 2) (match-string 2))) (goto-char (match-beginning 0)) @@ -444,6 +471,7 @@ to be run from that hook to function properly." '(clipboards . 1) (car clipboards)))))) (char + ;; These are the date/time related ones (setq org-time-was-given (equal (upcase char) char)) (setq time (org-read-date (equal (upcase char) "U") t nil prompt)) @@ -464,6 +492,11 @@ to be run from that hook to function properly." (org-set-local 'org-finish-function 'org-remember-finalize)) (when (save-excursion (goto-char (point-min)) + (re-search-forward "%&" nil t)) + (replace-match "") + (org-set-local 'org-jump-to-target-location t)) + (when (save-excursion + (goto-char (point-min)) (re-search-forward "%!" nil t)) (replace-match "") (add-hook 'post-command-hook 'org-remember-finish-immediately 'append))) @@ -476,15 +509,34 @@ from that hook." (when org-finish-function (funcall org-finish-function))) -(defvar org-clock-marker) ; Defined below +(defun org-remember-visit-immediately () + "File remember note immediately. +This should be run in `post-command-hook' and will remove itself +from that hook." + (org-remember '(16)) + (goto-char (or (text-property-any + (point) (save-excursion (org-end-of-subtree t t)) + 'org-position-cursor t) + (point))) + (message "%s" + (format + (substitute-command-keys + "Restore window configuration with \\[jump-to-register] %c") + remember-register))) + +(defvar org-clock-marker) ; Defined in org.el (defun org-remember-finalize () "Finalize the remember process." (unless (fboundp 'remember-finalize) (defalias 'remember-finalize 'remember-buffer)) (when (and org-clock-marker (equal (marker-buffer org-clock-marker) (current-buffer))) - ;; FIXME: test this, this is w/o notetaking! - (let (org-log-note-clock-out) (org-clock-out))) + ;; the clock is running in this buffer. + (when (and (equal (marker-buffer org-clock-marker) (current-buffer)) + (or (eq org-remember-clock-out-on-exit t) + (and org-remember-clock-out-on-exit + (y-or-n-p "The clock is running in this buffer. Clock out now? ")))) + (let (org-log-note-clock-out) (org-clock-out)))) (when buffer-file-name (save-buffer) (setq buffer-file-name nil)) @@ -525,10 +577,14 @@ associated with a template in `org-remember-templates'." (org-do-remember (buffer-substring (point) (mark))) (org-do-remember)))))) +(defvar org-remember-last-stored-marker (make-marker) + "Marker pointing to the entry most recently stored with `org-remember'.") + (defun org-remember-goto-last-stored () "Go to the location where the last remember note was stored." (interactive) - (bookmark-jump "org-remember-last-stored") + (org-goto-marker-or-bmk org-remember-last-stored-marker + "org-remember-last-stored") (message "This is the last note stored by remember")) (defun org-go-to-remember-target (&optional template-key) @@ -594,6 +650,11 @@ also indented so that it starts in the same column as the headline \(i.e. after the stars). See also the variable `org-reverse-note-order'." + (when (org-bound-and-true-p org-jump-to-target-location) + (let* ((end (min (point-max) (1+ (point)))) + (beg (point))) + (if (= end beg) (setq beg (1- beg))) + (put-text-property beg end 'org-position-cursor t))) (goto-char (point-min)) (while (looking-at "^[ \t]*\n\\|^##.*\n") (replace-match "")) @@ -604,7 +665,7 @@ See also the variable `org-reverse-note-order'." (beginning-of-line 1)) (catch 'quit (if org-note-abort (throw 'quit nil)) - (let* ((txt (buffer-substring (point-min) (point-max))) + (let* ((visitp (org-bound-and-true-p org-jump-to-target-location)) (fastp (org-xor (equal current-prefix-arg '(4)) org-remember-store-without-prompt)) (file (cond @@ -620,46 +681,39 @@ See also the variable `org-reverse-note-order'." (org-startup-folded nil) (org-startup-align-all-tables nil) (org-goto-start-pos 1) - spos exitcmd level indent reversed) + spos exitcmd level reversed txt) (if (and (equal current-prefix-arg '(16)) org-remember-previous-location) (setq file (car org-remember-previous-location) heading (cdr org-remember-previous-location) fastp t)) (setq current-prefix-arg nil) - (if (string-match "[ \t\n]+\\'" txt) - (setq txt (replace-match "" t t txt))) ;; Modify text so that it becomes a nice subtree which can be inserted ;; into an org tree. - (let* ((lines (split-string txt "\n")) - first) - (setq first (car lines) lines (cdr lines)) - (if (string-match "^\\*+ " first) - ;; Is already a headline - (setq indent nil) - ;; We need to add a headline: Use time and first buffer line - (setq lines (cons first lines) - first (concat "* " (current-time-string) - " (" (remember-buffer-desc) ")") - indent " ")) - (if (and org-adapt-indentation indent) - (setq lines (mapcar - (lambda (x) - (if (string-match "\\S-" x) - (concat indent x) x)) - lines))) - (setq txt (concat first "\n" - (mapconcat 'identity lines "\n")))) - (if (string-match "\n[ \t]*\n[ \t\n]*\\'" txt) - (setq txt (replace-match "\n\n" t t txt)) - (if (string-match "[ \t\n]*\\'" txt) - (setq txt (replace-match "\n" t t txt)))) - ;; Put the modified text back into the remember buffer, for refile. - (erase-buffer) - (insert txt) (goto-char (point-min)) + (if (re-search-forward "[ \t\n]+\\'" nil t) + ;; remove empty lines at end + (replace-match "")) + (goto-char (point-min)) + (unless (looking-at org-outline-regexp) + ;; add a headline + (insert (concat "* " (current-time-string) + " (" (remember-buffer-desc) ")\n")) + (backward-char 1) + (when org-adapt-indentation + (while (re-search-forward "^" nil t) + (insert " ")))) + (goto-char (point-min)) + (if (re-search-forward "\n[ \t]*\n[ \t\n]*\\'" nil t) + (replace-match "\n\n") + (if (re-search-forward "[ \t\n]*\\'") + (replace-match "\n"))) + (goto-char (point-min)) + (setq txt (buffer-string)) + (org-save-markers-in-region (point-min) (point-max)) (when (and (eq org-remember-interactive-interface 'refile) (not fastp)) (org-refile nil (or visiting (find-file-noselect file))) + (and visitp (run-with-idle-timer 0.01 nil 'org-remember-visit-immediately)) (throw 'quit t)) ;; Find the file (if (not visiting) (find-file-noselect file)) @@ -671,25 +725,43 @@ See also the variable `org-reverse-note-order'." (widen) (and (goto-char (point-min)) (not (re-search-forward "^\\* " nil t)) - (insert "\n* " (or heading "Notes") "\n")) + (insert "\n* " (or (and (stringp heading) heading) + "Notes") "\n")) (setq reversed (org-notes-order-reversed-p)) ;; Find the default location - (when (and heading (stringp heading) (string-match "\\S-" heading)) - (goto-char (point-min)) - (if (re-search-forward - (concat "^\\*+[ \t]+" (regexp-quote heading) - (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$")) - nil t) - (setq org-goto-start-pos (match-beginning 0)) - (when fastp - (goto-char (point-max)) - (unless (bolp) (newline)) - (insert "* " heading "\n") - (setq org-goto-start-pos (point-at-bol 0))))) + (when heading + (cond + ((eq heading 'top) + (goto-char (point-min)) + (or (looking-at org-outline-regexp) + (re-search-forward org-outline-regexp nil t)) + (setq org-goto-start-pos (or (match-beginning 0) (point-min)))) + ((eq heading 'bottom) + (goto-char (point-max)) + (re-search-backward "^\\* " nil t) + (or (bolp) (newline)) + (setq org-goto-start-pos (point))) + ((and (stringp heading) (string-match "\\S-" heading)) + (goto-char (point-min)) + (if (re-search-forward + (concat "^\\*+[ \t]+" (regexp-quote heading) + (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$")) + nil t) + (setq org-goto-start-pos (match-beginning 0)) + (when fastp + (goto-char (point-max)) + (unless (bolp) (newline)) + (insert "* " heading "\n") + (setq org-goto-start-pos (point-at-bol 0))))) + (t (goto-char (point-min)) (setq org-goto-start-pos (point) + heading 'top)))) ;; Ask the User for a location, using the appropriate interface (cond + ((and fastp (memq heading '(top bottom))) + (setq spos org-goto-start-pos + exitcmd (if (eq heading 'top) 'left 'right))) (fastp (setq spos org-goto-start-pos exitcmd 'return)) ((eq org-remember-interactive-interface 'outline) @@ -706,6 +778,7 @@ See also the variable `org-reverse-note-order'." (t (error "This should not happen"))) (if (not spos) (throw 'quit nil)) ; return nil to show we did ; not handle this note + (and visitp (run-with-idle-timer 0.01 nil 'org-remember-visit-immediately)) (goto-char spos) (cond ((org-on-heading-p t) (org-back-to-heading t) @@ -724,17 +797,23 @@ See also the variable `org-reverse-note-order'." (beginning-of-line 2) (end-of-line 1) (insert "\n")))) + (org-paste-subtree (org-get-valid-level level 1) txt) + (and org-auto-align-tags (org-set-tags nil t)) (bookmark-set "org-remember-last-stored") - (org-paste-subtree (org-get-valid-level level 1) txt)) + (move-marker org-remember-last-stored-marker (point))) ((eq exitcmd 'left) ;; before current + (org-paste-subtree level txt) + (and org-auto-align-tags (org-set-tags nil t)) (bookmark-set "org-remember-last-stored") - (org-paste-subtree level txt)) + (move-marker org-remember-last-stored-marker (point))) ((eq exitcmd 'right) ;; after current (org-end-of-subtree t) + (org-paste-subtree level txt) + (and org-auto-align-tags (org-set-tags nil t)) (bookmark-set "org-remember-last-stored") - (org-paste-subtree level txt)) + (move-marker org-remember-last-stored-marker (point))) (t (error "This should not happen")))) ((and (bobp) (not reversed)) @@ -743,8 +822,10 @@ See also the variable `org-reverse-note-order'." (widen) (goto-char (point-max)) (if (not (bolp)) (newline)) + (org-paste-subtree (org-get-valid-level 1 1) txt) + (and org-auto-align-tags (org-set-tags nil t)) (bookmark-set "org-remember-last-stored") - (org-paste-subtree (org-get-valid-level 1 1) txt))) + (move-marker org-remember-last-stored-marker (point)))) ((and (bobp) reversed) ;; Put it at the start, as level 1 @@ -753,18 +834,26 @@ See also the variable `org-reverse-note-order'." (goto-char (point-min)) (re-search-forward "^\\*+ " nil t) (beginning-of-line 1) + (org-paste-subtree 1 txt) + (and org-auto-align-tags (org-set-tags nil t)) (bookmark-set "org-remember-last-stored") - (org-paste-subtree 1 txt))) + (move-marker org-remember-last-stored-marker (point)))) (t ;; Put it right there, with automatic level determined by ;; org-paste-subtree or from prefix arg - (bookmark-set "org-remember-last-stored") (org-paste-subtree (if (numberp current-prefix-arg) current-prefix-arg) - txt))) + txt) + (and org-auto-align-tags (org-set-tags nil t)) + (bookmark-set "org-remember-last-stored") + (move-marker org-remember-last-stored-marker (point)))) + (when remember-save-after-remembering (save-buffer) - (if (not visiting) (kill-buffer (current-buffer))))))))) + (if (and (not visiting) + (not (equal (marker-buffer org-clock-marker) + (current-buffer)))) + (kill-buffer (current-buffer))))))))) t) ;; return t to indicate that we took care of this note. @@ -775,6 +864,6 @@ See also the variable `org-reverse-note-order'." (provide 'org-remember) -;;; org-remember.el ends here - ;; arch-tag: 497f30d0-4bc3-4097-8622-2d27ac5f2698 + +;;; org-remember.el ends here diff --git a/lisp/org/org-rmail.el b/lisp/org/org-rmail.el index af0e88780d3..337909f3af7 100644 --- a/lisp/org/org-rmail.el +++ b/lisp/org/org-rmail.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -105,4 +105,5 @@ (provide 'org-rmail) ;; arch-tag: c6cf4a8b-6639-4b7f-821f-bdf10746b173 + ;;; org-rmail.el ends here diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el index 6f9b57f38d0..45981776c43 100644 --- a/lisp/org/org-table.el +++ b/lisp/org/org-table.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -187,7 +187,7 @@ t: accept as input and present for editing" (defcustom org-calc-default-modes '(calc-internal-prec 12 - calc-float-format (float 5) + calc-float-format (float 8) calc-angle-mode deg calc-prefer-frac nil calc-symbolic-mode nil @@ -249,12 +249,11 @@ Automatically means, when TAB or RET or C-c C-c are pressed in the line." :tag "Org Table Import Export" :group 'org-table) -(defcustom org-table-export-default-format - "orgtbl-to-generic :splice t :sep \"\t\"" +(defcustom org-table-export-default-format "orgtbl-to-tsv" "Default export parameters for org-table-export. These can be - overridden on for a specific table by setting the - TABLE_EXPORT_FORMAT parameter. See orgtbl-export for the - different export transforms and available parameters." +overridden on for a specific table by setting the TABLE_EXPORT_FORMAT +property. See the manual section on orgtbl radio tables for the different +export transformations and available parameters." :group 'org-table-import-export :type 'string) @@ -428,7 +427,7 @@ are found, lines will be split on whitespace into fields." (defvar org-table-last-alignment) (defvar org-table-last-column-widths) (defun org-table-export (&optional file format) - "Export table as a tab-separated file. + "Export table to a file, with configurable format. Such a file can be imported into a spreadsheet program like Excel. FILE can be the output file name. If not given, it will be taken from a TABLE_EXPORT_FILE property in the current entry or higher up in the @@ -439,19 +438,33 @@ be found in the variable `org-table-export-default-format', but the function first checks if there is an export format specified in a TABLE_EXPORT_FORMAT property, locally or anywhere up in the hierarchy." (interactive) + (unless (org-at-table-p) + (error "No table at point")) + (require 'org-exp) (org-table-align) ;; make sure we have everything we need (let* ((beg (org-table-begin)) (end (org-table-end)) (txt (buffer-substring-no-properties beg end)) - (file (or file (org-entry-get beg "TABLE_EXPORT_FILE" t) - (read-file-name "Export table to: "))) - (format (or (org-entry-get beg "TABLE_EXPORT_FORMAT" t) - org-table-export-default-format)) - buf) - (unless (or (not (file-exists-p file)) - (y-or-n-p (format "Overwrite file %s? " file))) - (error "Abort")) - (message format) + (file (or file (org-entry-get beg "TABLE_EXPORT_FILE" t))) + (format (or format (org-entry-get beg "TABLE_EXPORT_FORMAT" t))) + buf deffmt-readable) + (unless file + (setq file (read-file-name "Export table to: ")) + (unless (or (not (file-exists-p file)) + (y-or-n-p (format "Overwrite file %s? " file))) + (error "Abort"))) + (if (file-directory-p file) + (error "This is a directory path, not a file")) + (if (equal (file-truename file) + (file-truename (buffer-file-name))) + (error "Please specify a file name that is different from current")) + (unless format + (setq deffmt-readable org-table-export-default-format) + (while (string-match "\t" deffmt-readable) + (setq deffmt-readable (replace-match "\\t" t t deffmt-readable))) + (while (string-match "\n" deffmt-readable) + (setq deffmt-readable (replace-match "\\n" t t deffmt-readable))) + (setq format (read-string "Format: " deffmt-readable))) (if (string-match "\\([^ \t\r\n]+\\)\\( +.*\\)?" format) (let* ((transform (intern (match-string 1 format))) @@ -2363,7 +2376,7 @@ With prefix arg ALL, do this for all lines in the table." (goto-char beg) (and all (message "Re-applying formulas to full table...")) - ;; First find the named fields, and mark them untouchanble + ;; First find the named fields, and mark them untouchable (remove-text-properties beg end '(org-untouchable t)) (while (setq eq (pop eqlname)) (setq name (car eq) @@ -2371,8 +2384,11 @@ With prefix arg ALL, do this for all lines in the table." (and (not a) (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name) (setq a (list name - (aref org-table-dlines - (string-to-number (match-string 1 name))) + (condition-case nil + (aref org-table-dlines + (string-to-number (match-string 1 name))) + (error (error "Invalid row number in %s" + name))) (string-to-number (match-string 2 name))))) (when (and a (or all (equal (nth 1 a) thisline))) (message "Re-applying formula to field: %s" name) @@ -3497,7 +3513,7 @@ a radio table." (goto-char (org-table-begin)) (let (rtn) (beginning-of-line 0) - (while (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?") + (while (looking-at "#\\+ORGTBL[: \t][ \t]*SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?") (let ((name (org-no-properties (match-string 1))) (transform (intern (match-string 2))) (params (if (match-end 3) @@ -3629,6 +3645,7 @@ First element has index 0, or I0 if given." ;; Formatting parameters for the current table section. (defvar *orgtbl-hline* nil "Text used for horizontal lines") (defvar *orgtbl-sep* nil "Text used as a column separator") +(defvar *orgtbl-default-fmt* nil "Default format for each entry") (defvar *orgtbl-fmt* nil "Format for each entry") (defvar *orgtbl-efmt* nil "Format for numbers") (defvar *orgtbl-lfmt* nil "Format for an entire line, overrides fmt") @@ -3670,7 +3687,9 @@ First element has index 0, or I0 if given." (orgtbl-apply-fmt efmt (match-string 1 f) (match-string 2 f)) f))) - (orgtbl-apply-fmt (orgtbl-get-fmt *orgtbl-fmt* i) f))) + (orgtbl-apply-fmt (or (orgtbl-get-fmt *orgtbl-fmt* i) + *orgtbl-default-fmt*) + f))) line))) (push (if *orgtbl-lfmt* (orgtbl-apply-fmt *orgtbl-lfmt* line) @@ -3698,13 +3717,14 @@ TABLE is a list, each entry either the symbol `hline' for a horizontal separator line, or a list of fields for that line. PARAMS is a property list of parameters that can influence the conversion. For the generic converter, some parameters are obligatory: You need to -specify either :lfmt, or all of (:lstart :lend :sep). If you do not use -:splice, you must have :tstart and :tend. +specify either :lfmt, or all of (:lstart :lend :sep). Valid parameters are :splice When set to t, return only table body lines, don't wrap - them into :tstart and :tend. Default is nil. + them into :tstart and :tend. Default is nil. When :splice + is non-nil, this also means that the exporter should not look + for and interpret header and footer sections. :hline String to be inserted on horizontal separation lines. May be nil to ignore hlines. @@ -3713,8 +3733,8 @@ Valid parameters are :remove-nil-lines Do not include lines that evaluate to nil. - Each in the following group may be either a string or a function - of no arguments returning a string: +Each in the following group may be either a string or a function +of no arguments returning a string: :tstart String to start the table. Ignored when :splice is t. :tend String to end the table. Ignored when :splice is t. :lstart String to start a new table line. @@ -3722,9 +3742,9 @@ Valid parameters are :lend String to end a table line :llend String to end the last table line, defaults to :lend. - Each in the following group may be a string, a function of one - argument (the field or line) returning a string, or a plist - mapping columns to either of the above: +Each in the following group may be a string, a function of one +argument (the field or line) returning a string, or a plist +mapping columns to either of the above: :lfmt Format for entire line, with enough %s to capture all fields. If this is present, :lstart, :lend, and :sep are ignored. :llfmt Format for the entire last line, defaults to :lfmt. @@ -3739,7 +3759,7 @@ Valid parameters are All lines before the first hline are treated as header. If any of these is not present, the data line value is used. - This may be either a string or a function of two arguments: +This may be either a string or a function of two arguments: :efmt Use this format to print numbers with exponentials. The format should have %s twice for inserting mantissa and exponent, for example \"%s\\\\times10^{%s}\". This @@ -3768,8 +3788,9 @@ directly by `orgtbl-send-table'. See manual." ;; Put header (unless splicep - (push (or (orgtbl-eval-str (plist-get params :tstart)) - "ERROR: no :tstart") *orgtbl-rtn*)) + (when (plist-member params :tstart) + (let ((tstart (orgtbl-eval-str (plist-get params :tstart)))) + (if tstart (push tstart *orgtbl-rtn*))))) ;; Do we have a heading section? If so, format it and handle the ;; trailing hline. @@ -3796,13 +3817,24 @@ directly by `orgtbl-send-table'. See manual." (orgtbl-format-section nil) (unless splicep - (push (or (orgtbl-eval-str (plist-get params :tend)) - "ERROR: no :tend") *orgtbl-rtn*)) + (when (plist-member params :tend) + (let ((tend (orgtbl-eval-str (plist-get params :tend)))) + (if tend (push tend *orgtbl-rtn*))))) (mapconcat 'identity (nreverse (if remove-nil-linesp (remq nil *orgtbl-rtn*) *orgtbl-rtn*)) "\n"))) +(defun orgtbl-to-tsv (table params) + "Convert the orgtbl-mode table to TAB separated material." + (orgtbl-to-generic table (org-combine-plists '(:sep "\t") params))) +(defun orgtbl-to-csv (table params) + "Convert the orgtbl-mode table to CSV material. +This does take care of the proper quoting of fields with comma or quotes." + (orgtbl-to-generic table (org-combine-plists + '(:sep "," :fmt org-quote-csv-field) + params))) + (defun orgtbl-to-latex (table params) "Convert the orgtbl-mode TABLE to LaTeX. TABLE is a list, each entry either the symbol `hline' for a horizontal @@ -3908,7 +3940,24 @@ this function is called." :hlstart "@headitem "))) (orgtbl-to-generic table (org-combine-plists params2 params)))) +(defun orgtbl-to-orgtbl (table params) + "Convert the orgtbl-mode TABLE into another orgtbl-mode table. +Useful when slicing one table into many. The :hline, :sep, +:lstart, and :lend provide orgtbl framing. The default nil :tstart +and :tend suppress strings without splicing; they can be set to +provide ORGTBL directives for the generated table." + (let* ((params2 + (list + :tstart nil :tend nil + :hline "|---" + :sep " | " + :lstart "| " + :lend " |")) + (params (org-combine-plists params2 params))) + (orgtbl-to-generic table params))) + (provide 'org-table) ;; arch-tag: 4d21cfdd-0268-440a-84b0-09237a0fe0ef + ;;; org-table.el ends here diff --git a/lisp/org/org-vm.el b/lisp/org/org-vm.el index 1c93619bd86..032881e3eea 100644 --- a/lisp/org/org-vm.el +++ b/lisp/org/org-vm.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -126,4 +126,5 @@ (provide 'org-vm) ;; arch-tag: cbc3047b-935e-4d2a-96e7-c5b0117aaa6d + ;;; org-vm.el ends here diff --git a/lisp/org/org-wl.el b/lisp/org/org-wl.el index 9382edd217c..56ad2123972 100644 --- a/lisp/org/org-wl.el +++ b/lisp/org/org-wl.el @@ -5,7 +5,7 @@ ;; Author: Tokuya Kameshima <kames at fa2 dot so-net dot ne dot jp> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -142,4 +142,5 @@ (provide 'org-wl) ;; arch-tag: 29b75a0f-ef2e-430b-8abc-acff75bde54a + ;;; org-wl.el ends here diff --git a/lisp/org/org.el b/lisp/org/org.el index 281b4ab732f..b47b52c879b 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -5,7 +5,7 @@ ;; Author: Carsten Dominik <carsten at orgmode dot org> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: http://orgmode.org -;; Version: 6.02b +;; Version: 6.05a ;; ;; This file is part of GNU Emacs. ;; @@ -91,7 +91,7 @@ ;;; Version -(defconst org-version "6.02b" +(defconst org-version "6.05a" "The version number of the file org.el.") (defun org-version (&optional here) @@ -161,6 +161,7 @@ to add the symbol `xyz', and the package must have a call to (const :tag " bbdb: Links to BBDB entries" org-bbdb) (const :tag " bibtex: Links to BibTeX entries" org-bibtex) (const :tag " gnus: Links to GNUS folders/messages" org-gnus) + (const :tag " id: Global id's for identifying entries" org-id) (const :tag " info: Links to Info nodes" org-info) (const :tag " jsinfo: Set up Sebastian Rose's JavaScript org-info.js" org-jsinfo) (const :tag " irc: Links to IRC/ERC chat sessions" org-irc) @@ -173,15 +174,17 @@ to add the symbol `xyz', and the package must have a call to (const :tag " mouse: Additional mouse support" org-mouse) (const :tag "C annotate-file: Annotate a file with org syntax" org-annotate-file) + (const :tag "C annotation-helper: Call Remeber directly from Browser" org-annotation-helper) (const :tag "C bookmark: Org links to bookmarks" org-bookmark) (const :tag "C depend: TODO dependencies for Org-mode" org-depend) (const :tag "C elisp-symbol: Org links to emacs-lisp symbols" org-elisp-symbol) + (const :tag "C eval: Include command output as text" org-eval) (const :tag "C expiry: Expiry mechanism for Org entries" org-expiry) (const :tag "C id: Global id's for identifying entries" org-id) (const :tag "C interactive-query: Interactive modification of tags query" org-interactive-query) (const :tag "C mairix: Hook mairix search into Org for different MUAs" org-mairix) (const :tag "C man: Support for links to manpages in Org-mode" org-man) - (const :tag "C mew: Support for links to messages in Mew" org-mew) + (const :tag "C mtags: Support for muse-like tags" org-mtags) (const :tag "C panel: Simple routines for us with bad memory" org-panel) (const :tag "C registry: A registry for Org links" org-registry) (const :tag "C org2rem: Convert org appointments into reminders" org2rem) @@ -217,6 +220,20 @@ uninteresting. Also tables look terrible when wrapped." :group 'org-startup :type 'boolean) +(defcustom org-startup-indented nil + "Non-nil means, turn on `org-indent-mode' on startup. +This can also be configured on a per-file basis by adding one of +the following lines anywhere in the buffer: + + #+STARTUP: localindent + #+STARTUP: indent + #+STARTUP: noindent" + :group 'org-structure + :type '(choice + (const :tag "Not" nil) + (const :tag "Locally" local) + (const :tag "Globally (slow on startup in large files)" t))) + (defcustom org-startup-align-all-tables nil "Non-nil means, align all tables when visiting a file. This is useful when the column width in tables is forced with <N> cookies @@ -748,6 +765,12 @@ with \\[org-ctrl-c-ctrl-c\\]." :group 'org-plain-lists :type 'boolean) +(defcustom org-description-max-indent 20 + "Maximum indentation for the second line of a description list. +When the indentation would be larger than this, it will become +5 characters instead." + :group 'org-plain-lists + :type 'integer) (defgroup org-imenu-and-speedbar nil "Options concerning imenu and speedbar in Org-mode." @@ -1380,6 +1403,13 @@ by a letter in parenthesis, like TODO(t)." (const :tag "By default" t) (const :tag "Only with C-u C-c C-t" prefix))) +(defcustom org-provide-todo-statistics t + "Non-nil means, update todo statistics after insert and toggle. +When this is set, todo statistics is updated in the parent of the current +entry each time a todo state is changed." + :group 'org-todo + :type 'boolean) + (defcustom org-after-todo-state-change-hook nil "Hook which is run after the state of a TODO item was changed. The new state (a string with a TODO keyword, or nil) is available in the @@ -1463,8 +1493,8 @@ When nil, the notes will be orderer according to time." "Non-nil means, record moving through the DONE state when triggering repeat. An auto-repeating tasks is immediately switched back to TODO when marked done. If you are not logging state changes (by adding \"@\" or \"!\" to -the TODO keyword definition, or recording a cloing note by setting -`org-log-done', there will be no record of the task moving trhough DONE. +the TODO keyword definition, or recording a closing note by setting +`org-log-done', there will be no record of the task moving through DONE. This variable forces taking a note anyway. Possible values are: nil Don't force a record @@ -1590,6 +1620,12 @@ end of the second format." (concat "[" (substring f 1 -1) "]") f))) +(defcustom org-time-clocksum-format "%d:%02d" + "The format string used when creating CLOCKSUM lines, or when +org-mode generates a time duration." + :group 'org-time + :type 'string) + (defcustom org-deadline-warning-days 14 "No. of days before expiration during which a deadline becomes active. This variable governs the display in sparse trees and in the agenda. @@ -1682,6 +1718,12 @@ See the manual for details." (const :tag "Start radio group" (:startgroup)) (const :tag "End radio group" (:endgroup))))) +(defvar org-file-tags nil + "List of tags that can be inherited by all entries in the file. +The tags will be inherited if the variable `org-use-tag-inheritance' +says they should be. +This variable is populated from #+TAG lines.") + (defcustom org-use-fast-tag-selection 'auto "Non-nil means, use fast tag selection scheme. This is a special interface to select and deselect tags with single keys. @@ -1732,8 +1774,10 @@ the tags are again aligned to `org-tags-column'." (defcustom org-use-tag-inheritance t "Non-nil means, tags in levels apply also for sublevels. When nil, only the tags directly given in a specific line apply there. -If you turn off this option, you very likely want to turn on the -companion option `org-tags-match-list-sublevels'. +If this option is t, a match early-on in a tree can lead to a large +number of matches in the subtree. If you only want to see the first +match in a tree during a search, check out the variable +`org-tags-match-list-sublevels'. This may also be a list of tags that should be inherited, or a regexp that matches tags that should be inherited." @@ -1755,7 +1799,7 @@ matches tags that should be inherited." (member tag org-use-tag-inheritance)) (t (error "Invalid setting of `org-use-tag-inheritance'")))) -(defcustom org-tags-match-list-sublevels nil +(defcustom org-tags-match-list-sublevels t "Non-nil means list also sublevels of headlines matching tag search. Because of tag inheritance (see variable `org-use-tag-inheritance'), the sublevels of a headline matching a tag search often also match @@ -1839,6 +1883,17 @@ This variable can be set on the per-file basis by inserting a line :group 'org-properties :type 'string) +(defcustom org-columns-ellipses ".." + "The ellipses to be used when a field in column view is truncated. +When this is the empty string, as many characters as possible are shown, +but then there will be no visual indication that the field has been truncated. +When this is a string of length N, the last N characters of a truncated +field are replaced by this string. If the column is narrower than the +ellipses string, only part of the ellipses string will be shown." + :group 'org-properties + :type 'string) + + (defcustom org-effort-property "Effort" "The property that is being used to keep track of effort estimates. Effort estimates given in this property need to have the format H:MM." @@ -1846,6 +1901,12 @@ Effort estimates given in this property need to have the format H:MM." :group 'org-progress :type '(string :tag "Property")) +(defconst org-global-properties-fixed + '(("VISIBILITY_ALL" . "folded children content all")) + "List of property/value pairs that can be inherited by any entry. +These are fixed values, for the preset properties.") + + (defcustom org-global-properties nil "List of property/value pairs that can be inherited by any entry. You can set buffer-local values for this by adding lines like @@ -1856,10 +1917,11 @@ You can set buffer-local values for this by adding lines like (cons (string :tag "Property") (string :tag "Value")))) -(defvar org-local-properties nil +(defvar org-file-properties nil "List of property/value pairs that can be inherited by any entry. Valid for the current buffer. This variable is populated from #+PROPERTY lines.") +(make-variable-buffer-local 'org-file-properties) (defgroup org-agenda nil "Options concerning agenda views in Org-mode." @@ -1938,9 +2000,19 @@ forth between agenda and calendar." :group 'org-agenda :type 'sexp) +(defcustom org-calendar-agenda-action-key [?k] + "The key to be installed in `calendar-mode-map' for agenda-action. +The command `org-agenda-action' will be bound to this key. The +default is the character `k' because we use the same key in the agenda." + :group 'org-agenda + :type 'sexp) + (eval-after-load "calendar" - '(org-defkey calendar-mode-map org-calendar-to-agenda-key - 'org-calendar-goto-agenda)) + '(progn + (org-defkey calendar-mode-map org-calendar-to-agenda-key + 'org-calendar-goto-agenda) + (org-defkey calendar-mode-map org-calendar-agenda-action-key + 'org-agenda-action))) (defgroup org-latex nil "Options for embedding LaTeX code into Org-mode." @@ -2123,7 +2195,7 @@ Use customize to modify this, or restart Emacs after changing it." (sexp :tag "Forbidden chars in border ") (sexp :tag "Regexp for body ") (integer :tag "number of newlines allowed") - (option (boolean :tag "Stacking (DISABLED) ")))) + (option (boolean :tag "Please ignore this button")))) (defcustom org-emphasis-alist `(("*" bold "<b>" "</b>") @@ -2200,6 +2272,8 @@ Normal means, no org-mode-specific context." (newhead hdmarker &optional fixface)) (declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type)) (declare-function org-agenda-maybe-redo "org-agenda" ()) +(declare-function org-agenda-save-markers-for-cut-and-paste "org-agenda" + (beg end)) (declare-function parse-time-string "parse-time" (string)) (declare-function remember "remember" (&optional initial)) (declare-function remember-buffer-desc "remember" ()) @@ -2345,6 +2419,7 @@ If TABLE-TYPE is non-nil, also check for table.el-type tables." org-replace-region-by-html org-export-region-as-html org-export-as-html org-export-icalendar-this-file org-export-icalendar-all-agenda-files + org-table-clean-before-export org-export-icalendar-combine-agenda-files org-export-as-xoxo))) ;; Declare and autoload functions from org-exp.el @@ -2364,6 +2439,11 @@ If TABLE-TYPE is non-nil, also check for table.el-type tables." ;; Autoload org-clock.el + +(declare-function org-clock-save-markers-for-cut-and-paste "org-clock" + (beg end)) +(declare-function org-update-mode-line "org-clock" ()) +(defvar org-clock-start-time) (defvar org-clock-marker (make-marker) "Marker recording the last clock-in.") @@ -2385,15 +2465,26 @@ Otherwise, return nil." (skip-chars-forward " \t") (when (looking-at org-clock-string) (let ((re (concat "[ \t]*" org-clock-string - " *[[<]\\([^]>]+\\)[]>]-+[[<]\\([^]>]+\\)[]>]" - "\\([ \t]*=>.*\\)?")) + " *[[<]\\([^]>]+\\)[]>]\\(-+[[<]\\([^]>]+\\)[]>]" + "\\([ \t]*=>.*\\)?\\)?")) ts te h m s) - (if (not (looking-at re)) - nil - (and (match-end 3) (delete-region (match-beginning 3) (match-end 3))) + (cond + ((not (looking-at re)) + nil) + ((not (match-end 2)) + (when (and (equal (marker-buffer org-clock-marker) (current-buffer)) + (> org-clock-marker (point)) + (<= org-clock-marker (point-at-eol))) + ;; The clock is running here + (setq org-clock-start-time + (apply 'encode-time + (org-parse-time-string (match-string 1)))) + (org-update-mode-line))) + (t + (and (match-end 4) (delete-region (match-beginning 4) (match-end 4))) (end-of-line 1) (setq ts (match-string 1) - te (match-string 2)) + te (match-string 3)) (setq s (- (time-to-seconds (apply 'encode-time (org-parse-time-string te))) (time-to-seconds @@ -2403,7 +2494,7 @@ Otherwise, return nil." m (floor (/ s 60)) s (- s (* 60 s))) (insert " => " (format "%2d:%02d" h m)) - t))))) + t)))))) (defun org-check-running-clock () "Check if the current buffer contains the running clock. @@ -2552,6 +2643,14 @@ collapsed state." org-columns-compute org-agenda-columns org-columns-remove-overlays org-columns org-insert-columns-dblock)) +;; Autoload ID code + +(org-autoload "org-id" + '(org-id-get-create org-id-new org-id-copy org-id-get + org-id-get-with-outline-path-completion + org-id-get-with-outline-drilling + org-id-goto org-id-find)) + ;;; Variables for pre-computed regular expressions, all buffer local (defvar org-drawer-regexp nil @@ -2699,19 +2798,27 @@ means to push this value onto the list in the variable.") (org-set-local 'org-todo-heads nil) (org-set-local 'org-todo-sets nil) (org-set-local 'org-todo-log-states nil) + (org-set-local 'org-file-properties nil) + (org-set-local 'org-file-tags nil) (let ((re (org-make-options-regexp '("CATEGORY" "SEQ_TODO" "TYP_TODO" "TODO" "COLUMNS" - "STARTUP" "ARCHIVE" "TAGS" "LINK" "PRIORITIES" - "CONSTANTS" "PROPERTY" "DRAWERS"))) + "STARTUP" "ARCHIVE" "FILETAGS" "TAGS" "LINK" "PRIORITIES" + "CONSTANTS" "PROPERTY" "DRAWERS" "SETUPFILE"))) (splitre "[ \t]+") kwds kws0 kwsa key log value cat arch tags const links hw dws - tail sep kws1 prio props drawers) + tail sep kws1 prio props ftags drawers + ext-setup-or-nil setup-contents (start 0)) (save-excursion (save-restriction (widen) (goto-char (point-min)) - (while (re-search-forward re nil t) - (setq key (match-string 1) value (org-match-string-no-properties 2)) + (while (or (and ext-setup-or-nil + (string-match re ext-setup-or-nil start) + (setq start (match-end 0))) + (and (setq ext-setup-or-nil nil start 0) + (re-search-forward re nil t))) + (setq key (upcase (match-string 1 ext-setup-or-nil)) + value (org-match-string-no-properties 2 ext-setup-or-nil)) (cond ((equal key "CATEGORY") (if (string-match "[ \t]+$" value) @@ -2736,6 +2843,14 @@ means to push this value onto the list in the variable.") (when (string-match "\\(\\S-+\\)\\s-+\\(.*\\)" value) (push (cons (match-string 1 value) (match-string 2 value)) props))) + ((equal key "FILETAGS") + (when (string-match "\\S-" value) + (setq ftags + (append + ftags + (apply 'append + (mapcar (lambda (x) (org-split-string x ":")) + (org-split-string value))))))) ((equal key "DRAWERS") (setq drawers (org-split-string value splitre))) ((equal key "CONSTANTS") @@ -2756,8 +2871,19 @@ means to push this value onto the list in the variable.") (string-match " *$" value) (setq arch (replace-match "" t t value)) (remove-text-properties 0 (length arch) - '(face t fontified t) arch))) - ))) + '(face t fontified t) arch)) + ((equal key "SETUPFILE") + (setq setup-contents (org-file-contents + (expand-file-name + (org-remove-double-quotes value)) + 'noerror)) + (if (not ext-setup-or-nil) + (setq ext-setup-or-nil setup-contents start 0) + (setq ext-setup-or-nil + (concat (substring ext-setup-or-nil 0 start) + "\n" setup-contents "\n" + (substring ext-setup-or-nil start))))) + )))) (when cat (org-set-local 'org-category (intern cat)) (push (cons "CATEGORY" cat) props)) @@ -2767,7 +2893,8 @@ means to push this value onto the list in the variable.") (org-set-local 'org-highest-priority (nth 0 prio)) (org-set-local 'org-lowest-priority (nth 1 prio)) (org-set-local 'org-default-priority (nth 2 prio))) - (and props (org-set-local 'org-local-properties (nreverse props))) + (and props (org-set-local 'org-file-properties (nreverse props))) + (and ftags (org-set-local 'org-file-tags ftags)) (and drawers (org-set-local 'org-drawers drawers)) (and arch (org-set-local 'org-archive-location arch)) (and links (setq org-link-abbrev-alist-local (nreverse links))) @@ -2838,87 +2965,101 @@ means to push this value onto the list in the variable.") (while (setq e (pop tgs)) (or (and (stringp (car e)) (assoc (car e) org-tag-alist)) - (push e org-tag-alist)))))) - - ;; Compute the regular expressions and other local variables - (if (not org-done-keywords) - (setq org-done-keywords (list (org-last org-todo-keywords-1)))) - (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string) - (length org-scheduled-string) - (length org-clock-string) - (length org-closed-string))) - org-drawer-regexp - (concat "^[ \t]*:\\(" - (mapconcat 'regexp-quote org-drawers "\\|") - "\\):[ \t]*$") - org-not-done-keywords - (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1)) - org-todo-regexp - (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1 - "\\|") "\\)\\>") - org-not-done-regexp - (concat "\\<\\(" - (mapconcat 'regexp-quote org-not-done-keywords "\\|") - "\\)\\>") - org-todo-line-regexp - (concat "^\\(\\*+\\)[ \t]+\\(?:\\(" - (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") - "\\)\\>\\)?[ \t]*\\(.*\\)") - org-complex-heading-regexp - (concat "^\\(\\*+\\)\\(?:[ \t]+\\(" - (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") - "\\)\\>\\)?\\(?:[ \t]*\\(\\[#.\\]\\)\\)?[ \t]*\\(.*?\\)" - "\\(?:[ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$") - org-nl-done-regexp - (concat "\n\\*+[ \t]+" - "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|") - "\\)" "\\>") - org-todo-line-tags-regexp - (concat "^\\(\\*+\\)[ \t]+\\(?:\\(" - (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") - (org-re - "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@]+:[ \t]*\\)?$\\)")) - org-looking-at-done-regexp - (concat "^" "\\(?:" - (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)" - "\\>") - org-deadline-regexp (concat "\\<" org-deadline-string) - org-deadline-time-regexp - (concat "\\<" org-deadline-string " *<\\([^>]+\\)>") - org-deadline-line-regexp - (concat "\\<\\(" org-deadline-string "\\).*") - org-scheduled-regexp - (concat "\\<" org-scheduled-string) - org-scheduled-time-regexp - (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>") - org-closed-time-regexp - (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]") - org-keyword-time-regexp - (concat "\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\|" org-clock-string "\\)" - " *[[<]\\([^]>]+\\)[]>]") - org-keyword-time-not-clock-regexp - (concat "\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\)" - " *[[<]\\([^]>]+\\)[]>]") - org-maybe-keyword-time-regexp - (concat "\\(\\<\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string - "\\|" org-clock-string "\\)\\)?" - " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)") - org-planning-or-clock-line-re - (concat "\\(?:^[ \t]*\\(" org-scheduled-string - "\\|" org-deadline-string - "\\|" org-closed-string "\\|" org-clock-string - "\\)\\>\\)") - ) - (org-compute-latex-and-specials-regexp) - (org-set-font-lock-defaults))) + (push e org-tag-alist))))) + + ;; Compute the regular expressions and other local variables + (if (not org-done-keywords) + (setq org-done-keywords (list (org-last org-todo-keywords-1)))) + (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string) + (length org-scheduled-string) + (length org-clock-string) + (length org-closed-string))) + org-drawer-regexp + (concat "^[ \t]*:\\(" + (mapconcat 'regexp-quote org-drawers "\\|") + "\\):[ \t]*$") + org-not-done-keywords + (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1)) + org-todo-regexp + (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1 + "\\|") "\\)\\>") + org-not-done-regexp + (concat "\\<\\(" + (mapconcat 'regexp-quote org-not-done-keywords "\\|") + "\\)\\>") + org-todo-line-regexp + (concat "^\\(\\*+\\)[ \t]+\\(?:\\(" + (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") + "\\)\\>\\)?[ \t]*\\(.*\\)") + org-complex-heading-regexp + (concat "^\\(\\*+\\)\\(?:[ \t]+\\(" + (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") + "\\)\\>\\)?\\(?:[ \t]*\\(\\[#.\\]\\)\\)?[ \t]*\\(.*?\\)" + "\\(?:[ \t]+\\(:[[:alnum:]_@:]+:\\)\\)?[ \t]*$") + org-nl-done-regexp + (concat "\n\\*+[ \t]+" + "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|") + "\\)" "\\>") + org-todo-line-tags-regexp + (concat "^\\(\\*+\\)[ \t]+\\(?:\\(" + (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") + (org-re + "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@]+:[ \t]*\\)?$\\)")) + org-looking-at-done-regexp + (concat "^" "\\(?:" + (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)" + "\\>") + org-deadline-regexp (concat "\\<" org-deadline-string) + org-deadline-time-regexp + (concat "\\<" org-deadline-string " *<\\([^>]+\\)>") + org-deadline-line-regexp + (concat "\\<\\(" org-deadline-string "\\).*") + org-scheduled-regexp + (concat "\\<" org-scheduled-string) + org-scheduled-time-regexp + (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>") + org-closed-time-regexp + (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]") + org-keyword-time-regexp + (concat "\\<\\(" org-scheduled-string + "\\|" org-deadline-string + "\\|" org-closed-string + "\\|" org-clock-string "\\)" + " *[[<]\\([^]>]+\\)[]>]") + org-keyword-time-not-clock-regexp + (concat "\\<\\(" org-scheduled-string + "\\|" org-deadline-string + "\\|" org-closed-string + "\\)" + " *[[<]\\([^]>]+\\)[]>]") + org-maybe-keyword-time-regexp + (concat "\\(\\<\\(" org-scheduled-string + "\\|" org-deadline-string + "\\|" org-closed-string + "\\|" org-clock-string "\\)\\)?" + " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)") + org-planning-or-clock-line-re + (concat "\\(?:^[ \t]*\\(" org-scheduled-string + "\\|" org-deadline-string + "\\|" org-closed-string "\\|" org-clock-string + "\\)\\>\\)") + ) + (org-compute-latex-and-specials-regexp) + (org-set-font-lock-defaults)))) + +(defun org-file-contents (file &optional noerror) + "Return the contents of FILE, as a string." + (if (or (not file) + (not (file-readable-p file))) + (if noerror + (progn + (message "Cannot read file %s" file) + (ding) (sit-for 2) + "") + (error "Cannot read file %s" file)) + (with-temp-buffer + (insert-file-contents file) + (buffer-string)))) (defun org-extract-log-state-settings (x) "Extract the log state setting from a TODO keyword string. @@ -3123,13 +3264,7 @@ The following commands are available: (let ((bmp (buffer-modified-p))) (org-table-map-tables 'org-table-align) (set-buffer-modified-p bmp))) - (org-cycle-hide-drawers 'all) - (cond - ((eq org-startup-folded t) - (org-cycle '(4))) - ((eq org-startup-folded 'content) - (let ((this-command 'org-cycle) (last-command 'org-cycle)) - (org-cycle '(4)) (org-cycle '(4))))))) + (org-set-startup-visibility))) (put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify) @@ -3583,14 +3718,22 @@ between words." (defvar org-font-lock-keywords nil) -(defconst org-property-re (org-re "^[ \t]*\\(:\\([[:alnum:]_]+\\):\\)[ \t]*\\([^ \t\r\n].*\\)") +(defconst org-property-re (org-re "^[ \t]*\\(:\\([-[:alnum:]_]+\\):\\)[ \t]*\\([^ \t\r\n].*\\)") "Regular expression matching a property line.") +(defvar org-font-lock-hook nil + "Functions to be called for special font lock stuff.") + +(defun org-font-lock-hook (limit) + (run-hook-with-args 'org-font-lock-hook limit)) + (defun org-set-font-lock-defaults () (let* ((em org-fontify-emphasized-text) (lk org-activate-links) (org-font-lock-extra-keywords (list + ;; Call the hook + '(org-font-lock-hook) ;; Headlines '("^\\(\\**\\)\\(\\* \\)\\(.*\\)" (1 (org-get-level-face 1)) (2 (org-get-level-face 2)) (3 (org-get-level-face 3))) @@ -3647,6 +3790,9 @@ between words." (if org-provide-checkbox-statistics '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]" (0 (org-get-checkbox-statistics-face) t))) + ;; Description list items + '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(.*? ::\\)" + 2 'bold prepend) (list (concat "^\\*+ \\(.*:" org-archive-tag ":.*\\)") '(1 'org-archived prepend)) ;; Specials @@ -3716,6 +3862,9 @@ If KWD is a number, get the corresponding match group." 1. OVERVIEW: Show only top-level headlines. 2. CONTENTS: Show all headlines of all levels, but no body text. 3. SHOW ALL: Show everything. + When called with two C-c C-u prefixes, switch to the startup visibility, + determined by the variable `org-startup-folded', and by any VISIBILITY + properties in the buffer. - When point is at the beginning of a headline, rotate the subtree started by this line through 3 different states (local cycling) @@ -3729,8 +3878,8 @@ If KWD is a number, get the corresponding match group." a `show-subtree' and return to the previous cursor position. If ARG is negative, go up that many levels. -- When point is not at the beginning of a headline, execute - `indent-relative', like TAB normally does. See the option +- When point is not at the beginning of a headline, execute the global + binding for TAB, which is re-indenting the line. See the option `org-cycle-emulate-tab' for details. - Special case: if point is at the beginning of the buffer and there is @@ -3757,6 +3906,10 @@ If KWD is a number, get the corresponding match group." (cond + ((equal arg '(16)) + (org-set-startup-visibility) + (message "Startup visibility, plus VISIBILITY properties.")) + ((org-at-table-p 'any) ;; Enter the table or move to the next field in the table (or (org-table-recognize-table.el) @@ -3865,9 +4018,11 @@ If KWD is a number, get the corresponding match group." (setq org-cycle-subtree-status 'folded) (run-hook-with-args 'org-cycle-hook 'folded))))) - ;; TAB emulation + ;; TAB emulation and template completion (buffer-read-only (org-back-to-heading)) + ((org-try-structure-completion)) + ((org-try-cdlatex-tab)) ((and (eq org-cycle-emulate-tab 'exc-hl-bol) @@ -3891,16 +4046,67 @@ If KWD is a number, get the corresponding match group." ;;;###autoload (defun org-global-cycle (&optional arg) - "Cycle the global visibility. For details see `org-cycle'." + "Cycle the global visibility. For details see `org-cycle'. +With C-u prefix arg, switch to startup visibility. +With a numeric prefix, show all headlines up to that level." (interactive "P") (let ((org-cycle-include-plain-lists (if (org-mode-p) org-cycle-include-plain-lists nil))) - (if (integerp arg) - (progn - (show-all) - (hide-sublevels arg) - (setq org-cycle-global-status 'contents)) - (org-cycle '(4))))) + (cond + ((integerp arg) + (show-all) + (hide-sublevels arg) + (setq org-cycle-global-status 'contents)) + ((equal arg '(4)) + (org-set-startup-visibility) + (message "Startup visibility, plus VISIBILITY properties.")) + (t + (org-cycle '(4)))))) + +(defun org-set-startup-visibility () + "Set the visibility required by startup options and properties." + (cond + ((eq org-startup-folded t) + (org-cycle '(4))) + ((eq org-startup-folded 'content) + (let ((this-command 'org-cycle) (last-command 'org-cycle)) + (org-cycle '(4)) (org-cycle '(4))))) + (org-set-visibility-according-to-property 'no-cleanup) + (org-cycle-hide-archived-subtrees 'all) + (org-cycle-hide-drawers 'all) + (org-cycle-show-empty-lines 'all)) + +(defun org-set-visibility-according-to-property (&optional no-cleanup) + "Switch subtree visibilities according to :VISIBILITY: property." + (interactive) + (let (state) + (save-excursion + (goto-char (point-min)) + (while (re-search-forward + "^[ \t]*:VISIBILITY:[ \t]+\\([a-z]+\\)" + nil t) + (setq state (match-string 1)) + (save-excursion + (org-back-to-heading t) + (hide-subtree) + (org-reveal) + (cond + ((equal state '("fold" "folded")) + (hide-subtree)) + ((equal state "children") + (org-show-hidden-entry) + (show-children)) + ((equal state "content") + (save-excursion + (save-restriction + (org-narrow-to-subtree) + (org-content)))) + ((member state '("all" "showall")) + (show-subtree))))) + (unless no-cleanup + (org-cycle-hide-archived-subtrees 'all) + (org-cycle-hide-drawers 'all) + (org-cycle-show-empty-lines 'all))))) (defun org-overview () "Switch to overview mode, shoing only top-level headlines. @@ -4024,8 +4230,6 @@ are at least `org-cycle-separator-lines' empty lines before the headeline." (outline-flag-region b (point-at-eol) flag) (error ":END: line missing")))))) - - (defun org-subtree-end-visible-p () "Is the end of the current subtree visible?" (pos-visible-in-window-p @@ -4083,6 +4287,7 @@ RET=jump to location [Q]uit and return to previous location (defvar org-goto-start-pos) ; dynamically scoped parameter +;; FIXME: Docstring doe not mention both interfaces (defun org-goto (&optional alternative-interface) "Look up a different location in the current file, keeping current visibility. @@ -4405,7 +4610,9 @@ state (TODO by default). Also with prefix arg, force first state." (not (match-beginning 2)) (member (match-string 2) org-done-keywords)) (insert (car org-todo-keywords-1) " ") - (insert (match-string 2) " ")))) + (insert (match-string 2) " ")) + (when org-provide-todo-statistics + (org-update-parent-todo-statistics)))) (defun org-insert-subheading (arg) "Insert a new subheading and demote it. @@ -4665,10 +4872,14 @@ is signaled in this case." (setq ne-ins (org-back-over-empty-lines)) (move-marker ins-point (point)) (setq txt (buffer-substring beg end)) + (org-save-markers-in-region beg end) (delete-region beg end) (outline-flag-region (1- beg) beg nil) (outline-flag-region (1- (point)) (point) nil) - (insert txt) + (let ((bbb (point))) + (insert-before-markers txt) + (org-reinstall-markers-in-region bbb) + (move-marker ins-point bbb)) (or (bolp) (insert "\n")) (setq ins-end (point)) (goto-char ins-point) @@ -4705,11 +4916,14 @@ This is a short-hand for marking the subtree and then cutting it." (interactive "p") (org-copy-subtree n 'cut)) -(defun org-copy-subtree (&optional n cut) +(defun org-copy-subtree (&optional n cut force-store-markers) "Cut the current subtree into the clipboard. With prefix arg N, cut this many sequential subtrees. This is a short-hand for marking the subtree and then copying it. -If CUT is non-nil, actually cut the subtree." +If CUT is non-nil, actually cut the subtree. +If FORCE-STORE-MARKERS is non-nil, store the relative locations +of some markers in the region, even if CUT is non-nil. This is +useful if the caller implements cut-and-paste as copy-then-paste-then-cut." (interactive "p") (let (beg end folded (beg0 (point))) (if (interactive-p) @@ -4730,6 +4944,8 @@ If CUT is non-nil, actually cut the subtree." (goto-char beg0) (when (> end beg) (setq org-subtree-clip-folded folded) + (when (or cut force-store-markers) + (org-save-markers-in-region beg end)) (if cut (kill-region beg end) (copy-region-as-kill beg end)) (setq org-subtree-clip (current-kill 0)) (message "%s: Subtree(s) with %d characters" @@ -4807,6 +5023,7 @@ If optional TREE is given, use this text instead of the kill ring." (setq beg (point)) (insert-before-markers txt) (unless (string-match "\n\\'" txt) (insert "\n")) + (org-reinstall-markers-in-region beg) (setq end (point)) (goto-char beg) (skip-chars-forward " \t\n\r") @@ -4851,6 +5068,40 @@ If optional TXT is given, check this string instead of the current kill." (throw 'exit nil))) t)))) +(defvar org-markers-to-move nil + "Markers that should be moved with a cut-and-paste operation. +Those markers are stored together with their positions relative to +the start of the region.") + +(defun org-save-markers-in-region (beg end) + "Check markers in region. +If these markers are between BEG and END, record their position relative +to BEG, so that after moving the block of text, we can put the markers back +into place. +This function gets called just before an entry or tree gets cut from the +buffer. After re-insertion, `org-reinstall-markers-in-region' must be +called immediately, to move the markers with the entries." + (setq org-markers-to-move nil) + (when (featurep 'org-clock) + (org-clock-save-markers-for-cut-and-paste beg end)) + (when (featurep 'org-agenda) + (org-agenda-save-markers-for-cut-and-paste beg end))) + +(defun org-check-and-save-marker (marker beg end) + "Check if MARKER is between BEG and END. +If yes, remember the marker and the distance to BEG." + (when (and (marker-buffer marker) + (equal (marker-buffer marker) (current-buffer))) + (if (and (>= marker beg) (< marker end)) + (push (cons marker (- marker beg)) org-markers-to-move)))) + +(defun org-reinstall-markers-in-region (beg) + "Move all remembered markers to their position relative to BEG." + (mapc (lambda (x) + (move-marker (car x) (+ beg (cdr x)))) + org-markers-to-move) + (setq org-markers-to-move nil)) + (defun org-narrow-to-subtree () "Narrow buffer to the current subtree." (interactive) @@ -5104,6 +5355,147 @@ If WITH-CASE is non-nil, the sorting will be case-sensitive." table) (lambda (a b) (funcall comparefun (car a) (car b)))))) +;;; Editing source examples + +(defvar org-exit-edit-mode-map (make-sparse-keymap)) +(define-key org-exit-edit-mode-map "\C-c'" 'org-edit-src-exit) +(defvar org-edit-src-force-single-line nil) +(defvar org-edit-src-from-org-mode nil) + +(define-minor-mode org-exit-edit-mode + "Minor mode installing a single key binding, \"C-c '\" to exit special edit.") + +(defun org-edit-src-code () + "Edit the source code example at point. +An indirect buffer is created, and that buffer is then narrowed to the +example at point and switched to the correct language mode. When done, +exit by killing the buffer with \\[org-edit-src-exit]." + (interactive) + (let ((line (org-current-line)) + (case-fold-search t) + (msg (substitute-command-keys + "Edit, then exit with C-c ' (C-c and single quote)")) + (info (org-edit-src-find-region-and-lang)) + (org-mode-p (eq major-mode 'org-mode)) + beg end lang lang-f single) + (if (not info) + nil + (setq beg (nth 0 info) + end (nth 1 info) + lang (nth 2 info) + single (nth 3 info) + lang-f (intern (concat lang "-mode"))) + (unless (functionp lang-f) + (error "No such language mode: %s" lang-f)) + (goto-line line) + (if (get-buffer "*Org Edit Src Example*") + (kill-buffer "*Org Edit Src Example*")) + (switch-to-buffer (make-indirect-buffer (current-buffer) + "*Org Edit Src Example*")) + (narrow-to-region beg end) + (remove-text-properties beg end '(display nil invisible nil + intangible nil)) + (let ((org-inhibit-startup t)) + (funcall lang-f)) + (set (make-local-variable 'org-edit-src-force-single-line) single) + (set (make-local-variable 'org-edit-src-from-org-mode) org-mode-p) + (when org-mode-p + (goto-char (point-min)) + (while (re-search-forward "^," nil t) + (replace-match ""))) + (goto-line line) + (org-exit-edit-mode) + (org-set-local 'header-line-format msg) + (message "%s" msg) + t))) + +(defun org-edit-src-find-region-and-lang () + "Find the region and language for a local edit. +Return a list with beginning and end of the region, a string representing +the language, a switch telling of the content should be in a single line." + (let ((re-list + '( + ("<src\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</src>" lang) + ("<literal\\>[^<]*>[ \t]*\n?" "\n?[ \t]*</literal>" style) + ("<example>[ \t]*\n?" "\n?[ \t]*</example>" "fundamental") + ("<lisp>[ \t]*\n?" "\n?[ \t]*</lisp>" "emacs-lisp") + ("<perl>[ \t]*\n?" "\n?[ \t]*</perl>" "perl") + ("<python>[ \t]*\n?" "\n?[ \t]*</python>" "python") + ("<ruby>[ \t]*\n?" "\n?[ \t]*</ruby>" "ruby") + ("^#\\+begin_src\\( \\([^ \t\n]+\\)\\)?.*\n" "\n#\\+end_src" 2) + ("^#\\+begin_example.*\n" "^#\\+end_example" "fundamental") + ("^#\\+html:" "\n" "html" single-line) + ("^#\\+begin_html.*\n" "\n#\\+end_html" "html") + ("^#\\+begin_latex.*\n" "\n#\\+end_latex" "latex") + ("^#\\+latex:" "\n" "latex" single-line) + ("^#\\+begin_ascii.*\n" "\n#\\+end_ascii" "fundamental") + ("^#\\+ascii:" "\n" "ascii" single-line) + )) + (pos (point)) + re re1 re2 single beg end lang) + (catch 'exit + (while (setq entry (pop re-list)) + (setq re1 (car entry) re2 (nth 1 entry) lang (nth 2 entry) + single (nth 3 entry)) + (save-excursion + (if (or (looking-at re1) + (re-search-backward re1 nil t)) + (progn + (setq beg (match-end 0) lang (org-edit-src-get-lang lang)) + (if (and (re-search-forward re2 nil t) + (>= (match-end 0) pos)) + (throw 'exit (list beg (match-beginning 0) lang single)))) + (if (or (looking-at re2) + (re-search-forward re2 nil t)) + (progn + (setq end (match-beginning 0)) + (if (and (re-search-backward re1 nil t) + (<= (match-beginning 0) pos)) + (throw 'exit + (list (match-end 0) end + (org-edit-src-get-lang lang) single))))))))))) + +(defun org-edit-src-get-lang (lang) + "Extract the src language." + (let ((m (match-string 0))) + (cond + ((stringp lang) lang) + ((integerp lang) (match-string lang)) + ((and (eq lang lang) + (string-match "\\<lang=\"\\([^ \t\n\"]+\\)\"" m)) + (match-string 1 m)) + ((and (eq lang lang) + (string-match "\\<style=\"\\([^ \t\n\"]+\\)\"" m)) + (match-string 1 m)) + (t "fundamental")))) + +(defun org-edit-src-exit () + "Exit special edit and protect problematic lines." + (interactive) + (unless (buffer-base-buffer (current-buffer)) + (error "This is not an indirect buffer, something is wrong...")) + (unless (> (point-min) 1) + (error "This buffer is not narrowed, something is wrong...")) + (goto-char (point-min)) + (if (looking-at "[ \t\n]*\n") (replace-match "")) + (if (re-search-forward "\n[ \t\n]*\\'" nil t) (replace-match "")) + (when (org-bound-and-true-p org-edit-src-force-single-line) + (goto-char (point-min)) + (while (re-search-forward "\n" nil t) + (replace-match " ")) + (goto-char (point-min)) + (if (looking-at "\\s-*") (replace-match " ")) + (if (re-search-forward "\\s-+\\'" nil t) + (replace-match ""))) + (when (org-bound-and-true-p org-edit-src-from-org-mode) + (goto-char (point-min)) + (while (re-search-forward (if (org-mode-p) "^\\(.\\)" "^\\([*#]\\)") nil t) + (replace-match ",\\1")) + (when font-lock-mode + (font-lock-unfontify-region (point-min) (point-max))) + (put-text-property (point-min) (point-max) 'font-lock-fontified t)) + (kill-buffer (current-buffer))) + ;;;; Plain list items, including checkboxes ;;; Plain list items @@ -5143,10 +5535,15 @@ Return t when things worked, nil when we are not in an item." t) (error nil))) (let* ((bul (match-string 0)) + (descp (save-excursion (goto-char (match-beginning 0)) + (beginning-of-line 1) + (save-match-data + (looking-at "[ \t]*.*? ::")))) (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*") (match-end 0))) (blank (cdr (assq 'plain-list-item org-blank-before-new-entry))) pos) + (if descp (setq checkbox nil)) (cond ((and (org-at-item-p) (<= (point) eow)) ;; before the bullet @@ -5159,7 +5556,10 @@ Return t when things worked, nil when we are not in an item." (end-of-line 1) (delete-horizontal-space)) (newline (if blank 2 1)))) - (insert bul (if checkbox "[ ]" "")) + (insert bul + (if checkbox "[ ]" "") + (if descp (concat (if checkbox " " "") + (read-string "Term: ") " :: ") "")) (just-one-space) (setq pos (point)) (end-of-line 1) @@ -6197,7 +6597,10 @@ For file links, arg negates `org-context-in-file-links'." (t nil))) (when (or (null txt) (string-match "\\S-" txt)) (setq cpltxt - (concat cpltxt "::" (org-make-org-heading-search-string txt)) + (concat cpltxt "::" + (condition-case nil + (org-make-org-heading-search-string txt) + (error ""))) desc "NONE")))) (if (string-match "::\\'" cpltxt) (setq cpltxt (substring cpltxt 0 -2))) @@ -7084,6 +7487,10 @@ onto the ring." (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s))) (if (equal (substring s -1) ">") nil (setq s (concat s ">"))) s) +(defun org-remove-double-quotes (s) + (if (equal (substring s 0 1) "\"") (setq s (substring s 1))) + (if (equal (substring s -1) "\"") (setq s (substring s 0 -1))) + s) ;;; Following specific links @@ -7157,7 +7564,9 @@ If the file does not exist, an error is thrown." (setq cmd (replace-match "%s" t t cmd))) (while (string-match "%s" cmd) (setq cmd (replace-match - (save-match-data (shell-quote-argument file)) + (save-match-data + (shell-quote-argument + (convert-standard-filename file))) t t cmd))) (save-window-excursion (start-process-shell-command cmd nil cmd) @@ -7170,7 +7579,8 @@ If the file does not exist, an error is thrown." (if line (goto-line line) (if search (org-link-search search)))) ((consp cmd) - (eval cmd)) + (let ((file (convert-standard-filename file))) + (eval cmd))) (t (funcall (cdr (assq 'file org-link-frame-setup)) file))) (and (org-mode-p) (eq old-mode 'org-mode) (or (not (equal old-buffer (current-buffer))) @@ -7346,7 +7756,7 @@ operation has put the subtree." (switch-to-buffer nbuf) (goto-char pos) (org-show-context 'org-goto)) - (org-copy-special) + (org-copy-subtree 1 nil t) (save-excursion (set-buffer (setq nbuf (or (find-buffer-visiting file) (find-file-noselect file)))) @@ -7365,7 +7775,8 @@ operation has put the subtree." (point-max)))) (bookmark-set "org-refile-last-stored") (org-paste-subtree level)))) - (org-cut-special) + (org-cut-subtree) + (setq org-markers-to-move nil) (message "Entry refiled to \"%s\"" (car it))))))) (defun org-refile-goto-last-stored () @@ -7382,20 +7793,54 @@ operation has put the subtree." (unless org-refile-target-table (error "No refile targets")) (let* ((cbuf (current-buffer)) + (cfunc (if org-refile-use-outline-path + 'org-olpath-completing-read + 'completing-read)) + (extra (if org-refile-use-outline-path "/" "")) (filename (buffer-file-name (buffer-base-buffer cbuf))) (fname (and filename (file-truename filename))) (tbl (mapcar (lambda (x) (if (not (equal fname (file-truename (nth 1 x)))) - (cons (concat (car x) " (" (file-name-nondirectory - (nth 1 x)) ")") + (cons (concat (car x) extra " (" + (file-name-nondirectory (nth 1 x)) ")") (cdr x)) - x)) + (cons (concat (car x) extra) (cdr x)))) org-refile-target-table)) (completion-ignore-case t)) - (assoc (completing-read prompt tbl nil t nil 'org-refile-history) + (assoc (funcall cfunc prompt tbl nil t nil 'org-refile-history) tbl))) +(defun org-olpath-completing-read (prompt collection &rest args) + "Read an outline path like a file name." + (let ((thetable collection)) + (apply + 'completing-read prompt + (lambda (string predicate &optional flag) + (let (rtn r s f (l (length string))) + (cond + ((eq flag nil) + ;; try completion + (try-completion string thetable)) + ((eq flag t) + ;; all-completions + (setq rtn (all-completions string thetable predicate)) + (mapcar + (lambda (x) + (setq r (substring x l)) + (if (string-match " ([^)]*)$" x) + (setq f (match-string 0 x)) + (setq f "")) + (if (string-match "/" r) + (concat string (substring r 0 (match-end 0)) f) + x)) + rtn)) + ((eq flag 'lambda) + ;; exact match? + (assoc string thetable))) + )) + args))) + ;;;; Dynamic blocks (defun org-find-dblock (name) @@ -7521,6 +7966,82 @@ This function can be used in a hook." "ORGTBL" "HTML:" "LaTeX:" "BEGIN:" "END:" "TBLFM" "BEGIN_EXAMPLE" "END_EXAMPLE")) +(defcustom org-structure-template-alist + '( + ("s" "#+begin_src ?\n\n#+end_src" + "<src lang=\"?\">\n\n</src>") + ("e" "#+begin_example\n?\n#+end_example" + "<example>\n?\n</example>") + ("q" "#+begin_quote\n?\n#+end_quote" + "<quote>\n?\n</quote>") + ("v" "#+begin_verse\n?\n#+end_verse" + "<verse>\n?\n/verse>") + ("l" "#+begin_latex\n?\n#+end_latex" + "<literal style=\"latex\">\n?\n</literal>") + ("L" "#+latex: " + "<literal style=\"latex\">?</literal>") + ("h" "#+begin_html\n?\n#+end_html" + "<literal style=\"html\">\n?\n</literal>") + ("H" "#+html: " + "<literal style=\"html\">?</literal>") + ("a" "#+begin_ascii\n?\n#+end_ascii") + ("A" "#+ascii: ") + ("i" "#+include %file ?" + "<include file=%file markup=\"?\">") + ) + "Structure completion elements. +This is a list of abbreviation keys and values. The value gets inserted +it you type @samp{.} followed by the key and then the completion key, +usually `M-TAB'. %file will be replaced by a file name after prompting +for the file uning completion. +There are two templates for each key, the first uses the original Org syntax, +the second uses Emacs Muse-like syntax tags. These Muse-like tags become +the default when the /org-mtags.el/ module has been loaded. See also the +variable `org-mtags-prefere-muse-templates'. +This is an experimental feature, it is undecided if it is going to stay in." + :group 'org-completion + :type '(repeat + (string :tag "Key") + (string :tag "Template") + (string :tag "Muse Template"))) + +(defun org-try-structure-completion () + "Try to complete a structure template before point. +This looks for strings like \"<e\" on an otherwise empty line and +expands them." + (let ((l (buffer-substring (point-at-bol) (point))) + a) + (when (and (looking-at "[ \t]*$") + (string-match "^[ \t]*<\\([a-z]+\\)$"l) + (setq a (assoc (match-string 1 l) org-structure-template-alist))) + (org-complete-expand-structure-template (+ -1 (point-at-bol) + (match-beginning 1)) a) + t))) + +(defun org-complete-expand-structure-template (start cell) + "Expand a structure template." + (let* ((musep (org-bound-and-true-p org-mtags-prefere-muse-templates)) + (rpl (nth (if musep 2 1) cell))) + (delete-region start (point)) + (when (string-match "\\`#\\+" rpl) + (cond + ((bolp)) + ((not (string-match "\\S-" (buffer-substring (point-at-bol) (point)))) + (delete-region (point-at-bol) (point))) + (t (newline)))) + (setq start (point)) + (if (string-match "%file" rpl) + (setq rpl (replace-match + (concat + "\"" + (save-match-data + (abbreviate-file-name (read-file-name "Include file: "))) + "\"") + t t rpl))) + (insert rpl) + (if (re-search-backward "\\?" start t) (delete-char 1)))) + + (defun org-complete (&optional arg) "Perform completion on word at point. At the beginning of a headline, this completes TODO keywords as given in @@ -7535,7 +8056,8 @@ At all other locations, this simply calls the value of (interactive "P") (org-without-partial-completion (catch 'exit - (let* ((end (point)) + (let* ((a nil) + (end (point)) (beg1 (save-excursion (skip-chars-backward (org-re "[:alnum:]_@")) (point))) @@ -7544,6 +8066,12 @@ At all other locations, this simply calls the value of (point))) (confirm (lambda (x) (stringp (car x)))) (searchhead (equal (char-before beg) ?*)) + (struct + (when (and (member (char-before beg1) '(?. ?<)) + (setq a (assoc (buffer-substring beg1 (point)) + org-structure-template-alist))) + (org-complete-expand-structure-template (1- beg1) a) + (throw 'exit t))) (tag (and (equal (char-before beg1) ?:) (equal (char-after (point-at-bol)) ?*))) (prop (and (equal (char-before beg1) ?:) @@ -7868,6 +8396,8 @@ For calling through lisp, arg is also interpreted in the following way: (org-add-log-setup 'state state 'findpos dolog))) ;; Fixup tag positioning (and org-auto-align-tags (not org-setting-tags) (org-set-tags nil t)) + (when org-provide-todo-statistics + (org-update-parent-todo-statistics)) (run-hooks 'org-after-todo-state-change-hook) (if (and arg (not (member state org-done-keywords))) (setq head (org-get-todo-sequence-head state))) @@ -7887,6 +8417,51 @@ For calling through lisp, arg is also interpreted in the following way: (save-excursion (run-hook-with-args 'org-trigger-hook change-plist))))))) +(defun org-update-parent-todo-statistics () + "Update any statistics cookie in the parent of the current headline." + (interactive) + (let ((box-re "\\(\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)\\)") + level (cnt-all 0) (cnt-done 0) is-percent kwd) + (catch 'exit + (save-excursion + (setq level (org-up-heading-safe)) + (unless (and level + (re-search-forward box-re (point-at-eol) t)) + (throw 'exit nil)) + (setq is-percent (match-end 2)) + (save-match-data + (unless (outline-next-heading) (throw 'exit nil)) + (while (looking-at org-todo-line-regexp) + (setq kwd (match-string 2)) + (and kwd (setq cnt-all (1+ cnt-all))) + (and (member kwd org-done-keywords) + (setq cnt-done (1+ cnt-done))) + (condition-case nil + (outline-forward-same-level 1) + (error (end-of-line 1))))) + (replace-match + (if is-percent + (format "[%d%%]" (/ (* 100 cnt-done) (max 1 cnt-all))) + (format "[%d/%d]" cnt-done cnt-all))) + (run-hook-with-args 'org-after-todo-statistics-hook + cnt-done (- cnt-all cnt-done)))))) + +(defvar org-after-todo-statistics-hook nil + "Hook that is called after a TODO statistics cookie has been updated. +Each function is called with two arguments: the number of not-done entries +and the number of done entries. + +For example, the following function, when added to this hook, will switch +an entry to DONE when all children are done, and back to TODO when new +entries are set to a TODO status. Note that this hook is only called +when there is a statistics cookie in the headline! + + (defun org-summary-todo (n-done n-not-done) + \"Switch entry to DONE when all subentries are done, to TODO otherwise.\" + (let (org-log-done org-log-states) ; turn off logging + (org-todo (if (= n-not-done 0) \"DONE\" \"TODO\")))) +") + (defun org-local-logging (value) "Get logging settings from a property VALUE." (let* (words w a) @@ -8020,6 +8595,7 @@ Returns the new TODO keyword, or nil if no state change should occur." (match-string 1))))) (defvar org-last-changed-timestamp) +(defvar org-last-inserted-timestamp) (defvar org-log-post-message) (defvar org-log-note-purpose) (defvar org-log-note-how) @@ -8120,25 +8696,35 @@ of `org-todo-keywords-1'." (message "%d TODO entries found" (org-occur (concat "^" outline-regexp " *" kwd-re ))))) -(defun org-deadline (&optional remove) +(defun org-deadline (&optional remove time) "Insert the \"DEADLINE:\" string with a timestamp to make a deadline. -With argument REMOVE, remove any deadline from the item." +With argument REMOVE, remove any deadline from the item. +When TIME is set, it should be an internal time specification, and the +scheduling will use the corresponding date." (interactive "P") (if remove (progn (org-remove-timestamp-with-keyword org-deadline-string) (message "Item no longer has a deadline.")) - (org-add-planning-info 'deadline nil 'closed))) + (if (org-get-repeat) + (error "Cannot change deadline on task with repeater, please do that by hand") + (org-add-planning-info 'deadline time 'closed) + (message "Deadline on %s" org-last-inserted-timestamp)))) -(defun org-schedule (&optional remove) +(defun org-schedule (&optional remove time) "Insert the SCHEDULED: string with a timestamp to schedule a TODO item. -With argument REMOVE, remove any scheduling date from the item." +With argument REMOVE, remove any scheduling date from the item. +When TIME is set, it should be an internal time specification, and the +scheduling will use the corresponding date." (interactive "P") (if remove (progn (org-remove-timestamp-with-keyword org-scheduled-string) (message "Item is no longer scheduled.")) - (org-add-planning-info 'scheduled nil 'closed))) + (if (org-get-repeat) + (error "Cannot reschedule task with repeater, please do that by hand") + (org-add-planning-info 'scheduled time 'closed) + (message "Scheduled to %s" org-last-inserted-timestamp)))) (defun org-remove-timestamp-with-keyword (keyword) "Remove all time stamps with KEYWORD in the current entry." @@ -8150,8 +8736,13 @@ With argument REMOVE, remove any scheduling date from the item." (org-end-of-subtree t t) (while (re-search-backward re beg t) (replace-match "") - (unless (string-match "\\S-" (buffer-substring (point-at-bol) (point))) - (delete-region (point-at-bol) (min (1+ (point)) (point-max)))))))) + (if (and (string-match "\\S-" (buffer-substring (point-at-bol) (point))) + (equal (char-before) ?\ )) + (backward-delete-char 1) + (if (string-match "^[ \t]*$" (buffer-substring + (point-at-bol) (point-at-eol))) + (delete-region (point-at-bol) + (min (point-max) (1+ (point-at-eol)))))))))) (defun org-add-planning-info (what &optional time &rest remove) "Insert new timestamp with keyword in the line directly after the headline. @@ -8205,7 +8796,7 @@ be removed." (insert-before-markers "\n") (backward-char 1) (narrow-to-region (point) (point)) - (org-indent-to-column col)) + (and org-adapt-indentation (org-indent-to-column col))) ;; Check if we have to remove something. (setq list (cons what remove)) (while list @@ -8223,7 +8814,7 @@ be removed." (goto-char (point-max)) (when what (insert - (if (not (equal (char-before) ?\ )) " " "") + (if (not (or (bolp) (eq (char-before) ?\ ))) " " "") (cond ((eq what 'scheduled) org-scheduled-string) ((eq what 'deadline) org-deadline-string) ((eq what 'closed) org-closed-string)) @@ -8239,7 +8830,7 @@ be removed." (widen) (if (and (looking-at "[ \t]+\n") (equal (char-before) ?\n)) - (backward-delete-char 1)) + (delete-region (1- (point)) (point-at-eol))) ts))))) (defvar org-log-note-marker (make-marker)) @@ -8607,10 +9198,15 @@ ACTION can be `set', `up', `down', or a character." (defun org-scan-tags (action matcher &optional todo-only) "Scan headline tags with inheritance and produce output ACTION. -ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be -evaluated, testing if a given set of tags qualifies a headline for -inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword -are included in the output." + +ACTION can be `sparse-tree' to produce a sparse tree in the current buffer, +or `agenda' to produce an entry list for an agenda view. It can also be +a Lisp form or a function that should be called at each matched headline, in +this case the return value is a list of all return values from these calls. + +MATCHER is a Lisp form to be evaluated, testing if a given set of tags +qualifies a headline for inclusion. When TODO-ONLY is non-nil, +only lines with a TODO keyword are included in the output." (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1 "\\|") (org-re @@ -8628,9 +9224,12 @@ are included in the output." (or (buffer-file-name (buffer-base-buffer)) (buffer-name (buffer-base-buffer))))))) (case-fold-search nil) - lspos - tags tags-list tags-alist (llast 0) rtn level category i txt + lspos tags tags-list + (tags-alist (list (cons 0 (mapcar 'downcase org-file-tags)))) + (llast 0) rtn rtn1 level category i txt todo marker entry priority) + (when (not (member action '(agenda sparse-tree))) + (setq action (list 'lambda nil action))) (save-excursion (goto-char (point-min)) (when (eq action 'sparse-tree) @@ -8668,16 +9267,18 @@ are included in the output." (eval matcher) (or (not org-agenda-skip-archived-trees) (not (member org-archive-tag tags-list)))) - (and (eq action 'agenda) (org-agenda-skip)) - ;; list this headline + (unless (eq action 'sparse-tree) (org-agenda-skip)) - (if (eq action 'sparse-tree) - (progn - (and org-highlight-sparse-tree-matches - (org-get-heading) (match-end 0) - (org-highlight-new-match - (match-beginning 0) (match-beginning 1))) - (org-show-context 'tags-tree)) + ;; select this headline + + (cond + ((eq action 'sparse-tree) + (and org-highlight-sparse-tree-matches + (org-get-heading) (match-end 0) + (org-highlight-new-match + (match-beginning 0) (match-beginning 1))) + (org-show-context 'tags-tree)) + ((eq action 'agenda) (setq txt (org-format-agenda-item "" (concat @@ -8692,6 +9293,13 @@ are included in the output." 'org-marker marker 'org-hd-marker marker 'org-category category 'priority priority 'type "tagsmatch") (push txt rtn)) + ((functionp action) + (save-excursion + (setq rtn1 (funcall action)) + (push rtn1 rtn)) + (goto-char (point-at-eol))) + (t (error "Invalid action"))) + ;; if we are to skip sublevels, jump to end of subtree (or org-tags-match-list-sublevels (org-end-of-subtree t)))))) (when (and (eq action 'sparse-tree) @@ -8897,7 +9505,7 @@ also TODO lines." "Get a list of all headline tags applicable at POS. POS defaults to point. If tags are inherited, the list contains the targets in the same sequence as the headlines appear, i.e. -sthe tags of the current headline come last." +the tags of the current headline come last." (interactive) (let (tags ltags lastpos parent) (save-excursion @@ -8919,7 +9527,7 @@ sthe tags of the current headline come last." (org-up-heading-all 1) (setq parent t))) (error nil)))) - tags))) + (append (org-remove-uniherited-tags org-file-tags) tags)))) (defun org-toggle-tag (tag &optional onoff) "Toggle the tag TAG for the current line. @@ -8973,7 +9581,7 @@ If ONOFF is `on' or `off', don't toggle but set to this state." (setq p (point)) (insert (make-string (- ncol (current-column)) ?\ )) (setq ncol (current-column)) - (tabify p (point-at-eol)) + (when indent-tabs-mode (tabify p (point-at-eol))) (org-move-to-column (min ncol col) t)) (goto-char pos)))) @@ -9351,6 +9959,89 @@ Returns the new tags string, or nil to not change the current settings." (org-split-string (org-match-string-no-properties 1) ":"))))) (mapcar 'list tags))) +;;;; The mapping API + +;;;###autoload +(defun org-map-entries (func &optional match scope &rest skip) + "Call FUNC at each headline selected by MATCH in SCOPE. + +FUNC is a function or a lisp form. The function will be called without +arguments, with the cursor positioned at the beginning of the headline. +The return values of all calls to the function will be collected and +returned as a list. + +MATCH is a tags/property/todo match as it is used in the agenda tags view. +Only headlines that are matched by this query will be considered during +the iteration. When MATCH is nil or t, all headlines will be +visited by the iteration. + +SCOPE determines the scope of this command. It can be any of: + +nil The current buffer, respecting the restriction if any +tree The subtree started with the entry at point +file The current buffer, without restriction +file-with-archives + The current buffer, and any archives associated with it +agenda All agenda files +agenda-with-archives + All agenda files with any archive files associated with them +\(file1 file2 ...) + If this is a list, all files in the list will be scanned + +The remaining args are treated as settings for the skipping facilities of +the scanner. The following items can be given here: + + archive skip trees with the archive tag. + comment skip trees with the COMMENT keyword + function or Emacs Lisp form: + will be used as value for `org-agenda-skip-function', so whenever + the the function returns t, FUNC will not be called for that + entry and search will continue from the point where the + function leaves it." + (let* ((org-agenda-skip-archived-trees (memq 'archive skip)) + (org-agenda-skip-comment-trees (memq 'comment skip)) + (org-agenda-skip-function + (car (org-delete-all '(comment archive) skip))) + (org-tags-match-list-sublevels t) + matcher pos) + + (cond + ((eq match t) (setq matcher t)) + ((eq match nil) (setq matcher t)) + (t (setq matcher (if match (org-make-tags-matcher match) t)))) + + (when (eq scope 'tree) + (org-back-to-heading t) + (org-narrow-to-subtree) + (setq scope nil)) + + (if (not scope) + (progn + (org-prepare-agenda-buffers + (list (buffer-file-name (current-buffer)))) + (org-scan-tags func matcher)) + ;; Get the right scope + (setq pos (point)) + (cond + ((and scope (listp scope) (symbolp (car scope))) + (setq scope (eval scope))) + ((eq scope 'agenda) + (setq scope (org-agenda-files t))) + ((eq scope 'agenda-with-archives) + (setq scope (org-agenda-files t)) + (setq scope (org-add-archive-files scope))) + ((eq scope 'file) + (setq scope (list (buffer-file-name)))) + ((eq scope 'file-with-archives) + (setq scope (org-add-archive-files (list (buffer-file-name)))))) + (org-prepare-agenda-buffers scope) + (while (setq file (pop scope)) + (with-current-buffer (org-find-base-buffer-visiting file) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (org-scan-tags func matcher)))))))) ;;;; Properties @@ -9366,7 +10057,9 @@ but in some other way.") (defconst org-default-properties '("ARCHIVE" "CATEGORY" "SUMMARY" "DESCRIPTION" - "LOCATION" "LOGGING" "COLUMNS") + "LOCATION" "LOGGING" "COLUMNS" "VISIBILITY" + "TABLE_EXPORT_FORMAT" "TABLE_EXPORT_FILE" + "EXPORT_FILE_NAME" "EXPORT_TITLE") "Some properties that are used by Org-mode for various purposes. Being in this list makes sure that they are offered for completion.") @@ -9594,8 +10287,10 @@ If yes, return this value. If not, return the current value of the variable." (move-marker org-entry-property-inherited-from (point)) (throw 'ex tmp)) (or (org-up-heading-safe) (throw 'ex nil))))) - (or tmp (cdr (assoc property org-local-properties)) - (cdr (assoc property org-global-properties)))))) + (or tmp + (cdr (assoc property org-file-properties)) + (cdr (assoc property org-global-properties)) + (cdr (assoc property org-global-properties-fixed)))))) (defun org-entry-put (pom property value) "Set PROPERTY to VALUE for entry at point-or-marker POM." @@ -9751,14 +10446,21 @@ for a value, offering competion either on allowed values (via an inherited xxx_ALL property) or on existing values in other instances of this property in the current file." (interactive - (let* ((prop (completing-read - "Property: " (mapcar 'list (org-buffer-property-keys nil t t)))) + (let* ((completion-ignore-case t) + (keys (org-buffer-property-keys nil t t)) + (prop0 (completing-read "Property: " (mapcar 'list keys))) + (prop (if (member prop0 keys) + prop0 + (or (cdr (assoc (downcase prop0) + (mapcar (lambda (x) (cons (downcase x) x)) + keys))) + prop0))) (cur (org-entry-get nil prop)) (allowed (org-property-get-allowed-values nil prop 'table)) (existing (mapcar 'list (org-property-values prop))) (val (if allowed - (completing-read "Value: " allowed nil 'req-match) - (completing-read + (org-completing-read "Value: " allowed nil 'req-match) + (org-completing-read (concat "Value" (if (and cur (string-match "\\S-" cur)) (concat "[" cur "]") "") ": ") @@ -9770,7 +10472,8 @@ in the current file." (defun org-delete-property (property) "In the current entry, delete PROPERTY." (interactive - (let* ((prop (completing-read + (let* ((completion-ignore-case t) + (prop (completing-read "Property: " (org-entry-properties nil 'standard)))) (list prop))) (message "Property %s %s" property @@ -9781,7 +10484,8 @@ in the current file." (defun org-delete-property-globally (property) "Remove PROPERTY globally, from all entries." (interactive - (let* ((prop (completing-read + (let* ((completion-ignore-case t) + (prop (completing-read "Globally remove property: " (mapcar 'list (org-buffer-property-keys))))) (list prop))) @@ -9894,6 +10598,8 @@ Return the position where this entry starts, or nil if there is no such entry." ;;;; Timestamps (defvar org-last-changed-timestamp nil) +(defvar org-last-inserted-timestamp nil + "The last time stamp inserted with `org-insert-time-stamp'.") (defvar org-time-was-given) ; dynamically scoped parameter (defvar org-end-time-was-given) ; dynamically scoped parameter (defvar org-ts-what) ; dynamically scoped parameter @@ -9983,6 +10689,7 @@ So these are more for recording a certain time/date." (defvar org-plain-time-of-day-regexp) ; defined below +(defvar org-overriding-default-time nil) ; dynamically scoped (defvar org-read-date-overlay nil) (defvar org-dcst nil) ; dynamically scoped @@ -10040,7 +10747,7 @@ user." (if (equal with-time '(16)) '(0 0) org-time-stamp-rounding-minutes)) (org-dcst org-display-custom-times) (ct (org-current-time)) - (def (or default-time ct)) + (def (or org-overriding-default-time default-time ct)) (defdecode (decode-time def)) (dummy (progn (when (< (nth 2 defdecode) org-extend-today-until) @@ -10181,6 +10888,9 @@ user." hour minute second wday pm h2 m2 tl wday1 iso-year iso-weekday iso-week iso-year iso-date) + (when (string-match "\\`[ \t]*\\.[ \t]*\\'" ans) + (setq ans "+0")) + (when (setq delta (org-read-date-get-relative ans (current-time) def)) (setq ans (replace-match "" t t ans) deltan (car delta) @@ -10401,7 +11111,7 @@ The command returns the inserted time stamp." (insert-before-markers extra) (forward-char 1)) (insert-before-markers (or post "")) - stamp)) + (setq org-last-inserted-timestamp stamp))) (defun org-toggle-time-stamp-overlays () "Toggle the use of custom time stamp formats." @@ -10425,7 +11135,7 @@ The command returns the inserted time stamp." (message "Time stamp overlays removed"))) (defun org-display-custom-time (beg end) - "Overlay modified time stamp format over timestamp between BED and END." + "Overlay modified time stamp format over timestamp between BEG and END." (let* ((ts (buffer-substring beg end)) t1 w1 with-hm tf time str w2 (off 0)) (save-match-data @@ -10724,7 +11434,6 @@ This uses the icalendar.el library." (setq e (match-end 0))) (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") ""))) (kill-buffer buf) - (kill-buffer frombuf) (delete-file tmpfile) rtn)) @@ -11055,7 +11764,7 @@ If there is already a time stamp at the cursor position, update it." "Compute H:MM from a number of minutes." (let ((h (/ m 60))) (setq m (- m (* 60 h))) - (format "%d:%02d" h m))) + (format org-time-clocksum-format h m))) (defun org-hh:mm-string-to-minutes (s) "Convert a string H:MM to a number of minutes." @@ -11768,7 +12477,7 @@ The images can be removed again with \\[org-ctrl-c-ctrl-c]." (org-defkey org-mode-map "\C-c " 'org-table-blank-field) (org-defkey org-mode-map "\C-c+" 'org-table-sum) (org-defkey org-mode-map "\C-c=" 'org-table-eval-formula) -(org-defkey org-mode-map "\C-c'" 'org-table-edit-formulas) +(org-defkey org-mode-map "\C-c'" 'org-edit-special) (org-defkey org-mode-map "\C-c`" 'org-table-edit-field) (org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region) (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks) @@ -11780,7 +12489,7 @@ The images can be removed again with \\[org-ctrl-c-ctrl-c]." (org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section) (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize) -(org-defkey org-mode-map "\C-c\C-x\C-k" 'org-cut-special) +(org-defkey org-mode-map "\C-c\C-x\C-k" 'org-mark-entry-for-agenda-action) (org-defkey org-mode-map "\C-c\C-x\C-w" 'org-cut-special) (org-defkey org-mode-map "\C-c\C-x\M-w" 'org-copy-special) (org-defkey org-mode-map "\C-c\C-x\C-y" 'org-paste-special) @@ -11937,9 +12646,10 @@ See the individual commands for more information." (interactive "P") (cond ((org-at-table-p) (call-interactively 'org-table-previous-field)) - (arg (message "Content view to level: ") - (org-content (prefix-numeric-value arg)) - (setq org-cycle-global-status 'overview)) + ((integerp arg) + (message "Content view to level: %d" arg) + (org-content (prefix-numeric-value arg)) + (setq org-cycle-global-status 'overview)) (t (call-interactively 'org-global-cycle)))) (defun org-shiftmetaleft () @@ -12135,6 +12845,23 @@ See the individual commands for more information." (org-table-paste-rectangle) (org-paste-subtree arg))) +(defun org-edit-special () + "Call a special editor for the stuff at point. +When at a table, call the formula editor with `org-table-edit-formulas'. +When at the first line of an src example, call `org-edit-src-code'. +When in an #+include line, visit the include file. Otherwise call +`ffap' to visit the file at point." + (interactive) + (cond + ((org-at-table-p) + (call-interactively 'org-table-edit-formulas)) + ((save-excursion + (beginning-of-line 1) + (looking-at "\\(?:#\\+\\(?:setupfile\\|include\\):?[ \t]+\"?\\|[ \t]*<include\\>.*?file=\"\\)\\([^\"\n>]+\\)")) + (find-file (org-trim (match-string 1)))) + ((org-edit-src-code)) + (t (call-interactively 'ffap)))) + (defun org-ctrl-c-ctrl-c (&optional arg) "Set tags in headline, or update according to changed information at point. @@ -12216,15 +12943,18 @@ This command does many different things, depending on context: (if (org-at-table-p) (org-call-with-arg 'org-table-recalculate t)))) (t - (call-interactively 'org-mode-restart)))) +; (org-set-regexps-and-options) +; (org-restart-font-lock) + (let ((org-inhibit-startup t)) (org-mode-restart)) + (message "Local setup has been refreshed")))) (t (error "C-c C-c can do nothing useful at this location."))))) (defun org-mode-restart () "Restart Org-mode, to scan again for special lines. Also updates the keyword regular expressions." (interactive) - (let ((org-inhibit-startup t)) (org-mode)) - (message "Org-mode restarted to refresh keyword and special line setup")) + (org-mode) + (message "Org-mode restarted")) (defun org-kill-note-or-show-branches () "If this is a Note buffer, abort storing the note. Else call `show-branches'." @@ -12261,7 +12991,7 @@ context. See the individual commands for more information." (defun org-ctrl-c-star () "Compute table, or change heading status of lines. -Calls `org-table-recalculate' or `org-toggle-region-headlines', +Calls `org-table-recalculate' or `org-toggle-region-headings', depending on context. This will also turn a plain list item or a normal line into a subheading." (interactive) @@ -12412,7 +13142,7 @@ See the individual commands for more information." ("Calculate" ["Set Column Formula" org-table-eval-formula (org-at-table-p)] ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="] - ["Edit Formulas" org-table-edit-formulas (org-at-table-p)] + ["Edit Formulas" org-edit-special (org-at-table-p)] "--" ["Recalculate line" org-table-recalculate (org-at-table-p)] ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"] @@ -12477,7 +13207,8 @@ See the individual commands for more information." ["Convert to odd levels" org-convert-to-odd-levels t] ["Convert to odd/even levels" org-convert-to-oddeven-levels t]) ("Editing" - ["Emphasis..." org-emphasize t]) + ["Emphasis..." org-emphasize t] + ["Edit Source Example" org-edit-special t]) ("Archive" ["Toggle ARCHIVE tag" org-toggle-archive-tag t] ; ["Check and Tag Children" (org-toggle-archive-tag (4)) @@ -12633,13 +13364,15 @@ With optional NODE, go directly to that node." ;;;; Documentation +;;;###autoload (defun org-require-autoloaded-modules () (interactive) (mapc 'require '(org-agenda org-archive org-clock org-colview - org-exp org-export-latex org-publish + org-exp org-id org-export-latex org-publish org-remember org-table))) +;;;###autoload (defun org-customize () "Call the customize function with org as argument." (interactive) @@ -12671,6 +13404,41 @@ With optional NODE, go directly to that node." ;;; Generally useful functions +(defun org-display-warning (message) ;; Copied from Emacs-Muse + "Display the given MESSAGE as a warning." + (if (fboundp 'display-warning) + (display-warning 'org message + (if (featurep 'xemacs) + 'warning + :warning)) + (let ((buf (get-buffer-create "*Org warnings*"))) + (with-current-buffer buf + (goto-char (point-max)) + (insert "Warning (Org): " message) + (unless (bolp) + (newline))) + (display-buffer buf) + (sit-for 0)))) + +(defun org-goto-marker-or-bmk (marker &optional bookmark) + "Go to MARKER, widen if necesary. When marker is not live, try BOOKMARK." + (if (and marker (marker-buffer marker) + (buffer-live-p (marker-buffer marker))) + (progn + (switch-to-buffer (marker-buffer marker)) + (if (or (> marker (point-max)) (< marker (point-min))) + (widen)) + (goto-char marker)) + (if bookmark + (bookmark-jump bookmark) + (error "Cannot find location")))) + +(defun org-quote-csv-field (s) + "Quote field for inclusion in CSV material." + (if (string-match "[\",]" s) + (concat "\"" (mapconcat 'identity (split-string s "\"") "\"\"") "\"") + s)) + (defun org-plist-delete (plist property) "Delete PROPERTY from PLIST. This is in contrast to merely setting it to 0." @@ -12708,6 +13476,12 @@ upon the next fontification round." (setq l (- l (get-text-property b 'org-dwidth-n s)))) l)) +(defun org-base-buffer (buffer) + "Return the base buffer of BUFFER, if it has one. Else return the buffer." + (if (not buffer) + buffer + (or (buffer-base-buffer buffer) + buffer))) (defun org-trim (s) "Remove whitespace at beginning and end of string." @@ -13083,6 +13857,37 @@ not an indirect buffer." (save-match-data (string-match (org-image-file-name-regexp) file))) +(defun org-get-cursor-date () + "Return the date at cursor in as a time. +This works in the calendar and in the agenda, anywhere else it just +returns the current time." + (let (date day defd) + (cond + ((eq major-mode 'calendar-mode) + (setq date (calendar-cursor-to-date) + defd (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date)))) + ((eq major-mode 'org-agenda-mode) + (setq day (get-text-property (point) 'day)) + (if day + (setq date (calendar-gregorian-from-absolute day) + defd (encode-time 0 0 0 (nth 1 date) (nth 0 date) + (nth 2 date)))))) + (or defd (current-time)))) + +(defvar org-agenda-action-marker (make-marker) + "Marker pointing to the entry for the next agenda action.") + +(defun org-mark-entry-for-agenda-action () + "Mark the current entry as target of an agenda action. +Agenda actions are actions executed from the agenda with the key `k', +which make use of the date at the cursor." + (interactive) + (move-marker org-agenda-action-marker + (save-excursion (org-back-to-heading t) (point)) + (current-buffer)) + (message + "Entry marked for action; press `k' at desired date in agenda or calendar")) + ;;; Paragraph filling stuff. ;; We want this to be just right, so use the full arsenal. @@ -13103,17 +13908,21 @@ not an indirect buffer." (beginning-of-line 0)) (cond ((looking-at "\\*+[ \t]+") - (goto-char (match-end 0)) - (setq column (current-column))) + (if (not org-adapt-indentation) + (setq column 0) + (goto-char (match-end 0)) + (setq column (current-column)))) ((org-in-item-p) (org-beginning-of-item) ; (looking-at "[ \t]*\\(\\S-+\\)[ \t]*") - (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\[[- X]\\][ \t]*\\)?") + (looking-at "[ \t]*\\(\\S-+\\)[ \t]*\\(\\[[- X]\\][ \t]*\\|.*? :: \\)?") (setq bpos (match-beginning 1) tpos (match-end 0) bcol (progn (goto-char bpos) (current-column)) tcol (progn (goto-char tpos) (current-column)) bullet (match-string 1) bullet-type (if (string-match "[0-9]" bullet) "n" bullet)) + (if (> tcol (+ bcol org-description-max-indent)) + (setq tcol (+ bcol 5))) (if (not itemp) (setq column tcol) (goto-char pos) @@ -13197,6 +14006,13 @@ In particular, this makes sure hanging paragraphs for hand-formatted lists work correctly." (cond ((looking-at "#[ \t]+") (match-string 0)) + ((looking-at "[ \t]*\\([-*+] .*? :: \\)") + (save-excursion + (if (> (match-end 1) (+ (match-beginning 1) + org-description-max-indent)) + (goto-char (+ (match-beginning 1) 5)) + (goto-char (match-end 0))) + (make-string (current-column) ?\ ))) ((looking-at "[ \t]*\\([-*+] \\|[0-9]+[.)] \\)?") (save-excursion (goto-char (match-end 0)) @@ -13259,7 +14075,7 @@ If this is a headline, and `org-special-ctrl-a/e' is set, ignore tags on the first attempt, and only move to after the tags when the cursor is already beyond the end of the headline." (interactive "P") - (let ((pos (point))) + (let ((pos (point)) refpos) (beginning-of-line 1) (if (bobp) nil @@ -13271,16 +14087,18 @@ beyond the end of the headline." (forward-char 1))) (when org-special-ctrl-a/e (cond - ((and (looking-at org-todo-line-regexp) + ((and (looking-at org-complex-heading-regexp) (= (char-after (match-end 1)) ?\ )) + (setq refpos (min (1+ (or (match-end 3) (match-end 2) (match-end 1))) + (point-at-eol))) (goto-char (if (eq org-special-ctrl-a/e t) - (cond ((> pos (match-beginning 3)) (match-beginning 3)) - ((= pos (point)) (match-beginning 3)) + (cond ((> pos refpos) refpos) + ((= pos (point)) refpos) (t (point))) (cond ((> pos (point)) (point)) ((not (eq last-command this-command)) (point)) - (t (match-beginning 3)))))) + (t refpos))))) ((org-at-item-p) (goto-char (if (eq org-special-ctrl-a/e t) @@ -13289,7 +14107,9 @@ beyond the end of the headline." (t (point))) (cond ((> pos (point)) (point)) ((not (eq last-command this-command)) (point)) - (t (match-end 4)))))))))) + (t (match-end 4)))))))) + (org-no-warnings + (and (featurep 'xemacs) (setq zmacs-region-stays t))))) (defun org-end-of-line (&optional arg) "Go to the end of the line. @@ -13311,7 +14131,10 @@ beyond the end of the headline." (if (or (< pos (match-end 0)) (not (eq this-command last-command))) (goto-char (match-end 0)) (goto-char (match-beginning 1)))) - (end-of-line arg))))) + (end-of-line arg)))) + (org-no-warnings + (and (featurep 'xemacs) (setq zmacs-region-stays t)))) + (define-key org-mode-map "\C-a" 'org-beginning-of-line) (define-key org-mode-map "\C-e" 'org-end-of-line) @@ -13688,6 +14511,6 @@ Still experimental, may disappear in the future." (run-hooks 'org-load-hook) ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd -;;; org.el ends here +;;; org.el ends here |