Release 5.02
[org-mode/org-kjn.git] / org.el
blob0a7bfc7db0c87f625714d982e137347facb2875f
1 ;;; org.el --- Outline-based notes management and organizer
2 ;; Carstens outline-mode for keeping track of everything.
3 ;; Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Carsten Dominik <dominik at science dot uva dot nl>
6 ;; Keywords: outlines, hypermedia, calendar, wp
7 ;; Homepage: http://www.astro.uva.nl/~dominik/Tools/org/
8 ;; Version: 5.02
9 ;;
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28 ;;; Commentary:
30 ;; Org-mode is a mode for keeping notes, maintaining ToDo lists, and doing
31 ;; project planning with a fast and effective plain-text system.
33 ;; Org-mode develops organizational tasks around NOTES files that contain
34 ;; information about projects as plain text. Org-mode is implemented on
35 ;; top of outline-mode, which makes it possible to keep the content of
36 ;; large files well structured. Visibility cycling and structure editing
37 ;; help to work with the tree. Tables are easily created with a built-in
38 ;; table editor. Org-mode supports ToDo items, deadlines, time stamps,
39 ;; and scheduling. It dynamically compiles entries into an agenda that
40 ;; utilizes and smoothly integrates much of the Emacs calendar and diary.
41 ;; Plain text URL-like links connect to websites, emails, Usenet
42 ;; messages, BBDB entries, and any files related to the projects. For
43 ;; printing and sharing of notes, an Org-mode file can be exported as a
44 ;; structured ASCII file, as HTML, or (todo and agenda items only) as an
45 ;; iCalendar file. It can also serve as a publishing tool for a set of
46 ;; linked webpages.
48 ;; Installation and Activation
49 ;; ---------------------------
50 ;; See the corresponding sections in the manual at
52 ;; http://staff.science.uva.nl/~dominik/Tools/org/org.html#Installation
54 ;; Documentation
55 ;; -------------
56 ;; The documentation of Org-mode can be found in the TeXInfo file. The
57 ;; distribution also contains a PDF version of it. At the homepage of
58 ;; Org-mode, you can read the same text online as HTML. There is also an
59 ;; excellent reference card made by Philip Rooke. This card can be found
60 ;; in the etc/ directory of Emacs 22.
62 ;; A list of recent changes can be found at
63 ;; http://www.astro.uva.nl/~dominik/Tools/org/Changes
65 ;;; Code:
67 ;;;; Require other packages
69 (eval-when-compile
70 (require 'cl)
71 (require 'gnus-sum)
72 (require 'calendar))
73 ;; For XEmacs, noutline is not yet provided by outline.el, so arrange for
74 ;; the file noutline.el being loaded.
75 (if (featurep 'xemacs) (condition-case nil (require 'noutline)))
76 ;; We require noutline, which might be provided in outline.el
77 (require 'outline) (require 'noutline)
78 ;; Other stuff we need.
79 (require 'time-date)
80 (require 'easymenu)
82 ;;;; Customization variables
84 ;;; Version
86 (defconst org-version "5.02"
87 "The version number of the file org.el.")
88 (defun org-version ()
89 (interactive)
90 (message "Org-mode version %s" org-version))
92 ;;; Compatibility constants
93 (defconst org-xemacs-p (featurep 'xemacs)) ; not used by org.el itself
94 (defconst org-format-transports-properties-p
95 (let ((x "a"))
96 (add-text-properties 0 1 '(test t) x)
97 (get-text-property 0 'test (format "%s" x)))
98 "Does format transport text properties?")
100 (defmacro org-unmodified (&rest body)
101 "Execute body without changing buffer-modified-p."
102 `(set-buffer-modified-p
103 (prog1 (buffer-modified-p) ,@body)))
105 (defmacro org-re (s)
106 "Replace posix classes in regular expression."
107 (if (featurep 'xemacs)
108 (let ((ss s))
109 (save-match-data
110 (while (string-match "\\[:alnum:\\]" ss)
111 (setq ss (replace-match "a-zA-Z0-9" t t ss)))
112 ss))
115 (defmacro org-preserve-lc (&rest body)
116 `(let ((_line (org-current-line))
117 (_col (current-column)))
118 (unwind-protect
119 (progn ,@body)
120 (goto-line _line)
121 (move-to-column _col))))
123 ;;; The custom variables
125 (defgroup org nil
126 "Outline-based notes management and organizer."
127 :tag "Org"
128 :group 'outlines
129 :group 'hypermedia
130 :group 'calendar)
132 (defgroup org-startup nil
133 "Options concerning startup of Org-mode."
134 :tag "Org Startup"
135 :group 'org)
137 (defcustom org-startup-folded t
138 "Non-nil means, entering Org-mode will switch to OVERVIEW.
139 This can also be configured on a per-file basis by adding one of
140 the following lines anywhere in the buffer:
142 #+STARTUP: fold
143 #+STARTUP: nofold
144 #+STARTUP: content"
145 :group 'org-startup
146 :type '(choice
147 (const :tag "nofold: show all" nil)
148 (const :tag "fold: overview" t)
149 (const :tag "content: all headlines" content)))
151 (defcustom org-startup-truncated t
152 "Non-nil means, entering Org-mode will set `truncate-lines'.
153 This is useful since some lines containing links can be very long and
154 uninteresting. Also tables look terrible when wrapped."
155 :group 'org-startup
156 :type 'boolean)
158 (defcustom org-startup-align-all-tables nil
159 "Non-nil means, align all tables when visiting a file.
160 This is useful when the column width in tables is forced with <N> cookies
161 in table fields. Such tables will look correct only after the first re-align.
162 This can also be configured on a per-file basis by adding one of
163 the following lines anywhere in the buffer:
164 #+STARTUP: align
165 #+STARTUP: noalign"
166 :group 'org-startup
167 :type 'boolean)
169 (defcustom org-insert-mode-line-in-empty-file nil
170 "Non-nil means insert the first line setting Org-mode in empty files.
171 When the function `org-mode' is called interactively in an empty file, this
172 normally means that the file name does not automatically trigger Org-mode.
173 To ensure that the file will always be in Org-mode in the future, a
174 line enforcing Org-mode will be inserted into the buffer, if this option
175 has been set."
176 :group 'org-startup
177 :type 'boolean)
179 (defcustom org-replace-disputed-keys nil
180 "Non-nil means use alternative key bindings for some keys.
181 Org-mode uses S-<cursor> keys for changing timestamps and priorities.
182 These keys are also used by other packages like `CUA-mode' or `windmove.el'.
183 If you want to use Org-mode together with one of these other modes,
184 or more generally if you would like to move some Org-mode commands to
185 other keys, set this variable and configure the keys with the variable
186 `org-disputed-keys'.
188 This option is only relevant at load-time of Org-mode, and must be set
189 *before* org.el is loaded. Changing it requires a restart of Emacs to
190 become effective."
191 :group 'org-startup
192 :type 'boolean)
194 (if (fboundp 'defvaralias)
195 (defvaralias 'org-CUA-compatible 'org-replace-disputed-keys))
197 (defcustom org-disputed-keys
198 '(([(shift up)] . [(meta p)])
199 ([(shift down)] . [(meta n)])
200 ([(shift left)] . [(meta -)])
201 ([(shift right)] . [(meta +)])
202 ([(control shift right)] . [(meta shift +)])
203 ([(control shift left)] . [(meta shift -)]))
204 "Keys for which Org-mode and other modes compete.
205 This is an alist, cars are the default keys, second element specifies
206 the alternative to use when `org-replace-disputed-keys' is t.
208 Keys can be specified in any syntax supported by `define-key'.
209 The value of this option takes effect only at Org-mode's startup,
210 therefore you'll have to restart Emacs to apply it after changing."
211 :group 'org-startup
212 :type 'alist)
214 (defun org-key (key)
215 "Select key according to `org-replace-disputed-keys' and `org-disputed-keys'.
216 Or return the original if not disputed."
217 (if org-replace-disputed-keys
218 (let* ((nkey (key-description key))
219 (x (org-find-if (lambda (x)
220 (equal (key-description (car x)) nkey))
221 org-disputed-keys)))
222 (if x (cdr x) key))
223 key))
225 (defun org-find-if (predicate seq)
226 (catch 'exit
227 (while seq
228 (if (funcall predicate (car seq))
229 (throw 'exit (car seq))
230 (pop seq)))))
232 (defun org-defkey (keymap key def)
233 "Define a key, possibly translated, as returned by `org-key'."
234 (define-key keymap (org-key key) def))
236 (defcustom org-ellipsis nil
237 "The ellipsis to use in the Org-mode outline.
238 When nil, just use the standard three dots. When a string, use that instead,
239 and just in Org-mode (which will then use its own display table).
240 Changing this requires executing `M-x org-mode' in a buffer to become
241 effective."
242 :group 'org-startup
243 :type '(choice (const :tag "Default" nil)
244 (string :tag "String" :value "...#")))
246 (defvar org-display-table nil
247 "The display table for org-mode, in case `org-ellipsis' is non-nil.")
249 (defgroup org-keywords nil
250 "Keywords in Org-mode."
251 :tag "Org Keywords"
252 :group 'org)
254 (defcustom org-deadline-string "DEADLINE:"
255 "String to mark deadline entries.
256 A deadline is this string, followed by a time stamp. Should be a word,
257 terminated by a colon. You can insert a schedule keyword and
258 a timestamp with \\[org-deadline].
259 Changes become only effective after restarting Emacs."
260 :group 'org-keywords
261 :type 'string)
263 (defcustom org-scheduled-string "SCHEDULED:"
264 "String to mark scheduled TODO entries.
265 A schedule is this string, followed by a time stamp. Should be a word,
266 terminated by a colon. You can insert a schedule keyword and
267 a timestamp with \\[org-schedule].
268 Changes become only effective after restarting Emacs."
269 :group 'org-keywords
270 :type 'string)
272 (defcustom org-closed-string "CLOSED:"
273 "String used as the prefix for timestamps logging closing a TODO entry."
274 :group 'org-keywords
275 :type 'string)
277 (defcustom org-archived-string "ARCHIVED:"
278 "String used as the prefix for timestamps logging archiving a TODO entry."
279 :group 'org-keywords
280 :type 'string)
282 (defcustom org-clock-string "CLOCK:"
283 "String used as prefix for timestamps clocking work hours on an item."
284 :group 'org-keywords
285 :type 'string)
287 (defcustom org-comment-string "COMMENT"
288 "Entries starting with this keyword will never be exported.
289 An entry can be toggled between COMMENT and normal with
290 \\[org-toggle-comment].
291 Changes become only effective after restarting Emacs."
292 :group 'org-keywords
293 :type 'string)
295 (defcustom org-quote-string "QUOTE"
296 "Entries starting with this keyword will be exported in fixed-width font.
297 Quoting applies only to the text in the entry following the headline, and does
298 not extend beyond the next headline, even if that is lower level.
299 An entry can be toggled between QUOTE and normal with
300 \\[org-toggle-fixed-width-section]."
301 :group 'org-keywords
302 :type 'string)
304 (defconst org-repeat-re
305 (concat "\\(?:\\<\\(?:" org-scheduled-string "\\|" org-deadline-string "\\)"
306 " +<[0-9]\\{4\\}-[0-9][0-9]-[0-9][0-9] [^>\n]*\\)\\(\\+[0-9]+[dwmy]\\)")
307 "Regular expression for specifying repeated events.
308 After a match, group 1 contains the repeat expression.")
310 (defgroup org-structure nil
311 "Options concerning the general structure of Org-mode files."
312 :tag "Org Structure"
313 :group 'org)
315 (defgroup org-reveal-location nil
316 "Options about how to make context of a location visible."
317 :tag "Org Reveal Location"
318 :group 'org-structure)
320 (defcustom org-show-hierarchy-above '((default . t))
321 "Non-nil means, show full hierarchy when revealing a location.
322 Org-mode often shows locations in an org-mode file which might have
323 been invisible before. When this is set, the hierarchy of headings
324 above the exposed location is shown.
325 Turning this off for example for sparse trees makes them very compact.
326 Instead of t, this can also be an alist specifying this option for different
327 contexts. Valid contexts are
328 agenda when exposing an entry from the agenda
329 org-goto when using the command `org-goto' on key C-c C-j
330 occur-tree when using the command `org-occur' on key C-c /
331 tags-tree when constructing a sparse tree based on tags matches
332 link-search when exposing search matches associated with a link
333 mark-goto when exposing the jump goal of a mark
334 bookmark-jump when exposing a bookmark location
335 isearch when exiting from an incremental search
336 default default for all contexts not set explicitly"
337 :group 'org-reveal-location
338 :type '(choice
339 (const :tag "Always" t)
340 (const :tag "Never" nil)
341 (repeat :greedy t :tag "Individual contexts"
342 (cons
343 (choice :tag "Context"
344 (const agenda)
345 (const org-goto)
346 (const occur-tree)
347 (const tags-tree)
348 (const link-search)
349 (const mark-goto)
350 (const bookmark-jump)
351 (const isearch)
352 (const default))
353 (boolean)))))
355 (defcustom org-show-following-heading '((default . nil))
356 "Non-nil means, show following heading when revealing a location.
357 Org-mode often shows locations in an org-mode file which might have
358 been invisible before. When this is set, the heading following the
359 match is shown.
360 Turning this off for example for sparse trees makes them very compact,
361 but makes it harder to edit the location of the match. In such a case,
362 use the command \\[org-reveal] to show more context.
363 Instead of t, this can also be an alist specifying this option for different
364 contexts. See `org-show-hierarchy-above' for valid contexts."
365 :group 'org-reveal-location
366 :type '(choice
367 (const :tag "Always" t)
368 (const :tag "Never" nil)
369 (repeat :greedy t :tag "Individual contexts"
370 (cons
371 (choice :tag "Context"
372 (const agenda)
373 (const org-goto)
374 (const occur-tree)
375 (const tags-tree)
376 (const link-search)
377 (const mark-goto)
378 (const bookmark-jump)
379 (const isearch)
380 (const default))
381 (boolean)))))
383 (defcustom org-show-siblings '((default . nil) (isearch t))
384 "Non-nil means, show all sibling heading when revealing a location.
385 Org-mode often shows locations in an org-mode file which might have
386 been invisible before. When this is set, the sibling of the current entry
387 heading are all made visible. If `org-show-hierarchy-above' is t,
388 the same happens on each level of the hierarchy above the current entry.
390 By default this is on for the isearch context, off for all other contexts.
391 Turning this off for example for sparse trees makes them very compact,
392 but makes it harder to edit the location of the match. In such a case,
393 use the command \\[org-reveal] to show more context.
394 Instead of t, this can also be an alist specifying this option for different
395 contexts. See `org-show-hierarchy-above' for valid contexts."
396 :group 'org-reveal-location
397 :type '(choice
398 (const :tag "Always" t)
399 (const :tag "Never" nil)
400 (repeat :greedy t :tag "Individual contexts"
401 (cons
402 (choice :tag "Context"
403 (const agenda)
404 (const org-goto)
405 (const occur-tree)
406 (const tags-tree)
407 (const link-search)
408 (const mark-goto)
409 (const bookmark-jump)
410 (const isearch)
411 (const default))
412 (boolean)))))
414 (defgroup org-cycle nil
415 "Options concerning visibility cycling in Org-mode."
416 :tag "Org Cycle"
417 :group 'org-structure)
419 (defcustom org-drawers '("PROPERTIES")
420 "Names of drawers. Drawers are not opened by cycling on the headline above.
421 Drawers only open with a TAB on the drawer line itself. A drawer looks like
422 this:
423 :DRAWERNAME:
424 .....
425 :END:
426 The drawer \"PROPERTIES\" is special for capturing properties through
427 the property API."
428 :group 'org-structure
429 :type '(repeat (string :tag "Drawer Name")))
431 (defcustom org-cycle-global-at-bob t
432 "Cycle globally if cursor is at beginning of buffer and not at a headline.
433 This makes it possible to do global cycling without having to use S-TAB or
434 C-u TAB. For this special case to work, the first line of the buffer
435 must not be a headline - it may be empty ot some other text. When used in
436 this way, `org-cycle-hook' is disables temporarily, to make sure the
437 cursor stays at the beginning of the buffer.
438 When this option is nil, don't do anything special at the beginning
439 of the buffer."
440 :group 'org-cycle
441 :type 'boolean)
443 (defcustom org-cycle-emulate-tab t
444 "Where should `org-cycle' emulate TAB.
445 nil Never
446 white Only in completely white lines
447 whitestart Only at the beginning of lines, before the first non-white char.
448 t Everywhere except in headlines
449 exc-hl-bol Everywhere except at the start of a headline
450 If TAB is used in a place where it does not emulate TAB, the current subtree
451 visibility is cycled."
452 :group 'org-cycle
453 :type '(choice (const :tag "Never" nil)
454 (const :tag "Only in completely white lines" white)
455 (const :tag "Before first char in a line" whitestart)
456 (const :tag "Everywhere except in headlines" t)
457 (const :tag "Everywhere except at bol in headlines" exc-hl-bol)
460 (defcustom org-cycle-separator-lines 2
461 "Number of empty lines needed to keep an empty line between collapsed trees.
462 If you leave an empty line between the end of a subtree and the following
463 headline, this empty line is hidden when the subtree is folded.
464 Org-mode will leave (exactly) one empty line visible if the number of
465 empty lines is equal or larger to the number given in this variable.
466 So the default 2 means, at least 2 empty lines after the end of a subtree
467 are needed to produce free space between a collapsed subtree and the
468 following headline.
470 Special case: when 0, never leave empty lines in collapsed view."
471 :group 'org-cycle
472 :type 'integer)
474 (defcustom org-cycle-hook '(org-cycle-hide-archived-subtrees
475 org-cycle-hide-drawers
476 org-cycle-show-empty-lines
477 org-optimize-window-after-visibility-change)
478 "Hook that is run after `org-cycle' has changed the buffer visibility.
479 The function(s) in this hook must accept a single argument which indicates
480 the new state that was set by the most recent `org-cycle' command. The
481 argument is a symbol. After a global state change, it can have the values
482 `overview', `content', or `all'. After a local state change, it can have
483 the values `folded', `children', or `subtree'."
484 :group 'org-cycle
485 :type 'hook)
487 (defgroup org-edit-structure nil
488 "Options concerning structure editing in Org-mode."
489 :tag "Org Edit Structure"
490 :group 'org-structure)
492 (defcustom org-special-ctrl-a nil
493 "Non-nil means `C-a' behaves specially in headlines.
494 When set, `C-a' will bring back the cursor to the beginning of the
495 headline text, i.e. after the stars and after a possible TODO keyword.
496 When the cursor is already at that position, another `C-a' will bring
497 it to the beginning of the line."
498 :group 'org-edit-structure
499 :type 'boolean)
501 (defcustom org-odd-levels-only nil
502 "Non-nil means, skip even levels and only use odd levels for the outline.
503 This has the effect that two stars are being added/taken away in
504 promotion/demotion commands. It also influences how levels are
505 handled by the exporters.
506 Changing it requires restart of `font-lock-mode' to become effective
507 for fontification also in regions already fontified.
508 You may also set this on a per-file basis by adding one of the following
509 lines to the buffer:
511 #+STARTUP: odd
512 #+STARTUP: oddeven"
513 :group 'org-edit-structure
514 :group 'org-font-lock
515 :type 'boolean)
517 (defcustom org-adapt-indentation t
518 "Non-nil means, adapt indentation when promoting and demoting.
519 When this is set and the *entire* text in an entry is indented, the
520 indentation is increased by one space in a demotion command, and
521 decreased by one in a promotion command. If any line in the entry
522 body starts at column 0, indentation is not changed at all."
523 :group 'org-edit-structure
524 :type 'boolean)
526 (defcustom org-blank-before-new-entry '((heading . nil)
527 (plain-list-item . nil))
528 "Should `org-insert-heading' leave a blank line before new heading/item?
529 The value is an alist, with `heading' and `plain-list-item' as car,
530 and a boolean flag as cdr."
531 :group 'org-edit-structure
532 :type '(list
533 (cons (const heading) (boolean))
534 (cons (const plain-list-item) (boolean))))
536 (defcustom org-insert-heading-hook nil
537 "Hook being run after inserting a new heading."
538 :group 'org-edit-structure
539 :type 'boolean)
541 (defcustom org-enable-fixed-width-editor t
542 "Non-nil means, lines starting with \":\" are treated as fixed-width.
543 This currently only means, they are never auto-wrapped.
544 When nil, such lines will be treated like ordinary lines.
545 See also the QUOTE keyword."
546 :group 'org-edit-structure
547 :type 'boolean)
549 (defgroup org-sparse-trees nil
550 "Options concerning sparse trees in Org-mode."
551 :tag "Org Sparse Trees"
552 :group 'org-structure)
554 (defcustom org-highlight-sparse-tree-matches t
555 "Non-nil means, highlight all matches that define a sparse tree.
556 The highlights will automatically disappear the next time the buffer is
557 changed by an edit command."
558 :group 'org-sparse-trees
559 :type 'boolean)
561 (defcustom org-remove-highlights-with-change t
562 "Non-nil means, any change to the buffer will remove temporary highlights.
563 Such highlights are created by `org-occur' and `org-clock-display'.
564 When nil, `C-c C-c needs to be used to get rid of the highlights.
565 The highlights created by `org-preview-latex-fragment' always need
566 `C-c C-c' to be removed."
567 :group 'org-sparse-trees
568 :group 'org-time
569 :type 'boolean)
572 (defcustom org-occur-hook '(org-first-headline-recenter)
573 "Hook that is run after `org-occur' has constructed a sparse tree.
574 This can be used to recenter the window to show as much of the structure
575 as possible."
576 :group 'org-sparse-trees
577 :type 'hook)
579 (defgroup org-plain-lists nil
580 "Options concerning plain lists in Org-mode."
581 :tag "Org Plain lists"
582 :group 'org-structure)
584 (defcustom org-cycle-include-plain-lists nil
585 "Non-nil means, include plain lists into visibility cycling.
586 This means that during cycling, plain list items will *temporarily* be
587 interpreted as outline headlines with a level given by 1000+i where i is the
588 indentation of the bullet. In all other operations, plain list items are
589 not seen as headlines. For example, you cannot assign a TODO keyword to
590 such an item."
591 :group 'org-plain-lists
592 :type 'boolean)
594 (defcustom org-plain-list-ordered-item-terminator t
595 "The character that makes a line with leading number an ordered list item.
596 Valid values are ?. and ?\). To get both terminators, use t. While
597 ?. may look nicer, it creates the danger that a line with leading
598 number may be incorrectly interpreted as an item. ?\) therefore is
599 the safe choice."
600 :group 'org-plain-lists
601 :type '(choice (const :tag "dot like in \"2.\"" ?.)
602 (const :tag "paren like in \"2)\"" ?\))
603 (const :tab "both" t)))
605 (defcustom org-auto-renumber-ordered-lists t
606 "Non-nil means, automatically renumber ordered plain lists.
607 Renumbering happens when the sequence have been changed with
608 \\[org-shiftmetaup] or \\[org-shiftmetadown]. After other editing commands,
609 use \\[org-ctrl-c-ctrl-c] to trigger renumbering."
610 :group 'org-plain-lists
611 :type 'boolean)
613 (defcustom org-provide-checkbox-statistics t
614 "Non-nil means, update checkbox statistics after insert and toggle.
615 When this is set, checkbox statistics is updated each time you either insert
616 a new checkbox with \\[org-insert-todo-heading] or toggle a checkbox
617 with \\[org-ctrl-c-ctrl-c\\]."
618 :group 'org-plain-lists
619 :type 'boolean)
621 (defgroup org-archive nil
622 "Options concerning archiving in Org-mode."
623 :tag "Org Archive"
624 :group 'org-structure)
626 (defcustom org-archive-tag "ARCHIVE"
627 "The tag that marks a subtree as archived.
628 An archived subtree does not open during visibility cycling, and does
629 not contribute to the agenda listings."
630 :group 'org-archive
631 :group 'org-keywords
632 :type 'string)
634 (defcustom org-agenda-skip-archived-trees t
635 "Non-nil means, the agenda will skip any items located in archived trees.
636 An archived tree is a tree marked with the tag ARCHIVE."
637 :group 'org-archive
638 :group 'org-agenda-skip
639 :type 'boolean)
641 (defcustom org-cycle-open-archived-trees nil
642 "Non-nil means, `org-cycle' will open archived trees.
643 An archived tree is a tree marked with the tag ARCHIVE.
644 When nil, archived trees will stay folded. You can still open them with
645 normal outline commands like `show-all', but not with the cycling commands."
646 :group 'org-archive
647 :group 'org-cycle
648 :type 'boolean)
650 (defcustom org-sparse-tree-open-archived-trees nil
651 "Non-nil means sparse tree construction shows matches in archived trees.
652 When nil, matches in these trees are highlighted, but the trees are kept in
653 collapsed state."
654 :group 'org-archive
655 :group 'org-sparse-trees
656 :type 'boolean)
658 (defcustom org-archive-location "%s_archive::"
659 "The location where subtrees should be archived.
660 This string consists of two parts, separated by a double-colon.
662 The first part is a file name - when omitted, archiving happens in the same
663 file. %s will be replaced by the current file name (without directory part).
664 Archiving to a different file is useful to keep archived entries from
665 contributing to the Org-mode Agenda.
667 The part after the double colon is a headline. The archived entries will be
668 filed under that headline. When omitted, the subtrees are simply filed away
669 at the end of the file, as top-level entries.
671 Here are a few examples:
672 \"%s_archive::\"
673 If the current file is Projects.org, archive in file
674 Projects.org_archive, as top-level trees. This is the default.
676 \"::* Archived Tasks\"
677 Archive in the current file, under the top-level headline
678 \"* Archived Tasks\".
680 \"~/org/archive.org::\"
681 Archive in file ~/org/archive.org (absolute path), as top-level trees.
683 \"basement::** Finished Tasks\"
684 Archive in file ./basement (relative path), as level 3 trees
685 below the level 2 heading \"** Finished Tasks\".
687 You may set this option on a per-file basis by adding to the buffer a
688 line like
690 #+ARCHIVE: basement::** Finished Tasks"
691 :group 'org-archive
692 :type 'string)
694 (defcustom org-archive-mark-done t
695 "Non-nil means, mark entries as DONE when they are moved to the archive file."
696 :group 'org-archive
697 :type 'boolean)
699 (defcustom org-archive-stamp-time t
700 "Non-nil means, add a time stamp to entries moved to an archive file."
701 :group 'org-archive
702 :type 'boolean)
704 (defgroup org-table nil
705 "Options concerning tables in Org-mode."
706 :tag "Org Table"
707 :group 'org)
709 (defcustom org-enable-table-editor 'optimized
710 "Non-nil means, lines starting with \"|\" are handled by the table editor.
711 When nil, such lines will be treated like ordinary lines.
713 When equal to the symbol `optimized', the table editor will be optimized to
714 do the following:
715 - Automatic overwrite mode in front of whitespace in table fields.
716 This makes the structure of the table stay in tact as long as the edited
717 field does not exceed the column width.
718 - Minimize the number of realigns. Normally, the table is aligned each time
719 TAB or RET are pressed to move to another field. With optimization this
720 happens only if changes to a field might have changed the column width.
721 Optimization requires replacing the functions `self-insert-command',
722 `delete-char', and `backward-delete-char' in Org-mode buffers, with a
723 slight (in fact: unnoticeable) speed impact for normal typing. Org-mode is
724 very good at guessing when a re-align will be necessary, but you can always
725 force one with \\[org-ctrl-c-ctrl-c].
727 If you would like to use the optimized version in Org-mode, but the
728 un-optimized version in OrgTbl-mode, see the variable `orgtbl-optimized'.
730 This variable can be used to turn on and off the table editor during a session,
731 but in order to toggle optimization, a restart is required.
733 See also the variable `org-table-auto-blank-field'."
734 :group 'org-table
735 :type '(choice
736 (const :tag "off" nil)
737 (const :tag "on" t)
738 (const :tag "on, optimized" optimized)))
740 (defcustom orgtbl-optimized (eq org-enable-table-editor 'optimized)
741 "Non-nil means, use the optimized table editor version for `orgtbl-mode'.
742 In the optimized version, the table editor takes over all simple keys that
743 normally just insert a character. In tables, the characters are inserted
744 in a way to minimize disturbing the table structure (i.e. in overwrite mode
745 for empty fields). Outside tables, the correct binding of the keys is
746 restored.
748 The default for this option is t if the optimized version is also used in
749 Org-mode. See the variable `org-enable-table-editor' for details. Changing
750 this variable requires a restart of Emacs to become effective."
751 :group 'org-table
752 :type 'boolean)
754 (defcustom orgtbl-radio-table-templates
755 '((latex-mode "% BEGIN RECEIVE ORGTBL %n
756 % END RECEIVE ORGTBL %n
757 \\begin{comment}
758 #+ORGTBL: SEND %n orgtbl-to-latex :splice nil :skip 0
759 | | |
760 \\end{comment}\n")
761 (texinfo-mode "@c BEGIN RECEIVE ORGTBL %n
762 @c END RECEIVE ORGTBL %n
763 @ignore
764 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
765 | | |
766 @end ignore\n")
767 (html-mode "<!-- BEGIN RECEIVE ORGTBL %n -->
768 <!-- END RECEIVE ORGTBL %n -->
769 <!--
770 #+ORGTBL: SEND %n orgtbl-to-html :splice nil :skip 0
771 | | |
772 -->\n"))
773 "Templates for radio tables in different major modes.
774 All occurrences of %n in a template will be replaced with the name of the
775 table, obtained by prompting the user."
776 :group 'org-table
777 :type '(repeat
778 (list (symbol :tag "Major mode")
779 (string :tag "Format"))))
781 (defgroup org-table-settings nil
782 "Settings for tables in Org-mode."
783 :tag "Org Table Settings"
784 :group 'org-table)
786 (defcustom org-table-default-size "5x2"
787 "The default size for newly created tables, Columns x Rows."
788 :group 'org-table-settings
789 :type 'string)
791 (defcustom org-table-number-regexp
792 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%:]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\)$"
793 "Regular expression for recognizing numbers in table columns.
794 If a table column contains mostly numbers, it will be aligned to the
795 right. If not, it will be aligned to the left.
797 The default value of this option is a regular expression which allows
798 anything which looks remotely like a number as used in scientific
799 context. For example, all of the following will be considered a
800 number:
801 12 12.2 2.4e-08 2x10^12 4.034+-0.02 2.7(10) >3.5
803 Other options offered by the customize interface are more restrictive."
804 :group 'org-table-settings
805 :type '(choice
806 (const :tag "Positive Integers"
807 "^[0-9]+$")
808 (const :tag "Integers"
809 "^[-+]?[0-9]+$")
810 (const :tag "Floating Point Numbers"
811 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.[0-9]*\\)$")
812 (const :tag "Floating Point Number or Integer"
813 "^[-+]?\\([0-9]*\\.[0-9]+\\|[0-9]+\\.?[0-9]*\\)$")
814 (const :tag "Exponential, Floating point, Integer"
815 "^[-+]?[0-9.]+\\([eEdD][-+0-9]+\\)?$")
816 (const :tag "Very General Number-Like, including hex"
817 "^\\([<>]?[-+^.0-9]*[0-9][-+^.0-9eEdDx()%]*\\|\\(0[xX]\\)[0-9a-fA-F]+\\)$")
818 (string :tag "Regexp:")))
820 (defcustom org-table-number-fraction 0.5
821 "Fraction of numbers in a column required to make the column align right.
822 In a column all non-white fields are considered. If at least this
823 fraction of fields is matched by `org-table-number-fraction',
824 alignment to the right border applies."
825 :group 'org-table-settings
826 :type 'number)
828 (defgroup org-table-editing nil
829 "Bahavior of tables during editing in Org-mode."
830 :tag "Org Table Editing"
831 :group 'org-table)
833 (defcustom org-table-automatic-realign t
834 "Non-nil means, automatically re-align table when pressing TAB or RETURN.
835 When nil, aligning is only done with \\[org-table-align], or after column
836 removal/insertion."
837 :group 'org-table-editing
838 :type 'boolean)
840 (defcustom org-table-auto-blank-field t
841 "Non-nil means, automatically blank table field when starting to type into it.
842 This only happens when typing immediately after a field motion
843 command (TAB, S-TAB or RET).
844 Only relevant when `org-enable-table-editor' is equal to `optimized'."
845 :group 'org-table-editing
846 :type 'boolean)
848 (defcustom org-table-tab-jumps-over-hlines t
849 "Non-nil means, tab in the last column of a table with jump over a hline.
850 If a horizontal separator line is following the current line,
851 `org-table-next-field' can either create a new row before that line, or jump
852 over the line. When this option is nil, a new line will be created before
853 this line."
854 :group 'org-table-editing
855 :type 'boolean)
857 (defcustom org-table-tab-recognizes-table.el t
858 "Non-nil means, TAB will automatically notice a table.el table.
859 When it sees such a table, it moves point into it and - if necessary -
860 calls `table-recognize-table'."
861 :group 'org-table-editing
862 :type 'boolean)
864 (defgroup org-table-calculation nil
865 "Options concerning tables in Org-mode."
866 :tag "Org Table Calculation"
867 :group 'org-table)
869 (defcustom org-table-use-standard-references t
870 "Should org-mode work with table refrences like B3 instead of @3$2?
871 Possible values are:
872 nil never use them
873 from accept as input, do not present for editing
874 t: accept as input and present for editing"
875 :group 'org-table-calculation
876 :type '(choice
877 (const :tag "Never, don't even check unser input for them" nil)
878 (const :tag "Always, both as user input, and when editing" t)
879 (const :tag "Convert user input, don't offer during editing" 'from)))
881 (defcustom org-table-copy-increment t
882 "Non-nil means, increment when copying current field with \\[org-table-copy-down]."
883 :group 'org-table-calculation
884 :type 'boolean)
886 (defcustom org-calc-default-modes
887 '(calc-internal-prec 12
888 calc-float-format (float 5)
889 calc-angle-mode deg
890 calc-prefer-frac nil
891 calc-symbolic-mode nil
892 calc-date-format (YYYY "-" MM "-" DD " " Www (" " HH ":" mm))
893 calc-display-working-message t
895 "List with Calc mode settings for use in calc-eval for table formulas.
896 The list must contain alternating symbols (Calc modes variables and values).
897 Don't remove any of the default settings, just change the values. Org-mode
898 relies on the variables to be present in the list."
899 :group 'org-table-calculation
900 :type 'plist)
902 (defcustom org-table-formula-evaluate-inline t
903 "Non-nil means, TAB and RET evaluate a formula in current table field.
904 If the current field starts with an equal sign, it is assumed to be a formula
905 which should be evaluated as described in the manual and in the documentation
906 string of the command `org-table-eval-formula'. This feature requires the
907 Emacs calc package.
908 When this variable is nil, formula calculation is only available through
909 the command \\[org-table-eval-formula]."
910 :group 'org-table-calculation
911 :type 'boolean)
913 (defcustom org-table-formula-use-constants t
914 "Non-nil means, interpret constants in formulas in tables.
915 A constant looks like `$c' or `$Grav' and will be replaced before evaluation
916 by the value given in `org-table-formula-constants', or by a value obtained
917 from the `constants.el' package."
918 :group 'org-table-calculation
919 :type 'boolean)
921 (defcustom org-table-formula-constants nil
922 "Alist with constant names and values, for use in table formulas.
923 The car of each element is a name of a constant, without the `$' before it.
924 The cdr is the value as a string. For example, if you'd like to use the
925 speed of light in a formula, you would configure
927 (setq org-table-formula-constants '((\"c\" . \"299792458.\")))
929 and then use it in an equation like `$1*$c'.
931 Constants can also be defined on a per-file basis using a line like
933 #+CONSTANTS: c=299792458. pi=3.14 eps=2.4e-6"
934 :group 'org-table-calculation
935 :type '(repeat
936 (cons (string :tag "name")
937 (string :tag "value"))))
939 (defvar org-table-formula-constants-local nil
940 "Local version of `org-table-formula-constants'.")
941 (make-variable-buffer-local 'org-table-formula-constants-local)
943 (defcustom org-table-allow-automatic-line-recalculation t
944 "Non-nil means, lines marked with |#| or |*| will be recomputed automatically.
945 Automatically means, when TAB or RET or C-c C-c are pressed in the line."
946 :group 'org-table-calculation
947 :type 'boolean)
949 (defgroup org-link nil
950 "Options concerning links in Org-mode."
951 :tag "Org Link"
952 :group 'org)
954 (defvar org-link-abbrev-alist-local nil
955 "Buffer-local version of `org-link-abbrev-alist', which see.
956 The value of this is taken from the #+LINK lines.")
957 (make-variable-buffer-local 'org-link-abbrev-alist-local)
959 (defcustom org-link-abbrev-alist nil
960 "Alist of link abbreviations.
961 The car of each element is a string, to be replaced at the start of a link.
962 The cdrs are replacement values, like (\"linkkey\" . REPLACE). Abbreviated
963 links in Org-mode buffers can have an optional tag after a double colon, e.g.
965 [[linkkey:tag][description]]
967 If REPLACE is a string, the tag will simply be appended to create the link.
968 If the string contains \"%s\", the tag will be inserted there. REPLACE may
969 also be a function that will be called with the tag as the only argument to
970 create the link. See the manual for examples."
971 :group 'org-link
972 :type 'alist)
974 (defcustom org-descriptive-links t
975 "Non-nil means, hide link part and only show description of bracket links.
976 Bracket links are like [[link][descritpion]]. This variable sets the initial
977 state in new org-mode buffers. The setting can then be toggled on a
978 per-buffer basis from the Org->Hyperlinks menu."
979 :group 'org-link
980 :type 'boolean)
982 (defcustom org-link-file-path-type 'adaptive
983 "How the path name in file links should be stored.
984 Valid values are:
986 relative relative to the current directory, i.e. the directory of the file
987 into which the link is being inserted.
988 absolute absolute path, if possible with ~ for home directory.
989 noabbrev absolute path, no abbreviation of home directory.
990 adaptive Use relative path for files in the current directory and sub-
991 directories of it. For other files, use an absolute path."
992 :group 'org-link
993 :type '(choice
994 (const relative)
995 (const absolute)
996 (const noabbrev)
997 (const adaptive)))
999 (defcustom org-activate-links '(bracket angle plain radio tag date)
1000 "Types of links that should be activated in Org-mode files.
1001 This is a list of symbols, each leading to the activation of a certain link
1002 type. In principle, it does not hurt to turn on most link types - there may
1003 be a small gain when turning off unused link types. The types are:
1005 bracket The recommended [[link][description]] or [[link]] links with hiding.
1006 angular Links in angular brackes that may contain whitespace like
1007 <bbdb:Carsten Dominik>.
1008 plain Plain links in normal text, no whitespace, like http://google.com.
1009 radio Text that is matched by a radio target, see manual for details.
1010 tag Tag settings in a headline (link to tag search).
1011 date Time stamps (link to calendar).
1013 Changing this variable requires a restart of Emacs to become effective."
1014 :group 'org-link
1015 :type '(set (const :tag "Double bracket links (new style)" bracket)
1016 (const :tag "Angular bracket links (old style)" angular)
1017 (const :tag "plain text links" plain)
1018 (const :tag "Radio target matches" radio)
1019 (const :tag "Tags" tag)
1020 (const :tag "Tags" target)
1021 (const :tag "Timestamps" date)))
1023 (defgroup org-link-store nil
1024 "Options concerning storing links in Org-mode"
1025 :tag "Org Store Link"
1026 :group 'org-link)
1028 (defcustom org-email-link-description-format "Email %c: %.30s"
1029 "Format of the description part of a link to an email or usenet message.
1030 The following %-excapes will be replaced by corresponding information:
1032 %F full \"From\" field
1033 %f name, taken from \"From\" field, address if no name
1034 %T full \"To\" field
1035 %t first name in \"To\" field, address if no name
1036 %c correspondent. Unually \"from NAME\", but if you sent it yourself, it
1037 will be \"to NAME\". See also the variable `org-from-is-user-regexp'.
1038 %s subject
1039 %m message-id.
1041 You may use normal field width specification between the % and the letter.
1042 This is for example useful to limit the length of the subject.
1044 Examples: \"%f on: %.30s\", \"Email from %f\", \"Email %c\""
1045 :group 'org-link-store
1046 :type 'string)
1048 (defcustom org-from-is-user-regexp
1049 (let (r1 r2)
1050 (when (and user-mail-address (not (string= user-mail-address "")))
1051 (setq r1 (concat "\\<" (regexp-quote user-mail-address) "\\>")))
1052 (when (and user-full-name (not (string= user-full-name "")))
1053 (setq r2 (concat "\\<" (regexp-quote user-full-name) "\\>")))
1054 (if (and r1 r2) (concat r1 "\\|" r2) (or r1 r2)))
1055 "Regexp mached against the \"From:\" header of an email or usenet message.
1056 It should match if the message is from the user him/herself."
1057 :group 'org-link-store
1058 :type 'regexp)
1060 (defcustom org-context-in-file-links t
1061 "Non-nil means, file links from `org-store-link' contain context.
1062 A search string will be added to the file name with :: as separator and
1063 used to find the context when the link is activated by the command
1064 `org-open-at-point'.
1065 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1066 negates this setting for the duration of the command."
1067 :group 'org-link-store
1068 :type 'boolean)
1070 (defcustom org-keep-stored-link-after-insertion nil
1071 "Non-nil means, keep link in list for entire session.
1073 The command `org-store-link' adds a link pointing to the current
1074 location to an internal list. These links accumulate during a session.
1075 The command `org-insert-link' can be used to insert links into any
1076 Org-mode file (offering completion for all stored links). When this
1077 option is nil, every link which has been inserted once using \\[org-insert-link]
1078 will be removed from the list, to make completing the unused links
1079 more efficient."
1080 :group 'org-link-store
1081 :type 'boolean)
1083 (defcustom org-usenet-links-prefer-google nil
1084 "Non-nil means, `org-store-link' will create web links to Google groups.
1085 When nil, Gnus will be used for such links.
1086 Using a prefix arg to the command \\[org-store-link] (`org-store-link')
1087 negates this setting for the duration of the command."
1088 :group 'org-link-store
1089 :type 'boolean)
1091 (defgroup org-link-follow nil
1092 "Options concerning following links in Org-mode"
1093 :tag "Org Follow Link"
1094 :group 'org-link)
1096 (defcustom org-tab-follows-link nil
1097 "Non-nil means, on links TAB will follow the link.
1098 Needs to be set before org.el is loaded."
1099 :group 'org-link-follow
1100 :type 'boolean)
1102 (defcustom org-return-follows-link nil
1103 "Non-nil means, on links RET will follow the link.
1104 Needs to be set before org.el is loaded."
1105 :group 'org-link-follow
1106 :type 'boolean)
1108 (defcustom org-mouse-1-follows-link t
1109 "Non-nil means, mouse-1 on a link will follow the link.
1110 A longer mouse click will still set point. Does not wortk on XEmacs.
1111 Needs to be set before org.el is loaded."
1112 :group 'org-link-follow
1113 :type 'boolean)
1115 (defcustom org-mark-ring-length 4
1116 "Number of different positions to be recorded in the ring
1117 Changing this requires a restart of Emacs to work correctly."
1118 :group 'org-link-follow
1119 :type 'interger)
1121 (defcustom org-link-frame-setup
1122 '((vm . vm-visit-folder-other-frame)
1123 (gnus . gnus-other-frame)
1124 (file . find-file-other-window))
1125 "Setup the frame configuration for following links.
1126 When following a link with Emacs, it may often be useful to display
1127 this link in another window or frame. This variable can be used to
1128 set this up for the different types of links.
1129 For VM, use any of
1130 `vm-visit-folder'
1131 `vm-visit-folder-other-frame'
1132 For Gnus, use any of
1133 `gnus'
1134 `gnus-other-frame'
1135 For FILE, use any of
1136 `find-file'
1137 `find-file-other-window'
1138 `find-file-other-frame'
1139 For the calendar, use the variable `calendar-setup'.
1140 For BBDB, it is currently only possible to display the matches in
1141 another window."
1142 :group 'org-link-follow
1143 :type '(list
1144 (cons (const vm)
1145 (choice
1146 (const vm-visit-folder)
1147 (const vm-visit-folder-other-window)
1148 (const vm-visit-folder-other-frame)))
1149 (cons (const gnus)
1150 (choice
1151 (const gnus)
1152 (const gnus-other-frame)))
1153 (cons (const file)
1154 (choice
1155 (const find-file)
1156 (const find-file-other-window)
1157 (const find-file-other-frame)))))
1159 (defcustom org-display-internal-link-with-indirect-buffer nil
1160 "Non-nil means, use indirect buffer to display infile links.
1161 Activating internal links (from one location in a file to another location
1162 in the same file) normally just jumps to the location. When the link is
1163 activated with a C-u prefix (or with mouse-3), the link is displayed in
1164 another window. When this option is set, the other window actually displays
1165 an indirect buffer clone of the current buffer, to avoid any visibility
1166 changes to the current buffer."
1167 :group 'org-link-follow
1168 :type 'boolean)
1170 (defcustom org-open-non-existing-files nil
1171 "Non-nil means, `org-open-file' will open non-existing files.
1172 When nil, an error will be generated."
1173 :group 'org-link-follow
1174 :type 'boolean)
1176 (defcustom org-link-mailto-program '(browse-url "mailto:%a?subject=%s")
1177 "Function and arguments to call for following mailto links.
1178 This is a list with the first element being a lisp function, and the
1179 remaining elements being arguments to the function. In string arguments,
1180 %a will be replaced by the address, and %s will be replaced by the subject
1181 if one was given like in <mailto:arthur@galaxy.org::this subject>."
1182 :group 'org-link-follow
1183 :type '(choice
1184 (const :tag "browse-url" (browse-url-mail "mailto:%a?subject=%s"))
1185 (const :tag "compose-mail" (compose-mail "%a" "%s"))
1186 (const :tag "message-mail" (message-mail "%a" "%s"))
1187 (cons :tag "other" (function) (repeat :tag "argument" sexp))))
1189 (defcustom org-confirm-shell-link-function 'yes-or-no-p
1190 "Non-nil means, ask for confirmation before executing shell links.
1191 Shell links can be dangerous, just thing about a link
1193 [[shell:rm -rf ~/*][Google Search]]
1195 This link would show up in your Org-mode document as \"Google Search\"
1196 but really it would remove your entire home directory.
1197 Therefore I *definitely* advise against setting this variable to nil.
1198 Just change it to `y-or-n-p' of you want to confirm with a single key press
1199 rather than having to type \"yes\"."
1200 :group 'org-link-follow
1201 :type '(choice
1202 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1203 (const :tag "with y-or-n (faster)" y-or-n-p)
1204 (const :tag "no confirmation (dangerous)" nil)))
1206 (defcustom org-confirm-elisp-link-function 'yes-or-no-p
1207 "Non-nil means, ask for confirmation before executing elisp links.
1208 Elisp links can be dangerous, just think about a link
1210 [[elisp:(shell-command \"rm -rf ~/*\")][Google Search]]
1212 This link would show up in your Org-mode document as \"Google Search\"
1213 but really it would remove your entire home directory.
1214 Therefore I *definitely* advise against setting this variable to nil.
1215 Just change it to `y-or-n-p' of you want to confirm with a single key press
1216 rather than having to type \"yes\"."
1217 :group 'org-link-follow
1218 :type '(choice
1219 (const :tag "with yes-or-no (safer)" yes-or-no-p)
1220 (const :tag "with y-or-n (faster)" y-or-n-p)
1221 (const :tag "no confirmation (dangerous)" nil)))
1223 (defconst org-file-apps-defaults-gnu
1224 '((remote . emacs)
1225 (t . mailcap))
1226 "Default file applications on a UNIX or GNU/Linux system.
1227 See `org-file-apps'.")
1229 (defconst org-file-apps-defaults-macosx
1230 '((remote . emacs)
1231 (t . "open %s")
1232 ("ps" . "gv %s")
1233 ("ps.gz" . "gv %s")
1234 ("eps" . "gv %s")
1235 ("eps.gz" . "gv %s")
1236 ("dvi" . "xdvi %s")
1237 ("fig" . "xfig %s"))
1238 "Default file applications on a MacOS X system.
1239 The system \"open\" is known as a default, but we use X11 applications
1240 for some files for which the OS does not have a good default.
1241 See `org-file-apps'.")
1243 (defconst org-file-apps-defaults-windowsnt
1244 (list
1245 '(remote . emacs)
1246 (cons t
1247 (list (if (featurep 'xemacs)
1248 'mswindows-shell-execute
1249 'w32-shell-execute)
1250 "open" 'file)))
1251 "Default file applications on a Windows NT system.
1252 The system \"open\" is used for most files.
1253 See `org-file-apps'.")
1255 (defcustom org-file-apps
1257 ("txt" . emacs)
1258 ("tex" . emacs)
1259 ("ltx" . emacs)
1260 ("org" . emacs)
1261 ("el" . emacs)
1262 ("bib" . emacs)
1264 "External applications for opening `file:path' items in a document.
1265 Org-mode uses system defaults for different file types, but
1266 you can use this variable to set the application for a given file
1267 extension. The entries in this list are cons cells where the car identifies
1268 files and the cdr the corresponding command. Possible values for the
1269 file identifier are
1270 \"ext\" A string identifying an extension
1271 `directory' Matches a directory
1272 `remote' Matches a remote file, accessible through tramp or efs.
1273 Remote files most likely should be visited through Emacs
1274 because external applications cannot handle such paths.
1275 t Default for all remaining files
1277 Possible values for the command are:
1278 `emacs' The file will be visited by the current Emacs process.
1279 `default' Use the default application for this file type.
1280 string A command to be executed by a shell; %s will be replaced
1281 by the path to the file.
1282 sexp A Lisp form which will be evaluated. The file path will
1283 be available in the Lisp variable `file'.
1284 For more examples, see the system specific constants
1285 `org-file-apps-defaults-macosx'
1286 `org-file-apps-defaults-windowsnt'
1287 `org-file-apps-defaults-gnu'."
1288 :group 'org-link-follow
1289 :type '(repeat
1290 (cons (choice :value ""
1291 (string :tag "Extension")
1292 (const :tag "Default for unrecognized files" t)
1293 (const :tag "Remote file" remote)
1294 (const :tag "Links to a directory" directory))
1295 (choice :value ""
1296 (const :tag "Visit with Emacs" emacs)
1297 (const :tag "Use system default" default)
1298 (string :tag "Command")
1299 (sexp :tag "Lisp form")))))
1301 (defcustom org-mhe-search-all-folders nil
1302 "Non-nil means, that the search for the mh-message will be extended to
1303 all folders if the message cannot be found in the folder given in the link.
1304 Searching all folders is very efficient with one of the search engines
1305 supported by MH-E, but will be slow with pick."
1306 :group 'org-link-follow
1307 :type 'boolean)
1309 (defgroup org-remember nil
1310 "Options concerning interaction with remember.el."
1311 :tag "Org Remember"
1312 :group 'org)
1314 (defcustom org-directory "~/org"
1315 "Directory with org files.
1316 This directory will be used as default to prompt for org files.
1317 Used by the hooks for remember.el."
1318 :group 'org-remember
1319 :type 'directory)
1321 (defcustom org-default-notes-file "~/.notes"
1322 "Default target for storing notes.
1323 Used by the hooks for remember.el. This can be a string, or nil to mean
1324 the value of `remember-data-file'.
1325 You can set this on a per-template basis with the variable
1326 `org-remember-templates'."
1327 :group 'org-remember
1328 :type '(choice
1329 (const :tag "Default from remember-data-file" nil)
1330 file))
1332 (defcustom org-remember-default-headline ""
1333 "The headline that should be the default location in the notes file.
1334 When filing remember notes, the cursor will start at that position.
1335 You can set this on a per-template basis with the variable
1336 `org-remember-templates'."
1337 :group 'org-remember
1338 :type 'string)
1340 (defcustom org-remember-templates nil
1341 "Templates for the creation of remember buffers.
1342 When nil, just let remember make the buffer.
1343 When not nil, this is a list of 4-element lists. In each entry, the first
1344 element is a character, a unique key to select this template.
1345 The second element is the template. The third element is optional and can
1346 specify a destination file for remember items created with this template.
1347 The default file is given by `org-default-notes-file'. An optional forth
1348 element can specify the headline in that file that should be offered
1349 first when the user is asked to file the entry. The default headline is
1350 given in the variable `org-remember-default-headline'.
1352 The template specifies the structure of the remember buffer. It should have
1353 a first line starting with a star, to act as the org-mode headline.
1354 Furthermore, the following %-escapes will be replaced with content:
1356 %^{prompt} prompt the user for a string and replace this sequence with it.
1357 %t time stamp, date only
1358 %T time stamp with date and time
1359 %u, %U like the above, but inactive time stamps
1360 %^t like %t, but prompt for date. Similarly %^T, %^u, %^U
1361 You may define a prompt like %^{Please specify birthday}t
1362 %n user name (taken from `user-full-name')
1363 %a annotation, normally the link created with org-store-link
1364 %i initial content, the region when remember is called with C-u.
1365 If %i is indented, the entire inserted text will be indented
1366 as well.
1368 %? After completing the template, position cursor here.
1370 Apart from these general escapes, you can access information specific to the
1371 link type that is created. For example, calling `remember' in emails or gnus
1372 will record the author and the subject of the message, which you can access
1373 with %:author and %:subject, respectively. Here is a complete list of what
1374 is recorded for each link type.
1376 Link type | Available information
1377 -------------------+------------------------------------------------------
1378 bbdb | %:type %:name %:company
1379 vm, wl, mh, rmail | %:type %:subject %:message-id
1380 | %:from %:fromname %:fromaddress
1381 | %:to %:toname %:toaddress
1382 | %:fromto (either \"to NAME\" or \"from NAME\")
1383 gnus | %:group, for messages also all email fields
1384 w3, w3m | %:type %:url
1385 info | %:type %:file %:node
1386 calendar | %:type %:date"
1387 :group 'org-remember
1388 :get (lambda (var) ; Make sure all entries have 4 elements
1389 (mapcar (lambda (x)
1390 (cond ((= (length x) 3) (append x '("")))
1391 ((= (length x) 2) (append x '("" "")))
1392 (t x)))
1393 (default-value var)))
1394 :type '(repeat
1395 :tag "enabled"
1396 (list :value (?a "\n" nil nil)
1397 (character :tag "Selection Key")
1398 (string :tag "Template")
1399 (file :tag "Destination file (optional)")
1400 (string :tag "Destination headline (optional)"))))
1402 (defcustom org-reverse-note-order nil
1403 "Non-nil means, store new notes at the beginning of a file or entry.
1404 When nil, new notes will be filed to the end of a file or entry."
1405 :group 'org-remember
1406 :type '(choice
1407 (const :tag "Reverse always" t)
1408 (const :tag "Reverse never" nil)
1409 (repeat :tag "By file name regexp"
1410 (cons regexp boolean))))
1412 (defgroup org-todo nil
1413 "Options concerning TODO items in Org-mode."
1414 :tag "Org TODO"
1415 :group 'org)
1417 (defgroup org-progress nil
1418 "Options concerning Progress logging in Org-mode."
1419 :tag "Org Progress"
1420 :group 'org-time)
1422 (defcustom org-todo-keywords '((sequence "TODO" "DONE"))
1423 "List of TODO entry keyword sequences and their interpretation.
1424 \\<org-mode-map>This is a list of sequences.
1426 Each sequence starts with a symbol, either `sequence' or `type',
1427 indicating if the keywords should be interpreted as a sequence of
1428 action steps, or as different types of TODO items. The first
1429 keywords are states requiring action - these states will select a headline
1430 for inclusion into the global TODO list Org-mode produces. If one of
1431 the \"keywords\" is the vertical bat \"|\" the remaining keywords
1432 signify that no further action is necessary. If \"|\" is not found,
1433 the last keyword is treated as the only DONE state of the sequence.
1435 The command \\[org-todo] cycles an entry through these states, and one
1436 additional state where no keyword is present. For details about this
1437 cycling, see the manual.
1439 TODO keywords and interpretation can also be set on a per-file basis with
1440 the special #+SEQ_TODO and #+TYP_TODO lines.
1442 For backward compatibility, this variable may also be just a list
1443 of keywords - in this case the interptetation (sequence or type) will be
1444 taken from the (otherwise obsolete) variable `org-todo-interpretation'."
1445 :group 'org-todo
1446 :group 'org-keywords
1447 :type '(choice
1448 (repeat :tag "Old syntax, just keywords"
1449 (string :tag "Keyword"))
1450 (repeat :tag "New syntax"
1451 (cons
1452 (choice
1453 :tag "Interpretation"
1454 (const :tag "Sequence (cycling hits every state)" sequence)
1455 (const :tag "Type (cycling directly to DONE)" type))
1456 (repeat
1457 (string :tag "Keyword"))))))
1459 (defvar org-todo-keywords-1 nil)
1460 (make-variable-buffer-local 'org-todo-keywords-1)
1461 (defvar org-todo-keywords-for-agenda nil)
1462 (defvar org-done-keywords-for-agenda nil)
1463 (defvar org-not-done-keywords nil)
1464 (make-variable-buffer-local 'org-not-done-keywords)
1465 (defvar org-done-keywords nil)
1466 (make-variable-buffer-local 'org-done-keywords)
1467 (defvar org-todo-heads nil)
1468 (make-variable-buffer-local 'org-todo-heads)
1469 (defvar org-todo-sets nil)
1470 (make-variable-buffer-local 'org-todo-sets)
1471 (defvar org-todo-kwd-alist nil)
1472 (make-variable-buffer-local 'org-todo-kwd-alist)
1474 (defcustom org-todo-interpretation 'sequence
1475 "Controls how TODO keywords are interpreted.
1476 This variable is in principle obsolete and is only used for
1477 backward compatibility, if the interpretation of todo keywords is
1478 not given already in `org-todo-keywords'. See that variable for
1479 more information."
1480 :group 'org-todo
1481 :group 'org-keywords
1482 :type '(choice (const sequence)
1483 (const type)))
1485 (defcustom org-after-todo-state-change-hook nil
1486 "Hook which is run after the state of a TODO item was changed.
1487 The new state (a string with a TODO keyword, or nil) is available in the
1488 Lisp variable `state'."
1489 :group 'org-todo
1490 :type 'hook)
1492 (defcustom org-log-done nil
1493 "When set, insert a (non-active) time stamp when TODO entry is marked DONE.
1494 When the state of an entry is changed from nothing to TODO, remove a previous
1495 closing date.
1497 This can also be a list of symbols indicating under which conditions
1498 the time stamp recording the action should be annotated with a short note.
1499 Valid members of this list are
1501 done Offer to record a note when marking entries done
1502 state Offer to record a note whenever changing the TODO state
1503 of an item. This is only relevant if TODO keywords are
1504 interpreted as sequence, see variable `org-todo-interpretation'.
1505 When `state' is set, this includes tracking `done'.
1506 clock-out Offer to record a note when clocking out of an item.
1508 A separate window will then pop up and allow you to type a note.
1509 After finishing with C-c C-c, the note will be added directly after the
1510 timestamp, as a plain list item. See also the variable
1511 `org-log-note-headings'.
1513 Logging can also be configured on a per-file basis by adding one of
1514 the following lines anywhere in the buffer:
1516 #+STARTUP: logdone
1517 #+STARTUP: nologging
1518 #+STARTUP: lognotedone
1519 #+STARTUP: lognotestate
1520 #+STARTUP: lognoteclock-out"
1521 :group 'org-todo
1522 :group 'org-progress
1523 :type '(choice
1524 (const :tag "off" nil)
1525 (const :tag "on" t)
1526 (set :tag "on, with notes, detailed control" :greedy t :value (done)
1527 (const :tag "when item is marked DONE" done)
1528 (const :tag "when TODO state changes" state)
1529 (const :tag "when clocking out" clock-out))))
1531 (defcustom org-log-done-with-time t
1532 "Non-nil means, the CLOSED time stamp will contain date and time.
1533 When nil, only the date will be recorded."
1534 :group 'org-progress
1535 :type 'boolean)
1537 (defcustom org-log-note-headings
1538 '((done . "CLOSING NOTE %t")
1539 (state . "State %-12s %t")
1540 (clock-out . ""))
1541 "Headings for notes added when clocking out or closing TODO items.
1542 The value is an alist, with the car being a sympol indicating the note
1543 context, and the cdr is the heading to be used. The heading may also be the
1544 empty string.
1545 %t in the heading will be replaced by a time stamp.
1546 %s will be replaced by the new TODO state, in double quotes.
1547 %u will be replaced by the user name.
1548 %U will be replaced by the full user name."
1549 :group 'org-todo
1550 :group 'org-progress
1551 :type '(list :greedy t
1552 (cons (const :tag "Heading when closing an item" done) string)
1553 (cons (const :tag
1554 "Heading when changing todo state (todo sequence only)"
1555 state) string)
1556 (cons (const :tag "Heading when clocking out" clock-out) string)))
1558 (defcustom org-log-repeat t
1559 "Non-nil means, prompt for a note when REPEAT is resetting a TODO entry.
1560 When nil, no note will be taken."
1561 :group 'org-todo
1562 :group 'org-progress
1563 :type 'boolean)
1565 (defgroup org-priorities nil
1566 "Priorities in Org-mode."
1567 :tag "Org Priorities"
1568 :group 'org-todo)
1570 (defcustom org-highest-priority ?A
1571 "The highest priority of TODO items. A character like ?A, ?B etc.
1572 Must have a smaller ASCII number than `org-lowest-priority'."
1573 :group 'org-priorities
1574 :type 'character)
1576 (defcustom org-lowest-priority ?C
1577 "The lowest priority of TODO items. A character like ?A, ?B etc.
1578 Must have a larger ASCII number than `org-highest-priority'."
1579 :group 'org-priorities
1580 :type 'character)
1582 (defcustom org-default-priority ?B
1583 "The default priority of TODO items.
1584 This is the priority an item get if no explicit priority is given."
1585 :group 'org-priorities
1586 :type 'character)
1588 (defgroup org-time nil
1589 "Options concerning time stamps and deadlines in Org-mode."
1590 :tag "Org Time"
1591 :group 'org)
1593 (defcustom org-insert-labeled-timestamps-at-point nil
1594 "Non-nil means, SCHEDULED and DEADLINE timestamps are inserted at point.
1595 When nil, these labeled time stamps are forces into the second line of an
1596 entry, just after the headline. When scheduling from the global TODO list,
1597 the time stamp will always be forced into the second line."
1598 :group 'org-time
1599 :type 'boolean)
1601 (defconst org-time-stamp-formats '("<%Y-%m-%d %a>" . "<%Y-%m-%d %a %H:%M>")
1602 "Formats for `format-time-string' which are used for time stamps.
1603 It is not recommended to change this constant.")
1605 (defcustom org-time-stamp-rounding-minutes 0
1606 "Number of minutes to round time stamps to upon insertion.
1607 When zero, insert the time unmodified. Useful rounding numbers
1608 should be factors of 60, so for example 5, 10, 15.
1609 When this is not zero, you can still force an exact time-stamp by using
1610 a double prefix argument to a time-stamp command like `C-c .' or `C-c !'."
1611 :group 'org-time
1612 :type 'integer)
1614 (defcustom org-display-custom-times nil
1615 "Non-nil means, overlay custom formats over all time stamps.
1616 The formats are defined through the variable `org-time-stamp-custom-formats'.
1617 To turn this on on a per-file basis, insert anywhere in the file:
1618 #+STARTUP: customtime"
1619 :group 'org-time
1620 :set 'set-default
1621 :type 'sexp)
1622 (make-variable-buffer-local 'org-display-custom-times)
1624 (defcustom org-time-stamp-custom-formats
1625 '("<%m/%d/%y %a>" . "<%m/%d/%y %a %H:%M>") ; american
1626 "Custom formats for time stamps. See `format-time-string' for the syntax.
1627 These are overlayed over the default ISO format if the variable
1628 `org-display-custom-times' is set. Time like %H:%M should be at the
1629 end of the second format."
1630 :group 'org-time
1631 :type 'sexp)
1633 (defun org-time-stamp-format (&optional long inactive)
1634 "Get the right format for a time string."
1635 (let ((f (if long (cdr org-time-stamp-formats)
1636 (car org-time-stamp-formats))))
1637 (if inactive
1638 (concat "[" (substring f 1 -1) "]")
1639 f)))
1641 (defcustom org-deadline-warning-days 30
1642 "No. of days before expiration during which a deadline becomes active.
1643 This variable governs the display in sparse trees and in the agenda."
1644 :group 'org-time
1645 :type 'number)
1647 (defcustom org-popup-calendar-for-date-prompt t
1648 "Non-nil means, pop up a calendar when prompting for a date.
1649 In the calendar, the date can be selected with mouse-1. However, the
1650 minibuffer will also be active, and you can simply enter the date as well.
1651 When nil, only the minibuffer will be available."
1652 :group 'org-time
1653 :type 'boolean)
1655 (defcustom org-calendar-follow-timestamp-change t
1656 "Non-nil means, make the calendar window follow timestamp changes.
1657 When a timestamp is modified and the calendar window is visible, it will be
1658 moved to the new date."
1659 :group 'org-time
1660 :type 'boolean)
1662 (defgroup org-tags nil
1663 "Options concerning tags in Org-mode."
1664 :tag "Org Tags"
1665 :group 'org)
1667 (defcustom org-tag-alist nil
1668 "List of tags allowed in Org-mode files.
1669 When this list is nil, Org-mode will base TAG input on what is already in the
1670 buffer.
1671 The value of this variable is an alist, the car may be (and should) be a
1672 character that is used to select that tag through the fast-tag-selection
1673 interface. See the manual for details."
1674 :group 'org-tags
1675 :type '(repeat
1676 (choice
1677 (cons (string :tag "Tag name")
1678 (character :tag "Access char"))
1679 (const :tag "Start radio group" (:startgroup))
1680 (const :tag "End radio group" (:endgroup)))))
1682 (defcustom org-use-fast-tag-selection 'auto
1683 "Non-nil means, use fast tag selection scheme.
1684 This is a special interface to select and deselect tags with single keys.
1685 When nil, fast selection is never used.
1686 When the symbol `auto', fast selection is used if and only if selection
1687 characters for tags have been configured, either through the variable
1688 `org-tag-alist' or through a #+TAGS line in the buffer.
1689 When t, fast selection is always used and selection keys are assigned
1690 automatically if necessary."
1691 :group 'org-tags
1692 :type '(choice
1693 (const :tag "Always" t)
1694 (const :tag "Never" nil)
1695 (const :tag "When selection characters are configured" 'auto)))
1697 (defcustom org-fast-tag-selection-single-key nil
1698 "Non-nil means, fast tag selection exits after first change.
1699 When nil, you have to press RET to exit it.
1700 During fast tag selection, you can toggle this flag with `C-c'.
1701 This variable can also have the value `expert'. In this case, the window
1702 displaying the tags menu is not even shown, until you press C-c again."
1703 :group 'org-tags
1704 :type '(choice
1705 (const :tag "No" nil)
1706 (const :tag "Yes" t)
1707 (const :tag "Expert" expert)))
1709 (defcustom org-tags-column 48
1710 "The column to which tags should be indented in a headline.
1711 If this number is positive, it specifies the column. If it is negative,
1712 it means that the tags should be flushright to that column. For example,
1713 -79 works well for a normal 80 character screen."
1714 :group 'org-tags
1715 :type 'integer)
1717 (defcustom org-auto-align-tags t
1718 "Non-nil means, realign tags after pro/demotion of TODO state change.
1719 These operations change the length of a headline and therefore shift
1720 the tags around. With this options turned on, after each such operation
1721 the tags are again aligned to `org-tags-column'."
1722 :group 'org-tags
1723 :type 'boolean)
1725 (defcustom org-use-tag-inheritance t
1726 "Non-nil means, tags in levels apply also for sublevels.
1727 When nil, only the tags directly given in a specific line apply there.
1728 If you turn off this option, you very likely want to turn on the
1729 companion option `org-tags-match-list-sublevels'."
1730 :group 'org-tags
1731 :type 'boolean)
1733 (defcustom org-tags-match-list-sublevels nil
1734 "Non-nil means list also sublevels of headlines matching tag search.
1735 Because of tag inheritance (see variable `org-use-tag-inheritance'),
1736 the sublevels of a headline matching a tag search often also match
1737 the same search. Listing all of them can create very long lists.
1738 Setting this variable to nil causes subtrees of a match to be skipped.
1739 This option is off by default, because inheritance in on. If you turn
1740 inheritance off, you very likely want to turn this option on.
1742 As a special case, if the tag search is restricted to TODO items, the
1743 value of this variable is ignored and sublevels are always checked, to
1744 make sure all corresponding TODO items find their way into the list."
1745 :group 'org-tags
1746 :type 'boolean)
1748 (defvar org-tags-history nil
1749 "History of minibuffer reads for tags.")
1750 (defvar org-last-tags-completion-table nil
1751 "The last used completion table for tags.")
1753 (defgroup org-properties nil
1754 "Options concerning properties in Org-mode."
1755 :tag "Org Properties"
1756 :group 'org)
1758 (defcustom org-property-format "%-10s %s"
1759 "How property key/value pairs should be formatted by `indent-line'.
1760 When `indent-line' hits a property definition, it will format the line
1761 according to this format, mainly to make sure that the values are
1762 lined-up with respect to each other."
1763 :group 'org-properties
1764 :type 'string)
1766 (defcustom org-columns-default-format "%25ITEM %TODO %3PRIORITY %TAGS"
1767 "The default column format, if no other format has been defined.
1768 This variable can be set on the per-file basis by inserting a line
1770 #+COLUMNS: %25ITEM ....."
1771 :group 'org-properties
1772 :type 'string)
1775 (defgroup org-agenda nil
1776 "Options concerning agenda views in Org-mode."
1777 :tag "Org Agenda"
1778 :group 'org)
1780 (defvar org-category nil
1781 "Variable used by org files to set a category for agenda display.
1782 Such files should use a file variable to set it, for example
1784 # -*- mode: org; org-category: \"ELisp\"
1786 or contain a special line
1788 #+CATEGORY: ELisp
1790 If the file does not specify a category, then file's base name
1791 is used instead.")
1792 (make-variable-buffer-local 'org-category)
1794 (defcustom org-agenda-files nil
1795 "The files to be used for agenda display.
1796 Entries may be added to this list with \\[org-agenda-file-to-front] and removed with
1797 \\[org-remove-file]. You can also use customize to edit the list.
1799 If the value of the variable is not a list but a single file name, then
1800 the list of agenda files is actually stored and maintained in that file, one
1801 agenda file per line."
1802 :group 'org-agenda
1803 :type '(choice
1804 (repeat :tag "List of files" file)
1805 (file :tag "Store list in a file\n" :value "~/.agenda_files")))
1808 (defcustom org-agenda-confirm-kill 1
1809 "When set, remote killing from the agenda buffer needs confirmation.
1810 When t, a confirmation is always needed. When a number N, confirmation is
1811 only needed when the text to be killed contains more than N non-white lines."
1812 :group 'org-agenda
1813 :type '(choice
1814 (const :tag "Never" nil)
1815 (const :tag "Always" t)
1816 (number :tag "When more than N lines")))
1818 (defcustom org-calendar-to-agenda-key [?c]
1819 "The key to be installed in `calendar-mode-map' for switching to the agenda.
1820 The command `org-calendar-goto-agenda' will be bound to this key. The
1821 default is the character `c' because then `c' can be used to switch back and
1822 forth between agenda and calendar."
1823 :group 'org-agenda
1824 :type 'sexp)
1826 (defgroup org-agenda-export nil
1827 "Options concerning exporting agenda views in Org-mode."
1828 :tag "Org Agenda Export"
1829 :group 'org-agenda)
1831 (defcustom org-agenda-with-colors t
1832 "Non-nil means, use colors in agenda views."
1833 :group 'org-agenda-export
1834 :type 'boolean)
1836 (defcustom org-agenda-exporter-settings nil
1837 "Alist of variable/value pairs that should be active during agenda export.
1838 This is a good place to set uptions for ps-print and for htmlize."
1839 :group 'org-agenda-export
1840 :type '(repeat
1841 (list
1842 (variable)
1843 (sexp :tag "Value"))))
1845 (defcustom org-agenda-export-html-style ""
1846 "The style specification for exported HTML Agenda files.
1847 If this variable contains a string, it will replace the default <style>
1848 section as produced by `htmlize'.
1849 Since there are different ways of setting style information, this variable
1850 needs to contain the full HTML structure to provide a style, including the
1851 surrounding HTML tags. The style specifications should include definitions
1852 the fonts used by the agenda, here is an example:
1854 <style type=\"text/css\">
1855 p { font-weight: normal; color: gray; }
1856 .org-agenda-structure {
1857 font-size: 110%;
1858 color: #003399;
1859 font-weight: 600;
1861 .org-todo {
1862 color: #cc6666;Week-agenda:
1863 font-weight: bold;
1865 .org-done {
1866 color: #339933;
1868 .title { text-align: center; }
1869 .todo, .deadline { color: red; }
1870 .done { color: green; }
1871 </style>
1873 or, if you want to keep the style in a file,
1875 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
1877 As the value of this option simply gets inserted into the HTML <head> header,
1878 you can \"misuse\" it to also add other text to the header. However,
1879 <style>...</style> is required, if not present the variable will be ignored."
1880 :group 'org-agenda-export
1881 :group 'org-export-html
1882 :type 'string)
1884 (defgroup org-agenda-custom-commands nil
1885 "Options concerning agenda views in Org-mode."
1886 :tag "Org Agenda Custom Commands"
1887 :group 'org-agenda)
1889 (defcustom org-agenda-custom-commands nil
1890 "Custom commands for the agenda.
1891 These commands will be offered on the splash screen displayed by the
1892 agenda dispatcher \\[org-agenda]. Each entry is a list like this:
1894 (key type match options files)
1896 key The key (a single char as a string) to be associated with the command.
1897 type The command type, any of the following symbols:
1898 todo Entries with a specific TODO keyword, in all agenda files.
1899 tags Tags match in all agenda files.
1900 tags-todo Tags match in all agenda files, TODO entries only.
1901 todo-tree Sparse tree of specific TODO keyword in *current* file.
1902 tags-tree Sparse tree with all tags matches in *current* file.
1903 occur-tree Occur sparse tree for *current* file.
1904 match What to search for:
1905 - a single keyword for TODO keyword searches
1906 - a tags match expression for tags searches
1907 - a regular expression for occur searches
1908 options A list of option setttings, similar to that in a let form, so like
1909 this: ((opt1 val1) (opt2 val2) ...)
1910 files A list of files file to write the produced agenda buffer to
1911 with the command `org-store-agenda-views'.
1912 If a file name ends in \".html\", an HTML version of the buffer
1913 is written out. If it ends in \".ps\", a postscript version is
1914 produced. Otherwide, only the plain text is written to the file.
1916 You can also define a set of commands, to create a composite agenda buffer.
1917 In this case, an entry looks like this:
1919 (key desc (cmd1 cmd2 ...) general-options file)
1921 where
1923 desc A description string to be displayed in the dispatcher menu.
1924 cmd An agenda command, similar to the above. However, tree commands
1925 are no allowed, but instead you can get agenda and global todo list.
1926 So valid commands for a set are:
1927 (agenda)
1928 (alltodo)
1929 (stuck)
1930 (todo \"match\" options files)
1931 (tags \"match\" options files)
1932 (tags-todo \"match\" options files)
1934 Each command can carry a list of options, and another set of options can be
1935 given for the whole set of commands. Individual command options take
1936 precedence over the general options."
1937 :group 'org-agenda-custom-commands
1938 :type '(repeat
1939 (choice :value ("a" tags "" nil)
1940 (list :tag "Single command"
1941 (string :tag "Key")
1942 (choice
1943 (const :tag "Agenda" agenda)
1944 (const :tag "TODO list" alltodo)
1945 (const :tag "Stuck projects" stuck)
1946 (const :tag "Tags search (all agenda files)" tags)
1947 (const :tag "Tags search of TODO entries (all agenda files)" tags-todo)
1948 (const :tag "TODO keyword search (all agenda files)" todo)
1949 (const :tag "Tags sparse tree (current buffer)" tags-tree)
1950 (const :tag "TODO keyword tree (current buffer)" todo-tree)
1951 (const :tag "Occur tree (current buffer)" occur-tree)
1952 (symbol :tag "Other, user-defined function"))
1953 (string :tag "Match")
1954 (repeat :tag "Local options"
1955 (list (variable :tag "Option") (sexp :tag "Value")))
1956 (option (repeat :tag "Export" (file :tag "Export to"))))
1957 (list :tag "Command series, all agenda files"
1958 (string :tag "Key")
1959 (string :tag "Description")
1960 (repeat
1961 (choice
1962 (const :tag "Agenda" (agenda))
1963 (const :tag "TODO list" (alltodo))
1964 (const :tag "Stuck projects" (stuck))
1965 (list :tag "Tags search"
1966 (const :format "" tags)
1967 (string :tag "Match")
1968 (repeat :tag "Local options"
1969 (list (variable :tag "Option")
1970 (sexp :tag "Value"))))
1972 (list :tag "Tags search, TODO entries only"
1973 (const :format "" tags-todo)
1974 (string :tag "Match")
1975 (repeat :tag "Local options"
1976 (list (variable :tag "Option")
1977 (sexp :tag "Value"))))
1979 (list :tag "TODO keyword search"
1980 (const :format "" todo)
1981 (string :tag "Match")
1982 (repeat :tag "Local options"
1983 (list (variable :tag "Option")
1984 (sexp :tag "Value"))))
1986 (list :tag "Other, user-defined function"
1987 (symbol :tag "function")
1988 (string :tag "Match")
1989 (repeat :tag "Local options"
1990 (list (variable :tag "Option")
1991 (sexp :tag "Value"))))))
1993 (repeat :tag "General options"
1994 (list (variable :tag "Option")
1995 (sexp :tag "Value")))
1996 (option (repeat :tag "Export" (file :tag "Export to")))))))
1998 (defcustom org-stuck-projects
1999 '("+LEVEL=2/-DONE" ("TODO" "NEXT" "NEXTACTION") nil "")
2000 "How to identify stuck projects.
2001 This is a list of four items:
2002 1. A tags/todo matcher string that is used to identify a project.
2003 The entire tree below a headline matched by this is considered one project.
2004 2. A list of TODO keywords identifying non-stuck projects.
2005 If the project subtree contains any headline with one of these todo
2006 keywords, the project is considered to be not stuck. If you specify
2007 \"*\" as a keyword, any TODO keyword will mark the project unstuck.
2008 3. A list of tags identifying non-stuck projects.
2009 If the project subtree contains any headline with one of these tags,
2010 the project is considered to be not stuck. If you specify \"*\" as
2011 a tag, any tag will mark the project unstuck.
2012 4. An arbitrary regular expression matching non-stuck projects.
2014 After defining this variable, you may use \\[org-agenda-list-stuck-projects]
2015 or `C-c a #' to produce the list."
2016 :group 'org-agenda-custom-commands
2017 :type '(list
2018 (string :tag "Tags/TODO match to identify a project")
2019 (repeat :tag "Projects are *not* stuck if they have an entry with TODO keyword any of" (string))
2020 (repeat :tag "Projects are *not* stuck if they have an entry with TAG being any of" (string))
2021 (regexp :tag "Projects are *not* stuck if this regexp matches\ninside the subtree")))
2024 (defgroup org-agenda-skip nil
2025 "Options concerning skipping parts of agenda files."
2026 :tag "Org Agenda Skip"
2027 :group 'org-agenda)
2029 (defcustom org-agenda-todo-list-sublevels t
2030 "Non-nil means, check also the sublevels of a TODO entry for TODO entries.
2031 When nil, the sublevels of a TODO entry are not checked, resulting in
2032 potentially much shorter TODO lists."
2033 :group 'org-agenda-skip
2034 :group 'org-todo
2035 :type 'boolean)
2037 (defcustom org-agenda-todo-ignore-scheduled nil
2038 "Non-nil means, don't show scheduled entries in the global todo list.
2039 The idea behind this is that by scheduling it, you have already taken care
2040 of this item."
2041 :group 'org-agenda-skip
2042 :group 'org-todo
2043 :type 'boolean)
2045 (defcustom org-agenda-todo-ignore-deadlines nil
2046 "Non-nil means, don't show near deadline entries in the global todo list.
2047 Near means closer than `org-deadline-warning-days' days.
2048 The idea behind this is that such items will appear in the agenda anyway."
2049 :group 'org-agenda-skip
2050 :group 'org-todo
2051 :type 'boolean)
2053 (defcustom org-agenda-skip-scheduled-if-done nil
2054 "Non-nil means don't show scheduled items in agenda when they are done.
2055 This is relevant for the daily/weekly agenda, not for the TODO list."
2056 :group 'org-agenda-skip
2057 :type 'boolean)
2059 (defcustom org-agenda-skip-deadline-if-done nil
2060 "Non-nil means don't show deadines when the corresponding item is done.
2061 When nil, the deadline is still shown and should give you a happy feeling.
2063 This is relevant for the daily/weekly agenda."
2064 :group 'org-agenda-skip
2065 :type 'boolean)
2067 (defcustom org-timeline-show-empty-dates 3
2068 "Non-nil means, `org-timeline' also shows dates without an entry.
2069 When nil, only the days which actually have entries are shown.
2070 When t, all days between the first and the last date are shown.
2071 When an integer, show also empty dates, but if there is a gap of more than
2072 N days, just insert a special line indicating the size of the gap."
2073 :group 'org-agenda-skip
2074 :type '(choice
2075 (const :tag "None" nil)
2076 (const :tag "All" t)
2077 (number :tag "at most")))
2080 (defgroup org-agenda-startup nil
2081 "Options concerning initial settings in the Agenda in Org Mode."
2082 :tag "Org Agenda Startup"
2083 :group 'org-agenda)
2085 (defcustom org-finalize-agenda-hook nil
2086 "Hook run just before displaying an agenda buffer."
2087 :group 'org-agenda-startup
2088 :type 'hook)
2090 (defcustom org-agenda-mouse-1-follows-link nil
2091 "Non-nil means, mouse-1 on a link will follow the link in the agenda.
2092 A longer mouse click will still set point. Does not wortk on XEmacs.
2093 Needs to be set before org.el is loaded."
2094 :group 'org-agenda-startup
2095 :type 'boolean)
2097 (defcustom org-agenda-start-with-follow-mode nil
2098 "The initial value of follow-mode in a newly created agenda window."
2099 :group 'org-agenda-startup
2100 :type 'boolean)
2102 (defgroup org-agenda-windows nil
2103 "Options concerning the windows used by the Agenda in Org Mode."
2104 :tag "Org Agenda Windows"
2105 :group 'org-agenda)
2107 (defcustom org-agenda-window-setup 'reorganize-frame
2108 "How the agenda buffer should be displayed.
2109 Possible values for this option are:
2111 current-window Show agenda in the current window, keeping all other windows.
2112 other-frame Use `switch-to-buffer-other-frame' to display agenda.
2113 other-window Use `switch-to-buffer-other-window' to display agenda.
2114 reorganize-frame Show only two windows on the current frame, the current
2115 window and the agenda.
2116 See also the variable `org-agenda-restore-windows-after-quit'."
2117 :group 'org-agenda-windows
2118 :type '(choice
2119 (const current-window)
2120 (const other-frame)
2121 (const other-window)
2122 (const reorganize-frame)))
2124 (defcustom org-agenda-restore-windows-after-quit nil
2125 "Non-nil means, restore window configuration open exiting agenda.
2126 Before the window configuration is changed for displaying the agenda,
2127 the current status is recorded. When the agenda is exited with
2128 `q' or `x' and this option is set, the old state is restored. If
2129 `org-agenda-window-setup' is `other-frame', the value of this
2130 option will be ignored.."
2131 :group 'org-agenda-windows
2132 :type 'boolean)
2134 (defcustom org-indirect-buffer-display 'other-window
2135 "How should indirect tree buffers be displayed?
2136 This applies to indirect buffers created with the commands
2137 \\[org-tree-to-indirect-buffer] and \\[org-agenda-tree-to-indirect-buffer].
2138 Valid values are:
2139 current-window Display in the current window
2140 other-window Just display in another window.
2141 dedicated-frame Create one new frame, and re-use it each time.
2142 new-frame Make a new frame each time."
2143 :group 'org-structure
2144 :group 'org-agenda-windows
2145 :type '(choice
2146 (const :tag "In current window" current-window)
2147 (const :tag "In current frame, other window" other-window)
2148 (const :tag "Each time a new frame" new-frame)
2149 (const :tag "One dedicated frame" dedicated-frame)))
2151 (defgroup org-agenda-daily/weekly nil
2152 "Options concerning the daily/weekly agenda."
2153 :tag "Org Agenda Daily/Weekly"
2154 :group 'org-agenda)
2156 (defcustom org-agenda-ndays 7
2157 "Number of days to include in overview display.
2158 Should be 1 or 7."
2159 :group 'org-agenda-daily/weekly
2160 :type 'number)
2162 (defcustom org-agenda-start-on-weekday 1
2163 "Non-nil means, start the overview always on the specified weekday.
2164 0 denotes Sunday, 1 denotes Monday etc.
2165 When nil, always start on the current day."
2166 :group 'org-agenda-daily/weekly
2167 :type '(choice (const :tag "Today" nil)
2168 (number :tag "Weekday No.")))
2170 (defcustom org-agenda-show-all-dates t
2171 "Non-nil means, `org-agenda' shows every day in the selected range.
2172 When nil, only the days which actually have entries are shown."
2173 :group 'org-agenda-daily/weekly
2174 :type 'boolean)
2176 (defcustom org-agenda-date-format "%A %d %B %Y"
2177 "Format string for displaying dates in the agenda.
2178 Used by the daily/weekly agenda and by the timeline. This should be
2179 a format string understood by `format-time-string'.
2180 FIXME: Not used currently, because of timezone problem."
2181 :group 'org-agenda-daily/weekly
2182 :type 'string)
2184 (defcustom org-agenda-include-diary nil
2185 "If non-nil, include in the agenda entries from the Emacs Calendar's diary."
2186 :group 'org-agenda-daily/weekly
2187 :type 'boolean)
2189 (defcustom org-agenda-include-all-todo nil
2190 "Set means weekly/daily agenda will always contain all TODO entries.
2191 The TODO entries will be listed at the top of the agenda, before
2192 the entries for specific days."
2193 :group 'org-agenda-daily/weekly
2194 :type 'boolean)
2196 (defgroup org-agenda-time-grid nil
2197 "Options concerning the time grid in the Org-mode Agenda."
2198 :tag "Org Agenda Time Grid"
2199 :group 'org-agenda)
2201 (defcustom org-agenda-use-time-grid t
2202 "Non-nil means, show a time grid in the agenda schedule.
2203 A time grid is a set of lines for specific times (like every two hours between
2204 8:00 and 20:00). The items scheduled for a day at specific times are
2205 sorted in between these lines.
2206 For details about when the grid will be shown, and what it will look like, see
2207 the variable `org-agenda-time-grid'."
2208 :group 'org-agenda-time-grid
2209 :type 'boolean)
2211 (defcustom org-agenda-time-grid
2212 '((daily today require-timed)
2213 "----------------"
2214 (800 1000 1200 1400 1600 1800 2000))
2216 "The settings for time grid for agenda display.
2217 This is a list of three items. The first item is again a list. It contains
2218 symbols specifying conditions when the grid should be displayed:
2220 daily if the agenda shows a single day
2221 weekly if the agenda shows an entire week
2222 today show grid on current date, independent of daily/weekly display
2223 require-timed show grid only if at least one item has a time specification
2225 The second item is a string which will be places behing the grid time.
2227 The third item is a list of integers, indicating the times that should have
2228 a grid line."
2229 :group 'org-agenda-time-grid
2230 :type
2231 '(list
2232 (set :greedy t :tag "Grid Display Options"
2233 (const :tag "Show grid in single day agenda display" daily)
2234 (const :tag "Show grid in weekly agenda display" weekly)
2235 (const :tag "Always show grid for today" today)
2236 (const :tag "Show grid only if any timed entries are present"
2237 require-timed)
2238 (const :tag "Skip grid times already present in an entry"
2239 remove-match))
2240 (string :tag "Grid String")
2241 (repeat :tag "Grid Times" (integer :tag "Time"))))
2243 (defgroup org-agenda-sorting nil
2244 "Options concerning sorting in the Org-mode Agenda."
2245 :tag "Org Agenda Sorting"
2246 :group 'org-agenda)
2248 (let ((sorting-choice
2249 '(choice
2250 (const time-up) (const time-down)
2251 (const category-keep) (const category-up) (const category-down)
2252 (const tag-down) (const tag-up)
2253 (const priority-up) (const priority-down))))
2255 (defcustom org-agenda-sorting-strategy
2256 '((agenda time-up category-keep priority-down)
2257 (todo category-keep priority-down)
2258 (tags category-keep priority-down))
2259 "Sorting structure for the agenda items of a single day.
2260 This is a list of symbols which will be used in sequence to determine
2261 if an entry should be listed before another entry. The following
2262 symbols are recognized:
2264 time-up Put entries with time-of-day indications first, early first
2265 time-down Put entries with time-of-day indications first, late first
2266 category-keep Keep the default order of categories, corresponding to the
2267 sequence in `org-agenda-files'.
2268 category-up Sort alphabetically by category, A-Z.
2269 category-down Sort alphabetically by category, Z-A.
2270 tag-up Sort alphabetically by last tag, A-Z.
2271 tag-down Sort alphabetically by last tag, Z-A.
2272 priority-up Sort numerically by priority, high priority last.
2273 priority-down Sort numerically by priority, high priority first.
2275 The different possibilities will be tried in sequence, and testing stops
2276 if one comparison returns a \"not-equal\". For example, the default
2277 '(time-up category-keep priority-down)
2278 means: Pull out all entries having a specified time of day and sort them,
2279 in order to make a time schedule for the current day the first thing in the
2280 agenda listing for the day. Of the entries without a time indication, keep
2281 the grouped in categories, don't sort the categories, but keep them in
2282 the sequence given in `org-agenda-files'. Within each category sort by
2283 priority.
2285 Leaving out `category-keep' would mean that items will be sorted across
2286 categories by priority."
2287 :group 'org-agenda-sorting
2288 :type `(choice
2289 (repeat :tag "General" ,sorting-choice)
2290 (list :tag "Individually"
2291 (cons (const :tag "Strategy for Weekly/Daily agenda" agenda)
2292 (repeat ,sorting-choice))
2293 (cons (const :tag "Strategy for TODO lists" todo)
2294 (repeat ,sorting-choice))
2295 (cons (const :tag "Strategy for Tags matches" tags)
2296 (repeat ,sorting-choice))))))
2298 (defcustom org-sort-agenda-notime-is-late t
2299 "Non-nil means, items without time are considered late.
2300 This is only relevant for sorting. When t, items which have no explicit
2301 time like 15:30 will be considered as 99:01, i.e. later than any items which
2302 do have a time. When nil, the default time is before 0:00. You can use this
2303 option to decide if the schedule for today should come before or after timeless
2304 agenda entries."
2305 :group 'org-agenda-sorting
2306 :type 'boolean)
2308 (defgroup org-agenda-prefix nil
2309 "Options concerning the entry prefix in the Org-mode agenda display."
2310 :tag "Org Agenda Prefix"
2311 :group 'org-agenda)
2313 (defcustom org-agenda-prefix-format
2314 '((agenda . " %-12:c%?-12t% s")
2315 (timeline . " % s")
2316 (todo . " %-12:c")
2317 (tags . " %-12:c"))
2318 "Format specifications for the prefix of items in the agenda views.
2319 An alist with four entries, for the different agenda types. The keys to the
2320 sublists are `agenda', `timeline', `todo', and `tags'. The values
2321 are format strings.
2322 This format works similar to a printf format, with the following meaning:
2324 %c the category of the item, \"Diary\" for entries from the diary, or
2325 as given by the CATEGORY keyword or derived from the file name.
2326 %T the *last* tag of the item. Last because inherited tags come
2327 first in the list.
2328 %t the time-of-day specification if one applies to the entry, in the
2329 format HH:MM
2330 %s Scheduling/Deadline information, a short string
2332 All specifiers work basically like the standard `%s' of printf, but may
2333 contain two additional characters: A question mark just after the `%' and
2334 a whitespace/punctuation character just before the final letter.
2336 If the first character after `%' is a question mark, the entire field
2337 will only be included if the corresponding value applies to the
2338 current entry. This is useful for fields which should have fixed
2339 width when present, but zero width when absent. For example,
2340 \"%?-12t\" will result in a 12 character time field if a time of the
2341 day is specified, but will completely disappear in entries which do
2342 not contain a time.
2344 If there is punctuation or whitespace character just before the final
2345 format letter, this character will be appended to the field value if
2346 the value is not empty. For example, the format \"%-12:c\" leads to
2347 \"Diary: \" if the category is \"Diary\". If the category were be
2348 empty, no additional colon would be interted.
2350 The default value of this option is \" %-12:c%?-12t% s\", meaning:
2351 - Indent the line with two space characters
2352 - Give the category in a 12 chars wide field, padded with whitespace on
2353 the right (because of `-'). Append a colon if there is a category
2354 (because of `:').
2355 - If there is a time-of-day, put it into a 12 chars wide field. If no
2356 time, don't put in an empty field, just skip it (because of '?').
2357 - Finally, put the scheduling information and append a whitespace.
2359 As another example, if you don't want the time-of-day of entries in
2360 the prefix, you could use:
2362 (setq org-agenda-prefix-format \" %-11:c% s\")
2364 See also the variables `org-agenda-remove-times-when-in-prefix' and
2365 `org-agenda-remove-tags'."
2366 :type '(choice
2367 (string :tag "General format")
2368 (list :greedy t :tag "View dependent"
2369 (cons (const agenda) (string :tag "Format"))
2370 (cons (const timeline) (string :tag "Format"))
2371 (cons (const todo) (string :tag "Format"))
2372 (cons (const tags) (string :tag "Format"))))
2373 :group 'org-agenda-prefix)
2375 (defvar org-prefix-format-compiled nil
2376 "The compiled version of the most recently used prefix format.
2377 See the variable `org-agenda-prefix-format'.")
2379 (defcustom org-agenda-remove-times-when-in-prefix t
2380 "Non-nil means, remove duplicate time specifications in agenda items.
2381 When the format `org-agenda-prefix-format' contains a `%t' specifier, a
2382 time-of-day specification in a headline or diary entry is extracted and
2383 placed into the prefix. If this option is non-nil, the original specification
2384 \(a timestamp or -range, or just a plain time(range) specification like
2385 11:30-4pm) will be removed for agenda display. This makes the agenda less
2386 cluttered.
2387 The option can be t or nil. It may also be the symbol `beg', indicating
2388 that the time should only be removed what it is located at the beginning of
2389 the headline/diary entry."
2390 :group 'org-agenda-prefix
2391 :type '(choice
2392 (const :tag "Always" t)
2393 (const :tag "Never" nil)
2394 (const :tag "When at beginning of entry" beg)))
2397 (defcustom org-agenda-default-appointment-duration nil
2398 "Default duration for appointments that only have a starting time.
2399 When nil, no duration is specified in such cases.
2400 When non-nil, this must be the number of minutes, e.g. 60 for one hour."
2401 :group 'org-agenda-prefix
2402 :type '(choice
2403 (integer :tag "Minutes")
2404 (const :tag "No default duration")))
2407 (defcustom org-agenda-remove-tags nil
2408 "Non-nil means, remove the tags from the headline copy in the agenda.
2409 When this is the symbol `prefix', only remove tags when
2410 `org-agenda-prefix-format' contains a `%T' specifier."
2411 :group 'org-agenda-prefix
2412 :type '(choice
2413 (const :tag "Always" t)
2414 (const :tag "Never" nil)
2415 (const :tag "When prefix format contains %T" prefix)))
2417 (if (fboundp 'defvaralias)
2418 (defvaralias 'org-agenda-remove-tags-when-in-prefix
2419 'org-agenda-remove-tags))
2421 (defcustom org-agenda-align-tags-to-column 65
2422 "Shift tags in agenda items to this column."
2423 :group 'org-agenda-prefix
2424 :type 'integer)
2426 (defgroup org-latex nil
2427 "Options for embedding LaTeX code into Org-mode"
2428 :tag "Org LaTeX"
2429 :group 'org)
2431 (defcustom org-format-latex-options
2432 '(:foreground default :background default :scale 1.0
2433 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0
2434 :matchers ("begin" "$" "$$" "\\(" "\\["))
2435 "Options for creating images from LaTeX fragments.
2436 This is a property list with the following properties:
2437 :foreground the foreground color for images embedded in emacs, e.g. \"Black\".
2438 `default' means use the forground of the default face.
2439 :background the background color, or \"Transparent\".
2440 `default' means use the background of the default face.
2441 :scale a scaling factor for the size of the images
2442 :html-foreground, :html-background, :html-scale
2443 The same numbers for HTML export.
2444 :matchers a list indicating which matchers should be used to
2445 find LaTeX fragments. Valid members of this list are:
2446 \"begin\" find environments
2447 \"$\" find math expressions surrounded by $...$
2448 \"$$\" find math expressions surrounded by $$....$$
2449 \"\\(\" find math expressions surrounded by \\(...\\)
2450 \"\\ [\" find math expressions surrounded by \\ [...\\]"
2451 :group 'org-latex
2452 :type 'plist)
2454 (defcustom org-format-latex-header "\\documentclass{article}
2455 \\usepackage{fullpage} % do not remove
2456 \\usepackage{amssymb}
2457 \\usepackage[usenames]{color}
2458 \\usepackage{amsmath}
2459 \\usepackage{latexsym}
2460 \\usepackage[mathscr]{eucal}
2461 \\pagestyle{empty} % do not remove"
2462 "The document header used for processing LaTeX fragments."
2463 :group 'org-latex
2464 :type 'string)
2466 (defgroup org-export nil
2467 "Options for exporting org-listings."
2468 :tag "Org Export"
2469 :group 'org)
2471 (defgroup org-export-general nil
2472 "General options for exporting Org-mode files."
2473 :tag "Org Export General"
2474 :group 'org-export)
2476 (defcustom org-export-publishing-directory "."
2477 "Path to the location where exported files should be located.
2478 This path may be relative to the directory where the Org-mode file lives.
2479 The default is to put them into the same directory as the Org-mode file.
2480 The variable may also be an alist with export types `:html', `:ascii',
2481 `:ical', or `:xoxo' and the corresponding directories. If a direcoty path
2482 is relative, it is interpreted relative to the directory where the exported
2483 Org-mode files lives."
2484 :group 'org-export-general
2485 :type '(choice
2486 (directory)
2487 (repeat
2488 (cons
2489 (choice :tag "Type"
2490 (const :html) (const :ascii) (const :ical) (const :xoxo))
2491 (directory)))))
2493 (defcustom org-export-language-setup
2494 '(("en" "Author" "Date" "Table of Contents")
2495 ("cs" "Autor" "Datum" "Obsah")
2496 ("da" "Ophavsmand" "Dato" "Indhold")
2497 ("de" "Autor" "Datum" "Inhaltsverzeichnis")
2498 ("es" "Autor" "Fecha" "\xccndice")
2499 ("fr" "Auteur" "Date" "Table des Mati\xe8res")
2500 ("it" "Autore" "Data" "Indice")
2501 ("nl" "Auteur" "Datum" "Inhoudsopgave")
2502 ("nn" "Forfattar" "Dato" "Innhold") ;; nn = Norsk (nynorsk)
2503 ("sv" "F\xf6rfattarens" "Datum" "Inneh\xe5ll"))
2504 "Terms used in export text, translated to different languages.
2505 Use the variable `org-export-default-language' to set the language,
2506 or use the +OPTION lines for a per-file setting."
2507 :group 'org-export-general
2508 :type '(repeat
2509 (list
2510 (string :tag "HTML language tag")
2511 (string :tag "Author")
2512 (string :tag "Date")
2513 (string :tag "Table of Contents"))))
2515 (defcustom org-export-default-language "en"
2516 "The default language of HTML export, as a string.
2517 This should have an association in `org-export-language-setup'."
2518 :group 'org-export-general
2519 :type 'string)
2521 (defcustom org-export-skip-text-before-1st-heading t
2522 "Non-nil means, skip all text before the first headline when exporting.
2523 When nil, that text is exported as well."
2524 :group 'org-export-general
2525 :type 'boolean)
2527 (defcustom org-export-headline-levels 3
2528 "The last level which is still exported as a headline.
2529 Inferior levels will produce itemize lists when exported.
2530 Note that a numeric prefix argument to an exporter function overrides
2531 this setting.
2533 This option can also be set with the +OPTIONS line, e.g. \"H:2\"."
2534 :group 'org-export-general
2535 :type 'number)
2537 (defcustom org-export-with-section-numbers t
2538 "Non-nil means, add section numbers to headlines when exporting.
2540 This option can also be set with the +OPTIONS line, e.g. \"num:t\"."
2541 :group 'org-export-general
2542 :type 'boolean)
2544 (defcustom org-export-with-toc t
2545 "Non-nil means, create a table of contents in exported files.
2546 The TOC contains headlines with levels up to`org-export-headline-levels'.
2547 When an integer, include levels up to N in the toc, this may then be
2548 different from `org-export-headline-levels', but it will not be allowed
2549 to be larger than the number of headline levels.
2550 When nil, no table of contents is made.
2552 Headlines which contain any TODO items will be marked with \"(*)\" in
2553 ASCII export, and with red color in HTML output, if the option
2554 `org-export-mark-todo-in-toc' is set.
2556 In HTML output, the TOC will be clickable.
2558 This option can also be set with the +OPTIONS line, e.g. \"toc:nil\"
2559 or \"toc:3\"."
2560 :group 'org-export-general
2561 :type '(choice
2562 (const :tag "No Table of Contents" nil)
2563 (const :tag "Full Table of Contents" t)
2564 (integer :tag "TOC to level")))
2566 (defcustom org-export-mark-todo-in-toc nil
2567 "Non-nil means, mark TOC lines that contain any open TODO items."
2568 :group 'org-export-general
2569 :type 'boolean)
2571 (defcustom org-export-preserve-breaks nil
2572 "Non-nil means, preserve all line breaks when exporting.
2573 Normally, in HTML output paragraphs will be reformatted. In ASCII
2574 export, line breaks will always be preserved, regardless of this variable.
2576 This option can also be set with the +OPTIONS line, e.g. \"\\n:t\"."
2577 :group 'org-export-general
2578 :type 'boolean)
2580 (defcustom org-export-with-archived-trees 'headline
2581 "Whether subtrees with the ARCHIVE tag should be exported.
2582 This can have three different values
2583 nil Do not export, pretend this tree is not present
2584 t Do export the entire tree
2585 headline Only export the headline, but skip the tree below it."
2586 :group 'org-export-general
2587 :group 'org-archive
2588 :type '(choice
2589 (const :tag "not at all" nil)
2590 (const :tag "headline only" 'headline)
2591 (const :tag "entirely" t)))
2593 (defcustom org-export-with-timestamps t
2594 "If nil, do not export time stamps and associated keywords."
2595 :group 'org-export-general
2596 :type 'boolean)
2598 (defcustom org-export-remove-timestamps-from-toc t
2599 "If nil, remove timestamps from the table of contents entries."
2600 :group 'org-export-general
2601 :type 'boolean)
2603 (defcustom org-export-with-tags 'not-in-toc
2604 "If nil, do not export tags, just remove them from headlines.
2605 If this is the symbol `not-in-toc', tags will be removed from table of
2606 contents entries, but still be shown in the headlines of the document."
2607 :group 'org-export-general
2608 :type '(choice
2609 (const :tag "Off" nil)
2610 (const :tag "Not in TOC" not-in-toc)
2611 (const :tag "On" t)))
2613 (defcustom org-export-with-property-drawer nil
2614 "Non-nil means, export property drawers.
2615 When nil, these drawers are removed before export.
2617 This option can also be set with the +OPTIONS line, e.g. \"p:t\"."
2618 :group 'org-export-general
2619 :type 'boolean)
2621 (defgroup org-export-translation nil
2622 "Options for translating special ascii sequences for the export backends."
2623 :tag "Org Export Translation"
2624 :group 'org-export)
2626 (defcustom org-export-with-emphasize t
2627 "Non-nil means, interpret *word*, /word/, and _word_ as emphasized text.
2628 If the export target supports emphasizing text, the word will be
2629 typeset in bold, italic, or underlined, respectively. Works only for
2630 single words, but you can say: I *really* *mean* *this*.
2631 Not all export backends support this.
2633 This option can also be set with the +OPTIONS line, e.g. \"*:nil\"."
2634 :group 'org-export-translation
2635 :type 'boolean)
2637 (defcustom org-export-with-footnotes t
2638 "If nil, export [1] as a footnote marker.
2639 Lines starting with [1] will be formatted as footnotes.
2641 This option can also be set with the +OPTIONS line, e.g. \"f:nil\"."
2642 :group 'org-export-translation
2643 :type 'boolean)
2645 (defcustom org-export-with-sub-superscripts t
2646 "Non-nil means, interpret \"_\" and \"^\" for export.
2647 When this option is turned on, you can use TeX-like syntax for sub- and
2648 superscripts. Several characters after \"_\" or \"^\" will be
2649 considered as a single item - so grouping with {} is normally not
2650 needed. For example, the following things will be parsed as single
2651 sub- or superscripts.
2653 10^24 or 10^tau several digits will be considered 1 item.
2654 10^-12 or 10^-tau a leading sign with digits or a word
2655 x^2-y^3 will be read as x^2 - y^3, because items are
2656 terminated by almost any nonword/nondigit char.
2657 x_{i^2} or x^(2-i) braces or parenthesis do grouping.
2659 Still, ambiguity is possible - so when in doubt use {} to enclose the
2660 sub/superscript. If you set this variable to the symbol `{}',
2661 the braces are *required* in order to trigger interpretations as
2662 sub/superscript. This can be helpful in documents that need \"_\"
2663 frequently in plain text.
2665 Not all export backends support this, but HTML does.
2667 This option can also be set with the +OPTIONS line, e.g. \"^:nil\"."
2668 :group 'org-export-translation
2669 :type '(choice
2670 (const :tag "Always interpret" t)
2671 (const :tag "Only with braces" {})
2672 (const :tag "Never interpret" nil)))
2674 (defcustom org-export-with-TeX-macros t
2675 "Non-nil means, interpret simple TeX-like macros when exporting.
2676 For example, HTML export converts \\alpha to &alpha; and \\AA to &Aring;.
2677 No only real TeX macros will work here, but the standard HTML entities
2678 for math can be used as macro names as well. For a list of supported
2679 names in HTML export, see the constant `org-html-entities'.
2680 Not all export backends support this.
2682 This option can also be set with the +OPTIONS line, e.g. \"TeX:nil\"."
2683 :group 'org-export-translation
2684 :group 'org-latex
2685 :type 'boolean)
2687 (defcustom org-export-with-LaTeX-fragments nil
2688 "Non-nil means, convert LaTeX fragments to images when exporting to HTML.
2689 When set, the exporter will find LaTeX environments if the \\begin line is
2690 the first non-white thing on a line. It will also find the math delimiters
2691 like $a=b$ and \\( a=b \\) for inline math, $$a=b$$ and \\[ a=b \\] for
2692 display math.
2694 This option can also be set with the +OPTIONS line, e.g. \"LaTeX:t\"."
2695 :group 'org-export-translation
2696 :group 'org-latex
2697 :type 'boolean)
2699 (defcustom org-export-with-fixed-width t
2700 "Non-nil means, lines starting with \":\" will be in fixed width font.
2701 This can be used to have pre-formatted text, fragments of code etc. For
2702 example:
2703 : ;; Some Lisp examples
2704 : (while (defc cnt)
2705 : (ding))
2706 will be looking just like this in also HTML. See also the QUOTE keyword.
2707 Not all export backends support this.
2709 This option can also be set with the +OPTIONS line, e.g. \"::nil\"."
2710 :group 'org-export-translation
2711 :type 'boolean)
2713 (defcustom org-match-sexp-depth 3
2714 "Number of stacked braces for sub/superscript matching.
2715 This has to be set before loading org.el to be effective."
2716 :group 'org-export-translation
2717 :type 'integer)
2719 (defgroup org-export-tables nil
2720 "Options for exporting tables in Org-mode."
2721 :tag "Org Export Tables"
2722 :group 'org-export)
2724 (defcustom org-export-with-tables t
2725 "If non-nil, lines starting with \"|\" define a table.
2726 For example:
2728 | Name | Address | Birthday |
2729 |-------------+----------+-----------|
2730 | Arthur Dent | England | 29.2.2100 |
2732 Not all export backends support this.
2734 This option can also be set with the +OPTIONS line, e.g. \"|:nil\"."
2735 :group 'org-export-tables
2736 :type 'boolean)
2738 (defcustom org-export-highlight-first-table-line t
2739 "Non-nil means, highlight the first table line.
2740 In HTML export, this means use <th> instead of <td>.
2741 In tables created with table.el, this applies to the first table line.
2742 In Org-mode tables, all lines before the first horizontal separator
2743 line will be formatted with <th> tags."
2744 :group 'org-export-tables
2745 :type 'boolean)
2747 (defcustom org-export-table-remove-special-lines t
2748 "Remove special lines and marking characters in calculating tables.
2749 This removes the special marking character column from tables that are set
2750 up for spreadsheet calculations. It also removes the entire lines
2751 marked with `!', `_', or `^'. The lines with `$' are kept, because
2752 the values of constants may be useful to have."
2753 :group 'org-export-tables
2754 :type 'boolean)
2756 (defcustom org-export-prefer-native-exporter-for-tables nil
2757 "Non-nil means, always export tables created with table.el natively.
2758 Natively means, use the HTML code generator in table.el.
2759 When nil, Org-mode's own HTML generator is used when possible (i.e. if
2760 the table does not use row- or column-spanning). This has the
2761 advantage, that the automatic HTML conversions for math symbols and
2762 sub/superscripts can be applied. Org-mode's HTML generator is also
2763 much faster."
2764 :group 'org-export-tables
2765 :type 'boolean)
2767 (defgroup org-export-ascii nil
2768 "Options specific for ASCII export of Org-mode files."
2769 :tag "Org Export ASCII"
2770 :group 'org-export)
2772 (defcustom org-export-ascii-underline '(?\$ ?\# ?^ ?\~ ?\= ?\-)
2773 "Characters for underlining headings in ASCII export.
2774 In the given sequence, these characters will be used for level 1, 2, ..."
2775 :group 'org-export-ascii
2776 :type '(repeat character))
2778 (defcustom org-export-ascii-bullets '(?* ?+ ?-)
2779 "Bullet characters for headlines converted to lists in ASCII export.
2780 The first character is is used for the first lest level generated in this
2781 way, and so on. If there are more levels than characters given here,
2782 the list will be repeated.
2783 Note that plain lists will keep the same bullets as the have in the
2784 Org-mode file."
2785 :group 'org-export-ascii
2786 :type '(repeat character))
2788 (defgroup org-export-xml nil
2789 "Options specific for XML export of Org-mode files."
2790 :tag "Org Export XML"
2791 :group 'org-export)
2793 (defgroup org-export-html nil
2794 "Options specific for HTML export of Org-mode files."
2795 :tag "Org Export HTML"
2796 :group 'org-export)
2798 (defcustom org-export-html-coding-system nil
2800 :group 'org-export-html
2801 :type 'coding-system)
2803 (defcustom org-export-html-style
2804 "<style type=\"text/css\">
2805 html {
2806 font-family: Times, serif;
2807 font-size: 12pt;
2809 .title { text-align: center; }
2810 .todo { color: red; }
2811 .done { color: green; }
2812 .timestamp { color: grey }
2813 .timestamp-kwd { color: CadetBlue }
2814 .tag { background-color:lightblue; font-weight:normal }
2815 .target { background-color: lavender; }
2816 pre {
2817 border: 1pt solid #AEBDCC;
2818 background-color: #F3F5F7;
2819 padding: 5pt;
2820 font-family: courier, monospace;
2822 table { border-collapse: collapse; }
2823 td, th {
2824 vertical-align: top;
2825 <!--border: 1pt solid #ADB9CC;-->
2827 </style>"
2828 "The default style specification for exported HTML files.
2829 Since there are different ways of setting style information, this variable
2830 needs to contain the full HTML structure to provide a style, including the
2831 surrounding HTML tags. The style specifications should include definitions
2832 for new classes todo, done, title, and deadline. For example, legal values
2833 would be:
2835 <style type=\"text/css\">
2836 p { font-weight: normal; color: gray; }
2837 h1 { color: black; }
2838 .title { text-align: center; }
2839 .todo, .deadline { color: red; }
2840 .done { color: green; }
2841 </style>
2843 or, if you want to keep the style in a file,
2845 <link rel=\"stylesheet\" type=\"text/css\" href=\"mystyles.css\">
2847 As the value of this option simply gets inserted into the HTML <head> header,
2848 you can \"misuse\" it to add arbitrary text to the header."
2849 :group 'org-export-html
2850 :type 'string)
2853 (defcustom org-export-html-title-format "<h1 class=\"title\">%s</h1>\n"
2854 "Format for typesetting the document title in HTML export."
2855 :group 'org-export-html
2856 :type 'string)
2858 (defcustom org-export-html-toplevel-hlevel 2
2859 "The <H> level for level 1 headings in HTML export."
2860 :group 'org-export-html
2861 :type 'string)
2863 (defcustom org-export-html-link-org-files-as-html t
2864 "Non-nil means, make file links to `file.org' point to `file.html'.
2865 When org-mode is exporting an org-mode file to HTML, links to
2866 non-html files are directly put into a href tag in HTML.
2867 However, links to other Org-mode files (recognized by the
2868 extension `.org.) should become links to the corresponding html
2869 file, assuming that the linked org-mode file will also be
2870 converted to HTML.
2871 When nil, the links still point to the plain `.org' file."
2872 :group 'org-export-html
2873 :type 'boolean)
2875 (defcustom org-export-html-inline-images 'maybe
2876 "Non-nil means, inline images into exported HTML pages.
2877 This is done using an <img> tag. When nil, an anchor with href is used to
2878 link to the image. If this option is `maybe', then images in links with
2879 an empty description will be inlined, while images with a description will
2880 be linked only."
2881 :group 'org-export-html
2882 :type '(choice (const :tag "Never" nil)
2883 (const :tag "Always" t)
2884 (const :tag "When there is no description" maybe)))
2886 ;; FIXME: rename
2887 (defcustom org-export-html-expand t
2888 "Non-nil means, for HTML export, treat @<...> as HTML tag.
2889 When nil, these tags will be exported as plain text and therefore
2890 not be interpreted by a browser.
2892 This option can also be set with the +OPTIONS line, e.g. \"@:nil\"."
2893 :group 'org-export-html
2894 :type 'boolean)
2896 (defcustom org-export-html-table-tag
2897 "<table border=\"2\" cellspacing=\"0\" cellpadding=\"6\" rules=\"groups\" frame=\"hsides\">"
2898 "The HTML tag that is used to start a table.
2899 This must be a <table> tag, but you may change the options like
2900 borders and spacing."
2901 :group 'org-export-html
2902 :type 'string)
2904 (defcustom org-export-table-header-tags '("<th>" . "</th>")
2905 "The opening tag for table header fields.
2906 This is customizable so that alignment options can be specified."
2907 :group 'org-export-tables
2908 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
2910 (defcustom org-export-table-data-tags '("<td>" . "</td>")
2911 "The opening tag for table data fields.
2912 This is customizable so that alignment options can be specified."
2913 :group 'org-export-tables
2914 :type '(cons (string :tag "Opening tag") (string :tag "Closing tag")))
2916 (defcustom org-export-html-with-timestamp nil
2917 "If non-nil, write `org-export-html-html-helper-timestamp'
2918 into the exported HTML text. Otherwise, the buffer will just be saved
2919 to a file."
2920 :group 'org-export-html
2921 :type 'boolean)
2923 (defcustom org-export-html-html-helper-timestamp
2924 "<br/><br/><hr><p><!-- hhmts start --> <!-- hhmts end --></p>\n"
2925 "The HTML tag used as timestamp delimiter for HTML-helper-mode."
2926 :group 'org-export-html
2927 :type 'string)
2929 (defgroup org-export-icalendar nil
2930 "Options specific for iCalendar export of Org-mode files."
2931 :tag "Org Export iCalendar"
2932 :group 'org-export)
2934 (defcustom org-combined-agenda-icalendar-file "~/org.ics"
2935 "The file name for the iCalendar file covering all agenda files.
2936 This file is created with the command \\[org-export-icalendar-all-agenda-files].
2937 The file name should be absolute."
2938 :group 'org-export-icalendar
2939 :type 'file)
2941 (defcustom org-icalendar-include-todo nil
2942 "Non-nil means, export to iCalendar files should also cover TODO items."
2943 :group 'org-export-icalendar
2944 :type '(choice
2945 (const :tag "None" nil)
2946 (const :tag "Unfinished" t)
2947 (const :tag "All" all)))
2949 (defcustom org-icalendar-include-sexps t
2950 "Non-nil means, export to iCalendar files should also cover sexp entries.
2951 These are entries like in the diary, but directly in an Org-mode file."
2952 :group 'org-export-icalendar
2953 :type 'boolean)
2955 (defcustom org-icalendar-combined-name "OrgMode"
2956 "Calendar name for the combined iCalendar representing all agenda files."
2957 :group 'org-export-icalendar
2958 :type 'string)
2960 (defgroup org-font-lock nil
2961 "Font-lock settings for highlighting in Org-mode."
2962 :tag "Org Font Lock"
2963 :group 'org)
2965 (defcustom org-level-color-stars-only nil
2966 "Non-nil means fontify only the stars in each headline.
2967 When nil, the entire headline is fontified.
2968 Changing it requires restart of `font-lock-mode' to become effective
2969 also in regions already fontified."
2970 :group 'org-font-lock
2971 :type 'boolean)
2973 (defcustom org-hide-leading-stars nil
2974 "Non-nil means, hide the first N-1 stars in a headline.
2975 This works by using the face `org-hide' for these stars. This
2976 face is white for a light background, and black for a dark
2977 background. You may have to customize the face `org-hide' to
2978 make this work.
2979 Changing it requires restart of `font-lock-mode' to become effective
2980 also in regions already fontified.
2981 You may also set this on a per-file basis by adding one of the following
2982 lines to the buffer:
2984 #+STARTUP: hidestars
2985 #+STARTUP: showstars"
2986 :group 'org-font-lock
2987 :type 'boolean)
2989 (defcustom org-fontify-done-headline nil
2990 "Non-nil means, change the face of a headline if it is marked DONE.
2991 Normally, only the TODO/DONE keyword indicates the state of a headline.
2992 When this is non-nil, the headline after the keyword is set to the
2993 `org-headline-done' as an additional indication."
2994 :group 'org-font-lock
2995 :type 'boolean)
2997 (defcustom org-fontify-emphasized-text t
2998 "Non-nil means fontify *bold*, /italic/ and _underlined_ text.
2999 Changing this variable requires a restart of Emacs to take effect."
3000 :group 'org-font-lock
3001 :type 'boolean)
3003 (defvar org-emph-re nil
3004 "Regular expression for matching emphasis.")
3005 (defvar org-emphasis-regexp-components) ; defined just below
3006 (defvar org-emphasis-alist) ; defined just below
3007 (defun org-set-emph-re (var val)
3008 "Set variable and compute the emphasis regular expression."
3009 (set var val)
3010 (when (and (boundp 'org-emphasis-alist)
3011 (boundp 'org-emphasis-regexp-components)
3012 org-emphasis-alist org-emphasis-regexp-components)
3013 (let* ((e org-emphasis-regexp-components)
3014 (pre (car e))
3015 (post (nth 1 e))
3016 (border (nth 2 e))
3017 (body (nth 3 e))
3018 (nl (nth 4 e))
3019 (stacked (nth 5 e))
3020 (body1 (concat body "*?"))
3021 (markers (mapconcat 'car org-emphasis-alist "")))
3022 ;; make sure special characters appear at the right position in the class
3023 (if (string-match "\\^" markers)
3024 (setq markers (concat (replace-match "" t t markers) "^")))
3025 (if (string-match "-" markers)
3026 (setq markers (concat (replace-match "" t t markers) "-")))
3027 (if (> nl 0)
3028 (setq body1 (concat body1 "\\(?:\n" body "*?\\)\\{0,"
3029 (int-to-string nl) "\\}")))
3030 ;; Make the regexp
3031 (setq org-emph-re
3032 (concat "\\([" pre (if stacked markers) "]\\|^\\)"
3033 "\\("
3034 "\\([" markers "]\\)"
3035 "\\("
3036 "[^" border (if (and nil stacked) markers) "]"
3037 body1
3038 "[^" border (if (and nil stacked) markers) "]"
3039 "\\)"
3040 "\\3\\)"
3041 "\\([" post (if stacked markers) "]\\|$\\)")))))
3043 (defcustom org-emphasis-regexp-components
3044 '(" \t('\"" "- \t.,:?;'\")" " \t\r\n,\"'" "." 1 nil)
3045 "Components used to build the reqular expression for emphasis.
3046 This is a list with 6 entries. Terminology: In an emphasis string
3047 like \" *strong word* \", we call the initial space PREMATCH, the final
3048 space POSTMATCH, the stars MARKERS, \"s\" and \"d\" are BORDER characters
3049 and \"trong wor\" is the body. The different components in this variable
3050 specify what is allowed/forbidden in each part:
3052 pre Chars allowed as prematch. Beginning of line will be allowed too.
3053 post Chars allowed as postmatch. End of line will be allowed too.
3054 border The chars *forbidden* as border characters.
3055 body-regexp A regexp like \".\" to match a body character. Don't use
3056 non-shy groups here, and don't allow newline here.
3057 newline The maximum number of newlines allowed in an emphasis exp.
3058 stacked Non-nil means, allow stacked styles. This works only in HTML
3059 export. When this is set, all marker characters (as given in
3060 `org-emphasis-alist') will be allowed as pre/post, aiding
3061 inside-out matching.
3062 Use customize to modify this, or restart Emacs after changing it."
3063 :group 'org-font-lock
3064 :set 'org-set-emph-re
3065 :type '(list
3066 (sexp :tag "Allowed chars in pre ")
3067 (sexp :tag "Allowed chars in post ")
3068 (sexp :tag "Forbidden chars in border ")
3069 (sexp :tag "Regexp for body ")
3070 (integer :tag "number of newlines allowed")
3071 (boolean :tag "Stacking allowed ")))
3073 (defcustom org-emphasis-alist
3074 '(("*" bold "<b>" "</b>")
3075 ("/" italic "<i>" "</i>")
3076 ("_" underline "<u>" "</u>")
3077 ("=" shadow "<code>" "</code>")
3078 ("+" (:strike-through t) "<del>" "</del>")
3080 "Special syntax for emphasized text.
3081 Text starting and ending with a special character will be emphasized, for
3082 example *bold*, _underlined_ and /italic/. This variable sets the marker
3083 characters, the face to be used by font-lock for highlighting in Org-mode
3084 Emacs buffers, and the HTML tags to be used for this.
3085 Use customize to modify this, or restart Emacs after changing it."
3086 :group 'org-font-lock
3087 :set 'org-set-emph-re
3088 :type '(repeat
3089 (list
3090 (string :tag "Marker character")
3091 (choice
3092 (face :tag "Font-lock-face")
3093 (plist :tag "Face property list"))
3094 (string :tag "HTML start tag")
3095 (string :tag "HTML end tag"))))
3097 ;;; The faces
3099 (defgroup org-faces nil
3100 "Faces in Org-mode."
3101 :tag "Org Faces"
3102 :group 'org-font-lock)
3104 ;; FIXME: convert that into a macro? Not critical, because this
3105 ;; is only executed a few times at load time.
3106 (defun org-compatible-face (specs)
3107 "Make a compatible face specification.
3108 XEmacs and Emacs 21 do not know about the `min-colors' attribute.
3109 For them we convert a (min-colors 8) entry to a `tty' entry and move it
3110 to the top of the list. The `min-colors' attribute will be removed from
3111 any other entries, and any resulting duplicates will be removed entirely."
3112 (if (or (featurep 'xemacs) (< emacs-major-version 22))
3113 (let (r e a)
3114 (while (setq e (pop specs))
3115 (cond
3116 ((memq (car e) '(t default)) (push e r))
3117 ((setq a (member '(min-colors 8) (car e)))
3118 (nconc r (list (cons (cons '(type tty) (delq (car a) (car e)))
3119 (cdr e)))))
3120 ((setq a (assq 'min-colors (car e)))
3121 (setq e (cons (delq a (car e)) (cdr e)))
3122 (or (assoc (car e) r) (push e r)))
3123 (t (or (assoc (car e) r) (push e r)))))
3124 (nreverse r))
3125 specs))
3127 (defface org-hide
3128 '((((background light)) (:foreground "white"))
3129 (((background dark)) (:foreground "black")))
3130 "Face used to hide leading stars in headlines.
3131 The forground color of this face should be equal to the background
3132 color of the frame."
3133 :group 'org-faces)
3135 (defface org-level-1 ;; font-lock-function-name-face
3136 (org-compatible-face
3137 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3138 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3139 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3140 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3141 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
3142 (t (:bold t))))
3143 "Face used for level 1 headlines."
3144 :group 'org-faces)
3146 (defface org-level-2 ;; font-lock-variable-name-face
3147 (org-compatible-face
3148 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
3149 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
3150 (((class color) (min-colors 8) (background light)) (:foreground "yellow"))
3151 (((class color) (min-colors 8) (background dark)) (:foreground "yellow" :bold t))
3152 (t (:bold t))))
3153 "Face used for level 2 headlines."
3154 :group 'org-faces)
3156 (defface org-level-3 ;; font-lock-keyword-face
3157 (org-compatible-face
3158 '((((class color) (min-colors 88) (background light)) (:foreground "Purple"))
3159 (((class color) (min-colors 88) (background dark)) (:foreground "Cyan1"))
3160 (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
3161 (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
3162 (((class color) (min-colors 8) (background light)) (:foreground "purple" :bold t))
3163 (((class color) (min-colors 8) (background dark)) (:foreground "cyan" :bold t))
3164 (t (:bold t))))
3165 "Face used for level 3 headlines."
3166 :group 'org-faces)
3168 (defface org-level-4 ;; font-lock-comment-face
3169 (org-compatible-face
3170 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3171 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3172 (((class color) (min-colors 16) (background light)) (:foreground "red"))
3173 (((class color) (min-colors 16) (background dark)) (:foreground "red1"))
3174 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3175 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3176 (t (:bold t))))
3177 "Face used for level 4 headlines."
3178 :group 'org-faces)
3180 (defface org-level-5 ;; font-lock-type-face
3181 (org-compatible-face
3182 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
3183 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
3184 (((class color) (min-colors 8)) (:foreground "green"))))
3185 "Face used for level 5 headlines."
3186 :group 'org-faces)
3188 (defface org-level-6 ;; font-lock-constant-face
3189 (org-compatible-face
3190 '((((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
3191 (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
3192 (((class color) (min-colors 8)) (:foreground "magenta"))))
3193 "Face used for level 6 headlines."
3194 :group 'org-faces)
3196 (defface org-level-7 ;; font-lock-builtin-face
3197 (org-compatible-face
3198 '((((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
3199 (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
3200 (((class color) (min-colors 8)) (:foreground "blue"))))
3201 "Face used for level 7 headlines."
3202 :group 'org-faces)
3204 (defface org-level-8 ;; font-lock-string-face
3205 (org-compatible-face
3206 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3207 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3208 (((class color) (min-colors 8)) (:foreground "green"))))
3209 "Face used for level 8 headlines."
3210 :group 'org-faces)
3212 (defface org-special-keyword ;; font-lock-string-face
3213 (org-compatible-face
3214 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3215 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3216 (t (:italic t))))
3217 "Face used for special keywords."
3218 :group 'org-faces)
3220 (defface org-drawer ;; font-lock-function-name-face
3221 (org-compatible-face
3222 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3223 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3224 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3225 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3226 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
3227 (t (:bold t))))
3228 "Face used for drawers."
3229 :group 'org-faces)
3231 (defface org-property-value nil
3232 "Face used for the value of a property."
3233 :group 'org-faces)
3235 (defface org-column
3236 (org-compatible-face
3237 '((((class color) (min-colors 16) (background light))
3238 (:background "grey90"))
3239 (((class color) (min-colors 16) (background dark))
3240 (:background "grey30"))
3241 (((class color) (min-colors 8))
3242 (:background "cyan" :foreground "black"))
3243 (t (:inverse-video t))))
3244 "Face for column display of entry properties."
3245 :group 'org-faces)
3247 (when (fboundp 'set-face-attribute)
3248 ;; Make sure that a fixed-width face is used when we have a column table.
3249 (set-face-attribute 'org-column nil
3250 :height (face-attribute 'default :height)
3251 :family (face-attribute 'default :family)))
3253 (defface org-warning ;; font-lock-warning-face
3254 (org-compatible-face
3255 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
3256 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
3257 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3258 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3259 (t (:bold t))))
3260 "Face for deadlines and TODO keywords."
3261 :group 'org-faces)
3263 (defface org-archived ; similar to shadow
3264 (org-compatible-face
3265 '((((class color grayscale) (min-colors 88) (background light))
3266 (:foreground "grey50"))
3267 (((class color grayscale) (min-colors 88) (background dark))
3268 (:foreground "grey70"))
3269 (((class color) (min-colors 8) (background light))
3270 (:foreground "green"))
3271 (((class color) (min-colors 8) (background dark))
3272 (:foreground "yellow"))))
3273 "Face for headline with the ARCHIVE tag."
3274 :group 'org-faces)
3276 (defface org-link
3277 '((((class color) (background light)) (:foreground "Purple" :underline t))
3278 (((class color) (background dark)) (:foreground "Cyan" :underline t))
3279 (t (:underline t)))
3280 "Face for links."
3281 :group 'org-faces)
3283 (defface org-target
3284 '((((class color) (background light)) (:underline t))
3285 (((class color) (background dark)) (:underline t))
3286 (t (:underline t)))
3287 "Face for links."
3288 :group 'org-faces)
3290 (defface org-date
3291 '((((class color) (background light)) (:foreground "Purple" :underline t))
3292 (((class color) (background dark)) (:foreground "Cyan" :underline t))
3293 (t (:underline t)))
3294 "Face for links."
3295 :group 'org-faces)
3297 (defface org-sexp-date
3298 '((((class color) (background light)) (:foreground "Purple"))
3299 (((class color) (background dark)) (:foreground "Cyan"))
3300 (t (:underline t)))
3301 "Face for links."
3302 :group 'org-faces)
3304 (defface org-tag
3305 '((t (:bold t)))
3306 "Face for tags."
3307 :group 'org-faces)
3309 (defface org-todo ;; font-lock-warning-face
3310 (org-compatible-face
3311 '((((class color) (min-colors 16) (background light)) (:foreground "Red1" :bold t))
3312 (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :bold t))
3313 (((class color) (min-colors 8) (background light)) (:foreground "red" :bold t))
3314 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3315 (t (:inverse-video t :bold t))))
3316 "Face for TODO keywords."
3317 :group 'org-faces)
3319 (defface org-done ;; font-lock-type-face
3320 (org-compatible-face
3321 '((((class color) (min-colors 16) (background light)) (:foreground "ForestGreen" :bold t))
3322 (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen" :bold t))
3323 (((class color) (min-colors 8)) (:foreground "green"))
3324 (t (:bold t))))
3325 "Face used for todo keywords that indicate DONE items."
3326 :group 'org-faces)
3328 (defface org-headline-done ;; font-lock-string-face
3329 (org-compatible-face
3330 '((((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
3331 (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
3332 (((class color) (min-colors 8) (background light)) (:bold nil))))
3333 "Face used to indicate that a headline is DONE.
3334 This face is only used if `org-fontify-done-headline' is set. If applies
3335 to the part of the headline after the DONE keyword."
3336 :group 'org-faces)
3338 (defface org-table ;; font-lock-function-name-face
3339 (org-compatible-face
3340 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3341 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3342 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3343 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3344 (((class color) (min-colors 8) (background light)) (:foreground "blue"))
3345 (((class color) (min-colors 8) (background dark)))))
3346 "Face used for tables."
3347 :group 'org-faces)
3349 (defface org-formula
3350 (org-compatible-face
3351 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3352 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3353 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3354 (((class color) (min-colors 8) (background dark)) (:foreground "red"))
3355 (t (:bold t :italic t))))
3356 "Face for formulas."
3357 :group 'org-faces)
3359 (defface org-agenda-structure ;; font-lock-function-name-face
3360 (org-compatible-face
3361 '((((class color) (min-colors 88) (background light)) (:foreground "Blue1"))
3362 (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
3363 (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
3364 (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
3365 (((class color) (min-colors 8)) (:foreground "blue" :bold t))
3366 (t (:bold t))))
3367 "Face used in agenda for captions and dates."
3368 :group 'org-faces)
3370 (defface org-scheduled-today
3371 (org-compatible-face
3372 '((((class color) (min-colors 88) (background light)) (:foreground "DarkGreen"))
3373 (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
3374 (((class color) (min-colors 8)) (:foreground "green"))
3375 (t (:bold t :italic t))))
3376 "Face for items scheduled for a certain day."
3377 :group 'org-faces)
3379 (defface org-scheduled-previously
3380 (org-compatible-face
3381 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3382 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3383 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3384 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3385 (t (:bold t))))
3386 "Face for items scheduled previously, and not yet done."
3387 :group 'org-faces)
3389 (defface org-upcoming-deadline
3390 (org-compatible-face
3391 '((((class color) (min-colors 88) (background light)) (:foreground "Firebrick"))
3392 (((class color) (min-colors 88) (background dark)) (:foreground "chocolate1"))
3393 (((class color) (min-colors 8) (background light)) (:foreground "red"))
3394 (((class color) (min-colors 8) (background dark)) (:foreground "red" :bold t))
3395 (t (:bold t))))
3396 "Face for items scheduled previously, and not yet done."
3397 :group 'org-faces)
3399 (defface org-time-grid ;; font-lock-variable-name-face
3400 (org-compatible-face
3401 '((((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
3402 (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
3403 (((class color) (min-colors 8)) (:foreground "yellow" :weight light))))
3404 "Face used for time grids."
3405 :group 'org-faces)
3407 (defconst org-level-faces
3408 '(org-level-1 org-level-2 org-level-3 org-level-4
3409 org-level-5 org-level-6 org-level-7 org-level-8
3411 (defconst org-n-levels (length org-level-faces))
3414 ;;; Variables for pre-computed regular expressions, all buffer local
3416 (defvar org-drawer-regexp nil
3417 "Matches first line of a hidden block.")
3418 (make-variable-buffer-local 'org-drawer-regexp)
3419 (defvar org-todo-regexp nil
3420 "Matches any of the TODO state keywords.")
3421 (make-variable-buffer-local 'org-todo-regexp)
3422 (defvar org-not-done-regexp nil
3423 "Matches any of the TODO state keywords except the last one.")
3424 (make-variable-buffer-local 'org-not-done-regexp)
3425 (defvar org-todo-line-regexp nil
3426 "Matches a headline and puts TODO state into group 2 if present.")
3427 (make-variable-buffer-local 'org-todo-line-regexp)
3428 (defvar org-todo-line-tags-regexp nil
3429 "Matches a headline and puts TODO state into group 2 if present.
3430 Also put tags into group 4 if tags are present.")
3431 (make-variable-buffer-local 'org-todo-line-tags-regexp)
3432 (defvar org-nl-done-regexp nil
3433 "Matches newline followed by a headline with the DONE keyword.")
3434 (make-variable-buffer-local 'org-nl-done-regexp)
3435 (defvar org-looking-at-done-regexp nil
3436 "Matches the DONE keyword a point.")
3437 (make-variable-buffer-local 'org-looking-at-done-regexp)
3438 (defvar org-ds-keyword-length 12
3439 "Maximum length of the Deadline and SCHEDULED keywords.")
3440 (make-variable-buffer-local 'org-ds-keyword-length)
3441 (defvar org-deadline-regexp nil
3442 "Matches the DEADLINE keyword.")
3443 (make-variable-buffer-local 'org-deadline-regexp)
3444 (defvar org-deadline-time-regexp nil
3445 "Matches the DEADLINE keyword together with a time stamp.")
3446 (make-variable-buffer-local 'org-deadline-time-regexp)
3447 (defvar org-deadline-line-regexp nil
3448 "Matches the DEADLINE keyword and the rest of the line.")
3449 (make-variable-buffer-local 'org-deadline-line-regexp)
3450 (defvar org-scheduled-regexp nil
3451 "Matches the SCHEDULED keyword.")
3452 (make-variable-buffer-local 'org-scheduled-regexp)
3453 (defvar org-scheduled-time-regexp nil
3454 "Matches the SCHEDULED keyword together with a time stamp.")
3455 (make-variable-buffer-local 'org-scheduled-time-regexp)
3456 (defvar org-closed-time-regexp nil
3457 "Matches the CLOSED keyword together with a time stamp.")
3458 (make-variable-buffer-local 'org-closed-time-regexp)
3460 (defvar org-keyword-time-regexp nil
3461 "Matches any of the 4 keywords, together with the time stamp.")
3462 (make-variable-buffer-local 'org-keyword-time-regexp)
3463 (defvar org-keyword-time-not-clock-regexp nil
3464 "Matches any of the 3 keywords, together with the time stamp.")
3465 (make-variable-buffer-local 'org-keyword-time-not-clock-regexp)
3466 (defvar org-maybe-keyword-time-regexp nil
3467 "Matches a timestamp, possibly preceeded by a keyword.")
3468 (make-variable-buffer-local 'org-maybe-keyword-time-regexp)
3469 (defvar org-planning-or-clock-line-re nil
3470 "Matches a line with planning or clock info.")
3471 (make-variable-buffer-local 'org-planning-or-clock-line-re)
3473 (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t
3474 rear-nonsticky t mouse-map t fontified t)
3475 "Properties to remove when a string without properties is wanted.")
3477 (defsubst org-match-string-no-properties (num &optional string)
3478 (if (featurep 'xemacs)
3479 (let ((s (match-string num string)))
3480 (remove-text-properties 0 (length s) org-rm-props s)
3482 (match-string-no-properties num string)))
3484 (defsubst org-no-properties (s)
3485 (if (fboundp 'set-text-properties)
3486 (set-text-properties 0 (length s) nil s)
3487 (remove-text-properties 0 (length s) org-rm-props s))
3490 (defsubst org-get-alist-option (option key)
3491 (cond ((eq key t) t)
3492 ((eq option t) t)
3493 ((assoc key option) (cdr (assoc key option)))
3494 (t (cdr (assq 'default option)))))
3496 (defsubst org-inhibit-invisibility ()
3497 "Modified `buffer-invisibility-spec' for Emacs 21.
3498 Some ops with invisible text do not work correctly on Emacs 21. For these
3499 we turn off invisibility temporarily. Use this in a `let' form."
3500 (if (< emacs-major-version 22) nil buffer-invisibility-spec))
3502 (defsubst org-set-local (var value)
3503 "Make VAR local in current buffer and set it to VALUE."
3504 (set (make-variable-buffer-local var) value))
3506 (defsubst org-mode-p ()
3507 "Check if the current buffer is in Org-mode."
3508 (eq major-mode 'org-mode))
3510 (defsubst org-last (list)
3511 "Return the last element of LIST."
3512 (car (last list)))
3514 (defun org-let (list &rest body)
3515 (eval (cons 'let (cons list body))))
3516 (put 'org-let 'lisp-indent-function 1)
3518 (defun org-let2 (list1 list2 &rest body)
3519 (eval (cons 'let (cons list1 (list (cons 'let (cons list2 body)))))))
3520 (put 'org-let2 'lisp-indent-function 2)
3521 (defconst org-startup-options
3522 '(("fold" org-startup-folded t)
3523 ("overview" org-startup-folded t)
3524 ("nofold" org-startup-folded nil)
3525 ("showall" org-startup-folded nil)
3526 ("content" org-startup-folded content)
3527 ("hidestars" org-hide-leading-stars t)
3528 ("showstars" org-hide-leading-stars nil)
3529 ("odd" org-odd-levels-only t)
3530 ("oddeven" org-odd-levels-only nil)
3531 ("align" org-startup-align-all-tables t)
3532 ("noalign" org-startup-align-all-tables nil)
3533 ("customtime" org-display-custom-times t)
3534 ("logging" org-log-done t)
3535 ("logdone" org-log-done t)
3536 ("nologging" org-log-done nil)
3537 ("lognotedone" org-log-done done push)
3538 ("lognotestate" org-log-done state push)
3539 ("lognoteclock-out" org-log-done clock-out push)
3540 ("logrepeat" org-log-repeat t)
3541 ("nologrepeat" org-log-repeat nil)
3542 ("constcgs" constants-unit-system cgs)
3543 ("constSI" constants-unit-system SI))
3544 "Variable associated with STARTUP options for org-mode.
3545 Each element is a list of three items: The startup options as written
3546 in the #+STARTUP line, the corresponding variable, and the value to
3547 set this variable to if the option is found. An optional forth element PUSH
3548 means to push this value onto the list in the variable.")
3550 (defun org-set-regexps-and-options ()
3551 "Precompute regular expressions for current buffer."
3552 (when (org-mode-p)
3553 (org-set-local 'org-todo-kwd-alist nil)
3554 (org-set-local 'org-todo-keywords-1 nil)
3555 (org-set-local 'org-done-keywords nil)
3556 (org-set-local 'org-todo-heads nil)
3557 (org-set-local 'org-todo-sets nil)
3558 (let ((re (org-make-options-regexp
3559 '("CATEGORY" "SEQ_TODO" "PRI_TODO" "TYP_TODO" "COLUMNS"
3560 "STARTUP" "ARCHIVE" "TAGS" "LINK" "PRIORITIES"
3561 "CONSTANTS")))
3562 (splitre "[ \t]+")
3563 kwds key value cat arch tags const links hw dws tail sep kws1 prio)
3564 (save-excursion
3565 (save-restriction
3566 (widen)
3567 (goto-char (point-min))
3568 (while (re-search-forward re nil t)
3569 (setq key (match-string 1) value (org-match-string-no-properties 2))
3570 (cond
3571 ((equal key "CATEGORY")
3572 (if (string-match "[ \t]+$" value)
3573 (setq value (replace-match "" t t value)))
3574 (setq cat (intern value)))
3575 ((equal key "SEQ_TODO")
3576 (push (cons 'sequence (org-split-string value splitre)) kwds))
3577 ((equal key "TYP_TODO")
3578 (push (cons 'type (org-split-string value splitre)) kwds))
3579 ((equal key "TAGS")
3580 (setq tags (append tags (org-split-string value splitre))))
3581 ((equal key "COLUMNS")
3582 (org-set-local 'org-columns-default-format value))
3583 ((equal key "LINK")
3584 (when (string-match "^\\(\\S-+\\)[ \t]+\\(.+\\)" value)
3585 (push (cons (match-string 1 value)
3586 (org-trim (match-string 2 value)))
3587 links)))
3588 ((equal key "PRIORITIES")
3589 (setq prio (org-split-string value " +")))
3590 ((equal key "CONSTANTS")
3591 (setq const (append const (org-split-string value splitre))))
3592 ((equal key "STARTUP")
3593 (let ((opts (org-split-string value splitre))
3594 l var val)
3595 (while (setq l (pop opts))
3596 (when (setq l (assoc l org-startup-options))
3597 (setq var (nth 1 l) val (nth 2 l))
3598 (if (not (nth 3 l))
3599 (set (make-local-variable var) val)
3600 (if (not (listp (symbol-value var)))
3601 (set (make-local-variable var) nil))
3602 (set (make-local-variable var) (symbol-value var))
3603 (add-to-list var val))))))
3604 ((equal key "ARCHIVE")
3605 (string-match " *$" value)
3606 (setq arch (replace-match "" t t value))
3607 (remove-text-properties 0 (length arch)
3608 '(face t fontified t) arch)))
3610 (and cat (org-set-local 'org-category cat))
3611 (when prio
3612 (if (< (length prio) 3) (setq prio '("A" "C" "B")))
3613 (setq prio (mapcar 'string-to-char prio))
3614 (org-set-local 'org-highest-priority (nth 0 prio))
3615 (org-set-local 'org-lowest-priority (nth 1 prio))
3616 (org-set-local 'org-default-priority (nth 2 prio)))
3617 (and arch (org-set-local 'org-archive-location arch))
3618 (and links (setq org-link-abbrev-alist-local (nreverse links)))
3619 ;; Process the TODO keywords
3620 (unless kwds
3621 ;; Use the global values as if they had been given locally.
3622 (setq kwds (default-value 'org-todo-keywords))
3623 (if (stringp (car kwds))
3624 (setq kwds (list (cons org-todo-interpretation
3625 (default-value 'org-todo-keywords)))))
3626 (setq kwds (reverse kwds)))
3627 (setq kwds (nreverse kwds))
3628 (let (inter kws)
3629 (while (setq kws (pop kwds))
3630 (setq inter (pop kws) sep (member "|" kws)
3631 kws1 (delete "|" (copy-sequence kws))
3632 hw (car kws1)
3633 dws (if sep (cdr sep) (last kws1))
3634 tail (list inter hw (car dws) (org-last dws)))
3635 (add-to-list 'org-todo-heads hw 'append)
3636 (push kws1 org-todo-sets)
3637 (setq org-done-keywords (append org-done-keywords dws nil))
3638 (mapc (lambda (x) (push (cons x tail) org-todo-kwd-alist)) kws1)
3639 (setq org-todo-keywords-1 (append org-todo-keywords-1 kws1 nil)))
3640 (setq org-todo-sets (nreverse org-todo-sets)
3641 org-todo-kwd-alist (nreverse org-todo-kwd-alist)))
3642 ;; Process the constants
3643 (when const
3644 (let (e cst)
3645 (while (setq e (pop const))
3646 (if (string-match "^\\([a-zA-Z0][_a-zA-Z0-9]*\\)=\\(.*\\)" e)
3647 (push (cons (match-string 1 e) (match-string 2 e)) cst)))
3648 (setq org-table-formula-constants-local cst)))
3650 ;; Process the tags.
3651 (when tags
3652 (let (e tgs)
3653 (while (setq e (pop tags))
3654 (cond
3655 ((equal e "{") (push '(:startgroup) tgs))
3656 ((equal e "}") (push '(:endgroup) tgs))
3657 ((string-match (org-re "^\\([[:alnum:]_@]+\\)(\\(.\\))$") e)
3658 (push (cons (match-string 1 e)
3659 (string-to-char (match-string 2 e)))
3660 tgs))
3661 (t (push (list e) tgs))))
3662 (org-set-local 'org-tag-alist nil)
3663 (while (setq e (pop tgs))
3664 (or (and (stringp (car e))
3665 (assoc (car e) org-tag-alist))
3666 (push e org-tag-alist))))))
3668 ;; Compute the regular expressions and other local variables
3669 (if (not org-done-keywords)
3670 (setq org-done-keywords (list (org-last org-todo-keywords-1))))
3671 (setq org-ds-keyword-length (+ 2 (max (length org-deadline-string)
3672 (length org-scheduled-string)))
3673 org-drawer-regexp
3674 (concat "^[ \t]*:\\("
3675 (mapconcat 'regexp-quote org-drawers "\\|")
3676 "\\):[ \t]*$")
3677 org-not-done-keywords
3678 (org-delete-all org-done-keywords (copy-sequence org-todo-keywords-1))
3679 org-todo-regexp
3680 (concat "\\<\\(" (mapconcat 'regexp-quote org-todo-keywords-1
3681 "\\|") "\\)\\>")
3682 org-not-done-regexp
3683 (concat "\\<\\("
3684 (mapconcat 'regexp-quote org-not-done-keywords "\\|")
3685 "\\)\\>")
3686 org-todo-line-regexp
3687 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
3688 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
3689 "\\)\\>\\)? *\\(.*\\)")
3690 org-nl-done-regexp
3691 (concat "\n\\*+[ \t]+"
3692 "\\(?:" (mapconcat 'regexp-quote org-done-keywords "\\|")
3693 "\\)" "\\>")
3694 org-todo-line-tags-regexp
3695 (concat "^\\(\\*+\\)[ \t]+\\(?:\\("
3696 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
3697 (org-re
3698 "\\)\\>\\)? *\\(.*?\\([ \t]:[[:alnum:]:_@]+:[ \t]*\\)?$\\)"))
3699 org-looking-at-done-regexp
3700 (concat "^" "\\(?:"
3701 (mapconcat 'regexp-quote org-done-keywords "\\|") "\\)"
3702 "\\>")
3703 org-deadline-regexp (concat "\\<" org-deadline-string)
3704 org-deadline-time-regexp
3705 (concat "\\<" org-deadline-string " *<\\([^>]+\\)>")
3706 org-deadline-line-regexp
3707 (concat "\\<\\(" org-deadline-string "\\).*")
3708 org-scheduled-regexp
3709 (concat "\\<" org-scheduled-string)
3710 org-scheduled-time-regexp
3711 (concat "\\<" org-scheduled-string " *<\\([^>]+\\)>")
3712 org-closed-time-regexp
3713 (concat "\\<" org-closed-string " *\\[\\([^]]+\\)\\]")
3714 org-keyword-time-regexp
3715 (concat "\\<\\(" org-scheduled-string
3716 "\\|" org-deadline-string
3717 "\\|" org-closed-string
3718 "\\|" org-archived-string
3719 "\\|" org-clock-string "\\)"
3720 " *[[<]\\([^]>]+\\)[]>]")
3721 org-keyword-time-not-clock-regexp
3722 (concat "\\<\\(" org-scheduled-string
3723 "\\|" org-deadline-string
3724 "\\|" org-closed-string
3725 "\\|" org-archived-string
3726 "\\)"
3727 " *[[<]\\([^]>]+\\)[]>]")
3728 org-maybe-keyword-time-regexp
3729 (concat "\\(\\<\\(" org-scheduled-string
3730 "\\|" org-deadline-string
3731 "\\|" org-closed-string
3732 "\\|" org-archived-string
3733 "\\|" org-clock-string "\\)\\)?"
3734 " *\\([[<][0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^]\r\n>]*?[]>]\\|<%%([^\r\n>]*>\\)")
3735 org-planning-or-clock-line-re
3736 (concat "\\(?:^[ \t]*\\(" org-scheduled-string
3737 "\\|" org-deadline-string
3738 "\\|" org-closed-string "\\|" org-clock-string
3739 "\\|" org-archived-string "\\)\\>\\)")
3742 (org-set-font-lock-defaults)))
3745 ;;; Some variables ujsed in various places
3747 (defvar org-window-configuration nil
3748 "Used in various places to store a window configuration.")
3749 (defvar org-finish-function nil
3750 "Function to be called when `C-c C-c' is used.
3751 This is for getting out of special buffers like remember.")
3753 ;;; Foreign variables, to inform the compiler
3755 ;; XEmacs only
3756 (defvar outline-mode-menu-heading)
3757 (defvar outline-mode-menu-show)
3758 (defvar outline-mode-menu-hide)
3759 (defvar zmacs-regions) ; XEmacs regions
3760 ;; Emacs only
3761 (defvar mark-active)
3763 ;; Packages that org-mode interacts with
3764 (defvar calc-embedded-close-formula)
3765 (defvar calc-embedded-open-formula)
3766 (defvar font-lock-unfontify-region-function)
3767 (defvar org-goto-start-pos)
3768 (defvar vm-message-pointer)
3769 (defvar vm-folder-directory)
3770 (defvar wl-summary-buffer-elmo-folder)
3771 (defvar wl-summary-buffer-folder-name)
3772 (defvar gnus-other-frame-object)
3773 (defvar gnus-group-name)
3774 (defvar gnus-article-current)
3775 (defvar w3m-current-url)
3776 (defvar w3m-current-title)
3777 (defvar mh-progs)
3778 (defvar mh-current-folder)
3779 (defvar mh-show-folder-buffer)
3780 (defvar mh-index-folder)
3781 (defvar mh-searcher)
3782 (defvar calendar-mode-map)
3783 (defvar Info-current-file)
3784 (defvar Info-current-node)
3785 (defvar texmathp-why)
3786 (defvar remember-save-after-remembering)
3787 (defvar remember-data-file)
3788 (defvar annotation) ; from remember.el, dynamically scoped in `remember-mode'
3789 (defvar initial) ; from remember.el, dynamically scoped in `remember-mode'
3790 (defvar org-latex-regexps)
3791 (defvar constants-unit-system)
3793 (defvar original-date) ; dynamically scoped in calendar.el does scope this
3795 ;; FIXME: Occasionally check by commenting these, to make sure
3796 ;; no other functions uses these, forgetting to let-bind them.
3797 (defvar entry)
3798 (defvar state)
3799 (defvar last-state)
3800 (defvar date)
3801 (defvar description)
3804 ;; Defined somewhere in this file, but used before definition.
3805 (defvar orgtbl-mode-menu) ; defined when orgtbl mode get initialized
3806 (defvar org-agenda-undo-list)
3807 (defvar org-agenda-pending-undo-list)
3808 (defvar org-agenda-overriding-header)
3809 (defvar orgtbl-mode)
3810 (defvar org-html-entities)
3811 (defvar org-struct-menu)
3812 (defvar org-org-menu)
3813 (defvar org-tbl-menu)
3814 (defvar org-agenda-keymap)
3815 (defvar org-category-table)
3817 ;;;; Emacs/XEmacs compatibility
3819 ;; Overlay compatibility functions
3820 (defun org-make-overlay (beg end &optional buffer)
3821 (if (featurep 'xemacs)
3822 (make-extent beg end buffer)
3823 (make-overlay beg end buffer)))
3824 (defun org-delete-overlay (ovl)
3825 (if (featurep 'xemacs) (delete-extent ovl) (delete-overlay ovl)))
3826 (defun org-detach-overlay (ovl)
3827 (if (featurep 'xemacs) (detach-extent ovl) (delete-overlay ovl)))
3828 (defun org-move-overlay (ovl beg end &optional buffer)
3829 (if (featurep 'xemacs)
3830 (set-extent-endpoints ovl beg end (or buffer (current-buffer)))
3831 (move-overlay ovl beg end buffer)))
3832 (defun org-overlay-put (ovl prop value)
3833 (if (featurep 'xemacs)
3834 (set-extent-property ovl prop value)
3835 (overlay-put ovl prop value)))
3836 (defun org-overlay-display (ovl text &optional face evap)
3837 "Make overlay OVL display TEXT with face FACE."
3838 (if (featurep 'xemacs)
3839 (let ((gl (make-glyph text)))
3840 (and face (set-glyph-face gl face))
3841 (set-extent-property ovl 'invisible t)
3842 (set-extent-property ovl 'end-glyph gl))
3843 (overlay-put ovl 'display text)
3844 (if face (overlay-put ovl 'face face))
3845 (if evap (overlay-put ovl 'evaporate t))))
3846 (defun org-overlay-before-string (ovl text &optional face evap)
3847 "Make overlay OVL display TEXT with face FACE."
3848 (if (featurep 'xemacs)
3849 (let ((gl (make-glyph text)))
3850 (and face (set-glyph-face gl face))
3851 (set-extent-property ovl 'begin-glyph gl))
3852 (if face (org-add-props text nil 'face face))
3853 (overlay-put ovl 'before-string text)
3854 (if evap (overlay-put ovl 'evaporate t))))
3855 (defun org-overlay-get (ovl prop)
3856 (if (featurep 'xemacs)
3857 (extent-property ovl prop)
3858 (overlay-get ovl prop)))
3859 (defun org-overlays-at (pos)
3860 (if (featurep 'xemacs) (extents-at pos) (overlays-at pos)))
3861 ;; FIXME: this is currently not used
3862 (defun org-overlays-in (&optional start end)
3863 (if (featurep 'xemacs)
3864 (extent-list nil start end)
3865 (overlays-in start end)))
3866 (defun org-overlay-start (o)
3867 (if (featurep 'xemacs) (extent-start-position o) (overlay-start o)))
3868 (defun org-overlay-end (o)
3869 (if (featurep 'xemacs) (extent-end-position o) (overlay-end o)))
3870 ;; FIXME: this is currently not used
3871 (defun org-find-overlays (prop &optional pos delete)
3872 "Find all overlays specifying PROP at POS or point.
3873 If DELETE is non-nil, delete all those overlays."
3874 (let ((overlays (org-overlays-at (or pos (point))))
3875 ov found)
3876 (while (setq ov (pop overlays))
3877 (if (org-overlay-get ov prop)
3878 (if delete (org-delete-overlay ov) (push ov found))))
3879 found))
3881 ;; Region compatibility
3883 (defun org-add-hook (hook function &optional append local)
3884 "Add-hook, compatible with both Emacsen."
3885 (if (and local (featurep 'xemacs))
3886 (add-local-hook hook function append)
3887 (add-hook hook function append local)))
3889 (defvar org-ignore-region nil
3890 "To temporarily disable the active region.")
3892 (defun org-region-active-p ()
3893 "Is `transient-mark-mode' on and the region active?
3894 Works on both Emacs and XEmacs."
3895 (if org-ignore-region
3897 (if (featurep 'xemacs)
3898 (and zmacs-regions (region-active-p))
3899 (and transient-mark-mode mark-active))))
3901 ;; Invisibility compatibility
3903 (defun org-add-to-invisibility-spec (arg)
3904 "Add elements to `buffer-invisibility-spec'.
3905 See documentation for `buffer-invisibility-spec' for the kind of elements
3906 that can be added."
3907 (cond
3908 ((fboundp 'add-to-invisibility-spec)
3909 (add-to-invisibility-spec arg))
3910 ((or (null buffer-invisibility-spec) (eq buffer-invisibility-spec t))
3911 (setq buffer-invisibility-spec (list arg)))
3913 (setq buffer-invisibility-spec
3914 (cons arg buffer-invisibility-spec)))))
3916 (defun org-remove-from-invisibility-spec (arg)
3917 "Remove elements from `buffer-invisibility-spec'."
3918 (if (fboundp 'remove-from-invisibility-spec)
3919 (remove-from-invisibility-spec arg)
3920 (if (consp buffer-invisibility-spec)
3921 (setq buffer-invisibility-spec
3922 (delete arg buffer-invisibility-spec)))))
3924 ;; FIXME: this is currently not used
3925 (defun org-in-invisibility-spec-p (arg)
3926 "Is ARG a member of `buffer-invisibility-spec'?"
3927 (if (consp buffer-invisibility-spec)
3928 (member arg buffer-invisibility-spec)
3929 nil))
3931 ;;;; Define the Org-mode
3933 (if (and (not (keymapp outline-mode-map)) (featurep 'allout))
3934 (error "Conflict with outdated version of allout.el. Load org.el before allout.el, or ugrade to newer allout, for example by switching to Emacs 22."))
3937 ;; We use a before-change function to check if a table might need
3938 ;; an update.
3939 (defvar org-table-may-need-update t
3940 "Indicates that a table might need an update.
3941 This variable is set by `org-before-change-function'.
3942 `org-table-align' sets it back to nil.")
3943 (defvar org-mode-map)
3944 (defvar org-mode-hook nil)
3945 (defvar org-inhibit-startup nil) ; Dynamically-scoped param.
3946 (defvar org-agenda-keep-modes nil) ; Dynamically-scoped param.
3947 (defvar org-table-buffer-is-an nil)
3950 ;;;###autoload
3951 (define-derived-mode org-mode outline-mode "Org"
3952 "Outline-based notes management and organizer, alias
3953 \"Carsten's outline-mode for keeping track of everything.\"
3955 Org-mode develops organizational tasks around a NOTES file which
3956 contains information about projects as plain text. Org-mode is
3957 implemented on top of outline-mode, which is ideal to keep the content
3958 of large files well structured. It supports ToDo items, deadlines and
3959 time stamps, which magically appear in the diary listing of the Emacs
3960 calendar. Tables are easily created with a built-in table editor.
3961 Plain text URL-like links connect to websites, emails (VM), Usenet
3962 messages (Gnus), BBDB entries, and any files related to the project.
3963 For printing and sharing of notes, an Org-mode file (or a part of it)
3964 can be exported as a structured ASCII or HTML file.
3966 The following commands are available:
3968 \\{org-mode-map}"
3970 ;; Get rid of Outline menus, they are not needed
3971 ;; Need to do this here because define-derived-mode sets up
3972 ;; the keymap so late. Still, it is a waste to call this each time
3973 ;; we switch another buffer into org-mode.
3974 (if (featurep 'xemacs)
3975 (when (boundp 'outline-mode-menu-heading)
3976 ;; Assume this is Greg's port, it used easymenu
3977 (easy-menu-remove outline-mode-menu-heading)
3978 (easy-menu-remove outline-mode-menu-show)
3979 (easy-menu-remove outline-mode-menu-hide))
3980 (define-key org-mode-map [menu-bar headings] 'undefined)
3981 (define-key org-mode-map [menu-bar hide] 'undefined)
3982 (define-key org-mode-map [menu-bar show] 'undefined))
3984 (easy-menu-add org-org-menu)
3985 (easy-menu-add org-tbl-menu)
3986 (org-install-agenda-files-menu)
3987 (if org-descriptive-links (org-add-to-invisibility-spec '(org-link)))
3988 (org-add-to-invisibility-spec '(org-cwidth))
3989 (when (featurep 'xemacs)
3990 (org-set-local 'line-move-ignore-invisible t))
3991 (setq outline-regexp "\\*+ ")
3992 (setq outline-level 'org-outline-level)
3993 (when (and org-ellipsis (stringp org-ellipsis)
3994 (fboundp 'set-display-table-slot) (boundp 'buffer-display-table))
3995 (unless org-display-table
3996 (setq org-display-table (make-display-table)))
3997 (set-display-table-slot org-display-table
3998 4 (string-to-vector org-ellipsis))
3999 (setq buffer-display-table org-display-table))
4000 (org-set-regexps-and-options)
4001 ;; Calc embedded
4002 (org-set-local 'calc-embedded-open-mode "# ")
4003 (modify-syntax-entry ?# "<")
4004 (modify-syntax-entry ?@ "w")
4005 (if org-startup-truncated (setq truncate-lines t))
4006 (org-set-local 'font-lock-unfontify-region-function
4007 'org-unfontify-region)
4008 ;; Activate before-change-function
4009 (org-set-local 'org-table-may-need-update t)
4010 (org-add-hook 'before-change-functions 'org-before-change-function nil
4011 'local)
4012 ;; Check for running clock before killing a buffer
4013 (org-add-hook 'kill-buffer-hook 'org-check-running-clock nil 'local)
4014 ;; Paragraphs and auto-filling
4015 (org-set-autofill-regexps)
4016 (setq indent-line-function 'org-indent-line-function)
4017 (org-update-radio-target-regexp)
4019 ;; Comment characters
4020 ; (org-set-local 'comment-start "#") ;; FIXME: this breaks wrapping
4021 (org-set-local 'comment-padding " ")
4023 ;; Make isearch reveal context
4024 (if (or (featurep 'xemacs)
4025 (not (boundp 'outline-isearch-open-invisible-function)))
4026 ;; Emacs 21 and XEmacs make use of the hook
4027 (org-add-hook 'isearch-mode-end-hook 'org-isearch-end 'append 'local)
4028 ;; Emacs 22 deals with this through a special variable
4029 (org-set-local 'outline-isearch-open-invisible-function
4030 (lambda (&rest ignore) (org-show-context 'isearch))))
4032 ;; If empty file that did not turn on org-mode automatically, make it to.
4033 (if (and org-insert-mode-line-in-empty-file
4034 (interactive-p)
4035 (= (point-min) (point-max)))
4036 (insert "# -*- mode: org -*-\n\n"))
4038 (unless org-inhibit-startup
4039 (when org-startup-align-all-tables
4040 (let ((bmp (buffer-modified-p)))
4041 (org-table-map-tables 'org-table-align)
4042 (set-buffer-modified-p bmp)))
4043 (cond
4044 ((eq org-startup-folded t)
4045 (org-cycle '(4)))
4046 ((eq org-startup-folded 'content)
4047 (let ((this-command 'org-cycle) (last-command 'org-cycle))
4048 (org-cycle '(4)) (org-cycle '(4)))))))
4050 (put 'org-mode 'flyspell-mode-predicate 'org-mode-flyspell-verify)
4052 (defsubst org-call-with-arg (command arg)
4053 "Call COMMAND interactively, but pretend prefix are was ARG."
4054 (let ((current-prefix-arg arg)) (call-interactively command)))
4056 (defsubst org-current-line (&optional pos)
4057 (save-excursion
4058 (and pos (goto-char pos))
4059 (+ (if (bolp) 1 0) (count-lines 1 (point)))))
4061 (defun org-current-time ()
4062 "Current time, possibly rounded to `org-time-stamp-rounding-minutes'."
4063 (if (> org-time-stamp-rounding-minutes 0)
4064 (let ((r org-time-stamp-rounding-minutes)
4065 (time (decode-time)))
4066 (apply 'encode-time
4067 (append (list 0 (* r (floor (+ .5 (/ (float (nth 1 time)) r)))))
4068 (nthcdr 2 time))))
4069 (current-time)))
4071 (defun org-add-props (string plist &rest props)
4072 "Add text properties to entire string, from beginning to end.
4073 PLIST may be a list of properties, PROPS are individual properties and values
4074 that will be added to PLIST. Returns the string that was modified."
4075 (add-text-properties
4076 0 (length string) (if props (append plist props) plist) string)
4077 string)
4078 (put 'org-add-props 'lisp-indent-function 2)
4081 ;;;; Font-Lock stuff, including the activators
4083 (defvar org-mouse-map (make-sparse-keymap))
4084 (org-defkey org-mouse-map
4085 (if (featurep 'xemacs) [button2] [mouse-2]) 'org-open-at-mouse)
4086 (org-defkey org-mouse-map
4087 (if (featurep 'xemacs) [button3] [mouse-3]) 'org-find-file-at-mouse)
4088 (when org-mouse-1-follows-link
4089 (org-defkey org-mouse-map [follow-link] 'mouse-face))
4090 (when org-tab-follows-link
4091 (org-defkey org-mouse-map [(tab)] 'org-open-at-point)
4092 (org-defkey org-mouse-map "\C-i" 'org-open-at-point))
4093 (when org-return-follows-link
4094 (org-defkey org-mouse-map [(return)] 'org-open-at-point)
4095 (org-defkey org-mouse-map "\C-m" 'org-open-at-point))
4097 (require 'font-lock)
4099 (defconst org-non-link-chars "]\t\n\r<>")
4100 (defconst org-link-types '("http" "https" "ftp" "mailto" "file" "news" "bbdb" "vm"
4101 "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
4102 (defconst org-link-re-with-space
4103 (concat
4104 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
4105 "\\([^" org-non-link-chars " ]"
4106 "[^" org-non-link-chars "]*"
4107 "[^" org-non-link-chars " ]\\)>?")
4108 "Matches a link with spaces, optional angular brackets around it.")
4110 (defconst org-link-re-with-space2
4111 (concat
4112 "<?\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
4113 "\\([^" org-non-link-chars " ]"
4114 "[^]\t\n\r]*"
4115 "[^" org-non-link-chars " ]\\)>?")
4116 "Matches a link with spaces, optional angular brackets around it.")
4118 (defconst org-angle-link-re
4119 (concat
4120 "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
4121 "\\([^" org-non-link-chars " ]"
4122 "[^" org-non-link-chars "]*"
4123 "\\)>")
4124 "Matches link with angular brackets, spaces are allowed.")
4125 (defconst org-plain-link-re
4126 (concat
4127 "\\(" (mapconcat 'identity org-link-types "\\|") "\\):"
4128 "\\([^]\t\n\r<>,;() ]+\\)")
4129 "Matches plain link, without spaces.")
4131 (defconst org-bracket-link-regexp
4132 "\\[\\[\\([^][]+\\)\\]\\(\\[\\([^][]+\\)\\]\\)?\\]"
4133 "Matches a link in double brackets.")
4135 (defconst org-bracket-link-analytic-regexp
4136 (concat
4137 "\\[\\["
4138 "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?"
4139 "\\([^]]+\\)"
4140 "\\]"
4141 "\\(\\[" "\\([^]]+\\)" "\\]\\)?"
4142 "\\]"))
4143 ; 1: http:
4144 ; 2: http
4145 ; 3: path
4146 ; 4: [desc]
4147 ; 5: desc
4149 (defconst org-any-link-re
4150 (concat "\\(" org-bracket-link-regexp "\\)\\|\\("
4151 org-angle-link-re "\\)\\|\\("
4152 org-plain-link-re "\\)")
4153 "Regular expression matching any link.")
4155 (defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)>"
4156 "Regular expression for fast time stamp matching.")
4157 (defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} [^\r\n>]*?\\)[]>]"
4158 "Regular expression for fast time stamp matching.")
4159 (defconst org-ts-regexp0 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\)\\([^]0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
4160 "Regular expression matching time strings for analysis.
4161 This one does not require the space after the date.")
4162 (defconst org-ts-regexp1 "\\(\\([0-9]\\{4\\}\\)-\\([0-9]\\{2\\}\\)-\\([0-9]\\{2\\}\\) \\([^]0-9>\r\n]*\\)\\(\\([0-9]\\{2\\}\\):\\([0-9]\\{2\\}\\)\\)?\\)"
4163 "Regular expression matching time strings for analysis.")
4164 (defconst org-ts-regexp2 (concat "<" org-ts-regexp1 "[^>\n]\\{0,11\\}>")
4165 "Regular expression matching time stamps, with groups.")
4166 (defconst org-ts-regexp3 (concat "[[<]" org-ts-regexp1 "[^]>\n]\\{0,11\\}[]>]")
4167 "Regular expression matching time stamps (also [..]), with groups.")
4168 (defconst org-tr-regexp (concat org-ts-regexp "--?-?" org-ts-regexp)
4169 "Regular expression matching a time stamp range.")
4170 (defconst org-tr-regexp-both
4171 (concat org-ts-regexp-both "--?-?" org-ts-regexp-both)
4172 "Regular expression matching a time stamp range.")
4173 (defconst org-tsr-regexp (concat org-ts-regexp "\\(--?-?"
4174 org-ts-regexp "\\)?")
4175 "Regular expression matching a time stamp or time stamp range.")
4176 (defconst org-tsr-regexp-both (concat org-ts-regexp-both "\\(--?-?"
4177 org-ts-regexp-both "\\)?")
4178 "Regular expression matching a time stamp or time stamp range.
4179 The time stamps may be either active or inactive.")
4181 (defvar org-emph-face nil)
4183 (defun org-do-emphasis-faces (limit)
4184 "Run through the buffer and add overlays to links."
4185 (let (rtn)
4186 (while (and (not rtn) (re-search-forward org-emph-re limit t))
4187 (if (not (= (char-after (match-beginning 3))
4188 (char-after (match-beginning 4))))
4189 (progn
4190 (setq rtn t)
4191 (font-lock-prepend-text-property (match-beginning 2) (match-end 2)
4192 'face
4193 (nth 1 (assoc (match-string 3)
4194 org-emphasis-alist)))
4195 (add-text-properties (match-beginning 2) (match-end 2)
4196 '(font-lock-multiline t))
4197 (backward-char 1))))
4198 rtn))
4200 (defun org-emphasize (&optional char)
4201 "Insert or change an emphasis, i.e. a font like bold or italic.
4202 If there is an active region, change that region to a new emphasis.
4203 If there is no region, just insert the marker characters and position
4204 the cursor between them.
4205 CHAR should be either the marker character, or the first character of the
4206 HTML tag associated with that emphasis. If CHAR is a space, the means
4207 to remove the emphasis of the selected region.
4208 If char is not given (for example in an interactive call) it
4209 will be prompted for."
4210 (interactive)
4211 (let ((eal org-emphasis-alist) e det
4212 (erc org-emphasis-regexp-components)
4213 (prompt "")
4214 (string "") beg end move tag c s)
4215 (if (org-region-active-p)
4216 (setq beg (region-beginning) end (region-end)
4217 string (buffer-substring beg end))
4218 (setq move t))
4220 (while (setq e (pop eal))
4221 (setq tag (car (org-split-string (nth 2 e) "[ <>/]+"))
4222 c (aref tag 0))
4223 (push (cons c (string-to-char (car e))) det)
4224 (setq prompt (concat prompt (format " [%s%c]%s" (car e) c
4225 (substring tag 1)))))
4226 (unless char
4227 (message "%s" (concat "Emphasis marker or tag:" prompt))
4228 (setq char (read-char-exclusive)))
4229 (setq char (or (cdr (assoc char det)) char))
4230 (if (equal char ?\ )
4231 (setq s "" move nil)
4232 (unless (assoc (char-to-string char) org-emphasis-alist)
4233 (error "No such emphasis marker: \"%c\"" char))
4234 (setq s (char-to-string char)))
4235 (while (and (> (length string) 1)
4236 (equal (substring string 0 1) (substring string -1))
4237 (assoc (substring string 0 1) org-emphasis-alist))
4238 (setq string (substring string 1 -1)))
4239 (setq string (concat s string s))
4240 (if beg (delete-region beg end))
4241 (unless (or (bolp)
4242 (string-match (concat "[" (nth 0 erc) "\n]")
4243 (char-to-string (char-before (point)))))
4244 (insert " "))
4245 (unless (string-match (concat "[" (nth 1 erc) "\n]")
4246 (char-to-string (char-after (point))))
4247 (insert " ") (backward-char 1))
4248 (insert string)
4249 (and move (backward-char 1))))
4251 (defun org-activate-plain-links (limit)
4252 "Run through the buffer and add overlays to links."
4253 (catch 'exit
4254 (let (f)
4255 (while (re-search-forward org-plain-link-re limit t)
4256 (setq f (get-text-property (match-beginning 0) 'face))
4257 (if (or (eq f 'org-tag)
4258 (and (listp f) (memq 'org-tag f)))
4260 (add-text-properties (match-beginning 0) (match-end 0)
4261 (list 'mouse-face 'highlight
4262 'rear-nonsticky t
4263 'keymap org-mouse-map
4265 (throw 'exit t))))))
4267 (defun org-activate-angle-links (limit)
4268 "Run through the buffer and add overlays to links."
4269 (if (re-search-forward org-angle-link-re limit t)
4270 (progn
4271 (add-text-properties (match-beginning 0) (match-end 0)
4272 (list 'mouse-face 'highlight
4273 'rear-nonsticky t
4274 'keymap org-mouse-map
4276 t)))
4278 (defmacro org-maybe-intangible (props)
4279 "Add '(intangigble t) to PROPS if Emacs version is earlier than Emacs 22.
4280 In emacs 21, invisible text is not avoided by the command loop, so the
4281 intangible property is needed to make sure point skips this text.
4282 In Emacs 22, this is not necessary. The intangible text property has
4283 led to problems with flyspell. These problems are fixed in flyspell.el,
4284 but we still avoid setting the property in Emacs 22 and later.
4285 We use a macro so that the test can happen at compilation time."
4286 (if (< emacs-major-version 22)
4287 `(append '(intangible t) ,props)
4288 props))
4290 (defun org-activate-bracket-links (limit)
4291 "Run through the buffer and add overlays to bracketed links."
4292 (if (re-search-forward org-bracket-link-regexp limit t)
4293 (let* ((help (concat "LINK: "
4294 (org-match-string-no-properties 1)))
4295 ;; FIXME: above we should remove the escapes.
4296 ;; but that requires another match, protecting match data,
4297 ;; a lot of overhead for font-lock.
4298 (ip (org-maybe-intangible
4299 (list 'invisible 'org-link 'rear-nonsticky t
4300 'keymap org-mouse-map 'mouse-face 'highlight
4301 'help-echo help)))
4302 (vp (list 'rear-nonsticky t
4303 'keymap org-mouse-map 'mouse-face 'highlight
4304 'help-echo help)))
4305 ;; We need to remove the invisible property here. Table narrowing
4306 ;; may have made some of this invisible.
4307 (remove-text-properties (match-beginning 0) (match-end 0)
4308 '(invisible nil))
4309 (if (match-end 3)
4310 (progn
4311 (add-text-properties (match-beginning 0) (match-beginning 3) ip)
4312 (add-text-properties (match-beginning 3) (match-end 3) vp)
4313 (add-text-properties (match-end 3) (match-end 0) ip))
4314 (add-text-properties (match-beginning 0) (match-beginning 1) ip)
4315 (add-text-properties (match-beginning 1) (match-end 1) vp)
4316 (add-text-properties (match-end 1) (match-end 0) ip))
4317 t)))
4319 (defun org-activate-dates (limit)
4320 "Run through the buffer and add overlays to dates."
4321 (if (re-search-forward org-tsr-regexp-both limit t)
4322 (progn
4323 (add-text-properties (match-beginning 0) (match-end 0)
4324 (list 'mouse-face 'highlight
4325 'rear-nonsticky t
4326 'keymap org-mouse-map))
4327 (when org-display-custom-times
4328 (if (match-end 3)
4329 (org-display-custom-time (match-beginning 3) (match-end 3)))
4330 (org-display-custom-time (match-beginning 1) (match-end 1)))
4331 t)))
4333 (defvar org-target-link-regexp nil
4334 "Regular expression matching radio targets in plain text.")
4335 (defvar org-target-regexp "<<\\([^<>\n\r]+\\)>>"
4336 "Regular expression matching a link target.")
4337 (defvar org-radio-target-regexp "<<<\\([^<>\n\r]+\\)>>>"
4338 "Regular expression matching a radio target.")
4339 (defvar org-any-target-regexp "<<<?\\([^<>\n\r]+\\)>>>?" ; FIXME, not exact, would match <<<aaa>> as a radio target.
4340 "Regular expression matching any target.")
4342 (defun org-activate-target-links (limit)
4343 "Run through the buffer and add overlays to target matches."
4344 (when org-target-link-regexp
4345 (let ((case-fold-search t))
4346 (if (re-search-forward org-target-link-regexp limit t)
4347 (progn
4348 (add-text-properties (match-beginning 0) (match-end 0)
4349 (list 'mouse-face 'highlight
4350 'rear-nonsticky t
4351 'keymap org-mouse-map
4352 'help-echo "Radio target link"
4353 'org-linked-text t))
4354 t)))))
4356 (defun org-update-radio-target-regexp ()
4357 "Find all radio targets in this file and update the regular expression."
4358 (interactive)
4359 (when (memq 'radio org-activate-links)
4360 (setq org-target-link-regexp
4361 (org-make-target-link-regexp (org-all-targets 'radio)))
4362 (org-restart-font-lock)))
4364 (defun org-hide-wide-columns (limit)
4365 (let (s e)
4366 (setq s (text-property-any (point) (or limit (point-max))
4367 'org-cwidth t))
4368 (when s
4369 (setq e (next-single-property-change s 'org-cwidth))
4370 (add-text-properties s e (org-maybe-intangible '(invisible org-cwidth)))
4371 (goto-char e)
4372 t)))
4374 (defun org-restart-font-lock ()
4375 "Restart font-lock-mode, to force refontification."
4376 (when (and (boundp 'font-lock-mode) font-lock-mode)
4377 (font-lock-mode -1)
4378 (font-lock-mode 1)))
4380 (defun org-all-targets (&optional radio)
4381 "Return a list of all targets in this file.
4382 With optional argument RADIO, only find radio targets."
4383 (let ((re (if radio org-radio-target-regexp org-target-regexp))
4384 rtn)
4385 (save-excursion
4386 (goto-char (point-min))
4387 (while (re-search-forward re nil t)
4388 (add-to-list 'rtn (downcase (org-match-string-no-properties 1))))
4389 rtn)))
4391 (defun org-make-target-link-regexp (targets)
4392 "Make regular expression matching all strings in TARGETS.
4393 The regular expression finds the targets also if there is a line break
4394 between words."
4395 (and targets
4396 (concat
4397 "\\<\\("
4398 (mapconcat
4399 (lambda (x)
4400 (while (string-match " +" x)
4401 (setq x (replace-match "\\s-+" t t x)))
4403 targets
4404 "\\|")
4405 "\\)\\>")))
4407 (defun org-activate-tags (limit)
4408 (if (re-search-forward (org-re "[ \t]\\(:[[:alnum:]_@:]+:\\)[ \r\n]") limit t)
4409 (progn
4410 (add-text-properties (match-beginning 1) (match-end 1)
4411 (list 'mouse-face 'highlight
4412 'rear-nonsticky t
4413 'keymap org-mouse-map))
4414 t)))
4416 (defun org-outline-level ()
4417 (save-excursion
4418 (looking-at outline-regexp)
4419 (if (match-beginning 1)
4420 (+ (org-get-string-indentation (match-string 1)) 1000)
4421 (1- (- (match-end 0) (match-beginning 0))))))
4423 (defvar org-font-lock-keywords nil)
4425 (defconst org-property-re "^[ \t]*\\(:\\([a-zA-Z_0-9]+\\):\\)[ \t]*\\(\\S-.*\\)"
4426 "Regular expression matching a property line.")
4428 (defun org-set-font-lock-defaults ()
4429 (let* ((em org-fontify-emphasized-text)
4430 (lk org-activate-links)
4431 (org-font-lock-extra-keywords
4432 ;; Headlines
4433 (list
4434 '("^\\(\\**\\)\\(\\* \\)\\(.*\\)" (1 (org-get-level-face 1))
4435 (2 (org-get-level-face 2)) (3 (org-get-level-face 3)))
4436 '("^[ \t]*\\(\\(|\\|\\+-[-+]\\).*\\S-\\)"
4437 (1 'org-table))
4438 ;; Links
4439 (if (memq 'tag lk) '(org-activate-tags (1 'org-tag prepend)))
4440 (if (memq 'angle lk) '(org-activate-angle-links (0 'org-link t)))
4441 (if (memq 'plain lk) '(org-activate-plain-links (0 'org-link t)))
4442 (if (memq 'bracket lk) '(org-activate-bracket-links (0 'org-link t)))
4443 (if (memq 'radio lk) '(org-activate-target-links (0 'org-link t)))
4444 (if (memq 'date lk) '(org-activate-dates (0 'org-date t)))
4445 '("^&?%%(.*\\|<%%([^>\n]*?>" (0 'org-sexp-date t))
4446 '(org-hide-wide-columns (0 nil append))
4447 ;; TODO lines
4448 (list (concat "^\\*+[ \t]+" org-not-done-regexp)
4449 '(1 'org-todo t))
4450 ;; Priorities
4451 (list (concat "\\[#[A-Z0-9]\\]") '(0 'org-special-keyword t))
4452 ;; Special keywords
4453 (list (concat "\\<" org-deadline-string) '(0 'org-special-keyword t))
4454 (list (concat "\\<" org-scheduled-string) '(0 'org-special-keyword t))
4455 (list (concat "\\<" org-closed-string) '(0 'org-special-keyword t))
4456 (list (concat "\\<" org-archived-string) '(0 'org-special-keyword t))
4457 (list (concat "\\<" org-clock-string) '(0 'org-special-keyword t))
4458 ;; Emphasis
4459 (if em
4460 (if (featurep 'xemacs)
4461 '(org-do-emphasis-faces (0 nil append))
4462 '(org-do-emphasis-faces)))
4463 ;; Checkboxes, similar to Frank Ruell's org-checklet.el
4464 '("^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)"
4465 2 'bold prepend)
4466 (if org-provide-checkbox-statistics
4467 '("\\[\\([0-9]*%\\)\\]\\|\\[\\([0-9]*\\)/\\([0-9]*\\)\\]"
4468 (0 (org-get-checkbox-statistics-face) t)))
4469 ;; COMMENT
4470 (list (concat "^\\*+[ \t]+\\<\\(" org-comment-string
4471 "\\|" org-quote-string "\\)\\>")
4472 '(1 'org-special-keyword t))
4473 '("^#.*" (0 'font-lock-comment-face t))
4474 ;; DONE
4475 (if org-fontify-done-headline
4476 (list (concat "^[*]+ +\\<\\("
4477 (mapconcat 'regexp-quote org-done-keywords "\\|")
4478 "\\)\\(.*\\)")
4479 '(1 'org-done t) '(2 'org-headline-done t))
4480 (list (concat "^[*]+ +\\<\\("
4481 (mapconcat 'regexp-quote org-done-keywords "\\|")
4482 "\\)\\>")
4483 '(1 'org-done t)))
4484 ;; Table stuff
4485 '("^[ \t]*\\(:.*\\)" (1 'org-table t))
4486 '("| *\\(:?=[^|\n]*\\)" (1 'org-formula t))
4487 ; '("^[ \t]*| *\\([#!$*_^/]\\) *|" (1 'org-formula t))
4488 '("^[ \t]*| *\\([#*]\\) *|" (1 'org-formula t))
4489 '("^[ \t]*|\\( *\\([$!_^/]\\) *|.*\\)|" (1 'org-formula t))
4490 ;; Drawers
4491 ; (list org-drawer-regexp '(0 'org-drawer t))
4492 ; (list "^[ \t]*:END:" '(0 'org-drawer t))
4493 (list org-drawer-regexp '(0 'org-special-keyword t))
4494 (list "^[ \t]*:END:" '(0 'org-special-keyword t))
4495 ;; Properties
4496 (list org-property-re
4497 '(1 'org-special-keyword t)
4498 '(3 'org-property-value t))
4499 (if org-format-transports-properties-p
4500 '("| *\\(<[0-9]+>\\) *" (1 'org-formula t)))
4501 '("^\\*+ \\(.*:ARCHIVE:.*\\)" (1 'org-archived prepend))
4503 (setq org-font-lock-extra-keywords (delq nil org-font-lock-extra-keywords))
4504 ;; Now set the full font-lock-keywords
4505 (org-set-local 'org-font-lock-keywords org-font-lock-extra-keywords)
4506 (org-set-local 'font-lock-defaults
4507 '(org-font-lock-keywords t nil nil backward-paragraph))
4508 (kill-local-variable 'font-lock-keywords) nil))
4510 (defvar org-m nil)
4511 (defvar org-l nil)
4512 (defvar org-f nil)
4513 (defun org-get-level-face (n)
4514 "Get the right face for match N in font-lock matching of healdines."
4515 (setq org-l (- (match-end 2) (match-beginning 1) 1))
4516 (if org-odd-levels-only (setq org-l (1+ (/ org-l 2))))
4517 (setq org-f (nth (% (1- org-l) org-n-levels) org-level-faces))
4518 (cond
4519 ((eq n 1) (if org-hide-leading-stars 'org-hide org-f))
4520 ((eq n 2) org-f)
4521 (t (if org-level-color-stars-only nil org-f))))
4523 (defun org-unfontify-region (beg end &optional maybe_loudly)
4524 "Remove fontification and activation overlays from links."
4525 (font-lock-default-unfontify-region beg end)
4526 (let* ((buffer-undo-list t)
4527 (inhibit-read-only t) (inhibit-point-motion-hooks t)
4528 (inhibit-modification-hooks t)
4529 deactivate-mark buffer-file-name buffer-file-truename)
4530 (remove-text-properties beg end
4531 '(mouse-face t keymap t org-linked-text t
4532 rear-nonsticky t
4533 invisible t intangible t))))
4535 ;;;; Visibility cycling, including org-goto and indirect buffer
4537 ;;; Cycling
4539 (defvar org-cycle-global-status nil)
4540 (make-variable-buffer-local 'org-cycle-global-status)
4541 (defvar org-cycle-subtree-status nil)
4542 (make-variable-buffer-local 'org-cycle-subtree-status)
4544 ;;;###autoload
4545 (defun org-cycle (&optional arg)
4546 "Visibility cycling for Org-mode.
4548 - When this function is called with a prefix argument, rotate the entire
4549 buffer through 3 states (global cycling)
4550 1. OVERVIEW: Show only top-level headlines.
4551 2. CONTENTS: Show all headlines of all levels, but no body text.
4552 3. SHOW ALL: Show everything.
4554 - When point is at the beginning of a headline, rotate the subtree started
4555 by this line through 3 different states (local cycling)
4556 1. FOLDED: Only the main headline is shown.
4557 2. CHILDREN: The main headline and the direct children are shown.
4558 From this state, you can move to one of the children
4559 and zoom in further.
4560 3. SUBTREE: Show the entire subtree, including body text.
4562 - When there is a numeric prefix, go up to a heading with level ARG, do
4563 a `show-subtree' and return to the previous cursor position. If ARG
4564 is negative, go up that many levels.
4566 - When point is not at the beginning of a headline, execute
4567 `indent-relative', like TAB normally does. See the option
4568 `org-cycle-emulate-tab' for details.
4570 - Special case: if point is at the beginning of the buffer and there is
4571 no headline in line 1, this function will act as if called with prefix arg."
4572 (interactive "P")
4573 (let* ((outline-regexp
4574 (if (and (org-mode-p) org-cycle-include-plain-lists)
4575 "\\(?:\\*+ \\|\\([ \t]*\\)\\([-+*]\\|[0-9]+[.)]\\) \\)"
4576 outline-regexp))
4577 (bob-special (and org-cycle-global-at-bob (bobp)
4578 (not (looking-at outline-regexp))))
4579 (org-cycle-hook
4580 (if bob-special
4581 (delq 'org-optimize-window-after-visibility-change
4582 (copy-sequence org-cycle-hook))
4583 org-cycle-hook))
4584 (pos (point)))
4586 (if (or bob-special (equal arg '(4)))
4587 ;; special case: use global cycling
4588 (setq arg t))
4590 (cond
4592 ((org-at-table-p 'any)
4593 ;; Enter the table or move to the next field in the table
4594 (or (org-table-recognize-table.el)
4595 (progn
4596 (if arg (org-table-edit-field t)
4597 (org-table-justify-field-maybe)
4598 (call-interactively 'org-table-next-field)))))
4600 ((eq arg t) ;; Global cycling
4602 (cond
4603 ((and (eq last-command this-command)
4604 (eq org-cycle-global-status 'overview))
4605 ;; We just created the overview - now do table of contents
4606 ;; This can be slow in very large buffers, so indicate action
4607 (message "CONTENTS...")
4608 (org-content)
4609 (message "CONTENTS...done")
4610 (setq org-cycle-global-status 'contents)
4611 (run-hook-with-args 'org-cycle-hook 'contents))
4613 ((and (eq last-command this-command)
4614 (eq org-cycle-global-status 'contents))
4615 ;; We just showed the table of contents - now show everything
4616 (show-all)
4617 (message "SHOW ALL")
4618 (setq org-cycle-global-status 'all)
4619 (run-hook-with-args 'org-cycle-hook 'all))
4622 ;; Default action: go to overview
4623 (org-overview)
4624 (message "OVERVIEW")
4625 (setq org-cycle-global-status 'overview)
4626 (run-hook-with-args 'org-cycle-hook 'overview))))
4628 ((and org-drawers
4629 (save-excursion
4630 (beginning-of-line 1)
4631 (looking-at org-drawer-regexp)))
4632 ;; Toggle block visibility
4633 (org-flag-drawer
4634 (not (get-char-property (match-end 0) 'invisible))))
4636 ((integerp arg)
4637 ;; Show-subtree, ARG levels up from here.
4638 (save-excursion
4639 (org-back-to-heading)
4640 (outline-up-heading (if (< arg 0) (- arg)
4641 (- (funcall outline-level) arg)))
4642 (org-show-subtree)))
4644 ((and (save-excursion (beginning-of-line 1) (looking-at outline-regexp))
4645 (or (bolp) (not (eq org-cycle-emulate-tab 'exc-hl-bol))))
4646 ;; At a heading: rotate between three different views
4647 (org-back-to-heading)
4648 (let ((goal-column 0) eoh eol eos)
4649 ;; First, some boundaries
4650 (save-excursion
4651 (org-back-to-heading)
4652 (save-excursion
4653 (beginning-of-line 2)
4654 (while (and (not (eobp)) ;; this is like `next-line'
4655 (get-char-property (1- (point)) 'invisible))
4656 (beginning-of-line 2)) (setq eol (point)))
4657 (outline-end-of-heading) (setq eoh (point))
4658 (org-end-of-subtree t)
4659 (unless (eobp)
4660 (skip-chars-forward " \t\n")
4661 (beginning-of-line 1) ; in case this is an item
4663 (setq eos (1- (point))))
4664 ;; Find out what to do next and set `this-command'
4665 (cond
4666 ((= eos eoh)
4667 ;; Nothing is hidden behind this heading
4668 (message "EMPTY ENTRY")
4669 (setq org-cycle-subtree-status nil)
4670 (save-excursion
4671 (goto-char eos)
4672 (outline-next-heading)
4673 (if (org-invisible-p) (org-flag-heading nil))))
4674 ((>= eol eos)
4675 ;; Entire subtree is hidden in one line: open it
4676 (org-show-entry)
4677 (show-children)
4678 (message "CHILDREN")
4679 (save-excursion
4680 (goto-char eos)
4681 (outline-next-heading)
4682 (if (org-invisible-p) (org-flag-heading nil)))
4683 (setq org-cycle-subtree-status 'children)
4684 (run-hook-with-args 'org-cycle-hook 'children))
4685 ((and (eq last-command this-command)
4686 (eq org-cycle-subtree-status 'children))
4687 ;; We just showed the children, now show everything.
4688 (org-show-subtree)
4689 (message "SUBTREE")
4690 (setq org-cycle-subtree-status 'subtree)
4691 (run-hook-with-args 'org-cycle-hook 'subtree))
4693 ;; Default action: hide the subtree.
4694 (hide-subtree)
4695 (message "FOLDED")
4696 (setq org-cycle-subtree-status 'folded)
4697 (run-hook-with-args 'org-cycle-hook 'folded)))))
4699 ;; TAB emulation
4700 (buffer-read-only (org-back-to-heading))
4702 ((org-try-cdlatex-tab))
4704 ((and (eq org-cycle-emulate-tab 'exc-hl-bol)
4705 (or (not (bolp))
4706 (not (looking-at outline-regexp))))
4707 (call-interactively (global-key-binding "\t")))
4709 ((if (and (memq org-cycle-emulate-tab '(white whitestart))
4710 (save-excursion (beginning-of-line 1) (looking-at "[ \t]*"))
4711 (or (and (eq org-cycle-emulate-tab 'white)
4712 (= (match-end 0) (point-at-eol)))
4713 (and (eq org-cycle-emulate-tab 'whitestart)
4714 (>= (match-end 0) pos))))
4716 (eq org-cycle-emulate-tab t))
4717 (if (and (looking-at "[ \n\r\t]")
4718 (string-match "^[ \t]*$" (buffer-substring
4719 (point-at-bol) (point))))
4720 (progn
4721 (beginning-of-line 1)
4722 (and (looking-at "[ \t]+") (replace-match ""))))
4723 (call-interactively (global-key-binding "\t")))
4725 (t (save-excursion
4726 (org-back-to-heading)
4727 (org-cycle))))))
4729 ;;;###autoload
4730 (defun org-global-cycle (&optional arg)
4731 "Cycle the global visibility. For details see `org-cycle'."
4732 (interactive "P")
4733 (let ((org-cycle-include-plain-lists
4734 (if (org-mode-p) org-cycle-include-plain-lists nil)))
4735 (if (integerp arg)
4736 (progn
4737 (show-all)
4738 (hide-sublevels arg)
4739 (setq org-cycle-global-status 'contents))
4740 (org-cycle '(4)))))
4742 (defun org-overview ()
4743 "Switch to overview mode, shoing only top-level headlines.
4744 Really, this shows all headlines with level equal or greater than the level
4745 of the first headline in the buffer. This is important, because if the
4746 first headline is not level one, then (hide-sublevels 1) gives confusing
4747 results."
4748 (interactive)
4749 (let ((level (save-excursion
4750 (goto-char (point-min))
4751 (if (re-search-forward (concat "^" outline-regexp) nil t)
4752 (progn
4753 (goto-char (match-beginning 0))
4754 (funcall outline-level))))))
4755 (and level (hide-sublevels level))))
4757 (defun org-content (&optional arg)
4758 "Show all headlines in the buffer, like a table of contents.
4759 With numerical argument N, show content up to level N."
4760 (interactive "P")
4761 (save-excursion
4762 ;; Visit all headings and show their offspring
4763 (and (integerp arg) (org-overview))
4764 (goto-char (point-max))
4765 (catch 'exit
4766 (while (and (progn (condition-case nil
4767 (outline-previous-visible-heading 1)
4768 (error (goto-char (point-min))))
4770 (looking-at outline-regexp))
4771 (if (integerp arg)
4772 (show-children (1- arg))
4773 (show-branches))
4774 (if (bobp) (throw 'exit nil))))))
4777 (defun org-optimize-window-after-visibility-change (state)
4778 "Adjust the window after a change in outline visibility.
4779 This function is the default value of the hook `org-cycle-hook'."
4780 (when (get-buffer-window (current-buffer))
4781 (cond
4782 ; ((eq state 'overview) (org-first-headline-recenter 1))
4783 ; ((eq state 'overview) (org-beginning-of-line))
4784 ((eq state 'content) nil)
4785 ((eq state 'all) nil)
4786 ((eq state 'folded) nil)
4787 ((eq state 'children) (or (org-subtree-end-visible-p) (recenter 1)))
4788 ((eq state 'subtree) (or (org-subtree-end-visible-p) (recenter 1))))))
4791 (defun org-cycle-show-empty-lines (state)
4792 "Show empty lines above all visible headlines.
4793 The region to be covered depends on STATE when called through
4794 `org-cycle-hook'. Lisp program can use t for STATE to get the
4795 entire buffer covered. Note that an empty line is only shown if there
4796 are at least `org-cycle-separator-lines' empty lines before the headeline."
4797 (when (> org-cycle-separator-lines 0)
4798 (save-excursion
4799 (let* ((n org-cycle-separator-lines)
4800 (re (cond
4801 ((= n 1) "\\(\n[ \t]*\n\\*+\\) ")
4802 ((= n 2) "^[ \t]*\\(\n[ \t]*\n\\*+\\) ")
4803 (t (let ((ns (number-to-string (- n 2))))
4804 (concat "^\\(?:[ \t]*\n\\)\\{" ns "," ns "\\}"
4805 "[ \t]*\\(\n[ \t]*\n\\*+\\) ")))))
4806 beg end)
4807 (cond
4808 ((memq state '(overview contents t))
4809 (setq beg (point-min) end (point-max)))
4810 ((memq state '(children folded))
4811 (setq beg (point) end (progn (org-end-of-subtree t t)
4812 (beginning-of-line 2)
4813 (point)))))
4814 (when beg
4815 (goto-char beg)
4816 (while (re-search-forward re end t)
4817 (if (not (get-char-property (match-end 1) 'invisible))
4818 (outline-flag-region
4819 (match-beginning 1) (match-end 1) nil)))))))
4820 ;; Never hide empty lines at the end of the file.
4821 (save-excursion
4822 (goto-char (point-max))
4823 (outline-previous-heading)
4824 (outline-end-of-heading)
4825 (if (and (looking-at "[ \t\n]+")
4826 (= (match-end 0) (point-max)))
4827 (outline-flag-region (point) (match-end 0) nil))))
4829 (defun org-subtree-end-visible-p ()
4830 "Is the end of the current subtree visible?"
4831 (pos-visible-in-window-p
4832 (save-excursion (org-end-of-subtree t) (point))))
4834 (defun org-first-headline-recenter (&optional N)
4835 "Move cursor to the first headline and recenter the headline.
4836 Optional argument N means, put the headline into the Nth line of the window."
4837 (goto-char (point-min))
4838 (when (re-search-forward (concat "^\\(" outline-regexp "\\)") nil t)
4839 (beginning-of-line)
4840 (recenter (prefix-numeric-value N))))
4842 ;;; Org-goto
4844 (defvar org-goto-window-configuration nil)
4845 (defvar org-goto-marker nil)
4846 (defvar org-goto-map (make-sparse-keymap))
4847 (let ((cmds '(isearch-forward isearch-backward)) cmd)
4848 (while (setq cmd (pop cmds))
4849 (substitute-key-definition cmd cmd org-goto-map global-map)))
4850 (org-defkey org-goto-map "\C-m" 'org-goto-ret)
4851 (org-defkey org-goto-map [(left)] 'org-goto-left)
4852 (org-defkey org-goto-map [(right)] 'org-goto-right)
4853 (org-defkey org-goto-map [(?q)] 'org-goto-quit)
4854 (org-defkey org-goto-map [(control ?g)] 'org-goto-quit)
4855 (org-defkey org-goto-map "\C-i" 'org-cycle)
4856 (org-defkey org-goto-map [(tab)] 'org-cycle)
4857 (org-defkey org-goto-map [(down)] 'outline-next-visible-heading)
4858 (org-defkey org-goto-map [(up)] 'outline-previous-visible-heading)
4859 (org-defkey org-goto-map "n" 'outline-next-visible-heading)
4860 (org-defkey org-goto-map "p" 'outline-previous-visible-heading)
4861 (org-defkey org-goto-map "f" 'outline-forward-same-level)
4862 (org-defkey org-goto-map "b" 'outline-backward-same-level)
4863 (org-defkey org-goto-map "u" 'outline-up-heading)
4864 (org-defkey org-goto-map "\C-c\C-n" 'outline-next-visible-heading)
4865 (org-defkey org-goto-map "\C-c\C-p" 'outline-previous-visible-heading)
4866 (org-defkey org-goto-map "\C-c\C-f" 'outline-forward-same-level)
4867 (org-defkey org-goto-map "\C-c\C-b" 'outline-backward-same-level)
4868 (org-defkey org-goto-map "\C-c\C-u" 'outline-up-heading)
4869 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
4870 (while l (org-defkey org-goto-map (int-to-string (pop l)) 'digit-argument)))
4872 (defconst org-goto-help
4873 "Select a location to jump to, press RET
4874 \[Up]/[Down]=next/prev headline TAB=cycle visibility RET=select [Q]uit")
4876 (defun org-goto ()
4877 "Go to a different location of the document, keeping current visibility.
4879 When you want to go to a different location in a document, the fastest way
4880 is often to fold the entire buffer and then dive into the tree. This
4881 method has the disadvantage, that the previous location will be folded,
4882 which may not be what you want.
4884 This command works around this by showing a copy of the current buffer in
4885 overview mode. You can dive into the tree in that copy, to find the
4886 location you want to reach. When pressing RET, the command returns to the
4887 original buffer in which the visibility is still unchanged. It then jumps
4888 to the new location, making it and the headline hierarchy above it visible."
4889 (interactive)
4890 (let* ((org-goto-start-pos (point))
4891 (selected-point
4892 (org-get-location (current-buffer) org-goto-help)))
4893 (if selected-point
4894 (progn
4895 (org-mark-ring-push org-goto-start-pos)
4896 (goto-char selected-point)
4897 (if (or (org-invisible-p) (org-invisible-p2))
4898 (org-show-context 'org-goto)))
4899 (error "Quit"))))
4901 (defvar org-selected-point nil) ; dynamically scoped parameter
4903 (defun org-get-location (buf help)
4904 "Let the user select a location in the Org-mode buffer BUF.
4905 This function uses a recursive edit. It returns the selected position
4906 or nil."
4907 (let (org-selected-point)
4908 (save-excursion
4909 (save-window-excursion
4910 (delete-other-windows)
4911 (switch-to-buffer (get-buffer-create "*org-goto*"))
4912 (with-output-to-temp-buffer "*Help*"
4913 (princ help))
4914 (shrink-window-if-larger-than-buffer (get-buffer-window "*Help*"))
4915 (setq buffer-read-only nil)
4916 (erase-buffer)
4917 (insert-buffer-substring buf)
4918 (let ((org-startup-truncated t)
4919 (org-startup-folded t)
4920 (org-startup-align-all-tables nil))
4921 (org-mode))
4922 (setq buffer-read-only t)
4923 (if (and (boundp 'org-goto-start-pos)
4924 (integer-or-marker-p org-goto-start-pos))
4925 (let ((org-show-hierarchy-above t)
4926 (org-show-siblings t)
4927 (org-show-following-heading t))
4928 (goto-char org-goto-start-pos)
4929 (and (org-invisible-p) (org-show-context)))
4930 (goto-char (point-min)))
4931 (org-beginning-of-line)
4932 (message "Select location and press RET")
4933 ;; now we make sure that during selection, ony very few keys work
4934 ;; and that it is impossible to switch to another window.
4935 (let ((gm (current-global-map))
4936 (overriding-local-map org-goto-map))
4937 (unwind-protect
4938 (progn
4939 (use-global-map org-goto-map)
4940 (recursive-edit))
4941 (use-global-map gm)))))
4942 (kill-buffer "*org-goto*")
4943 org-selected-point))
4945 (defun org-goto-ret (&optional arg)
4946 "Finish `org-goto' by going to the new location."
4947 (interactive "P")
4948 (setq org-selected-point (point)
4949 current-prefix-arg arg)
4950 (throw 'exit nil))
4952 (defun org-goto-left ()
4953 "Finish `org-goto' by going to the new location."
4954 (interactive)
4955 (if (org-on-heading-p)
4956 (progn
4957 (beginning-of-line 1)
4958 (setq org-selected-point (point)
4959 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4960 (throw 'exit nil))
4961 (error "Not on a heading")))
4963 (defun org-goto-right ()
4964 "Finish `org-goto' by going to the new location."
4965 (interactive)
4966 (if (org-on-heading-p)
4967 (progn
4968 (outline-end-of-subtree)
4969 (or (eobp) (forward-char 1))
4970 (setq org-selected-point (point)
4971 current-prefix-arg (- (match-end 0) (match-beginning 0)))
4972 (throw 'exit nil))
4973 (error "Not on a heading")))
4975 (defun org-goto-quit ()
4976 "Finish `org-goto' without cursor motion."
4977 (interactive)
4978 (setq org-selected-point nil)
4979 (throw 'exit nil))
4981 ;;; Indirect buffer display of subtrees
4983 (defvar org-indirect-dedicated-frame nil
4984 "This is the frame being used for indirect tree display.")
4985 (defvar org-last-indirect-buffer nil)
4987 (defun org-tree-to-indirect-buffer (&optional arg)
4988 "Create indirect buffer and narrow it to current subtree.
4989 With numerical prefix ARG, go up to this level and then take that tree.
4990 If ARG is negative, go up that many levels.
4991 Normally this command removes the indirect buffer previously made
4992 with this command. However, when called with a C-u prefix, the last buffer
4993 is kept so that you can work with several indirect buffers at the same time.
4994 If `org-indirect-buffer-display' is `dedicated-frame', the C-u prefix also
4995 requests that a new frame be made for the new buffer, so that the dedicated
4996 frame is not changed."
4997 (interactive "P")
4998 (let ((cbuf (current-buffer))
4999 (cwin (selected-window))
5000 (pos (point))
5001 beg end level heading ibuf)
5002 (save-excursion
5003 (org-back-to-heading t)
5004 (when (numberp arg)
5005 (setq level (org-outline-level))
5006 (if (< arg 0) (setq arg (+ level arg)))
5007 (while (> (setq level (org-outline-level)) arg)
5008 (outline-up-heading 1 t)))
5009 (setq beg (point)
5010 heading (org-get-heading))
5011 (org-end-of-subtree t) (setq end (point)))
5012 (if (and (not arg)
5013 (buffer-live-p org-last-indirect-buffer))
5014 (kill-buffer org-last-indirect-buffer))
5015 (setq ibuf (org-get-indirect-buffer cbuf)
5016 org-last-indirect-buffer ibuf)
5017 (cond
5018 ((or (eq org-indirect-buffer-display 'new-frame)
5019 (and arg (eq org-indirect-buffer-display 'dedicated-frame)))
5020 (select-frame (make-frame))
5021 (delete-other-windows)
5022 (switch-to-buffer ibuf)
5023 (org-set-frame-title heading))
5024 ((eq org-indirect-buffer-display 'dedicated-frame)
5025 (raise-frame
5026 (select-frame (or (and org-indirect-dedicated-frame
5027 (frame-live-p org-indirect-dedicated-frame)
5028 org-indirect-dedicated-frame)
5029 (setq org-indirect-dedicated-frame (make-frame)))))
5030 (delete-other-windows)
5031 (switch-to-buffer ibuf)
5032 (org-set-frame-title (concat "Indirect: " heading)))
5033 ((eq org-indirect-buffer-display 'current-window)
5034 (switch-to-buffer ibuf))
5035 ((eq org-indirect-buffer-display 'other-window)
5036 (pop-to-buffer ibuf))
5037 (t (error "Invalid value.")))
5038 (if (featurep 'xemacs)
5039 (save-excursion (org-mode) (turn-on-font-lock)))
5040 (narrow-to-region beg end)
5041 (show-all)
5042 (goto-char pos)
5043 (and (window-live-p cwin) (select-window cwin))))
5045 (defun org-get-indirect-buffer (&optional buffer)
5046 (setq buffer (or buffer (current-buffer)))
5047 (let ((n 1) (base (buffer-name buffer)) bname)
5048 (while (buffer-live-p
5049 (get-buffer (setq bname (concat base "-" (number-to-string n)))))
5050 (setq n (1+ n)))
5051 (condition-case nil
5052 (make-indirect-buffer buffer bname 'clone)
5053 (error (make-indirect-buffer buffer bname)))))
5055 (defun org-set-frame-title (title)
5056 "Set the title of the current frame to the string TITLE."
5057 ;; FIXME: how to name a single frame in XEmacs???
5058 (unless (featurep 'xemacs)
5059 (modify-frame-parameters (selected-frame) (list (cons 'name title)))))
5061 ;;;; Structure editing
5063 ;;; Inserting headlines
5065 (defun org-insert-heading (&optional force-heading)
5066 "Insert a new heading or item with same depth at point.
5067 If point is in a plain list and FORCE-HEADING is nil, create a new list item.
5068 If point is at the beginning of a headline, insert a sibling before the
5069 current headline. If point is in the middle of a headline, split the headline
5070 at that position and make the rest of the headline part of the sibling below
5071 the current headline."
5072 (interactive "P")
5073 (if (= (buffer-size) 0)
5074 (insert "\n* ")
5075 (when (or force-heading (not (org-insert-item)))
5076 (let* ((head (save-excursion
5077 (condition-case nil
5078 (progn
5079 (org-back-to-heading)
5080 (match-string 0))
5081 (error "*"))))
5082 (blank (cdr (assq 'heading org-blank-before-new-entry)))
5083 pos)
5084 (cond
5085 ((and (org-on-heading-p) (bolp)
5086 (or (bobp)
5087 (save-excursion (backward-char 1) (not (org-invisible-p)))))
5088 (open-line (if blank 2 1)))
5089 ((and (bolp)
5090 (or (bobp)
5091 (save-excursion
5092 (backward-char 1) (not (org-invisible-p)))))
5093 nil)
5094 (t (newline (if blank 2 1))))
5095 (insert head) (just-one-space)
5096 (setq pos (point))
5097 (end-of-line 1)
5098 (unless (= (point) pos) (just-one-space) (backward-delete-char 1))
5099 (run-hooks 'org-insert-heading-hook)))))
5102 (defun org-insert-todo-heading (arg)
5103 "Insert a new heading with the same level and TODO state as current heading.
5104 If the heading has no TODO state, or if the state is DONE, use the first
5105 state (TODO by default). Also with prefix arg, force first state."
5106 (interactive "P")
5107 (when (not (org-insert-item 'checkbox))
5108 (org-insert-heading)
5109 (save-excursion
5110 (org-back-to-heading)
5111 (outline-previous-heading)
5112 (looking-at org-todo-line-regexp))
5113 (if (or arg
5114 (not (match-beginning 2))
5115 (member (match-string 2) org-done-keywords))
5116 (insert (car org-todo-keywords-1) " ")
5117 (insert (match-string 2) " "))))
5119 ;;; Promotion and Demotion
5121 (defun org-promote-subtree ()
5122 "Promote the entire subtree.
5123 See also `org-promote'."
5124 (interactive)
5125 (save-excursion
5126 (org-map-tree 'org-promote))
5127 (org-fix-position-after-promote))
5129 (defun org-demote-subtree ()
5130 "Demote the entire subtree. See `org-demote'.
5131 See also `org-promote'."
5132 (interactive)
5133 (save-excursion
5134 (org-map-tree 'org-demote))
5135 (org-fix-position-after-promote))
5138 (defun org-do-promote ()
5139 "Promote the current heading higher up the tree.
5140 If the region is active in `transient-mark-mode', promote all headings
5141 in the region."
5142 (interactive)
5143 (save-excursion
5144 (if (org-region-active-p)
5145 (org-map-region 'org-promote (region-beginning) (region-end))
5146 (org-promote)))
5147 (org-fix-position-after-promote))
5149 (defun org-do-demote ()
5150 "Demote the current heading lower down the tree.
5151 If the region is active in `transient-mark-mode', demote all headings
5152 in the region."
5153 (interactive)
5154 (save-excursion
5155 (if (org-region-active-p)
5156 (org-map-region 'org-demote (region-beginning) (region-end))
5157 (org-demote)))
5158 (org-fix-position-after-promote))
5160 (defun org-fix-position-after-promote ()
5161 "Make sure that after pro/demotion cursor position is right."
5162 (let ((pos (point)))
5163 (when (save-excursion
5164 (beginning-of-line 1)
5165 (looking-at org-todo-line-regexp)
5166 (or (equal pos (match-end 1)) (equal pos (match-end 2))))
5167 (cond ((eobp) (insert " "))
5168 ((eolp) (insert " "))
5169 ((equal (char-after) ?\ ) (forward-char 1))))))
5171 (defun org-reduced-level (l)
5172 (if org-odd-levels-only (1+ (floor (/ l 2))) l))
5174 (defun org-get-legal-level (level &optional change)
5175 "Rectify a level change under the influence of `org-odd-levels-only'
5176 LEVEL is a current level, CHANGE is by how much the level should be
5177 modified. Even if CHANGE is nil, LEVEL may be returned modified because
5178 even level numbers will become the next higher odd number."
5179 (if org-odd-levels-only
5180 (cond ((or (not change) (= 0 change)) (1+ (* 2 (/ level 2))))
5181 ((> change 0) (1+ (* 2 (/ (+ level (* 2 change)) 2))))
5182 ((< change 0) (max 1 (1+ (* 2 (/ (+ level (* 2 change)) 2))))))
5183 (max 1 (+ level change))))
5185 (defun org-promote ()
5186 "Promote the current heading higher up the tree.
5187 If the region is active in `transient-mark-mode', promote all headings
5188 in the region."
5189 (org-back-to-heading t)
5190 (let* ((level (save-match-data (funcall outline-level)))
5191 (up-head (concat (make-string (org-get-legal-level level -1) ?*) " "))
5192 (diff (abs (- level (length up-head) -1))))
5193 (if (= level 1) (error "Cannot promote to level 0. UNDO to recover if necessary"))
5194 (replace-match up-head nil t)
5195 ;; Fixup tag positioning
5196 (and org-auto-align-tags (org-set-tags nil t))
5197 (if org-adapt-indentation (org-fixup-indentation (- diff)))))
5199 (defun org-demote ()
5200 "Demote the current heading lower down the tree.
5201 If the region is active in `transient-mark-mode', demote all headings
5202 in the region."
5203 (org-back-to-heading t)
5204 (let* ((level (save-match-data (funcall outline-level)))
5205 (down-head (concat (make-string (org-get-legal-level level 1) ?*) " "))
5206 (diff (abs (- level (length down-head) -1))))
5207 (replace-match down-head nil t)
5208 ;; Fixup tag positioning
5209 (and org-auto-align-tags (org-set-tags nil t))
5210 (if org-adapt-indentation (org-fixup-indentation diff))))
5212 (defun org-map-tree (fun)
5213 "Call FUN for every heading underneath the current one."
5214 (org-back-to-heading)
5215 (let ((level (funcall outline-level)))
5216 (save-excursion
5217 (funcall fun)
5218 (while (and (progn
5219 (outline-next-heading)
5220 (> (funcall outline-level) level))
5221 (not (eobp)))
5222 (funcall fun)))))
5224 (defun org-map-region (fun beg end)
5225 "Call FUN for every heading between BEG and END."
5226 (let ((org-ignore-region t))
5227 (save-excursion
5228 (setq end (copy-marker end))
5229 (goto-char beg)
5230 (if (and (re-search-forward (concat "^" outline-regexp) nil t)
5231 (< (point) end))
5232 (funcall fun))
5233 (while (and (progn
5234 (outline-next-heading)
5235 (< (point) end))
5236 (not (eobp)))
5237 (funcall fun)))))
5239 (defun org-fixup-indentation (diff)
5240 "Change the indentation in the current entry by DIFF
5241 However, if any line in the current entry has no indentation, or if it
5242 would end up with no indentation after the change, nothing at all is done."
5243 (save-excursion
5244 (let ((end (save-excursion (outline-next-heading)
5245 (point-marker)))
5246 (prohibit (if (> diff 0)
5247 "^\\S-"
5248 (concat "^ \\{0," (int-to-string (- diff)) "\\}\\S-")))
5249 col)
5250 (unless (save-excursion (re-search-forward prohibit end t))
5251 (while (re-search-forward "^[ \t]+" end t)
5252 (goto-char (match-end 0))
5253 (setq col (current-column))
5254 (if (< diff 0) (replace-match ""))
5255 (indent-to (+ diff col))))
5256 (move-marker end nil))))
5258 (defun org-convert-to-odd-levels ()
5259 "Convert an org-mode file with all levels allowed to one with odd levels.
5260 This will leave level 1 alone, convert level 2 to level 3, level 3 to
5261 level 5 etc."
5262 (interactive)
5263 (when (yes-or-no-p "Are you sure you want to globally change levels to odd? ")
5264 (let ((org-odd-levels-only nil) n)
5265 (save-excursion
5266 (goto-char (point-min))
5267 (while (re-search-forward "^\\*\\*+ " nil t)
5268 (setq n (- (length (match-string 0)) 2))
5269 (while (>= (setq n (1- n)) 0)
5270 (org-demote))
5271 (end-of-line 1))))))
5274 (defun org-convert-to-oddeven-levels ()
5275 "Convert an org-mode file with only odd levels to one with odd and even levels.
5276 This promotes level 3 to level 2, level 5 to level 3 etc. If the file contains a
5277 section with an even level, conversion would destroy the structure of the file. An error
5278 is signaled in this case."
5279 (interactive)
5280 (goto-char (point-min))
5281 ;; First check if there are no even levels
5282 (when (re-search-forward "^\\(\\*\\*\\)+ " nil t)
5283 (org-show-context t)
5284 (error "Not all levels are odd in this file. Conversion not possible."))
5285 (when (yes-or-no-p "Are you sure you want to globally change levels to odd-even? ")
5286 (let ((org-odd-levels-only nil) n)
5287 (save-excursion
5288 (goto-char (point-min))
5289 (while (re-search-forward "^\\*\\*+ " nil t)
5290 (setq n (/ (length (1- (match-string 0))) 2))
5291 (while (>= (setq n (1- n)) 0)
5292 (org-promote))
5293 (end-of-line 1))))))
5295 (defun org-tr-level (n)
5296 "Make N odd if required."
5297 (if org-odd-levels-only (1+ (/ n 2)) n))
5299 ;;; Vertical tree motion, cutting and pasting of subtrees
5301 (defun org-move-subtree-up (&optional arg)
5302 "Move the current subtree up past ARG headlines of the same level."
5303 (interactive "p")
5304 (org-move-subtree-down (- (prefix-numeric-value arg))))
5306 (defun org-move-subtree-down (&optional arg)
5307 "Move the current subtree down past ARG headlines of the same level."
5308 (interactive "p")
5309 (setq arg (prefix-numeric-value arg))
5310 (let ((movfunc (if (> arg 0) 'outline-get-next-sibling
5311 'outline-get-last-sibling))
5312 (ins-point (make-marker))
5313 (cnt (abs arg))
5314 beg end txt folded)
5315 ;; Select the tree
5316 (org-back-to-heading)
5317 (setq beg (point))
5318 (save-match-data
5319 (save-excursion (outline-end-of-heading)
5320 (setq folded (org-invisible-p)))
5321 (outline-end-of-subtree))
5322 (outline-next-heading)
5323 (setq end (point))
5324 ;; Find insertion point, with error handling
5325 (goto-char beg)
5326 (while (> cnt 0)
5327 (or (and (funcall movfunc) (looking-at outline-regexp))
5328 (progn (goto-char beg)
5329 (error "Cannot move past superior level or buffer limit")))
5330 (setq cnt (1- cnt)))
5331 (if (> arg 0)
5332 ;; Moving forward - still need to move over subtree
5333 (progn (outline-end-of-subtree)
5334 (outline-next-heading)
5335 (if (not (or (looking-at (concat "^" outline-regexp))
5336 (bolp)))
5337 (newline))))
5338 (move-marker ins-point (point))
5339 (setq txt (buffer-substring beg end))
5340 (delete-region beg end)
5341 (insert txt)
5342 (or (bolp) (insert "\n"))
5343 (goto-char ins-point)
5344 (if folded (hide-subtree))
5345 (move-marker ins-point nil)))
5347 (defvar org-subtree-clip ""
5348 "Clipboard for cut and paste of subtrees.
5349 This is actually only a copy of the kill, because we use the normal kill
5350 ring. We need it to check if the kill was created by `org-copy-subtree'.")
5352 (defvar org-subtree-clip-folded nil
5353 "Was the last copied subtree folded?
5354 This is used to fold the tree back after pasting.")
5356 (defun org-cut-subtree ()
5357 "Cut the current subtree into the clipboard.
5358 This is a short-hand for marking the subtree and then cutting it."
5359 (interactive)
5360 (org-copy-subtree 'cut))
5362 (defun org-copy-subtree (&optional cut)
5363 "Cut the current subtree into the clipboard.
5364 This is a short-hand for marking the subtree and then copying it.
5365 If CUT is non-nil, actually cut the subtree."
5366 (interactive)
5367 (let (beg end folded)
5368 (if (interactive-p)
5369 (org-back-to-heading nil) ; take what looks like a subtree
5370 (org-back-to-heading t)) ; take what is really there
5371 (setq beg (point))
5372 (save-match-data
5373 (save-excursion (outline-end-of-heading)
5374 (setq folded (org-invisible-p)))
5375 (outline-end-of-subtree))
5376 (if (equal (char-after) ?\n) (forward-char 1))
5377 (setq end (point))
5378 (goto-char beg)
5379 (when (> end beg)
5380 (setq org-subtree-clip-folded folded)
5381 (if cut (kill-region beg end) (copy-region-as-kill beg end))
5382 (setq org-subtree-clip (current-kill 0))
5383 (message "%s: Subtree with %d characters"
5384 (if cut "Cut" "Copied")
5385 (length org-subtree-clip)))))
5387 (defun org-paste-subtree (&optional level tree)
5388 "Paste the clipboard as a subtree, with modification of headline level.
5389 The entire subtree is promoted or demoted in order to match a new headline
5390 level. By default, the new level is derived from the visible headings
5391 before and after the insertion point, and taken to be the inferior headline
5392 level of the two. So if the previous visible heading is level 3 and the
5393 next is level 4 (or vice versa), level 4 will be used for insertion.
5394 This makes sure that the subtree remains an independent subtree and does
5395 not swallow low level entries.
5397 You can also force a different level, either by using a numeric prefix
5398 argument, or by inserting the heading marker by hand. For example, if the
5399 cursor is after \"*****\", then the tree will be shifted to level 5.
5401 If you want to insert the tree as is, just use \\[yank].
5403 If optional TREE is given, use this text instead of the kill ring."
5404 (interactive "P")
5405 (unless (org-kill-is-subtree-p tree)
5406 (error
5407 (substitute-command-keys
5408 "The kill is not a (set of) tree(s) - please use \\[yank] to yank anyway")))
5409 (let* ((txt (or tree (and kill-ring (current-kill 0))))
5410 (^re (concat "^\\(" outline-regexp "\\)"))
5411 (re (concat "\\(" outline-regexp "\\)"))
5412 (^re_ (concat "\\(" outline-regexp "\\)[ \t]*"))
5414 (old-level (if (string-match ^re txt)
5415 (- (match-end 0) (match-beginning 0))
5416 -1))
5417 (force-level (cond (level (prefix-numeric-value level))
5418 ((string-match
5419 ^re_ (buffer-substring (point-at-bol) (point)))
5420 (- (match-end 0) (match-beginning 0)))
5421 (t nil)))
5422 (previous-level (save-excursion
5423 (condition-case nil
5424 (progn
5425 (outline-previous-visible-heading 1)
5426 (if (looking-at re)
5427 (- (match-end 0) (match-beginning 0))
5429 (error 1))))
5430 (next-level (save-excursion
5431 (condition-case nil
5432 (progn
5433 (outline-next-visible-heading 1)
5434 (if (looking-at re)
5435 (- (match-end 0) (match-beginning 0))
5437 (error 1))))
5438 (new-level (or force-level (max previous-level next-level)))
5439 (shift (if (or (= old-level -1)
5440 (= new-level -1)
5441 (= old-level new-level))
5443 (- new-level old-level)))
5444 (shift1 shift)
5445 (delta (if (> shift 0) -1 1))
5446 (func (if (> shift 0) 'org-demote 'org-promote))
5447 (org-odd-levels-only nil)
5448 beg end)
5449 ;; Remove the forces level indicator
5450 (if force-level
5451 (delete-region (point-at-bol) (point)))
5452 ;; Make sure we start at the beginning of an empty line
5453 (if (not (bolp)) (insert "\n"))
5454 (if (not (looking-at "[ \t]*$"))
5455 (progn (insert "\n") (backward-char 1)))
5456 ;; Paste
5457 (setq beg (point))
5458 (if (string-match "[ \t\r\n]+\\'" txt)
5459 (setq txt (replace-match "\n" t t txt)))
5460 (insert txt)
5461 (setq end (point))
5462 (if (looking-at "[ \t\r\n]+")
5463 (replace-match "\n"))
5464 (goto-char beg)
5465 ;; Shift if necessary
5466 (if (= shift 0)
5467 (message "Pasted at level %d, without shift" new-level)
5468 (save-restriction
5469 (narrow-to-region beg end)
5470 (while (not (= shift 0))
5471 (org-map-region func (point-min) (point-max))
5472 (setq shift (+ delta shift)))
5473 (goto-char (point-min))
5474 (message "Pasted at level %d, with shift by %d levels"
5475 new-level shift1)))
5476 (if (and kill-ring
5477 (eq org-subtree-clip (current-kill 0))
5478 org-subtree-clip-folded)
5479 ;; The tree was folded before it was killed/copied
5480 (hide-subtree))))
5482 (defun org-kill-is-subtree-p (&optional txt)
5483 "Check if the current kill is an outline subtree, or a set of trees.
5484 Returns nil if kill does not start with a headline, or if the first
5485 headline level is not the largest headline level in the tree.
5486 So this will actually accept several entries of equal levels as well,
5487 which is OK for `org-paste-subtree'.
5488 If optional TXT is given, check this string instead of the current kill."
5489 (let* ((kill (or txt (and kill-ring (current-kill 0)) ""))
5490 (start-level (and kill
5491 (string-match (concat "\\`" outline-regexp) kill)
5492 (- (match-end 0) (match-beginning 0))))
5493 (re (concat "^" outline-regexp))
5494 (start 1))
5495 (if (not start-level)
5496 nil ;; does not even start with a heading
5497 (catch 'exit
5498 (while (setq start (string-match re kill (1+ start)))
5499 (if (< (- (match-end 0) (match-beginning 0)) start-level)
5500 (throw 'exit nil)))
5501 t))))
5503 (defun org-narrow-to-subtree ()
5504 "Narrow buffer to the current subtree."
5505 (interactive)
5506 (save-excursion
5507 (narrow-to-region
5508 (progn (org-back-to-heading) (point))
5509 (progn (org-end-of-subtree t t) (point)))))
5512 ;;; Outline Sorting
5514 (defun org-sort (with-case)
5515 "Call `org-sort-entries' or `org-table-sort-lines', depending on context."
5516 (interactive "P")
5517 (if (org-at-table-p)
5518 (org-call-with-arg 'org-table-sort-lines with-case)
5519 (org-call-with-arg 'org-sort-entries with-case)))
5521 (defun org-sort-entries (&optional with-case sorting-type)
5522 "Sort entries on a certain level of an outline tree.
5523 If there is an active region, the entries in the region are sorted.
5524 Else, if the cursor is before the first entry, sort the top-level items.
5525 Else, the children of the entry at point are sorted.
5527 Sorting can be alphabetically, numerically, and by date/time as given by
5528 the first time stamp in the entry. The command prompts for the sorting
5529 type unless it has been given to the function through the SORTING-TYPE
5530 argument, which needs to a character, any of (?n ?N ?a ?A ?t ?T).
5532 Comparing entries ignores case by default. However, with an optional argument
5533 WITH-CASE, the sorting considers case as well. With two prefix arguments
5534 `C-u C-u', sorting is case-sensitive and duplicate entries will be removed."
5535 (interactive "P")
5536 (let ((unique (equal with-case '(16)))
5537 start beg end entries stars re re2 p nentries (nremoved 0)
5538 last txt what)
5539 ;; Find beginning and end of region to sort
5540 (cond
5541 ((org-region-active-p)
5542 ;; we will sort the region
5543 (setq end (region-end)
5544 what "region")
5545 (goto-char (region-beginning))
5546 (if (not (org-on-heading-p)) (outline-next-heading))
5547 (setq start (point)))
5548 ((or (org-on-heading-p)
5549 (condition-case nil (progn (org-back-to-heading) t) (error nil)))
5550 ;; we will sort the children of the current headline
5551 (org-back-to-heading)
5552 (setq start (point) end (org-end-of-subtree) what "children")
5553 (goto-char start)
5554 (show-subtree)
5555 (outline-next-heading))
5557 ;; we will sort the top-level entries in this file
5558 (goto-char (point-min))
5559 (or (org-on-heading-p) (outline-next-heading))
5560 (setq start (point) end (point-max) what "top-level")
5561 (goto-char start)
5562 (show-all)))
5563 (setq beg (point))
5564 (if (>= (point) end) (error "Nothing to sort"))
5565 (looking-at "\\(\\*+\\)")
5566 (setq stars (match-string 1)
5567 re (concat "^" (regexp-quote stars) " +")
5568 re2 (concat "^" (regexp-quote (substring stars 0 -1)) "[^*]")
5569 txt (buffer-substring beg end))
5570 (if (not (equal (substring txt -1) "\n")) (setq txt (concat txt "\n")))
5571 (if (and (not (equal stars "*")) (string-match re2 txt))
5572 (error "Region to sort contains a level above the first entry"))
5573 ;; Make a list that can be sorted.
5574 ;; The car is the string for comparison, the cdr is the subtree
5575 (message "Sorting entries...")
5576 (setq entries
5577 (mapcar
5578 (lambda (x)
5579 (string-match "^.*\\(\n.*\\)?" x) ; take two lines
5580 (cons (match-string 0 x) x))
5581 (org-split-string txt re)))
5583 ;; Sort the list
5584 (save-excursion
5585 (goto-char start)
5586 (setq entries (org-do-sort entries what with-case sorting-type)))
5588 ;; Delete the old stuff
5589 (goto-char beg)
5590 (kill-region beg end)
5591 (setq nentries (length entries))
5592 ;; Insert the sorted entries, and remove duplicates if this is required
5593 (while (setq p (pop entries))
5594 (if (and unique (equal last (setq last (org-trim (cdr p)))))
5595 (setq nremoved (1+ nremoved)) ; same entry as before, skip it
5596 (insert stars " " (cdr p))))
5597 (goto-char start)
5598 (message "Sorting entries...done (%d entries%s)"
5599 nentries
5600 (if unique (format ", %d duplicates removed" nremoved) ""))))
5602 (defun org-do-sort (table what &optional with-case sorting-type)
5603 "Sort TABLE of WHAT according to SORTING-TYPE.
5604 The user will be prompted for the SORTING-TYPE if the call to this
5605 function does not specify it. WHAT is only for the prompt, to indicate
5606 what is being sorted. The sorting key will be extracted from
5607 the car of the elements of the table.
5608 If WITH-CASE is non-nil, the sorting will be case-sensitive."
5609 (unless sorting-type
5610 (message
5611 "Sort %s: [a]lphabetically [n]umerically [t]ime. A/N/T means reversed:"
5612 what)
5613 (setq sorting-type (read-char-exclusive)))
5614 (let ((dcst (downcase sorting-type))
5615 extractfun comparefun)
5616 ;; Define the appropriate functions
5617 (cond
5618 ((= dcst ?n)
5619 (setq extractfun 'string-to-number
5620 comparefun (if (= dcst sorting-type) '< '>)))
5621 ((= dcst ?a)
5622 (setq extractfun (if with-case 'identity 'downcase)
5623 comparefun (if (= dcst sorting-type)
5624 'string<
5625 (lambda (a b) (and (not (string< a b))
5626 (not (string= a b)))))))
5627 ((= dcst ?t)
5628 (setq extractfun
5629 (lambda (x)
5630 (if (string-match org-ts-regexp x)
5631 (time-to-seconds
5632 (org-time-string-to-time (match-string 0 x)))
5634 comparefun (if (= dcst sorting-type) '< '>)))
5635 (t (error "Invalid sorting type `%c'" sorting-type)))
5637 (sort (mapcar (lambda (x) (cons (funcall extractfun (car x)) (cdr x)))
5638 table)
5639 (lambda (a b) (funcall comparefun (car a) (car b))))))
5641 ;;;; Plain list items, including checkboxes
5643 ;;; Plain list items
5645 (defun org-at-item-p ()
5646 "Is point in a line starting a hand-formatted item?"
5647 (let ((llt org-plain-list-ordered-item-terminator))
5648 (save-excursion
5649 (goto-char (point-at-bol))
5650 (looking-at
5651 (cond
5652 ((eq llt t) "\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5653 ((= llt ?.) "\\([ \t]*\\([-+]\\|\\([0-9]+\\.\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5654 ((= llt ?\)) "\\([ \t]*\\([-+]\\|\\([0-9]+)\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)")
5655 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))))))
5657 (defun org-in-item-p ()
5658 "It the cursor inside a plain list item.
5659 Does not have to be the first line."
5660 (save-excursion
5661 (condition-case nil
5662 (progn
5663 (org-beginning-of-item)
5664 (org-at-item-p)
5666 (error nil))))
5668 (defun org-insert-item (&optional checkbox)
5669 "Insert a new item at the current level.
5670 Return t when things worked, nil when we are not in an item."
5671 (when (save-excursion
5672 (condition-case nil
5673 (progn
5674 (org-beginning-of-item)
5675 (org-at-item-p)
5676 (if (org-invisible-p) (error "Invisible item"))
5678 (error nil)))
5679 (let* ((bul (match-string 0))
5680 (eow (save-excursion (beginning-of-line 1) (looking-at "[ \t]*")
5681 (match-end 0)))
5682 (blank (cdr (assq 'plain-list-item org-blank-before-new-entry)))
5683 pos)
5684 (cond
5685 ((and (org-at-item-p) (<= (point) eow))
5686 ;; before the bullet
5687 (beginning-of-line 1)
5688 (open-line (if blank 2 1)))
5689 ((<= (point) eow)
5690 (beginning-of-line 1))
5691 (t (newline (if blank 2 1))))
5692 (insert bul (if checkbox "[ ]" ""))
5693 (just-one-space)
5694 (setq pos (point))
5695 (end-of-line 1)
5696 (unless (= (point) pos) (just-one-space) (backward-delete-char 1)))
5697 (org-maybe-renumber-ordered-list)
5698 (and checkbox (org-update-checkbox-count-maybe))
5701 ;;; Checkboxes
5703 (defun org-at-item-checkbox-p ()
5704 "Is point at a line starting a plain-list item with a checklet?"
5705 (and (org-at-item-p)
5706 (save-excursion
5707 (goto-char (match-end 0))
5708 (skip-chars-forward " \t")
5709 (looking-at "\\[[ X]\\]"))))
5711 (defun org-toggle-checkbox (&optional arg)
5712 "Toggle the checkbox in the current line."
5713 (interactive "P")
5714 (catch 'exit
5715 (let (beg end status (firstnew 'unknown))
5716 (cond
5717 ((org-region-active-p)
5718 (setq beg (region-beginning) end (region-end)))
5719 ((org-on-heading-p)
5720 (setq beg (point) end (save-excursion (outline-next-heading) (point))))
5721 ((org-at-item-checkbox-p)
5722 (save-excursion
5723 (replace-match (if (equal (match-string 0) "[ ]") "[X]" "[ ]") t t))
5724 (throw 'exit t))
5725 (t (error "Not at a checkbox or heading, and no active region")))
5726 (save-excursion
5727 (goto-char beg)
5728 (while (< (point) end)
5729 (when (org-at-item-checkbox-p)
5730 (setq status (equal (match-string 0) "[X]"))
5731 (when (eq firstnew 'unknown)
5732 (setq firstnew (not status)))
5733 (replace-match
5734 (if (if arg (not status) firstnew) "[X]" "[ ]") t t))
5735 (beginning-of-line 2)))))
5736 (org-update-checkbox-count-maybe))
5738 (defun org-update-checkbox-count-maybe ()
5739 "Update checkbox statistics unless turned off by user."
5740 (when org-provide-checkbox-statistics
5741 (org-update-checkbox-count)))
5743 (defun org-update-checkbox-count (&optional all)
5744 "Update the checkbox statistics in the current section.
5745 This will find all statistic cookies like [57%] and [6/12] and update them
5746 with the current numbers. With optional prefix argument ALL, do this for
5747 the whole buffer."
5748 (interactive "P")
5749 (save-excursion
5750 (let* ((buffer-invisibility-spec (org-inhibit-invisibility)) ; Emacs 21
5751 (beg (condition-case nil
5752 (progn (outline-back-to-heading) (point))
5753 (error (point-min))))
5754 (end (move-marker (make-marker)
5755 (progn (outline-next-heading) (point))))
5756 (re "\\(\\[[0-9]*%\\]\\)\\|\\(\\[[0-9]*/[0-9]*\\]\\)")
5757 (re-box "^[ \t]*\\([-+*]\\|[0-9]+[.)]\\) +\\(\\[[ X]\\]\\)")
5758 b1 e1 f1 c-on c-off lim (cstat 0))
5759 (when all
5760 (goto-char (point-min))
5761 (outline-next-heading)
5762 (setq beg (point) end (point-max)))
5763 (goto-char beg)
5764 (while (re-search-forward re end t)
5765 (setq cstat (1+ cstat)
5766 b1 (match-beginning 0)
5767 e1 (match-end 0)
5768 f1 (match-beginning 1)
5769 lim (cond
5770 ((org-on-heading-p) (outline-next-heading) (point))
5771 ((org-at-item-p) (org-end-of-item) (point))
5772 (t nil))
5773 c-on 0 c-off 0)
5774 (goto-char e1)
5775 (when lim
5776 (while (re-search-forward re-box lim t)
5777 (if (equal (match-string 2) "[ ]")
5778 (setq c-off (1+ c-off))
5779 (setq c-on (1+ c-on))))
5780 (delete-region b1 e1)
5781 (goto-char b1)
5782 (insert (if f1
5783 (format "[%d%%]" (/ (* 100 c-on) (max 1 (+ c-on c-off))))
5784 (format "[%d/%d]" c-on (+ c-on c-off))))))
5785 (when (interactive-p)
5786 (message "Checkbox satistics updated %s (%d places)"
5787 (if all "in entire file" "in current outline entry") cstat)))))
5789 (defun org-get-checkbox-statistics-face ()
5790 "Select the face for checkbox statistics.
5791 The face will be `org-done' when all relevant boxes are checked. Otherwise
5792 it will be `org-todo'."
5793 (if (match-end 1)
5794 (if (equal (match-string 1) "100%") 'org-done 'org-todo)
5795 (if (and (> (match-end 2) (match-beginning 2))
5796 (equal (match-string 2) (match-string 3)))
5797 'org-done
5798 'org-todo)))
5800 (defun org-get-indentation (&optional line)
5801 "Get the indentation of the current line, interpreting tabs.
5802 When LINE is given, assume it represents a line and compute its indentation."
5803 (if line
5804 (if (string-match "^ *" (org-remove-tabs line))
5805 (match-end 0))
5806 (save-excursion
5807 (beginning-of-line 1)
5808 (skip-chars-forward " \t")
5809 (current-column))))
5811 (defun org-remove-tabs (s &optional width)
5812 "Replace tabulators in S with spaces.
5813 Assumes that s is a single line, starting in column 0."
5814 (setq width (or width tab-width))
5815 (while (string-match "\t" s)
5816 (setq s (replace-match
5817 (make-string
5818 (- (* width (/ (+ (match-beginning 0) width) width))
5819 (match-beginning 0)) ?\ )
5820 t t s)))
5823 (defun org-fix-indentation (line ind)
5824 "Fix indentation in LINE.
5825 IND is a cons cell with target and minimum indentation.
5826 If the current indenation in LINE is smaller than the minimum,
5827 leave it alone. If it is larger than ind, set it to the target."
5828 (let* ((l (org-remove-tabs line))
5829 (i (org-get-indentation l))
5830 (i1 (car ind)) (i2 (cdr ind)))
5831 (if (>= i i2) (setq l (substring line i2)))
5832 (if (> i1 0)
5833 (concat (make-string i1 ?\ ) l)
5834 l)))
5836 (defcustom org-empty-line-terminates-plain-lists nil
5837 "Non-nil means, an empty line ends all plain list levels.
5838 When nil, empty lines are part of the preceeding item."
5839 :group 'org-plain-lists
5840 :type 'boolean)
5842 (defun org-beginning-of-item ()
5843 "Go to the beginning of the current hand-formatted item.
5844 If the cursor is not in an item, throw an error."
5845 (interactive)
5846 (let ((pos (point))
5847 (limit (save-excursion
5848 (condition-case nil
5849 (progn
5850 (org-back-to-heading)
5851 (beginning-of-line 2) (point))
5852 (error (point-min)))))
5853 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
5854 ind ind1)
5855 (if (org-at-item-p)
5856 (beginning-of-line 1)
5857 (beginning-of-line 1)
5858 (skip-chars-forward " \t")
5859 (setq ind (current-column))
5860 (if (catch 'exit
5861 (while t
5862 (beginning-of-line 0)
5863 (if (or (bobp) (< (point) limit)) (throw 'exit nil))
5865 (if (looking-at "[ \t]*$")
5866 (setq ind1 ind-empty)
5867 (skip-chars-forward " \t")
5868 (setq ind1 (current-column)))
5869 (if (< ind1 ind)
5870 (progn (beginning-of-line 1) (throw 'exit (org-at-item-p))))))
5872 (goto-char pos)
5873 (error "Not in an item")))))
5875 (defun org-end-of-item ()
5876 "Go to the end of the current hand-formatted item.
5877 If the cursor is not in an item, throw an error."
5878 (interactive)
5879 (let* ((pos (point))
5880 ind1
5881 (ind-empty (if org-empty-line-terminates-plain-lists 0 10000))
5882 (limit (save-excursion (outline-next-heading) (point)))
5883 (ind (save-excursion
5884 (org-beginning-of-item)
5885 (skip-chars-forward " \t")
5886 (current-column)))
5887 (end (catch 'exit
5888 (while t
5889 (beginning-of-line 2)
5890 (if (eobp) (throw 'exit (point)))
5891 (if (>= (point) limit) (throw 'exit (point-at-bol)))
5892 (if (looking-at "[ \t]*$")
5893 (setq ind1 ind-empty)
5894 (skip-chars-forward " \t")
5895 (setq ind1 (current-column)))
5896 (if (<= ind1 ind)
5897 (throw 'exit (point-at-bol)))))))
5898 (if end
5899 (goto-char end)
5900 (goto-char pos)
5901 (error "Not in an item"))))
5903 (defun org-next-item ()
5904 "Move to the beginning of the next item in the current plain list.
5905 Error if not at a plain list, or if this is the last item in the list."
5906 (interactive)
5907 (let (ind ind1 (pos (point)))
5908 (org-beginning-of-item)
5909 (setq ind (org-get-indentation))
5910 (org-end-of-item)
5911 (setq ind1 (org-get-indentation))
5912 (unless (and (org-at-item-p) (= ind ind1))
5913 (goto-char pos)
5914 (error "On last item"))))
5916 (defun org-previous-item ()
5917 "Move to the beginning of the previous item in the current plain list.
5918 Error if not at a plain list, or if this is the first item in the list."
5919 (interactive)
5920 (let (beg ind ind1 (pos (point)))
5921 (org-beginning-of-item)
5922 (setq beg (point))
5923 (setq ind (org-get-indentation))
5924 (goto-char beg)
5925 (catch 'exit
5926 (while t
5927 (beginning-of-line 0)
5928 (if (looking-at "[ \t]*$")
5930 (if (<= (setq ind1 (org-get-indentation)) ind)
5931 (throw 'exit t)))))
5932 (condition-case nil
5933 (if (or (not (org-at-item-p))
5934 (< ind1 (1- ind)))
5935 (error "")
5936 (org-beginning-of-item))
5937 (error (goto-char pos)
5938 (error "On first item")))))
5940 (defun org-move-item-down ()
5941 "Move the plain list item at point down, i.e. swap with following item.
5942 Subitems (items with larger indentation) are considered part of the item,
5943 so this really moves item trees."
5944 (interactive)
5945 (let (beg end ind ind1 (pos (point)) txt)
5946 (org-beginning-of-item)
5947 (setq beg (point))
5948 (setq ind (org-get-indentation))
5949 (org-end-of-item)
5950 (setq end (point))
5951 (setq ind1 (org-get-indentation))
5952 (if (and (org-at-item-p) (= ind ind1))
5953 (progn
5954 (org-end-of-item)
5955 (setq txt (buffer-substring beg end))
5956 (save-excursion
5957 (delete-region beg end))
5958 (setq pos (point))
5959 (insert txt)
5960 (goto-char pos)
5961 (org-maybe-renumber-ordered-list))
5962 (goto-char pos)
5963 (error "Cannot move this item further down"))))
5965 (defun org-move-item-up (arg)
5966 "Move the plain list item at point up, i.e. swap with previous item.
5967 Subitems (items with larger indentation) are considered part of the item,
5968 so this really moves item trees."
5969 (interactive "p")
5970 (let (beg end ind ind1 (pos (point)) txt)
5971 (org-beginning-of-item)
5972 (setq beg (point))
5973 (setq ind (org-get-indentation))
5974 (org-end-of-item)
5975 (setq end (point))
5976 (goto-char beg)
5977 (catch 'exit
5978 (while t
5979 (beginning-of-line 0)
5980 (if (looking-at "[ \t]*$")
5981 (if org-empty-line-terminates-plain-lists
5982 (progn
5983 (goto-char pos)
5984 (error "Cannot move this item further up"))
5985 nil)
5986 (if (<= (setq ind1 (org-get-indentation)) ind)
5987 (throw 'exit t)))))
5988 (condition-case nil
5989 (org-beginning-of-item)
5990 (error (goto-char beg)
5991 (error "Cannot move this item further up")))
5992 (setq ind1 (org-get-indentation))
5993 (if (and (org-at-item-p) (= ind ind1))
5994 (progn
5995 (setq txt (buffer-substring beg end))
5996 (save-excursion
5997 (delete-region beg end))
5998 (setq pos (point))
5999 (insert txt)
6000 (goto-char pos)
6001 (org-maybe-renumber-ordered-list))
6002 (goto-char pos)
6003 (error "Cannot move this item further up"))))
6005 (defun org-maybe-renumber-ordered-list ()
6006 "Renumber the ordered list at point if setup allows it.
6007 This tests the user option `org-auto-renumber-ordered-lists' before
6008 doing the renumbering."
6009 (interactive)
6010 (when (and org-auto-renumber-ordered-lists
6011 (org-at-item-p))
6012 (if (match-beginning 3)
6013 (org-renumber-ordered-list 1)
6014 (org-fix-bullet-type 1))))
6016 (defun org-maybe-renumber-ordered-list-safe ()
6017 (condition-case nil
6018 (save-excursion
6019 (org-maybe-renumber-ordered-list))
6020 (error nil)))
6022 (defun org-cycle-list-bullet (&optional which)
6023 "Cycle through the different itemize/enumerate bullets.
6024 This cycle the entire list level through the sequence:
6026 `-' -> `+' -> `*' -> `1.' -> `1)'
6028 If WHICH is a string, use that as the new bullet. If WHICH is an integer,
6029 0 meand `-', 1 means `+' etc."
6030 (interactive "P")
6031 (org-preserve-lc
6032 (org-beginning-of-item-list)
6033 (org-at-item-p)
6034 (beginning-of-line 1)
6035 (let ((current (match-string 0)) new)
6036 (setq new (cond
6037 ((and which (nth (1- which) '("-" "+" "*" "1." "1)"))))
6038 ((string-match "-" current) "+")
6039 ((string-match "\\+" current)
6040 (if (looking-at "\\S-") "1." "*"))
6041 ((string-match "\\*" current) "1.")
6042 ((string-match "\\." current) "1)")
6043 ((string-match ")" current) "-")
6044 (t (error "This should not happen"))))
6045 (and (looking-at "\\([ \t]*\\)\\S-+") (replace-match (concat "\\1" new)))
6046 (org-fix-bullet-type 1)
6047 (org-maybe-renumber-ordered-list))))
6049 (defun org-get-string-indentation (s)
6050 "What indentation has S due to SPACE and TAB at the beginning of the string?"
6051 (let ((n -1) (i 0) (w tab-width) c)
6052 (catch 'exit
6053 (while (< (setq n (1+ n)) (length s))
6054 (setq c (aref s n))
6055 (cond ((= c ?\ ) (setq i (1+ i)))
6056 ((= c ?\t) (setq i (* (/ (+ w i) w) w)))
6057 (t (throw 'exit t)))))
6060 (defun org-renumber-ordered-list (arg)
6061 "Renumber an ordered plain list.
6062 Cursor needs to be in the first line of an item, the line that starts
6063 with something like \"1.\" or \"2)\"."
6064 (interactive "p")
6065 (unless (and (org-at-item-p)
6066 (match-beginning 3))
6067 (error "This is not an ordered list"))
6068 (let ((line (org-current-line))
6069 (col (current-column))
6070 (ind (org-get-string-indentation
6071 (buffer-substring (point-at-bol) (match-beginning 3))))
6072 ;; (term (substring (match-string 3) -1))
6073 ind1 (n (1- arg))
6074 fmt)
6075 ;; find where this list begins
6076 (org-beginning-of-item-list)
6077 (looking-at "[ \t]*[0-9]+\\([.)]\\)")
6078 (setq fmt (concat "%d" (match-string 1)))
6079 (beginning-of-line 0)
6080 ;; walk forward and replace these numbers
6081 (catch 'exit
6082 (while t
6083 (catch 'next
6084 (beginning-of-line 2)
6085 (if (eobp) (throw 'exit nil))
6086 (if (looking-at "[ \t]*$") (throw 'next nil))
6087 (skip-chars-forward " \t") (setq ind1 (current-column))
6088 (if (> ind1 ind) (throw 'next t))
6089 (if (< ind1 ind) (throw 'exit t))
6090 (if (not (org-at-item-p)) (throw 'exit nil))
6091 (delete-region (match-beginning 2) (match-end 2))
6092 (goto-char (match-beginning 2))
6093 (insert (format fmt (setq n (1+ n)))))))
6094 (goto-line line)
6095 (move-to-column col)))
6097 (defun org-fix-bullet-type (arg)
6098 "Make sure all items in this list have the same bullet."
6099 (interactive "p")
6100 (unless (org-at-item-p) (error "This is not a list"))
6101 (let ((line (org-current-line))
6102 (col (current-column))
6103 (ind (current-indentation))
6104 ind1 bullet)
6105 ;; find where this list begins
6106 (org-beginning-of-item-list)
6107 (beginning-of-line 1)
6108 ;; find out what the bullet type is
6109 (looking-at "[ \t]*\\(\\S-+\\)")
6110 (setq bullet (match-string 1))
6111 ;; walk forward and replace these numbers
6112 (beginning-of-line 0)
6113 (catch 'exit
6114 (while t
6115 (catch 'next
6116 (beginning-of-line 2)
6117 (if (eobp) (throw 'exit nil))
6118 (if (looking-at "[ \t]*$") (throw 'next nil))
6119 (skip-chars-forward " \t") (setq ind1 (current-column))
6120 (if (> ind1 ind) (throw 'next t))
6121 (if (< ind1 ind) (throw 'exit t))
6122 (if (not (org-at-item-p)) (throw 'exit nil))
6123 (skip-chars-forward " \t")
6124 (looking-at "\\S-+")
6125 (replace-match bullet))))
6126 (goto-line line)
6127 (move-to-column col)
6128 (if (string-match "[0-9]" bullet)
6129 (org-renumber-ordered-list 1))))
6131 (defun org-beginning-of-item-list ()
6132 "Go to the beginning of the current item list.
6133 I.e. to the first item in this list."
6134 (interactive)
6135 (org-beginning-of-item)
6136 (let ((pos (point-at-bol))
6137 (ind (org-get-indentation))
6138 ind1)
6139 ;; find where this list begins
6140 (catch 'exit
6141 (while t
6142 (catch 'next
6143 (beginning-of-line 0)
6144 (if (looking-at "[ \t]*$") (throw 'next t))
6145 (skip-chars-forward " \t") (setq ind1 (current-column))
6146 (if (or (< ind1 ind)
6147 (and (= ind1 ind)
6148 (not (org-at-item-p))))
6149 (throw 'exit t)
6150 (when (org-at-item-p) (setq pos (point-at-bol)))))))
6151 (goto-char pos)))
6153 (defvar org-last-indent-begin-marker (make-marker))
6154 (defvar org-last-indent-end-marker (make-marker))
6156 (defun org-outdent-item (arg)
6157 "Outdent a local list item."
6158 (interactive "p")
6159 (org-indent-item (- arg)))
6161 (defun org-indent-item (arg)
6162 "Indent a local list item."
6163 (interactive "p")
6164 (unless (org-at-item-p)
6165 (error "Not on an item"))
6166 (save-excursion
6167 (let (beg end ind ind1 tmp delta ind-down ind-up)
6168 (if (memq last-command '(org-shiftmetaright org-shiftmetaleft))
6169 (setq beg org-last-indent-begin-marker
6170 end org-last-indent-end-marker)
6171 (org-beginning-of-item)
6172 (setq beg (move-marker org-last-indent-begin-marker (point)))
6173 (org-end-of-item)
6174 (setq end (move-marker org-last-indent-end-marker (point))))
6175 (goto-char beg)
6176 (setq tmp (org-item-indent-positions)
6177 ind (car tmp)
6178 ind-down (nth 2 tmp)
6179 ind-up (nth 1 tmp)
6180 delta (if (> arg 0)
6181 (if ind-down (- ind-down ind) (+ 2 ind))
6182 (if ind-up (- ind-up ind) (- ind 2))))
6183 (if (< (+ delta ind) 0) (error "Cannot outdent beyond margin"))
6184 (while (< (point) end)
6185 (beginning-of-line 1)
6186 (skip-chars-forward " \t") (setq ind1 (current-column))
6187 (delete-region (point-at-bol) (point))
6188 (or (eolp) (indent-to-column (+ ind1 delta)))
6189 (beginning-of-line 2))))
6190 (org-maybe-renumber-ordered-list-safe)
6191 (save-excursion
6192 (beginning-of-line 0)
6193 (condition-case nil (org-beginning-of-item) (error nil))
6194 (org-maybe-renumber-ordered-list-safe)))
6197 (defun org-item-indent-positions ()
6198 "Assumes cursor in item line. FIXME"
6199 (let* ((bolpos (point-at-bol))
6200 (ind (org-get-indentation))
6201 ind-down ind-up pos)
6202 (save-excursion
6203 (org-beginning-of-item-list)
6204 (skip-chars-backward "\n\r \t")
6205 (when (org-in-item-p)
6206 (org-beginning-of-item)
6207 (setq ind-up (org-get-indentation))))
6208 (setq pos (point))
6209 (save-excursion
6210 (cond
6211 ((and (condition-case nil (progn (org-previous-item) t)
6212 (error nil))
6213 (or (forward-char 1) t)
6214 (re-search-forward "^\\([ \t]*\\([-+]\\|\\([0-9]+[.)]\\)\\)\\|[ \t]+\\*\\)\\( \\|$\\)" bolpos t))
6215 (setq ind-down (org-get-indentation)))
6216 ((and (goto-char pos)
6217 (org-at-item-p))
6218 (goto-char (match-end 0))
6219 (skip-chars-forward " \t")
6220 (setq ind-down (current-column)))))
6221 (list ind ind-up ind-down)))
6223 ;;; The orgstruct minor mode
6225 ;; Define a minor mode which can be used in other modes in order to
6226 ;; integrate the org-mode structure editing commands.
6228 ;; This is really a hack, because the org-mode structure commands use
6229 ;; keys which normally belong to the major mode. Here is how it
6230 ;; works: The minor mode defines all the keys necessary to operate the
6231 ;; structure commands, but wraps the commands into a function which
6232 ;; tests if the cursor is currently at a headline or a plain list
6233 ;; item. If that is the case, the structure command is used,
6234 ;; temporarily setting many Org-mode variables like regular
6235 ;; expressions for filling etc. However, when any of those keys is
6236 ;; used at a different location, function uses `key-binding' to look
6237 ;; up if the key has an associated command in another currently active
6238 ;; keymap (minor modes, major mode, global), and executes that
6239 ;; command. There might be problems if any of the keys is otherwise
6240 ;; used as a prefix key.
6242 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
6243 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
6244 ;; addresses this by checking explicitly for both bindings.
6246 (defvar orgstruct-mode-map (make-sparse-keymap)
6247 "Keymap for the minor `org-cdlatex-mode'.")
6249 ;;;###autoload
6250 (define-minor-mode orgstruct-mode
6251 "Toggle the minor more `orgstruct-mode'.
6252 This mode is for using Org-mode structure commands in other modes.
6253 The following key behave as if Org-mode was active, if the cursor
6254 is on a headline, or on a plain list item (both in the definition
6255 of Org-mode).
6257 M-up Move entry/item up
6258 M-down Move entry/item down
6259 M-left Promote
6260 M-right Demote
6261 M-S-up Move entry/item up
6262 M-S-down Move entry/item down
6263 M-S-left Promote subtree
6264 M-S-right Demote subtree
6265 M-q Fill paragraph and items like in Org-mode
6266 C-c ^ Sort entries
6267 C-c - Cycle list bullet
6268 TAB Cycle item visibility
6269 M-RET Insert new heading/item
6270 S-M-RET Insert new TODO heading / Chekbox item
6271 C-c C-c Set tags / toggle checkbox"
6272 nil " OrgStruct" nil
6273 (and (orgstruct-setup) (defun orgstruct-setup () nil)))
6275 ;;;###autoload
6276 (defun turn-on-orgstruct ()
6277 "Unconditionally turn on `orgstruct-mode'."
6278 (orgstruct-mode 1))
6280 (defun orgstruct-error ()
6281 "Error when there is no default binding for a structure key."
6282 (interactive)
6283 (error "This key is has no function outside structure elements"))
6285 (defvar org-local-vars nil
6286 "List of local variables, for use by `orgstruct-mode'")
6288 (defun orgstruct-setup ()
6289 "Setup orgstruct keymaps."
6290 (let ((nfunc 0)
6291 (bindings
6292 (list
6293 '([(meta up)] org-metaup)
6294 '([(meta down)] org-metadown)
6295 '([(meta left)] org-metaleft)
6296 '([(meta right)] org-metaright)
6297 '([(meta shift up)] org-shiftmetaup)
6298 '([(meta shift down)] org-shiftmetadown)
6299 '([(meta shift left)] org-shiftmetaleft)
6300 '([(meta shift right)] org-shiftmetaright)
6301 '([(shift up)] org-shiftup)
6302 '([(shift down)] org-shiftdown)
6303 '("\M-q" fill-paragraph)
6304 '("\C-c^" org-sort)
6305 '("\C-c-" org-cycle-list-bullet)))
6306 elt key fun cmd)
6307 (while (setq elt (pop bindings))
6308 (setq nfunc (1+ nfunc))
6309 (setq key (org-key (car elt))
6310 fun (nth 1 elt)
6311 cmd (orgstruct-make-binding fun nfunc key))
6312 (org-defkey orgstruct-mode-map key cmd))
6314 ;; Special treatment needed for TAB and RET
6315 (org-defkey orgstruct-mode-map [(tab)]
6316 (orgstruct-make-binding 'org-cycle 102 [(tab)] "\C-i"))
6317 (org-defkey orgstruct-mode-map "\C-i"
6318 (orgstruct-make-binding 'org-cycle 103 "\C-i" [(tab)]))
6320 (org-defkey orgstruct-mode-map "\M-\C-m"
6321 (orgstruct-make-binding 'org-insert-heading 105
6322 "\M-\C-m" [(meta return)]))
6323 (org-defkey orgstruct-mode-map [(meta return)]
6324 (orgstruct-make-binding 'org-insert-heading 106
6325 [(meta return)] "\M-\C-m"))
6327 (org-defkey orgstruct-mode-map [(shift meta return)]
6328 (orgstruct-make-binding 'org-insert-todo-heading 107
6329 [(meta return)] "\M-\C-m"))
6331 (org-defkey orgstruct-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
6332 (setq org-local-vars (org-get-local-variables))
6336 (defun orgstruct-make-binding (fun n &rest keys)
6337 "Create a function for binding in the structure minor mode.
6338 FUN is the command to call inside a table. N is used to create a unique
6339 command name. KEYS are keys that should be checked in for a command
6340 to execute outside of tables."
6341 (eval
6342 (list 'defun
6343 (intern (concat "orgstruct-hijacker-command-" (int-to-string n)))
6344 '(arg)
6345 (concat "In Structure, run `" (symbol-name fun) "'.\n"
6346 "Outside of structure, run the binding of `"
6347 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
6348 "'.")
6349 '(interactive "p")
6350 (list 'if
6351 '(org-context-p 'headline 'item)
6352 (list 'org-run-like-in-org-mode (list 'quote fun))
6353 (list 'let '(orgstruct-mode)
6354 (list 'call-interactively
6355 (append '(or)
6356 (mapcar (lambda (k)
6357 (list 'key-binding k))
6358 keys)
6359 '('orgstruct-error))))))))
6361 (defun org-context-p (&rest contexts)
6362 "FIXME:"
6363 (let ((pos (point)))
6364 (goto-char (point-at-bol))
6365 (prog1 (or (and (memq 'table contexts)
6366 (looking-at "[ \t]*|"))
6367 (and (memq 'headline contexts)
6368 (looking-at "\\*+"))
6369 (and (memq 'item contexts)
6370 (looking-at "[ \t]*\\([-+*] \\|[0-9]+[.)] \\)")))
6371 (goto-char pos))))
6373 (defun org-get-local-variables ()
6374 "Return a list of all local variables in an org-mode buffer."
6375 (let (varlist)
6376 (with-current-buffer (get-buffer-create "*Org tmp*")
6377 (erase-buffer)
6378 (org-mode)
6379 (setq varlist (buffer-local-variables)))
6380 (kill-buffer "*Org tmp*")
6381 (delq nil
6382 (mapcar
6383 (lambda (x)
6384 (setq x
6385 (if (symbolp x)
6386 (list x)
6387 (list (car x) (list 'quote (cdr x)))))
6388 (if (string-match
6389 "^\\(org-\\|orgtbl-\\|outline-\\|comment-\\|paragraph-\\|auto-fill\\|fill-paragraph\\|adaptive-fill\\|indent-\\)"
6390 (symbol-name (car x)))
6391 x nil))
6392 varlist))))
6394 (defun org-run-like-in-org-mode (cmd)
6395 (eval (list 'let org-local-vars
6396 (list 'call-interactively (list 'quote cmd)))))
6398 ;;;; Archiving
6400 (defalias 'org-advertized-archive-subtree 'org-archive-subtree)
6402 (defun org-archive-subtree (&optional find-done)
6403 "Move the current subtree to the archive.
6404 The archive can be a certain top-level heading in the current file, or in
6405 a different file. The tree will be moved to that location, the subtree
6406 heading be marked DONE, and the current time will be added.
6408 When called with prefix argument FIND-DONE, find whole trees without any
6409 open TODO items and archive them (after getting confirmation from the user).
6410 If the cursor is not at a headline when this comand is called, try all level
6411 1 trees. If the cursor is on a headline, only try the direct children of
6412 this heading."
6413 (interactive "P")
6414 (if find-done
6415 (org-archive-all-done)
6416 ;; Save all relevant TODO keyword-relatex variables
6418 (let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
6419 (tr-org-todo-keywords-1 org-todo-keywords-1)
6420 (tr-org-todo-kwd-alist org-todo-kwd-alist)
6421 (tr-org-done-keywords org-done-keywords)
6422 (tr-org-todo-regexp org-todo-regexp)
6423 (tr-org-todo-line-regexp org-todo-line-regexp)
6424 (tr-org-odd-levels-only org-odd-levels-only)
6425 (this-buffer (current-buffer))
6426 (org-archive-location org-archive-location)
6427 (re "^#\\+ARCHIVE:[ \t]+\\(\\S-.*\\S-\\)[ \t]*$")
6428 file heading buffer level newfile-p)
6430 ;; Try to find a local archive location
6431 (save-excursion
6432 (save-restriction
6433 (widen)
6434 (if (or (re-search-backward re nil t) (re-search-forward re nil t))
6435 (setq org-archive-location (match-string 1)))))
6437 (if (string-match "\\(.*\\)::\\(.*\\)" org-archive-location)
6438 (progn
6439 (setq file (format (match-string 1 org-archive-location)
6440 (file-name-nondirectory buffer-file-name))
6441 heading (match-string 2 org-archive-location)))
6442 (error "Invalid `org-archive-location'"))
6443 (if (> (length file) 0)
6444 (setq newfile-p (not (file-exists-p file))
6445 buffer (find-file-noselect file))
6446 (setq buffer (current-buffer)))
6447 (unless buffer
6448 (error "Cannot access file \"%s\"" file))
6449 (if (and (> (length heading) 0)
6450 (string-match "^\\*+" heading))
6451 (setq level (match-end 0))
6452 (setq heading nil level 0))
6453 (save-excursion
6454 ;; We first only copy, in case something goes wrong
6455 ;; we need to protect this-command, to avoid kill-region sets it,
6456 ;; which would lead to duplication of subtrees
6457 (let (this-command) (org-copy-subtree))
6458 (set-buffer buffer)
6459 ;; Enforce org-mode for the archive buffer
6460 (if (not (org-mode-p))
6461 ;; Force the mode for future visits.
6462 (let ((org-insert-mode-line-in-empty-file t)
6463 (org-inhibit-startup t))
6464 (call-interactively 'org-mode)))
6465 (when newfile-p
6466 (goto-char (point-max))
6467 (insert (format "\nArchived entries from file %s\n\n"
6468 (buffer-file-name this-buffer))))
6469 ;; Force the TODO keywords of the original buffer
6470 (let ((org-todo-line-regexp tr-org-todo-line-regexp)
6471 (org-todo-keywords-1 tr-org-todo-keywords-1)
6472 (org-todo-kwd-alist tr-org-todo-kwd-alist)
6473 (org-done-keywords tr-org-done-keywords)
6474 (org-todo-regexp tr-org-todo-regexp)
6475 (org-todo-line-regexp tr-org-todo-line-regexp)
6476 (org-odd-levels-only
6477 (if (local-variable-p 'org-odd-levels-only (current-buffer))
6478 org-odd-levels-only
6479 tr-org-odd-levels-only)))
6480 (goto-char (point-min))
6481 (if heading
6482 (progn
6483 (if (re-search-forward
6484 (concat "^" (regexp-quote heading)
6485 (org-re "[ \t]*\\(:[[:alnum:]_@:]+:\\)?[ \t]*\\($\\|\r\\)"))
6486 nil t)
6487 (goto-char (match-end 0))
6488 ;; Heading not found, just insert it at the end
6489 (goto-char (point-max))
6490 (or (bolp) (insert "\n"))
6491 (insert "\n" heading "\n")
6492 (end-of-line 0))
6493 ;; Make the subtree visible
6494 (show-subtree)
6495 (org-end-of-subtree t)
6496 (skip-chars-backward " \t\r\n")
6497 (and (looking-at "[ \t\r\n]*")
6498 (replace-match "\n\n")))
6499 ;; No specific heading, just go to end of file.
6500 (goto-char (point-max)) (insert "\n"))
6501 ;; Paste
6502 (org-paste-subtree (org-get-legal-level level 1))
6503 ;; Mark the entry as done, i.e. set to last word in org-todo-keywords-1 FIXME: not right anymore!!!!!!!
6504 (when (and org-archive-mark-done
6505 (looking-at org-todo-line-regexp)
6506 (or (not (match-end 3))
6507 (not (member (match-string 3) org-done-keywords))))
6508 (let (org-log-done)
6509 (org-todo (car org-done-keywords))))
6511 ;; Move cursor to right after the TODO keyword
6512 (when org-archive-stamp-time
6513 (org-add-planning-info 'archived (org-current-time)))
6514 ;; Save the buffer, if it is not the same buffer.
6515 (if (not (eq this-buffer buffer)) (save-buffer))))
6516 ;; Here we are back in the original buffer. Everything seems to have
6517 ;; worked. So now cut the tree and finish up.
6518 (let (this-command) (org-cut-subtree))
6519 (if (and (not (eobp)) (looking-at "[ \t]*$")) (kill-line))
6520 (message "Subtree archived %s"
6521 (if (eq this-buffer buffer)
6522 (concat "under heading: " heading)
6523 (concat "in file: " (abbreviate-file-name file)))))))
6525 (defun org-archive-all-done (&optional tag)
6526 "Archive sublevels of the current tree without open TODO items.
6527 If the cursor is not on a headline, try all level 1 trees. If
6528 it is on a headline, try all direct children.
6529 When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
6530 (let ((re (concat "^\\*+ +" org-not-done-regexp)) re1
6531 (rea (concat ".*:" org-archive-tag ":"))
6532 (begm (make-marker))
6533 (endm (make-marker))
6534 (question (if tag "Set ARCHIVE tag (no open TODO items)? "
6535 "Move subtree to archive (no open TODO items)? "))
6536 beg end (cntarch 0))
6537 (if (org-on-heading-p)
6538 (progn
6539 (setq re1 (concat "^" (regexp-quote
6540 (make-string
6541 (1+ (- (match-end 0) (match-beginning 0)))
6542 ?*))
6543 " "))
6544 (move-marker begm (point))
6545 (move-marker endm (org-end-of-subtree t)))
6546 (setq re1 "^* ")
6547 (move-marker begm (point-min))
6548 (move-marker endm (point-max)))
6549 (save-excursion
6550 (goto-char begm)
6551 (while (re-search-forward re1 endm t)
6552 (setq beg (match-beginning 0)
6553 end (save-excursion (org-end-of-subtree t) (point)))
6554 (goto-char beg)
6555 (if (re-search-forward re end t)
6556 (goto-char end)
6557 (goto-char beg)
6558 (if (and (or (not tag) (not (looking-at rea)))
6559 (y-or-n-p question))
6560 (progn
6561 (if tag
6562 (org-toggle-tag org-archive-tag 'on)
6563 (org-archive-subtree))
6564 (setq cntarch (1+ cntarch)))
6565 (goto-char end)))))
6566 (message "%d trees archived" cntarch)))
6568 (defun org-cycle-hide-drawers (state)
6569 "Re-hide all archived subtrees after a visibility state change."
6570 (when (not (memq state '(overview folded)))
6571 (save-excursion
6572 (let* ((globalp (memq state '(contents all)))
6573 (beg (if globalp (point-min) (point)))
6574 (end (if globalp (point-max) (org-end-of-subtree t))))
6575 (goto-char beg)
6576 (while (re-search-forward org-drawer-regexp end t)
6577 (org-flag-drawer t))))))
6579 (defun org-flag-drawer (flag)
6580 (save-excursion
6581 (beginning-of-line 1)
6582 (when (looking-at "^[ \t]*:[a-zA-Z][a-zA-Z0-9]*:")
6583 (let ((b (match-end 0)))
6584 (if (re-search-forward
6585 "^[ \t]*:END:"
6586 (save-excursion (outline-next-heading) (point)) t)
6587 (outline-flag-region b (point-at-eol) flag)
6588 (error ":END: line missing"))))))
6590 (defun org-cycle-hide-archived-subtrees (state)
6591 "Re-hide all archived subtrees after a visibility state change."
6592 (when (and (not org-cycle-open-archived-trees)
6593 (not (memq state '(overview folded))))
6594 (save-excursion
6595 (let* ((globalp (memq state '(contents all)))
6596 (beg (if globalp (point-min) (point)))
6597 (end (if globalp (point-max) (org-end-of-subtree t))))
6598 (org-hide-archived-subtrees beg end)
6599 (goto-char beg)
6600 (if (looking-at (concat ".*:" org-archive-tag ":"))
6601 (message (substitute-command-keys
6602 "Subtree is archived and stays closed. Use \\[org-force-cycle-archived] to cycle it anyway.")))))))
6604 (defun org-force-cycle-archived ()
6605 "Cycle subtree even if it is archived."
6606 (interactive)
6607 (setq this-command 'org-cycle)
6608 (let ((org-cycle-open-archived-trees t))
6609 (call-interactively 'org-cycle)))
6611 (defun org-hide-archived-subtrees (beg end)
6612 "Re-hide all archived subtrees after a visibility state change."
6613 (save-excursion
6614 (let* ((re (concat ":" org-archive-tag ":")))
6615 (goto-char beg)
6616 (while (re-search-forward re end t)
6617 (and (org-on-heading-p) (hide-subtree))
6618 (org-end-of-subtree t)))))
6620 (defun org-toggle-tag (tag &optional onoff)
6621 "Toggle the tag TAG for the current line.
6622 If ONOFF is `on' or `off', don't toggle but set to this state."
6623 (unless (org-on-heading-p t) (error "Not on headling"))
6624 (let (res current)
6625 (save-excursion
6626 (beginning-of-line)
6627 (if (re-search-forward (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t]*$")
6628 (point-at-eol) t)
6629 (progn
6630 (setq current (match-string 1))
6631 (replace-match ""))
6632 (setq current ""))
6633 (setq current (nreverse (org-split-string current ":")))
6634 (cond
6635 ((eq onoff 'on)
6636 (setq res t)
6637 (or (member tag current) (push tag current)))
6638 ((eq onoff 'off)
6639 (or (not (member tag current)) (setq current (delete tag current))))
6640 (t (if (member tag current)
6641 (setq current (delete tag current))
6642 (setq res t)
6643 (push tag current))))
6644 (end-of-line 1)
6645 (when current
6646 (insert " :" (mapconcat 'identity (nreverse current) ":") ":"))
6647 (org-set-tags nil t))
6648 res))
6650 (defun org-toggle-archive-tag (&optional arg)
6651 "Toggle the archive tag for the current headline.
6652 With prefix ARG, check all children of current headline and offer tagging
6653 the children that do not contain any open TODO items."
6654 (interactive "P")
6655 (if arg
6656 (org-archive-all-done 'tag)
6657 (let (set)
6658 (save-excursion
6659 (org-back-to-heading t)
6660 (setq set (org-toggle-tag org-archive-tag))
6661 (when set (hide-subtree)))
6662 (and set (beginning-of-line 1))
6663 (message "Subtree %s" (if set "archived" "unarchived")))))
6666 ;;;; Tables
6668 ;;; The table editor
6670 ;; Watch out: Here we are talking about two different kind of tables.
6671 ;; Most of the code is for the tables created with the Org-mode table editor.
6672 ;; Sometimes, we talk about tables created and edited with the table.el
6673 ;; Emacs package. We call the former org-type tables, and the latter
6674 ;; table.el-type tables.
6676 (defun org-before-change-function (beg end)
6677 "Every change indicates that a table might need an update."
6678 (setq org-table-may-need-update t))
6680 (defconst org-table-line-regexp "^[ \t]*|"
6681 "Detects an org-type table line.")
6682 (defconst org-table-dataline-regexp "^[ \t]*|[^-]"
6683 "Detects an org-type table line.")
6684 (defconst org-table-auto-recalculate-regexp "^[ \t]*| *# *\\(|\\|$\\)"
6685 "Detects a table line marked for automatic recalculation.")
6686 (defconst org-table-recalculate-regexp "^[ \t]*| *[#*] *\\(|\\|$\\)"
6687 "Detects a table line marked for automatic recalculation.")
6688 (defconst org-table-calculate-mark-regexp "^[ \t]*| *[!$^_#*] *\\(|\\|$\\)"
6689 "Detects a table line marked for automatic recalculation.")
6690 (defconst org-table-hline-regexp "^[ \t]*|-"
6691 "Detects an org-type table hline.")
6692 (defconst org-table1-hline-regexp "^[ \t]*\\+-[-+]"
6693 "Detects a table-type table hline.")
6694 (defconst org-table-any-line-regexp "^[ \t]*\\(|\\|\\+-[-+]\\)"
6695 "Detects an org-type or table-type table.")
6696 (defconst org-table-border-regexp "^[ \t]*[^| \t]"
6697 "Searching from within a table (any type) this finds the first line
6698 outside the table.")
6699 (defconst org-table-any-border-regexp "^[ \t]*[^|+ \t]"
6700 "Searching from within a table (any type) this finds the first line
6701 outside the table.")
6703 (defvar org-table-last-highlighted-reference nil)
6704 (defvar org-table-formula-history nil)
6706 (defvar org-table-column-names nil
6707 "Alist with column names, derived from the `!' line.")
6708 (defvar org-table-column-name-regexp nil
6709 "Regular expression matching the current column names.")
6710 (defvar org-table-local-parameters nil
6711 "Alist with parameter names, derived from the `$' line.")
6712 (defvar org-table-named-field-locations nil
6713 "Alist with locations of named fields.")
6715 (defvar org-table-current-line-types nil
6716 "Table row types, non-nil only for the duration of a comand.")
6717 (defvar org-table-current-begin-line nil
6718 "Table begin line, non-nil only for the duration of a comand.")
6719 (defvar org-table-current-begin-pos nil
6720 "Table begin position, non-nil only for the duration of a comand.")
6721 (defvar org-table-dlines nil
6722 "Vector of data line line numbers in the current table.")
6723 (defvar org-table-hlines nil
6724 "Vector of hline line numbers in the current table.")
6726 (defconst org-table-range-regexp
6727 "@\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\(\\.\\.@?\\([-+]?I*[-+]?[0-9]*\\)?\\(\\$[-+]?[0-9]+\\)?\\)?"
6728 ;; 1 2 3 4 5
6729 "Regular expression for matching ranges in formulas.")
6731 (defconst org-table-range-regexp2
6732 (concat
6733 "\\(" "@[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)"
6734 "\\.\\."
6735 "\\(" "@?[-0-9I$&]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\|" "\\$[a-zA-Z0-9]+" "\\)")
6736 "Match a range for reference display.")
6738 (defconst org-table-translate-regexp
6739 (concat "\\(" "@[-0-9I$]+" "\\|" "[a-zA-Z]\\{1,2\\}\\([0-9]+\\|&\\)" "\\)")
6740 "Match a reference that needs translation, for reference display.")
6742 (defvar org-inhibit-highlight-removal nil) ; dynamically scoped param
6744 (defun org-table-create-with-table.el ()
6745 "Use the table.el package to insert a new table.
6746 If there is already a table at point, convert between Org-mode tables
6747 and table.el tables."
6748 (interactive)
6749 (require 'table)
6750 (cond
6751 ((org-at-table.el-p)
6752 (if (y-or-n-p "Convert table to Org-mode table? ")
6753 (org-table-convert)))
6754 ((org-at-table-p)
6755 (if (y-or-n-p "Convert table to table.el table? ")
6756 (org-table-convert)))
6757 (t (call-interactively 'table-insert))))
6759 (defun org-table-create-or-convert-from-region (arg)
6760 "Convert region to table, or create an empty table.
6761 If there is an active region, convert it to a table, using the function
6762 `org-table-convert-region'.
6763 If there is no such region, create an empty table with `org-table-create'."
6764 (interactive "P")
6765 (if (org-region-active-p)
6766 (org-table-convert-region (region-beginning) (region-end) arg)
6767 (org-table-create arg)))
6769 (defun org-table-create (&optional size)
6770 "Query for a size and insert a table skeleton.
6771 SIZE is a string Columns x Rows like for example \"3x2\"."
6772 (interactive "P")
6773 (unless size
6774 (setq size (read-string
6775 (concat "Table size Columns x Rows [e.g. "
6776 org-table-default-size "]: ")
6777 "" nil org-table-default-size)))
6779 (let* ((pos (point))
6780 (indent (make-string (current-column) ?\ ))
6781 (split (org-split-string size " *x *"))
6782 (rows (string-to-number (nth 1 split)))
6783 (columns (string-to-number (car split)))
6784 (line (concat (apply 'concat indent "|" (make-list columns " |"))
6785 "\n")))
6786 (if (string-match "^[ \t]*$" (buffer-substring-no-properties
6787 (point-at-bol) (point)))
6788 (beginning-of-line 1)
6789 (newline))
6790 ;; (mapcar (lambda (x) (insert line)) (make-list rows t))
6791 (dotimes (i rows) (insert line))
6792 (goto-char pos)
6793 (if (> rows 1)
6794 ;; Insert a hline after the first row.
6795 (progn
6796 (end-of-line 1)
6797 (insert "\n|-")
6798 (goto-char pos)))
6799 (org-table-align)))
6801 (defun org-table-convert-region (beg0 end0 &optional nspace)
6802 "Convert region to a table.
6803 The region goes from BEG0 to END0, but these borders will be moved
6804 slightly, to make sure a beginning of line in the first line is included.
6805 When NSPACE is non-nil, it indicates the minimum number of spaces that
6806 separate columns. By default, the function first checks if every line
6807 contains at lease one TAB. If yes, it assumes that the material is TAB
6808 separated. If not, it assumes a single space as separator."
6809 (interactive "rP")
6810 (let* ((beg (min beg0 end0))
6811 (end (max beg0 end0))
6812 (tabsep t)
6814 (goto-char beg)
6815 (beginning-of-line 1)
6816 (setq beg (move-marker (make-marker) (point)))
6817 (goto-char end)
6818 (if (bolp) (backward-char 1) (end-of-line 1))
6819 (setq end (move-marker (make-marker) (point)))
6820 ;; Lets see if this is tab-separated material. If every nonempty line
6821 ;; contains a tab, we will assume that it is tab-separated material
6822 (if nspace
6823 (setq tabsep nil)
6824 (goto-char beg)
6825 (and (re-search-forward "^[^\n\t]+$" end t) (setq tabsep nil)))
6826 (if nspace (setq tabsep nil))
6827 (if tabsep
6828 (setq re "^\\|\t")
6829 (setq re (format "^ *\\| *\t *\\| \\{%d,\\}"
6830 (max 1 (prefix-numeric-value nspace)))))
6831 (goto-char beg)
6832 (while (re-search-forward re end t)
6833 (replace-match "| " t t))
6834 (goto-char beg)
6835 (insert " ")
6836 (org-table-align)))
6838 (defun org-table-import (file arg)
6839 "Import FILE as a table.
6840 The file is assumed to be tab-separated. Such files can be produced by most
6841 spreadsheet and database applications. If no tabs (at least one per line)
6842 are found, lines will be split on whitespace into fields."
6843 (interactive "f\nP")
6844 (or (bolp) (newline))
6845 (let ((beg (point))
6846 (pm (point-max)))
6847 (insert-file-contents file)
6848 (org-table-convert-region beg (+ (point) (- (point-max) pm)) arg)))
6850 (defun org-table-export ()
6851 "Export table as a tab-separated file.
6852 Such a file can be imported into a spreadsheet program like Excel."
6853 (interactive)
6854 (let* ((beg (org-table-begin))
6855 (end (org-table-end))
6856 (table (buffer-substring beg end))
6857 (file (read-file-name "Export table to: "))
6858 buf)
6859 (unless (or (not (file-exists-p file))
6860 (y-or-n-p (format "Overwrite file %s? " file)))
6861 (error "Abort"))
6862 (with-current-buffer (find-file-noselect file)
6863 (setq buf (current-buffer))
6864 (erase-buffer)
6865 (fundamental-mode)
6866 (insert table)
6867 (goto-char (point-min))
6868 (while (re-search-forward "^[ \t]*|[ \t]*" nil t)
6869 (replace-match "" t t)
6870 (end-of-line 1))
6871 (goto-char (point-min))
6872 (while (re-search-forward "[ \t]*|[ \t]*$" nil t)
6873 (replace-match "" t t)
6874 (goto-char (min (1+ (point)) (point-max))))
6875 (goto-char (point-min))
6876 (while (re-search-forward "^-[-+]*$" nil t)
6877 (replace-match "")
6878 (if (looking-at "\n")
6879 (delete-char 1)))
6880 (goto-char (point-min))
6881 (while (re-search-forward "[ \t]*|[ \t]*" nil t)
6882 (replace-match "\t" t t))
6883 (save-buffer))
6884 (kill-buffer buf)))
6886 (defvar org-table-aligned-begin-marker (make-marker)
6887 "Marker at the beginning of the table last aligned.
6888 Used to check if cursor still is in that table, to minimize realignment.")
6889 (defvar org-table-aligned-end-marker (make-marker)
6890 "Marker at the end of the table last aligned.
6891 Used to check if cursor still is in that table, to minimize realignment.")
6892 (defvar org-table-last-alignment nil
6893 "List of flags for flushright alignment, from the last re-alignment.
6894 This is being used to correctly align a single field after TAB or RET.")
6895 (defvar org-table-last-column-widths nil
6896 "List of max width of fields in each column.
6897 This is being used to correctly align a single field after TAB or RET.")
6898 (defvar org-table-overlay-coordinates nil
6899 "Overlay coordinates after each align of a table.")
6900 (make-variable-buffer-local 'org-table-overlay-coordinates)
6902 (defvar org-last-recalc-line nil)
6903 (defconst org-narrow-column-arrow "=>"
6904 "Used as display property in narrowed table columns.")
6906 (defun org-table-align ()
6907 "Align the table at point by aligning all vertical bars."
6908 (interactive)
6909 (let* (
6910 ;; Limits of table
6911 (beg (org-table-begin))
6912 (end (org-table-end))
6913 ;; Current cursor position
6914 (linepos (org-current-line))
6915 (colpos (org-table-current-column))
6916 (winstart (window-start))
6917 (winstartline (org-current-line (min winstart (1- (point-max)))))
6918 lines (new "") lengths l typenums ty fields maxfields i
6919 column
6920 (indent "") cnt frac
6921 rfmt hfmt
6922 (spaces '(1 . 1))
6923 (sp1 (car spaces))
6924 (sp2 (cdr spaces))
6925 (rfmt1 (concat
6926 (make-string sp2 ?\ ) "%%%s%ds" (make-string sp1 ?\ ) "|"))
6927 (hfmt1 (concat
6928 (make-string sp2 ?-) "%s" (make-string sp1 ?-) "+"))
6929 emptystrings links dates narrow fmax f1 len c e)
6930 (untabify beg end)
6931 (remove-text-properties beg end '(org-cwidth t org-dwidth t display t))
6932 ;; Check if we have links or dates
6933 (goto-char beg)
6934 (setq links (re-search-forward org-bracket-link-regexp end t))
6935 (goto-char beg)
6936 (setq dates (and org-display-custom-times
6937 (re-search-forward org-ts-regexp-both end t)))
6938 ;; Make sure the link properties are right
6939 (when links (goto-char beg) (while (org-activate-bracket-links end)))
6940 ;; Make sure the date properties are right
6941 (when dates (goto-char beg) (while (org-activate-dates end)))
6943 ;; Check if we are narrowing any columns
6944 (goto-char beg)
6945 (setq narrow (and org-format-transports-properties-p
6946 (re-search-forward "<[0-9]+>" end t)))
6947 ;; Get the rows
6948 (setq lines (org-split-string
6949 (buffer-substring beg end) "\n"))
6950 ;; Store the indentation of the first line
6951 (if (string-match "^ *" (car lines))
6952 (setq indent (make-string (- (match-end 0) (match-beginning 0)) ?\ )))
6953 ;; Mark the hlines by setting the corresponding element to nil
6954 ;; At the same time, we remove trailing space.
6955 (setq lines (mapcar (lambda (l)
6956 (if (string-match "^ *|-" l)
6958 (if (string-match "[ \t]+$" l)
6959 (substring l 0 (match-beginning 0))
6960 l)))
6961 lines))
6962 ;; Get the data fields by splitting the lines.
6963 (setq fields (mapcar
6964 (lambda (l)
6965 (org-split-string l " *| *"))
6966 (delq nil (copy-sequence lines))))
6967 ;; How many fields in the longest line?
6968 (condition-case nil
6969 (setq maxfields (apply 'max (mapcar 'length fields)))
6970 (error
6971 (kill-region beg end)
6972 (org-table-create org-table-default-size)
6973 (error "Empty table - created default table")))
6974 ;; A list of empty strings to fill any short rows on output
6975 (setq emptystrings (make-list maxfields ""))
6976 ;; Check for special formatting.
6977 (setq i -1)
6978 (while (< (setq i (1+ i)) maxfields) ;; Loop over all columns
6979 (setq column (mapcar (lambda (x) (or (nth i x) "")) fields))
6980 ;; Check if there is an explicit width specified
6981 (when narrow
6982 (setq c column fmax nil)
6983 (while c
6984 (setq e (pop c))
6985 (if (and (stringp e) (string-match "^<\\([0-9]+\\)>$" e))
6986 (setq fmax (string-to-number (match-string 1 e)) c nil)))
6987 ;; Find fields that are wider than fmax, and shorten them
6988 (when fmax
6989 (loop for xx in column do
6990 (when (and (stringp xx)
6991 (> (org-string-width xx) fmax))
6992 (org-add-props xx nil
6993 'help-echo
6994 (concat "Clipped table field, use C-c ` to edit. Full value is:\n" (org-no-properties (copy-sequence xx))))
6995 (setq f1 (min fmax (or (string-match org-bracket-link-regexp xx) fmax)))
6996 (unless (> f1 1)
6997 (error "Cannot narrow field starting with wide link \"%s\""
6998 (match-string 0 xx)))
6999 (add-text-properties f1 (length xx) (list 'org-cwidth t) xx)
7000 (add-text-properties (- f1 2) f1
7001 (list 'display org-narrow-column-arrow)
7002 xx)))))
7003 ;; Get the maximum width for each column
7004 (push (apply 'max 1 (mapcar 'org-string-width column)) lengths)
7005 ;; Get the fraction of numbers, to decide about alignment of the column
7006 (setq cnt 0 frac 0.0)
7007 (loop for x in column do
7008 (if (equal x "")
7010 (setq frac ( / (+ (* frac cnt)
7011 (if (string-match org-table-number-regexp x) 1 0))
7012 (setq cnt (1+ cnt))))))
7013 (push (>= frac org-table-number-fraction) typenums))
7014 (setq lengths (nreverse lengths) typenums (nreverse typenums))
7016 ;; Store the alignment of this table, for later editing of single fields
7017 (setq org-table-last-alignment typenums
7018 org-table-last-column-widths lengths)
7020 ;; With invisible characters, `format' does not get the field width right
7021 ;; So we need to make these fields wide by hand.
7022 (when links
7023 (loop for i from 0 upto (1- maxfields) do
7024 (setq len (nth i lengths))
7025 (loop for j from 0 upto (1- (length fields)) do
7026 (setq c (nthcdr i (car (nthcdr j fields))))
7027 (if (and (stringp (car c))
7028 (string-match org-bracket-link-regexp (car c))
7029 (< (org-string-width (car c)) len))
7030 (setcar c (concat (car c) (make-string (- len (org-string-width (car c))) ?\ )))))))
7032 ;; Compute the formats needed for output of the table
7033 (setq rfmt (concat indent "|") hfmt (concat indent "|"))
7034 (while (setq l (pop lengths))
7035 (setq ty (if (pop typenums) "" "-")) ; number types flushright
7036 (setq rfmt (concat rfmt (format rfmt1 ty l))
7037 hfmt (concat hfmt (format hfmt1 (make-string l ?-)))))
7038 (setq rfmt (concat rfmt "\n")
7039 hfmt (concat (substring hfmt 0 -1) "|\n"))
7041 (setq new (mapconcat
7042 (lambda (l)
7043 (if l (apply 'format rfmt
7044 (append (pop fields) emptystrings))
7045 hfmt))
7046 lines ""))
7047 ;; Replace the old one
7048 (delete-region beg end)
7049 (move-marker end nil)
7050 (move-marker org-table-aligned-begin-marker (point))
7051 (insert new)
7052 (move-marker org-table-aligned-end-marker (point))
7053 (when (and orgtbl-mode (not (org-mode-p)))
7054 (goto-char org-table-aligned-begin-marker)
7055 (while (org-hide-wide-columns org-table-aligned-end-marker)))
7056 ;; Try to move to the old location
7057 (goto-line winstartline)
7058 (setq winstart (point-at-bol))
7059 (goto-line linepos)
7060 (set-window-start (selected-window) winstart 'noforce)
7061 (org-table-goto-column colpos)
7062 (and org-table-overlay-coordinates (org-table-overlay-coordinates))
7063 (setq org-table-may-need-update nil)
7066 (defun org-string-width (s)
7067 "Compute width of string, ignoring invisible characters.
7068 This ignores character with invisibility property `org-link', and also
7069 characters with property `org-cwidth', because these will become invisible
7070 upon the next fontification round."
7071 (let (b l)
7072 (when (or (eq t buffer-invisibility-spec)
7073 (assq 'org-link buffer-invisibility-spec))
7074 (while (setq b (text-property-any 0 (length s)
7075 'invisible 'org-link s))
7076 (setq s (concat (substring s 0 b)
7077 (substring s (or (next-single-property-change
7078 b 'invisible s) (length s)))))))
7079 (while (setq b (text-property-any 0 (length s) 'org-cwidth t s))
7080 (setq s (concat (substring s 0 b)
7081 (substring s (or (next-single-property-change
7082 b 'org-cwidth s) (length s))))))
7083 (setq l (string-width s) b -1)
7084 (while (setq b (text-property-any (1+ b) (length s) 'org-dwidth t s))
7085 (setq l (- l (get-text-property b 'org-dwidth-n s))))
7088 (defun org-table-begin (&optional table-type)
7089 "Find the beginning of the table and return its position.
7090 With argument TABLE-TYPE, go to the beginning of a table.el-type table."
7091 (save-excursion
7092 (if (not (re-search-backward
7093 (if table-type org-table-any-border-regexp
7094 org-table-border-regexp)
7095 nil t))
7096 (progn (goto-char (point-min)) (point))
7097 (goto-char (match-beginning 0))
7098 (beginning-of-line 2)
7099 (point))))
7101 (defun org-table-end (&optional table-type)
7102 "Find the end of the table and return its position.
7103 With argument TABLE-TYPE, go to the end of a table.el-type table."
7104 (save-excursion
7105 (if (not (re-search-forward
7106 (if table-type org-table-any-border-regexp
7107 org-table-border-regexp)
7108 nil t))
7109 (goto-char (point-max))
7110 (goto-char (match-beginning 0)))
7111 (point-marker)))
7113 (defun org-table-justify-field-maybe (&optional new)
7114 "Justify the current field, text to left, number to right.
7115 Optional argument NEW may specify text to replace the current field content."
7116 (cond
7117 ((and (not new) org-table-may-need-update)) ; Realignment will happen anyway
7118 ((org-at-table-hline-p))
7119 ((and (not new)
7120 (or (not (equal (marker-buffer org-table-aligned-begin-marker)
7121 (current-buffer)))
7122 (< (point) org-table-aligned-begin-marker)
7123 (>= (point) org-table-aligned-end-marker)))
7124 ;; This is not the same table, force a full re-align
7125 (setq org-table-may-need-update t))
7126 (t ;; realign the current field, based on previous full realign
7127 (let* ((pos (point)) s
7128 (col (org-table-current-column))
7129 (num (if (> col 0) (nth (1- col) org-table-last-alignment)))
7130 l f n o e)
7131 (when (> col 0)
7132 (skip-chars-backward "^|\n")
7133 (if (looking-at " *\\([^|\n]*?\\) *\\(|\\|$\\)")
7134 (progn
7135 (setq s (match-string 1)
7136 o (match-string 0)
7137 l (max 1 (- (match-end 0) (match-beginning 0) 3))
7138 e (not (= (match-beginning 2) (match-end 2))))
7139 (setq f (format (if num " %%%ds %s" " %%-%ds %s")
7140 l (if e "|" (setq org-table-may-need-update t) ""))
7141 n (format f s))
7142 (if new
7143 (if (<= (length new) l) ;; FIXME: length -> str-width?
7144 (setq n (format f new))
7145 (setq n (concat new "|") org-table-may-need-update t)))
7146 (or (equal n o)
7147 (let (org-table-may-need-update)
7148 (replace-match n))))
7149 (setq org-table-may-need-update t))
7150 (goto-char pos))))))
7152 (defun org-table-next-field ()
7153 "Go to the next field in the current table, creating new lines as needed.
7154 Before doing so, re-align the table if necessary."
7155 (interactive)
7156 (org-table-maybe-eval-formula)
7157 (org-table-maybe-recalculate-line)
7158 (if (and org-table-automatic-realign
7159 org-table-may-need-update)
7160 (org-table-align))
7161 (let ((end (org-table-end)))
7162 (if (org-at-table-hline-p)
7163 (end-of-line 1))
7164 (condition-case nil
7165 (progn
7166 (re-search-forward "|" end)
7167 (if (looking-at "[ \t]*$")
7168 (re-search-forward "|" end))
7169 (if (and (looking-at "-")
7170 org-table-tab-jumps-over-hlines
7171 (re-search-forward "^[ \t]*|\\([^-]\\)" end t))
7172 (goto-char (match-beginning 1)))
7173 (if (looking-at "-")
7174 (progn
7175 (beginning-of-line 0)
7176 (org-table-insert-row 'below))
7177 (if (looking-at " ") (forward-char 1))))
7178 (error
7179 (org-table-insert-row 'below)))))
7181 (defun org-table-previous-field ()
7182 "Go to the previous field in the table.
7183 Before doing so, re-align the table if necessary."
7184 (interactive)
7185 (org-table-justify-field-maybe)
7186 (org-table-maybe-recalculate-line)
7187 (if (and org-table-automatic-realign
7188 org-table-may-need-update)
7189 (org-table-align))
7190 (if (org-at-table-hline-p)
7191 (end-of-line 1))
7192 (re-search-backward "|" (org-table-begin))
7193 (re-search-backward "|" (org-table-begin))
7194 (while (looking-at "|\\(-\\|[ \t]*$\\)")
7195 (re-search-backward "|" (org-table-begin)))
7196 (if (looking-at "| ?")
7197 (goto-char (match-end 0))))
7199 (defun org-table-next-row ()
7200 "Go to the next row (same column) in the current table.
7201 Before doing so, re-align the table if necessary."
7202 (interactive)
7203 (org-table-maybe-eval-formula)
7204 (org-table-maybe-recalculate-line)
7205 (if (or (looking-at "[ \t]*$")
7206 (save-excursion (skip-chars-backward " \t") (bolp)))
7207 (newline)
7208 (if (and org-table-automatic-realign
7209 org-table-may-need-update)
7210 (org-table-align))
7211 (let ((col (org-table-current-column)))
7212 (beginning-of-line 2)
7213 (if (or (not (org-at-table-p))
7214 (org-at-table-hline-p))
7215 (progn
7216 (beginning-of-line 0)
7217 (org-table-insert-row 'below)))
7218 (org-table-goto-column col)
7219 (skip-chars-backward "^|\n\r")
7220 (if (looking-at " ") (forward-char 1)))))
7222 (defun org-table-copy-down (n)
7223 "Copy a field down in the current column.
7224 If the field at the cursor is empty, copy into it the content of the nearest
7225 non-empty field above. With argument N, use the Nth non-empty field.
7226 If the current field is not empty, it is copied down to the next row, and
7227 the cursor is moved with it. Therefore, repeating this command causes the
7228 column to be filled row-by-row.
7229 If the variable `org-table-copy-increment' is non-nil and the field is an
7230 integer or a timestamp, it will be incremented while copying. In the case of
7231 a timestamp, if the cursor is on the year, change the year. If it is on the
7232 month or the day, change that. Point will stay on the current date field
7233 in order to easily repeat the interval."
7234 (interactive "p")
7235 (let* ((colpos (org-table-current-column))
7236 (col (current-column))
7237 (field (org-table-get-field))
7238 (non-empty (string-match "[^ \t]" field))
7239 (beg (org-table-begin))
7240 txt)
7241 (org-table-check-inside-data-field)
7242 (if non-empty
7243 (progn
7244 (setq txt (org-trim field))
7245 (org-table-next-row)
7246 (org-table-blank-field))
7247 (save-excursion
7248 (setq txt
7249 (catch 'exit
7250 (while (progn (beginning-of-line 1)
7251 (re-search-backward org-table-dataline-regexp
7252 beg t))
7253 (org-table-goto-column colpos t)
7254 (if (and (looking-at
7255 "|[ \t]*\\([^| \t][^|]*?\\)[ \t]*|")
7256 (= (setq n (1- n)) 0))
7257 (throw 'exit (match-string 1))))))))
7258 (if txt
7259 (progn
7260 (if (and org-table-copy-increment
7261 (string-match "^[0-9]+$" txt))
7262 (setq txt (format "%d" (+ (string-to-number txt) 1))))
7263 (insert txt)
7264 (move-to-column col)
7265 (if (and org-table-copy-increment (org-at-timestamp-p t))
7266 (org-timestamp-up 1)
7267 (org-table-maybe-recalculate-line))
7268 (org-table-align)
7269 (move-to-column col))
7270 (error "No non-empty field found"))))
7272 (defun org-table-check-inside-data-field ()
7273 "Is point inside a table data field?
7274 I.e. not on a hline or before the first or after the last column?
7275 This actually throws an error, so it aborts the current command."
7276 (if (or (not (org-at-table-p))
7277 (= (org-table-current-column) 0)
7278 (org-at-table-hline-p)
7279 (looking-at "[ \t]*$"))
7280 (error "Not in table data field")))
7282 (defvar org-table-clip nil
7283 "Clipboard for table regions.")
7285 (defun org-table-blank-field ()
7286 "Blank the current table field or active region."
7287 (interactive)
7288 (org-table-check-inside-data-field)
7289 (if (and (interactive-p) (org-region-active-p))
7290 (let (org-table-clip)
7291 (org-table-cut-region (region-beginning) (region-end)))
7292 (skip-chars-backward "^|")
7293 (backward-char 1)
7294 (if (looking-at "|[^|\n]+")
7295 (let* ((pos (match-beginning 0))
7296 (match (match-string 0))
7297 (len (org-string-width match)))
7298 (replace-match (concat "|" (make-string (1- len) ?\ )))
7299 (goto-char (+ 2 pos))
7300 (substring match 1)))))
7302 (defun org-table-get-field (&optional n replace)
7303 "Return the value of the field in column N of current row.
7304 N defaults to current field.
7305 If REPLACE is a string, replace field with this value. The return value
7306 is always the old value."
7307 (and n (org-table-goto-column n))
7308 (skip-chars-backward "^|\n")
7309 (backward-char 1)
7310 (if (looking-at "|[^|\r\n]*")
7311 (let* ((pos (match-beginning 0))
7312 (val (buffer-substring (1+ pos) (match-end 0))))
7313 (if replace
7314 (replace-match (concat "|" replace) t t))
7315 (goto-char (min (point-at-eol) (+ 2 pos)))
7316 val)
7317 (forward-char 1) ""))
7320 (defun org-table-field-info (arg)
7321 "Show info about the current field, and highlight any reference at point."
7322 (interactive "P")
7323 (org-table-get-specials)
7324 (save-excursion
7325 (let* ((pos (point))
7326 (col (org-table-current-column))
7327 (cname (car (rassoc (int-to-string col) org-table-column-names)))
7328 (name (car (rassoc (list (org-current-line) col)
7329 org-table-named-field-locations)))
7330 (eql (org-table-get-stored-formulas))
7331 (dline (org-table-current-dline))
7332 (ref (format "@%d$%d" dline col))
7333 (ref1 (org-table-convert-refs-to-an ref))
7334 (fequation (or (assoc name eql) (assoc ref eql)))
7335 (cequation (assoc (int-to-string col) eql))
7336 (eqn (or fequation cequation)))
7337 (goto-char pos)
7338 (condition-case nil
7339 (org-table-show-reference 'local)
7340 (error nil))
7341 (message "line @%d, col $%s%s, ref @%d$%d or %s%s%s"
7342 dline col
7343 (if cname (concat " or $" cname) "")
7344 dline col ref1
7345 (if name (concat " or $" name) "")
7346 ;; FIXME: formula info not correct if special table line
7347 (if eqn
7348 (concat ", formula: "
7349 (org-table-formula-to-user
7350 (concat
7351 (if (string-match "^[$@]"(car eqn)) "" "$")
7352 (car eqn) "=" (cdr eqn))))
7353 "")))))
7355 (defun org-table-current-column ()
7356 "Find out which column we are in.
7357 When called interactively, column is also displayed in echo area."
7358 (interactive)
7359 (if (interactive-p) (org-table-check-inside-data-field))
7360 (save-excursion
7361 (let ((cnt 0) (pos (point)))
7362 (beginning-of-line 1)
7363 (while (search-forward "|" pos t)
7364 (setq cnt (1+ cnt)))
7365 (if (interactive-p) (message "This is table column %d" cnt))
7366 cnt)))
7368 (defun org-table-current-dline ()
7369 "Find out what table data line we are in.
7370 Only datalins count for this."
7371 (interactive)
7372 (if (interactive-p) (org-table-check-inside-data-field))
7373 (save-excursion
7374 (let ((cnt 0) (pos (point)))
7375 (goto-char (org-table-begin))
7376 (while (<= (point) pos)
7377 (if (looking-at org-table-dataline-regexp) (setq cnt (1+ cnt)))
7378 (beginning-of-line 2))
7379 (if (interactive-p) (message "This is table line %d" cnt))
7380 cnt)))
7382 (defun org-table-goto-column (n &optional on-delim force)
7383 "Move the cursor to the Nth column in the current table line.
7384 With optional argument ON-DELIM, stop with point before the left delimiter
7385 of the field.
7386 If there are less than N fields, just go to after the last delimiter.
7387 However, when FORCE is non-nil, create new columns if necessary."
7388 (interactive "p")
7389 (let ((pos (point-at-eol)))
7390 (beginning-of-line 1)
7391 (when (> n 0)
7392 (while (and (> (setq n (1- n)) -1)
7393 (or (search-forward "|" pos t)
7394 (and force
7395 (progn (end-of-line 1)
7396 (skip-chars-backward "^|")
7397 (insert " | "))))))
7398 ; (backward-char 2) t)))))
7399 (when (and force (not (looking-at ".*|")))
7400 (save-excursion (end-of-line 1) (insert " | ")))
7401 (if on-delim
7402 (backward-char 1)
7403 (if (looking-at " ") (forward-char 1))))))
7405 (defun org-at-table-p (&optional table-type)
7406 "Return t if the cursor is inside an org-type table.
7407 If TABLE-TYPE is non-nil, also check for table.el-type tables."
7408 (if org-enable-table-editor
7409 (save-excursion
7410 (beginning-of-line 1)
7411 (looking-at (if table-type org-table-any-line-regexp
7412 org-table-line-regexp)))
7413 nil))
7415 (defun org-at-table.el-p ()
7416 "Return t if and only if we are at a table.el table."
7417 (and (org-at-table-p 'any)
7418 (save-excursion
7419 (goto-char (org-table-begin 'any))
7420 (looking-at org-table1-hline-regexp))))
7422 (defun org-table-recognize-table.el ()
7423 "If there is a table.el table nearby, recognize it and move into it."
7424 (if org-table-tab-recognizes-table.el
7425 (if (org-at-table.el-p)
7426 (progn
7427 (beginning-of-line 1)
7428 (if (looking-at org-table-dataline-regexp)
7430 (if (looking-at org-table1-hline-regexp)
7431 (progn
7432 (beginning-of-line 2)
7433 (if (looking-at org-table-any-border-regexp)
7434 (beginning-of-line -1)))))
7435 (if (re-search-forward "|" (org-table-end t) t)
7436 (progn
7437 (require 'table)
7438 (if (table--at-cell-p (point))
7440 (message "recognizing table.el table...")
7441 (table-recognize-table)
7442 (message "recognizing table.el table...done")))
7443 (error "This should not happen..."))
7445 nil)
7446 nil))
7448 (defun org-at-table-hline-p ()
7449 "Return t if the cursor is inside a hline in a table."
7450 (if org-enable-table-editor
7451 (save-excursion
7452 (beginning-of-line 1)
7453 (looking-at org-table-hline-regexp))
7454 nil))
7456 (defun org-table-insert-column ()
7457 "Insert a new column into the table."
7458 (interactive)
7459 (if (not (org-at-table-p))
7460 (error "Not at a table"))
7461 (org-table-find-dataline)
7462 (let* ((col (max 1 (org-table-current-column)))
7463 (beg (org-table-begin))
7464 (end (org-table-end))
7465 ;; Current cursor position
7466 (linepos (org-current-line))
7467 (colpos col))
7468 (goto-char beg)
7469 (while (< (point) end)
7470 (if (org-at-table-hline-p)
7472 (org-table-goto-column col t)
7473 (insert "| "))
7474 (beginning-of-line 2))
7475 (move-marker end nil)
7476 (goto-line linepos)
7477 (org-table-goto-column colpos)
7478 (org-table-align)
7479 (org-table-fix-formulas "$" nil (1- col) 1)))
7481 (defun org-table-find-dataline ()
7482 "Find a dataline in the current table, which is needed for column commands."
7483 (if (and (org-at-table-p)
7484 (not (org-at-table-hline-p)))
7486 (let ((col (current-column))
7487 (end (org-table-end)))
7488 (move-to-column col)
7489 (while (and (< (point) end)
7490 (or (not (= (current-column) col))
7491 (org-at-table-hline-p)))
7492 (beginning-of-line 2)
7493 (move-to-column col))
7494 (if (and (org-at-table-p)
7495 (not (org-at-table-hline-p)))
7497 (error
7498 "Please position cursor in a data line for column operations")))))
7500 (defun org-table-delete-column ()
7501 "Delete a column from the table."
7502 (interactive)
7503 (if (not (org-at-table-p))
7504 (error "Not at a table"))
7505 (org-table-find-dataline)
7506 (org-table-check-inside-data-field)
7507 (let* ((col (org-table-current-column))
7508 (beg (org-table-begin))
7509 (end (org-table-end))
7510 ;; Current cursor position
7511 (linepos (org-current-line))
7512 (colpos col))
7513 (goto-char beg)
7514 (while (< (point) end)
7515 (if (org-at-table-hline-p)
7517 (org-table-goto-column col t)
7518 (and (looking-at "|[^|\n]+|")
7519 (replace-match "|")))
7520 (beginning-of-line 2))
7521 (move-marker end nil)
7522 (goto-line linepos)
7523 (org-table-goto-column colpos)
7524 (org-table-align)
7525 (org-table-fix-formulas "$" (list (cons (number-to-string col) "INVALID"))
7526 col -1 col)))
7528 (defun org-table-move-column-right ()
7529 "Move column to the right."
7530 (interactive)
7531 (org-table-move-column nil))
7532 (defun org-table-move-column-left ()
7533 "Move column to the left."
7534 (interactive)
7535 (org-table-move-column 'left))
7537 (defun org-table-move-column (&optional left)
7538 "Move the current column to the right. With arg LEFT, move to the left."
7539 (interactive "P")
7540 (if (not (org-at-table-p))
7541 (error "Not at a table"))
7542 (org-table-find-dataline)
7543 (org-table-check-inside-data-field)
7544 (let* ((col (org-table-current-column))
7545 (col1 (if left (1- col) col))
7546 (beg (org-table-begin))
7547 (end (org-table-end))
7548 ;; Current cursor position
7549 (linepos (org-current-line))
7550 (colpos (if left (1- col) (1+ col))))
7551 (if (and left (= col 1))
7552 (error "Cannot move column further left"))
7553 (if (and (not left) (looking-at "[^|\n]*|[^|\n]*$"))
7554 (error "Cannot move column further right"))
7555 (goto-char beg)
7556 (while (< (point) end)
7557 (if (org-at-table-hline-p)
7559 (org-table-goto-column col1 t)
7560 (and (looking-at "|\\([^|\n]+\\)|\\([^|\n]+\\)|")
7561 (replace-match "|\\2|\\1|")))
7562 (beginning-of-line 2))
7563 (move-marker end nil)
7564 (goto-line linepos)
7565 (org-table-goto-column colpos)
7566 (org-table-align)
7567 (org-table-fix-formulas
7568 "$" (list (cons (number-to-string col) (number-to-string colpos))
7569 (cons (number-to-string colpos) (number-to-string col))))))
7571 (defun org-table-move-row-down ()
7572 "Move table row down."
7573 (interactive)
7574 (org-table-move-row nil))
7575 (defun org-table-move-row-up ()
7576 "Move table row up."
7577 (interactive)
7578 (org-table-move-row 'up))
7580 (defun org-table-move-row (&optional up)
7581 "Move the current table line down. With arg UP, move it up."
7582 (interactive "P")
7583 (let* ((col (current-column))
7584 (pos (point))
7585 (hline1p (save-excursion (beginning-of-line 1)
7586 (looking-at org-table-hline-regexp)))
7587 (dline1 (org-table-current-dline))
7588 (dline2 (+ dline1 (if up -1 1)))
7589 (tonew (if up 0 2))
7590 txt hline2p)
7591 (beginning-of-line tonew)
7592 (unless (org-at-table-p)
7593 (goto-char pos)
7594 (error "Cannot move row further"))
7595 (setq hline2p (looking-at org-table-hline-regexp))
7596 (goto-char pos)
7597 (beginning-of-line 1)
7598 (setq pos (point))
7599 (setq txt (buffer-substring (point) (1+ (point-at-eol))))
7600 (delete-region (point) (1+ (point-at-eol)))
7601 (beginning-of-line tonew)
7602 (insert txt)
7603 (beginning-of-line 0)
7604 (move-to-column col)
7605 (unless (or hline1p hline2p)
7606 (org-table-fix-formulas
7607 "@" (list (cons (number-to-string dline1) (number-to-string dline2))
7608 (cons (number-to-string dline2) (number-to-string dline1)))))))
7610 (defun org-table-insert-row (&optional arg)
7611 "Insert a new row above the current line into the table.
7612 With prefix ARG, insert below the current line."
7613 (interactive "P")
7614 (if (not (org-at-table-p))
7615 (error "Not at a table"))
7616 (let* ((line (buffer-substring (point-at-bol) (point-at-eol)))
7617 (new (org-table-clean-line line)))
7618 ;; Fix the first field if necessary
7619 (if (string-match "^[ \t]*| *[#$] *|" line)
7620 (setq new (replace-match (match-string 0 line) t t new)))
7621 (beginning-of-line (if arg 2 1))
7622 (let (org-table-may-need-update) (insert-before-markers new "\n"))
7623 (beginning-of-line 0)
7624 (re-search-forward "| ?" (point-at-eol) t)
7625 (and (or org-table-may-need-update org-table-overlay-coordinates)
7626 (org-table-align))
7627 (org-table-fix-formulas "@" nil (1- (org-table-current-dline)) 1)))
7629 (defun org-table-insert-hline (&optional above)
7630 "Insert a horizontal-line below the current line into the table.
7631 With prefix ABOVE, insert above the current line."
7632 (interactive "P")
7633 (if (not (org-at-table-p))
7634 (error "Not at a table"))
7635 (let ((line (org-table-clean-line
7636 (buffer-substring (point-at-bol) (point-at-eol))))
7637 (col (current-column)))
7638 (while (string-match "|\\( +\\)|" line)
7639 (setq line (replace-match
7640 (concat "+" (make-string (- (match-end 1) (match-beginning 1))
7641 ?-) "|") t t line)))
7642 (and (string-match "\\+" line) (setq line (replace-match "|" t t line)))
7643 (beginning-of-line (if above 1 2))
7644 (insert line "\n")
7645 (beginning-of-line (if above 1 -1))
7646 (move-to-column col)
7647 (and org-table-overlay-coordinates (org-table-align))))
7649 (defun org-table-hline-and-move (&optional same-column)
7650 "Insert a hline and move to the row below that line."
7651 (interactive "P")
7652 (let ((col (org-table-current-column)))
7653 (org-table-maybe-eval-formula)
7654 (org-table-maybe-recalculate-line)
7655 (org-table-insert-hline)
7656 (end-of-line 2)
7657 (if (looking-at "\n[ \t]*|-")
7658 (progn (insert "\n|") (org-table-align))
7659 (org-table-next-field))
7660 (if same-column (org-table-goto-column col))))
7662 (defun org-table-clean-line (s)
7663 "Convert a table line S into a string with only \"|\" and space.
7664 In particular, this does handle wide and invisible characters."
7665 (if (string-match "^[ \t]*|-" s)
7666 ;; It's a hline, just map the characters
7667 (setq s (mapconcat (lambda (x) (if (member x '(?| ?+)) "|" " ")) s ""))
7668 (while (string-match "|\\([ \t]*?[^ \t\r\n|][^\r\n|]*\\)|" s)
7669 (setq s (replace-match
7670 (concat "|" (make-string (org-string-width (match-string 1 s))
7671 ?\ ) "|")
7672 t t s)))
7675 (defun org-table-kill-row ()
7676 "Delete the current row or horizontal line from the table."
7677 (interactive)
7678 (if (not (org-at-table-p))
7679 (error "Not at a table"))
7680 (let ((col (current-column))
7681 (dline (org-table-current-dline)))
7682 (kill-region (point-at-bol) (min (1+ (point-at-eol)) (point-max)))
7683 (if (not (org-at-table-p)) (beginning-of-line 0))
7684 (move-to-column col)
7685 (org-table-fix-formulas "@" (list (cons (number-to-string dline) "INVALID"))
7686 dline -1 dline)))
7689 (defun org-table-sort-lines (with-case &optional sorting-type)
7690 "Sort table lines according to the column at point.
7692 The position of point indicates the column to be used for
7693 sorting, and the range of lines is the range between the nearest
7694 horizontal separator lines, or the entire table of no such lines
7695 exist. If point is before the first column, you will be prompted
7696 for the sorting column. If there is an active region, the mark
7697 specifies the first line and the sorting column, while point
7698 should be in the last line to be included into the sorting.
7700 The command then prompts for the sorting type which can be
7701 alphabetically, numerically, or by time (as given in a time stamp
7702 in the field). Sorting in reverse order is also possible.
7704 With prefix argument WITH-CASE, alphabetic sorting will be case-sensitive.
7706 If SORTING-TYPE is specified when this function is called from a Lisp
7707 program, no prompting will take place. SORTING-TYPE must be a character,
7708 any of (?a ?A ?n ?N ?t ?T) where the capital letter indicate that sorting
7709 should be done in reverse order."
7710 (interactive "P")
7711 (let* ((thisline (org-current-line))
7712 (thiscol (org-table-current-column))
7713 beg end bcol ecol tend tbeg column lns pos)
7714 (when (equal thiscol 0)
7715 (if (interactive-p)
7716 (setq thiscol
7717 (string-to-number
7718 (read-string "Use column N for sorting: ")))
7719 (setq thiscol 1))
7720 (org-table-goto-column thiscol))
7721 (org-table-check-inside-data-field)
7722 (if (org-region-active-p)
7723 (progn
7724 (setq beg (region-beginning) end (region-end))
7725 (goto-char beg)
7726 (setq column (org-table-current-column)
7727 beg (point-at-bol))
7728 (goto-char end)
7729 (setq end (point-at-bol 2)))
7730 (setq column (org-table-current-column)
7731 pos (point)
7732 tbeg (org-table-begin)
7733 tend (org-table-end))
7734 (if (re-search-backward org-table-hline-regexp tbeg t)
7735 (setq beg (point-at-bol 2))
7736 (goto-char tbeg)
7737 (setq beg (point-at-bol 1)))
7738 (goto-char pos)
7739 (if (re-search-forward org-table-hline-regexp tend t)
7740 (setq end (point-at-bol 1))
7741 (goto-char tend)
7742 (setq end (point-at-bol))))
7743 (setq beg (move-marker (make-marker) beg)
7744 end (move-marker (make-marker) end))
7745 (untabify beg end)
7746 (goto-char beg)
7747 (org-table-goto-column column)
7748 (skip-chars-backward "^|")
7749 (setq bcol (current-column))
7750 (org-table-goto-column (1+ column))
7751 (skip-chars-backward "^|")
7752 (setq ecol (1- (current-column)))
7753 (org-table-goto-column column)
7754 (setq lns (mapcar (lambda(x) (cons (org-trim (substring x bcol ecol)) x))
7755 (org-split-string (buffer-substring beg end) "\n")))
7756 (setq lns (org-do-sort lns "Table" with-case sorting-type))
7757 (delete-region beg end)
7758 (move-marker beg nil)
7759 (move-marker end nil)
7760 (insert (mapconcat 'cdr lns "\n") "\n")
7761 (goto-line thisline)
7762 (org-table-goto-column thiscol)
7763 (message "%d lines sorted, based on column %d" (length lns) column)))
7765 (defun org-table-cut-region (beg end)
7766 "Copy region in table to the clipboard and blank all relevant fields."
7767 (interactive "r")
7768 (org-table-copy-region beg end 'cut))
7770 (defun org-table-copy-region (beg end &optional cut)
7771 "Copy rectangular region in table to clipboard.
7772 A special clipboard is used which can only be accessed
7773 with `org-table-paste-rectangle'."
7774 (interactive "rP")
7775 (let* (l01 c01 l02 c02 l1 c1 l2 c2 ic1 ic2
7776 region cols
7777 (rpl (if cut " " nil)))
7778 (goto-char beg)
7779 (org-table-check-inside-data-field)
7780 (setq l01 (org-current-line)
7781 c01 (org-table-current-column))
7782 (goto-char end)
7783 (org-table-check-inside-data-field)
7784 (setq l02 (org-current-line)
7785 c02 (org-table-current-column))
7786 (setq l1 (min l01 l02) l2 (max l01 l02)
7787 c1 (min c01 c02) c2 (max c01 c02))
7788 (catch 'exit
7789 (while t
7790 (catch 'nextline
7791 (if (> l1 l2) (throw 'exit t))
7792 (goto-line l1)
7793 (if (org-at-table-hline-p) (throw 'nextline (setq l1 (1+ l1))))
7794 (setq cols nil ic1 c1 ic2 c2)
7795 (while (< ic1 (1+ ic2))
7796 (push (org-table-get-field ic1 rpl) cols)
7797 (setq ic1 (1+ ic1)))
7798 (push (nreverse cols) region)
7799 (setq l1 (1+ l1)))))
7800 (setq org-table-clip (nreverse region))
7801 (if cut (org-table-align))
7802 org-table-clip))
7804 (defun org-table-paste-rectangle ()
7805 "Paste a rectangular region into a table.
7806 The upper right corner ends up in the current field. All involved fields
7807 will be overwritten. If the rectangle does not fit into the present table,
7808 the table is enlarged as needed. The process ignores horizontal separator
7809 lines."
7810 (interactive)
7811 (unless (and org-table-clip (listp org-table-clip))
7812 (error "First cut/copy a region to paste!"))
7813 (org-table-check-inside-data-field)
7814 (let* ((clip org-table-clip)
7815 (line (org-current-line))
7816 (col (org-table-current-column))
7817 (org-enable-table-editor t)
7818 (org-table-automatic-realign nil)
7819 c cols field)
7820 (while (setq cols (pop clip))
7821 (while (org-at-table-hline-p) (beginning-of-line 2))
7822 (if (not (org-at-table-p))
7823 (progn (end-of-line 0) (org-table-next-field)))
7824 (setq c col)
7825 (while (setq field (pop cols))
7826 (org-table-goto-column c nil 'force)
7827 (org-table-get-field nil field)
7828 (setq c (1+ c)))
7829 (beginning-of-line 2))
7830 (goto-line line)
7831 (org-table-goto-column col)
7832 (org-table-align)))
7834 (defun org-table-convert ()
7835 "Convert from `org-mode' table to table.el and back.
7836 Obviously, this only works within limits. When an Org-mode table is
7837 converted to table.el, all horizontal separator lines get lost, because
7838 table.el uses these as cell boundaries and has no notion of horizontal lines.
7839 A table.el table can be converted to an Org-mode table only if it does not
7840 do row or column spanning. Multiline cells will become multiple cells.
7841 Beware, Org-mode does not test if the table can be successfully converted - it
7842 blindly applies a recipe that works for simple tables."
7843 (interactive)
7844 (require 'table)
7845 (if (org-at-table.el-p)
7846 ;; convert to Org-mode table
7847 (let ((beg (move-marker (make-marker) (org-table-begin t)))
7848 (end (move-marker (make-marker) (org-table-end t))))
7849 (table-unrecognize-region beg end)
7850 (goto-char beg)
7851 (while (re-search-forward "^\\([ \t]*\\)\\+-.*\n" end t)
7852 (replace-match ""))
7853 (goto-char beg))
7854 (if (org-at-table-p)
7855 ;; convert to table.el table
7856 (let ((beg (move-marker (make-marker) (org-table-begin)))
7857 (end (move-marker (make-marker) (org-table-end))))
7858 ;; first, get rid of all horizontal lines
7859 (goto-char beg)
7860 (while (re-search-forward "^\\([ \t]*\\)|-.*\n" end t)
7861 (replace-match ""))
7862 ;; insert a hline before first
7863 (goto-char beg)
7864 (org-table-insert-hline 'above)
7865 (beginning-of-line -1)
7866 ;; insert a hline after each line
7867 (while (progn (beginning-of-line 3) (< (point) end))
7868 (org-table-insert-hline))
7869 (goto-char beg)
7870 (setq end (move-marker end (org-table-end)))
7871 ;; replace "+" at beginning and ending of hlines
7872 (while (re-search-forward "^\\([ \t]*\\)|-" end t)
7873 (replace-match "\\1+-"))
7874 (goto-char beg)
7875 (while (re-search-forward "-|[ \t]*$" end t)
7876 (replace-match "-+"))
7877 (goto-char beg)))))
7879 (defun org-table-wrap-region (arg)
7880 "Wrap several fields in a column like a paragraph.
7881 This is useful if you'd like to spread the contents of a field over several
7882 lines, in order to keep the table compact.
7884 If there is an active region, and both point and mark are in the same column,
7885 the text in the column is wrapped to minimum width for the given number of
7886 lines. Generally, this makes the table more compact. A prefix ARG may be
7887 used to change the number of desired lines. For example, `C-2 \\[org-table-wrap]'
7888 formats the selected text to two lines. If the region was longer than two
7889 lines, the remaining lines remain empty. A negative prefix argument reduces
7890 the current number of lines by that amount. The wrapped text is pasted back
7891 into the table. If you formatted it to more lines than it was before, fields
7892 further down in the table get overwritten - so you might need to make space in
7893 the table first.
7895 If there is no region, the current field is split at the cursor position and
7896 the text fragment to the right of the cursor is prepended to the field one
7897 line down.
7899 If there is no region, but you specify a prefix ARG, the current field gets
7900 blank, and the content is appended to the field above."
7901 (interactive "P")
7902 (org-table-check-inside-data-field)
7903 (if (org-region-active-p)
7904 ;; There is a region: fill as a paragraph
7905 (let* ((beg (region-beginning))
7906 (cline (save-excursion (goto-char beg) (org-current-line)))
7907 (ccol (save-excursion (goto-char beg) (org-table-current-column)))
7908 nlines)
7909 (org-table-cut-region (region-beginning) (region-end))
7910 (if (> (length (car org-table-clip)) 1)
7911 (error "Region must be limited to single column"))
7912 (setq nlines (if arg
7913 (if (< arg 1)
7914 (+ (length org-table-clip) arg)
7915 arg)
7916 (length org-table-clip)))
7917 (setq org-table-clip
7918 (mapcar 'list (org-wrap (mapconcat 'car org-table-clip " ")
7919 nil nlines)))
7920 (goto-line cline)
7921 (org-table-goto-column ccol)
7922 (org-table-paste-rectangle))
7923 ;; No region, split the current field at point
7924 (if arg
7925 ;; combine with field above
7926 (let ((s (org-table-blank-field))
7927 (col (org-table-current-column)))
7928 (beginning-of-line 0)
7929 (while (org-at-table-hline-p) (beginning-of-line 0))
7930 (org-table-goto-column col)
7931 (skip-chars-forward "^|")
7932 (skip-chars-backward " ")
7933 (insert " " (org-trim s))
7934 (org-table-align))
7935 ;; split field
7936 (when (looking-at "\\([^|]+\\)+|")
7937 (let ((s (match-string 1)))
7938 (replace-match " |")
7939 (goto-char (match-beginning 0))
7940 (org-table-next-row)
7941 (insert (org-trim s) " ")
7942 (org-table-align))))))
7944 (defvar org-field-marker nil)
7946 (defun org-table-edit-field (arg)
7947 "Edit table field in a different window.
7948 This is mainly useful for fields that contain hidden parts.
7949 When called with a \\[universal-argument] prefix, just make the full field visible so that
7950 it can be edited in place."
7951 (interactive "P")
7952 (if arg
7953 (let ((b (save-excursion (skip-chars-backward "^|") (point)))
7954 (e (save-excursion (skip-chars-forward "^|\r\n") (point))))
7955 (remove-text-properties b e '(org-cwidth t invisible t
7956 display t intangible t))
7957 (if (and (boundp 'font-lock-mode) font-lock-mode)
7958 (font-lock-fontify-block)))
7959 (let ((pos (move-marker (make-marker) (point)))
7960 (field (org-table-get-field))
7961 (cw (current-window-configuration))
7963 (switch-to-buffer-other-window "*Org tmp*")
7964 (erase-buffer)
7965 (insert "#\n# Edit field and finish with C-c C-c\n#\n")
7966 (let ((org-inhibit-startup t)) (org-mode))
7967 (goto-char (setq p (point-max)))
7968 (insert (org-trim field))
7969 (remove-text-properties p (point-max)
7970 '(invisible t org-cwidth t display t
7971 intangible t))
7972 (goto-char p)
7973 (org-set-local 'org-finish-function 'org-table-finish-edit-field)
7974 (org-set-local 'org-window-configuration cw)
7975 (org-set-local 'org-field-marker pos)
7976 (message "Edit and finish with C-c C-c"))))
7978 (defun org-table-finish-edit-field ()
7979 "Finish editing a table data field.
7980 Remove all newline characters, insert the result into the table, realign
7981 the table and kill the editing buffer."
7982 (let ((pos org-field-marker)
7983 (cw org-window-configuration)
7984 (cb (current-buffer))
7985 text)
7986 (goto-char (point-min))
7987 (while (re-search-forward "^#.*\n?" nil t) (replace-match ""))
7988 (while (re-search-forward "\\([ \t]*\n[ \t]*\\)+" nil t)
7989 (replace-match " "))
7990 (setq text (org-trim (buffer-string)))
7991 (set-window-configuration cw)
7992 (kill-buffer cb)
7993 (select-window (get-buffer-window (marker-buffer pos)))
7994 (goto-char pos)
7995 (move-marker pos nil)
7996 (org-table-check-inside-data-field)
7997 (org-table-get-field nil text)
7998 (org-table-align)
7999 (message "New field value inserted")))
8001 (defun org-trim (s)
8002 "Remove whitespace at beginning and end of string."
8003 (if (string-match "^[ \t\n\r]+" s) (setq s (replace-match "" t t s)))
8004 (if (string-match "[ \t\n\r]+$" s) (setq s (replace-match "" t t s)))
8007 (defun org-wrap (string &optional width lines)
8008 "Wrap string to either a number of lines, or a width in characters.
8009 If WIDTH is non-nil, the string is wrapped to that width, however many lines
8010 that costs. If there is a word longer than WIDTH, the text is actually
8011 wrapped to the length of that word.
8012 IF WIDTH is nil and LINES is non-nil, the string is forced into at most that
8013 many lines, whatever width that takes.
8014 The return value is a list of lines, without newlines at the end."
8015 (let* ((words (org-split-string string "[ \t\n]+"))
8016 (maxword (apply 'max (mapcar 'org-string-width words)))
8017 w ll)
8018 (cond (width
8019 (org-do-wrap words (max maxword width)))
8020 (lines
8021 (setq w maxword)
8022 (setq ll (org-do-wrap words maxword))
8023 (if (<= (length ll) lines)
8025 (setq ll words)
8026 (while (> (length ll) lines)
8027 (setq w (1+ w))
8028 (setq ll (org-do-wrap words w)))
8029 ll))
8030 (t (error "Cannot wrap this")))))
8033 (defun org-do-wrap (words width)
8034 "Create lines of maximum width WIDTH (in characters) from word list WORDS."
8035 (let (lines line)
8036 (while words
8037 (setq line (pop words))
8038 (while (and words (< (+ (length line) (length (car words))) width))
8039 (setq line (concat line " " (pop words))))
8040 (setq lines (push line lines)))
8041 (nreverse lines)))
8043 (defun org-split-string (string &optional separators)
8044 "Splits STRING into substrings at SEPARATORS.
8045 No empty strings are returned if there are matches at the beginning
8046 and end of string."
8047 (let ((rexp (or separators "[ \f\t\n\r\v]+"))
8048 (start 0)
8049 notfirst
8050 (list nil))
8051 (while (and (string-match rexp string
8052 (if (and notfirst
8053 (= start (match-beginning 0))
8054 (< start (length string)))
8055 (1+ start) start))
8056 (< (match-beginning 0) (length string)))
8057 (setq notfirst t)
8058 (or (eq (match-beginning 0) 0)
8059 (and (eq (match-beginning 0) (match-end 0))
8060 (eq (match-beginning 0) start))
8061 (setq list
8062 (cons (substring string start (match-beginning 0))
8063 list)))
8064 (setq start (match-end 0)))
8065 (or (eq start (length string))
8066 (setq list
8067 (cons (substring string start)
8068 list)))
8069 (nreverse list)))
8071 (defun org-table-map-tables (function)
8072 "Apply FUNCTION to the start of all tables in the buffer."
8073 (save-excursion
8074 (save-restriction
8075 (widen)
8076 (goto-char (point-min))
8077 (while (re-search-forward org-table-any-line-regexp nil t)
8078 (message "Mapping tables: %d%%" (/ (* 100.0 (point)) (buffer-size)))
8079 (beginning-of-line 1)
8080 (if (looking-at org-table-line-regexp)
8081 (save-excursion (funcall function)))
8082 (re-search-forward org-table-any-border-regexp nil 1))))
8083 (message "Mapping tables: done"))
8085 (defvar org-timecnt) ; dynamically scoped parameter
8087 (defun org-table-sum (&optional beg end nlast)
8088 "Sum numbers in region of current table column.
8089 The result will be displayed in the echo area, and will be available
8090 as kill to be inserted with \\[yank].
8092 If there is an active region, it is interpreted as a rectangle and all
8093 numbers in that rectangle will be summed. If there is no active
8094 region and point is located in a table column, sum all numbers in that
8095 column.
8097 If at least one number looks like a time HH:MM or HH:MM:SS, all other
8098 numbers are assumed to be times as well (in decimal hours) and the
8099 numbers are added as such.
8101 If NLAST is a number, only the NLAST fields will actually be summed."
8102 (interactive)
8103 (save-excursion
8104 (let (col (org-timecnt 0) diff h m s org-table-clip)
8105 (cond
8106 ((and beg end)) ; beg and end given explicitly
8107 ((org-region-active-p)
8108 (setq beg (region-beginning) end (region-end)))
8110 (setq col (org-table-current-column))
8111 (goto-char (org-table-begin))
8112 (unless (re-search-forward "^[ \t]*|[^-]" nil t)
8113 (error "No table data"))
8114 (org-table-goto-column col)
8115 (setq beg (point))
8116 (goto-char (org-table-end))
8117 (unless (re-search-backward "^[ \t]*|[^-]" nil t)
8118 (error "No table data"))
8119 (org-table-goto-column col)
8120 (setq end (point))))
8121 (let* ((items (apply 'append (org-table-copy-region beg end)))
8122 (items1 (cond ((not nlast) items)
8123 ((>= nlast (length items)) items)
8124 (t (setq items (reverse items))
8125 (setcdr (nthcdr (1- nlast) items) nil)
8126 (nreverse items))))
8127 (numbers (delq nil (mapcar 'org-table-get-number-for-summing
8128 items1)))
8129 (res (apply '+ numbers))
8130 (sres (if (= org-timecnt 0)
8131 (format "%g" res)
8132 (setq diff (* 3600 res)
8133 h (floor (/ diff 3600)) diff (mod diff 3600)
8134 m (floor (/ diff 60)) diff (mod diff 60)
8135 s diff)
8136 (format "%d:%02d:%02d" h m s))))
8137 (kill-new sres)
8138 (if (interactive-p)
8139 (message "%s"
8140 (substitute-command-keys
8141 (format "Sum of %d items: %-20s (\\[yank] will insert result into buffer)"
8142 (length numbers) sres))))
8143 sres))))
8145 (defun org-table-get-number-for-summing (s)
8146 (let (n)
8147 (if (string-match "^ *|? *" s)
8148 (setq s (replace-match "" nil nil s)))
8149 (if (string-match " *|? *$" s)
8150 (setq s (replace-match "" nil nil s)))
8151 (setq n (string-to-number s))
8152 (cond
8153 ((and (string-match "0" s)
8154 (string-match "\\`[-+ \t0.edED]+\\'" s)) 0)
8155 ((string-match "\\`[ \t]+\\'" s) nil)
8156 ((string-match "\\`\\([0-9]+\\):\\([0-9]+\\)\\(:\\([0-9]+\\)\\)?\\'" s)
8157 (let ((h (string-to-number (or (match-string 1 s) "0")))
8158 (m (string-to-number (or (match-string 2 s) "0")))
8159 (s (string-to-number (or (match-string 4 s) "0"))))
8160 (if (boundp 'org-timecnt) (setq org-timecnt (1+ org-timecnt)))
8161 (* 1.0 (+ h (/ m 60.0) (/ s 3600.0)))))
8162 ((equal n 0) nil)
8163 (t n))))
8165 (defun org-table-current-field-formula (&optional key noerror)
8166 "Return the formula active for the current field.
8167 Assumes that specials are in place.
8168 If KEY is given, return the key to this formula.
8169 Otherwise return the formula preceeded with \"=\" or \":=\"."
8170 (let* ((name (car (rassoc (list (org-current-line)
8171 (org-table-current-column))
8172 org-table-named-field-locations)))
8173 (col (org-table-current-column))
8174 (scol (int-to-string col))
8175 (ref (format "@%d$%d" (org-table-current-dline) col))
8176 (stored-list (org-table-get-stored-formulas noerror))
8177 (ass (or (assoc name stored-list)
8178 (assoc ref stored-list)
8179 (assoc scol stored-list))))
8180 (if key
8181 (car ass)
8182 (if ass (concat (if (string-match "^[0-9]+$" (car ass)) "=" ":=")
8183 (cdr ass))))))
8185 (defun org-table-get-formula (&optional equation named)
8186 "Read a formula from the minibuffer, offer stored formula as default.
8187 When NAMED is non-nil, look for a named equation."
8188 (let* ((stored-list (org-table-get-stored-formulas))
8189 (name (car (rassoc (list (org-current-line)
8190 (org-table-current-column))
8191 org-table-named-field-locations)))
8192 (ref (format "@%d$%d" (org-table-current-dline)
8193 (org-table-current-column)))
8194 (refass (assoc ref stored-list))
8195 (scol (if named
8196 (if name name ref)
8197 (int-to-string (org-table-current-column))))
8198 (dummy (and (or name refass) (not named)
8199 (not (y-or-n-p "Replace field formula with column formula? " ))
8200 (error "Abort")))
8201 (name (or name ref))
8202 (org-table-may-need-update nil)
8203 (stored (cdr (assoc scol stored-list)))
8204 (eq (cond
8205 ((and stored equation (string-match "^ *=? *$" equation))
8206 stored)
8207 ((stringp equation)
8208 equation)
8209 (t (org-table-formula-from-user
8210 (read-string
8211 (org-table-formula-to-user
8212 (format "%s formula %s%s="
8213 (if named "Field" "Column")
8214 (if (member (string-to-char scol) '(?$ ?@)) "" "$")
8215 scol))
8216 (if stored (org-table-formula-to-user stored) "")
8217 'org-table-formula-history
8218 )))))
8219 mustsave)
8220 (when (not (string-match "\\S-" eq))
8221 ;; remove formula
8222 (setq stored-list (delq (assoc scol stored-list) stored-list))
8223 (org-table-store-formulas stored-list)
8224 (error "Formula removed"))
8225 (if (string-match "^ *=?" eq) (setq eq (replace-match "" t t eq)))
8226 (if (string-match " *$" eq) (setq eq (replace-match "" t t eq)))
8227 (if (and name (not named))
8228 ;; We set the column equation, delete the named one.
8229 (setq stored-list (delq (assoc name stored-list) stored-list)
8230 mustsave t))
8231 (if stored
8232 (setcdr (assoc scol stored-list) eq)
8233 (setq stored-list (cons (cons scol eq) stored-list)))
8234 (if (or mustsave (not (equal stored eq)))
8235 (org-table-store-formulas stored-list))
8236 eq))
8238 (defun org-table-store-formulas (alist)
8239 "Store the list of formulas below the current table."
8240 (setq alist (sort alist 'org-table-formula-less-p))
8241 (save-excursion
8242 (goto-char (org-table-end))
8243 (if (looking-at "\\([ \t]*\n\\)*#\\+TBLFM:\\(.*\n?\\)")
8244 (progn
8245 ;; don't overwrite TBLFM, we might use text properties to store stuff
8246 (goto-char (match-beginning 2))
8247 (delete-region (match-beginning 2) (match-end 0)))
8248 (insert "#+TBLFM:"))
8249 (insert " "
8250 (mapconcat (lambda (x)
8251 (concat
8252 (if (equal (string-to-char (car x)) ?@) "" "$")
8253 (car x) "=" (cdr x)))
8254 alist "::")
8255 "\n")))
8257 (defsubst org-table-formula-make-cmp-string (a)
8258 (when (string-match "^\\(@\\([0-9]+\\)\\)?\\(\\$?\\([0-9]+\\)\\)?\\(\\$?[a-zA-Z0-9]+\\)?" a)
8259 (concat
8260 (if (match-end 2) (format "@%05d" (string-to-number (match-string 2 a))) "")
8261 (if (match-end 4) (format "$%05d" (string-to-number (match-string 4 a))) "")
8262 (if (match-end 5) (concat "@@" (match-string 5 a))))))
8264 (defun org-table-formula-less-p (a b)
8265 "Compare two formulas for sorting."
8266 (let ((as (org-table-formula-make-cmp-string (car a)))
8267 (bs (org-table-formula-make-cmp-string (car b))))
8268 (and as bs (string< as bs))))
8270 (defun org-table-get-stored-formulas (&optional noerror)
8271 "Return an alist with the stored formulas directly after current table."
8272 (interactive)
8273 (let (scol eq eq-alist strings string seen)
8274 (save-excursion
8275 (goto-char (org-table-end))
8276 (when (looking-at "\\([ \t]*\n\\)*#\\+TBLFM: *\\(.*\\)")
8277 (setq strings (org-split-string (match-string 2) " *:: *"))
8278 (while (setq string (pop strings))
8279 (when (string-match "\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*[^ \t]\\)" string)
8280 (setq scol (if (match-end 2)
8281 (match-string 2 string)
8282 (match-string 1 string))
8283 eq (match-string 3 string)
8284 eq-alist (cons (cons scol eq) eq-alist))
8285 (if (member scol seen)
8286 (if noerror
8287 (progn
8288 (message "Double definition `$%s=' in TBLFM line, please fix by hand" scol)
8289 (ding)
8290 (sit-for 2))
8291 (error "Double definition `$%s=' in TBLFM line, please fix by hand" scol))
8292 (push scol seen))))))
8293 (nreverse eq-alist)))
8295 (defun org-table-fix-formulas (key replace &optional limit delta remove)
8296 "Modify the equations after the table structure has been edited.
8297 KEY is \"@\" or \"$\". REPLACE is an alist of numbers to replace.
8298 For all numbers larger than LIMIT, shift them by DELTA."
8299 (save-excursion
8300 (goto-char (org-table-end))
8301 (when (looking-at "#\\+TBLFM:")
8302 (let ((re (concat key "\\([0-9]+\\)"))
8303 (re2
8304 (when remove
8305 (if (equal key "$")
8306 (format "\\(@[0-9]+\\)?\\$%d=.*?\\(::\\|$\\)" remove)
8307 (format "@%d\\$[0-9]+=.*?\\(::\\|$\\)" remove))))
8308 s n a)
8309 (when remove
8310 (while (re-search-forward re2 (point-at-eol) t)
8311 (replace-match "")))
8312 (while (re-search-forward re (point-at-eol) t)
8313 (setq s (match-string 1) n (string-to-number s))
8314 (cond
8315 ((setq a (assoc s replace))
8316 (replace-match (concat key (cdr a)) t t))
8317 ((and limit (> n limit))
8318 (replace-match (concat key (int-to-string (+ n delta))) t t))))))))
8320 (defun org-table-get-specials ()
8321 "Get the column names and local parameters for this table."
8322 (save-excursion
8323 (let ((beg (org-table-begin)) (end (org-table-end))
8324 names name fields fields1 field cnt
8325 c v l line col types dlines hlines)
8326 (setq org-table-column-names nil
8327 org-table-local-parameters nil
8328 org-table-named-field-locations nil
8329 org-table-current-begin-line nil
8330 org-table-current-begin-pos nil
8331 org-table-current-line-types nil)
8332 (goto-char beg)
8333 (when (re-search-forward "^[ \t]*| *! *\\(|.*\\)" end t)
8334 (setq names (org-split-string (match-string 1) " *| *")
8335 cnt 1)
8336 (while (setq name (pop names))
8337 (setq cnt (1+ cnt))
8338 (if (string-match "^[a-zA-Z][a-zA-Z0-9]*$" name)
8339 (push (cons name (int-to-string cnt)) org-table-column-names))))
8340 (setq org-table-column-names (nreverse org-table-column-names))
8341 (setq org-table-column-name-regexp
8342 (concat "\\$\\(" (mapconcat 'car org-table-column-names "\\|") "\\)\\>"))
8343 (goto-char beg)
8344 (while (re-search-forward "^[ \t]*| *\\$ *\\(|.*\\)" end t)
8345 (setq fields (org-split-string (match-string 1) " *| *"))
8346 (while (setq field (pop fields))
8347 (if (string-match "^\\([a-zA-Z][_a-zA-Z0-9]*\\|%\\) *= *\\(.*\\)" field)
8348 (push (cons (match-string 1 field) (match-string 2 field))
8349 org-table-local-parameters))))
8350 (goto-char beg)
8351 (while (re-search-forward "^[ \t]*| *\\([_^]\\) *\\(|.*\\)" end t)
8352 (setq c (match-string 1)
8353 fields (org-split-string (match-string 2) " *| *"))
8354 (save-excursion
8355 (beginning-of-line (if (equal c "_") 2 0))
8356 (setq line (org-current-line) col 1)
8357 (and (looking-at "^[ \t]*|[^|]*\\(|.*\\)")
8358 (setq fields1 (org-split-string (match-string 1) " *| *"))))
8359 (while (and fields1 (setq field (pop fields)))
8360 (setq v (pop fields1) col (1+ col))
8361 (when (and (stringp field) (stringp v)
8362 (string-match "^[a-zA-Z][a-zA-Z0-9]*$" field))
8363 (push (cons field v) org-table-local-parameters)
8364 (push (list field line col) org-table-named-field-locations))))
8365 ;; Analyse the line types
8366 (goto-char beg)
8367 (setq org-table-current-begin-line (org-current-line)
8368 org-table-current-begin-pos (point)
8369 l org-table-current-begin-line)
8370 (while (looking-at "[ \t]*|\\(-\\)?")
8371 (push (if (match-end 1) 'hline 'dline) types)
8372 (if (match-end 1) (push l hlines) (push l dlines))
8373 (beginning-of-line 2)
8374 (setq l (1+ l)))
8375 (setq org-table-current-line-types (apply 'vector (nreverse types))
8376 org-table-dlines (apply 'vector (cons nil (nreverse dlines)))
8377 org-table-hlines (apply 'vector (cons nil (nreverse hlines)))))))
8379 (defun org-table-maybe-eval-formula ()
8380 "Check if the current field starts with \"=\" or \":=\".
8381 If yes, store the formula and apply it."
8382 ;; We already know we are in a table. Get field will only return a formula
8383 ;; when appropriate. It might return a separator line, but no problem.
8384 (when org-table-formula-evaluate-inline
8385 (let* ((field (org-trim (or (org-table-get-field) "")))
8386 named eq)
8387 (when (string-match "^:?=\\(.*\\)" field)
8388 (setq named (equal (string-to-char field) ?:)
8389 eq (match-string 1 field))
8390 (if (or (fboundp 'calc-eval)
8391 (equal (substring eq 0 (min 2 (length eq))) "'("))
8392 (org-table-eval-formula (if named '(4) nil)
8393 (org-table-formula-from-user eq))
8394 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))))))
8396 (defvar org-recalc-commands nil
8397 "List of commands triggering the recalculation of a line.
8398 Will be filled automatically during use.")
8400 (defvar org-recalc-marks
8401 '((" " . "Unmarked: no special line, no automatic recalculation")
8402 ("#" . "Automatically recalculate this line upon TAB, RET, and C-c C-c in the line")
8403 ("*" . "Recalculate only when entire table is recalculated with `C-u C-c *'")
8404 ("!" . "Column name definition line. Reference in formula as $name.")
8405 ("$" . "Parameter definition line name=value. Reference in formula as $name.")
8406 ("_" . "Names for values in row below this one.")
8407 ("^" . "Names for values in row above this one.")))
8409 (defun org-table-rotate-recalc-marks (&optional newchar)
8410 "Rotate the recalculation mark in the first column.
8411 If in any row, the first field is not consistent with a mark,
8412 insert a new column for the markers.
8413 When there is an active region, change all the lines in the region,
8414 after prompting for the marking character.
8415 After each change, a message will be displayed indicating the meaning
8416 of the new mark."
8417 (interactive)
8418 (unless (org-at-table-p) (error "Not at a table"))
8419 (let* ((marks (append (mapcar 'car org-recalc-marks) '(" ")))
8420 (beg (org-table-begin))
8421 (end (org-table-end))
8422 (l (org-current-line))
8423 (l1 (if (org-region-active-p) (org-current-line (region-beginning))))
8424 (l2 (if (org-region-active-p) (org-current-line (region-end))))
8425 (have-col
8426 (save-excursion
8427 (goto-char beg)
8428 (not (re-search-forward "^[ \t]*|[^-|][^|]*[^#!$*_^| \t][^|]*|" end t))))
8429 (col (org-table-current-column))
8430 (forcenew (car (assoc newchar org-recalc-marks)))
8431 epos new)
8432 (when l1
8433 (message "Change region to what mark? Type # * ! $ or SPC: ")
8434 (setq newchar (char-to-string (read-char-exclusive))
8435 forcenew (car (assoc newchar org-recalc-marks))))
8436 (if (and newchar (not forcenew))
8437 (error "Invalid NEWCHAR `%s' in `org-table-rotate-recalc-marks'"
8438 newchar))
8439 (if l1 (goto-line l1))
8440 (save-excursion
8441 (beginning-of-line 1)
8442 (unless (looking-at org-table-dataline-regexp)
8443 (error "Not at a table data line")))
8444 (unless have-col
8445 (org-table-goto-column 1)
8446 (org-table-insert-column)
8447 (org-table-goto-column (1+ col)))
8448 (setq epos (point-at-eol))
8449 (save-excursion
8450 (beginning-of-line 1)
8451 (org-table-get-field
8452 1 (if (looking-at "^[ \t]*| *\\([#!$*^_ ]\\) *|")
8453 (concat " "
8454 (setq new (or forcenew
8455 (cadr (member (match-string 1) marks))))
8456 " ")
8457 " # ")))
8458 (if (and l1 l2)
8459 (progn
8460 (goto-line l1)
8461 (while (progn (beginning-of-line 2) (not (= (org-current-line) l2)))
8462 (and (looking-at org-table-dataline-regexp)
8463 (org-table-get-field 1 (concat " " new " "))))
8464 (goto-line l1)))
8465 (if (not (= epos (point-at-eol))) (org-table-align))
8466 (goto-line l)
8467 (and (interactive-p) (message (cdr (assoc new org-recalc-marks))))))
8469 (defun org-table-maybe-recalculate-line ()
8470 "Recompute the current line if marked for it, and if we haven't just done it."
8471 (interactive)
8472 (and org-table-allow-automatic-line-recalculation
8473 (not (and (memq last-command org-recalc-commands)
8474 (equal org-last-recalc-line (org-current-line))))
8475 (save-excursion (beginning-of-line 1)
8476 (looking-at org-table-auto-recalculate-regexp))
8477 (org-table-recalculate) t))
8479 (defvar org-table-formula-debug nil
8480 "Non-nil means, debug table formulas.
8481 When nil, simply write \"#ERROR\" in corrupted fields.")
8482 (make-variable-buffer-local 'org-table-formula-debug)
8484 (defvar modes)
8485 (defsubst org-set-calc-mode (var &optional value)
8486 (if (stringp var)
8487 (setq var (assoc var '(("D" calc-angle-mode deg)
8488 ("R" calc-angle-mode rad)
8489 ("F" calc-prefer-frac t)
8490 ("S" calc-symbolic-mode t)))
8491 value (nth 2 var) var (nth 1 var)))
8492 (if (memq var modes)
8493 (setcar (cdr (memq var modes)) value)
8494 (cons var (cons value modes)))
8495 modes)
8497 (defun org-table-eval-formula (&optional arg equation
8498 suppress-align suppress-const
8499 suppress-store suppress-analysis)
8500 "Replace the table field value at the cursor by the result of a calculation.
8502 This function makes use of Dave Gillespie's Calc package, in my view the
8503 most exciting program ever written for GNU Emacs. So you need to have Calc
8504 installed in order to use this function.
8506 In a table, this command replaces the value in the current field with the
8507 result of a formula. It also installs the formula as the \"current\" column
8508 formula, by storing it in a special line below the table. When called
8509 with a `C-u' prefix, the current field must ba a named field, and the
8510 formula is installed as valid in only this specific field.
8512 When called with two `C-u' prefixes, insert the active equation
8513 for the field back into the current field, so that it can be
8514 edited there. This is useful in order to use \\[org-table-show-reference]
8515 to check the referenced fields.
8517 When called, the command first prompts for a formula, which is read in
8518 the minibuffer. Previously entered formulas are available through the
8519 history list, and the last used formula is offered as a default.
8520 These stored formulas are adapted correctly when moving, inserting, or
8521 deleting columns with the corresponding commands.
8523 The formula can be any algebraic expression understood by the Calc package.
8524 For details, see the Org-mode manual.
8526 This function can also be called from Lisp programs and offers
8527 additional arguments: EQUATION can be the formula to apply. If this
8528 argument is given, the user will not be prompted. SUPPRESS-ALIGN is
8529 used to speed-up recursive calls by by-passing unnecessary aligns.
8530 SUPPRESS-CONST suppresses the interpretation of constants in the
8531 formula, assuming that this has been done already outside the function.
8532 SUPPRESS-STORE means the formula should not be stored, either because
8533 it is already stored, or because it is a modified equation that should
8534 not overwrite the stored one."
8535 (interactive "P")
8536 (org-table-check-inside-data-field)
8537 (or suppress-analysis (org-table-get-specials))
8538 (if (equal arg '(16))
8539 (let ((eq (org-table-current-field-formula)))
8540 (or eq (error "No equation active for current field"))
8541 (org-table-get-field nil eq)
8542 (org-table-align)
8543 (setq org-table-may-need-update t))
8544 (let* (fields
8545 (ndown (if (integerp arg) arg 1))
8546 (org-table-automatic-realign nil)
8547 (case-fold-search nil)
8548 (down (> ndown 1))
8549 (formula (if (and equation suppress-store)
8550 equation
8551 (org-table-get-formula equation (equal arg '(4)))))
8552 (n0 (org-table-current-column))
8553 (modes (copy-sequence org-calc-default-modes))
8554 (numbers nil) ; was a variable, now fixed default
8555 (keep-empty nil)
8556 n form form0 bw fmt x ev orig c lispp literal)
8557 ;; Parse the format string. Since we have a lot of modes, this is
8558 ;; a lot of work. However, I think calc still uses most of the time.
8559 (if (string-match ";" formula)
8560 (let ((tmp (org-split-string formula ";")))
8561 (setq formula (car tmp)
8562 fmt (concat (cdr (assoc "%" org-table-local-parameters))
8563 (nth 1 tmp)))
8564 (while (string-match "\\([pnfse]\\)\\(-?[0-9]+\\)" fmt)
8565 (setq c (string-to-char (match-string 1 fmt))
8566 n (string-to-number (match-string 2 fmt)))
8567 (if (= c ?p)
8568 (setq modes (org-set-calc-mode 'calc-internal-prec n))
8569 (setq modes (org-set-calc-mode
8570 'calc-float-format
8571 (list (cdr (assoc c '((?n . float) (?f . fix)
8572 (?s . sci) (?e . eng))))
8573 n))))
8574 (setq fmt (replace-match "" t t fmt)))
8575 (if (string-match "[NT]" fmt)
8576 (setq numbers (equal (match-string 0 fmt) "N")
8577 fmt (replace-match "" t t fmt)))
8578 (if (string-match "L" fmt)
8579 (setq literal t
8580 fmt (replace-match "" t t fmt)))
8581 (if (string-match "E" fmt)
8582 (setq keep-empty t
8583 fmt (replace-match "" t t fmt)))
8584 (while (string-match "[DRFS]" fmt)
8585 (setq modes (org-set-calc-mode (match-string 0 fmt)))
8586 (setq fmt (replace-match "" t t fmt)))
8587 (unless (string-match "\\S-" fmt)
8588 (setq fmt nil))))
8589 (if (and (not suppress-const) org-table-formula-use-constants)
8590 (setq formula (org-table-formula-substitute-names formula)))
8591 (setq orig (or (get-text-property 1 :orig-formula formula) "?"))
8592 (while (> ndown 0)
8593 (setq fields (org-split-string
8594 (org-no-properties
8595 (buffer-substring (point-at-bol) (point-at-eol)))
8596 " *| *"))
8597 (if (eq numbers t)
8598 (setq fields (mapcar
8599 (lambda (x) (number-to-string (string-to-number x)))
8600 fields)))
8601 (setq ndown (1- ndown))
8602 (setq form (copy-sequence formula)
8603 lispp (and (> (length form) 2)(equal (substring form 0 2) "'(")))
8604 (if (and lispp literal) (setq lispp 'literal))
8605 ;; Check for old vertical references
8606 (setq form (org-rewrite-old-row-references form))
8607 ;; Insert complex ranges
8608 (while (string-match org-table-range-regexp form)
8609 (setq form
8610 (replace-match
8611 (save-match-data
8612 (org-table-make-reference
8613 (org-table-get-range (match-string 0 form) nil n0)
8614 keep-empty numbers lispp))
8615 t t form)))
8616 ;; Insert simple ranges
8617 (while (string-match "\\$\\([0-9]+\\)\\.\\.\\$\\([0-9]+\\)" form)
8618 (setq form
8619 (replace-match
8620 (save-match-data
8621 (org-table-make-reference
8622 (org-sublist
8623 fields (string-to-number (match-string 1 form))
8624 (string-to-number (match-string 2 form)))
8625 keep-empty numbers lispp))
8626 t t form)))
8627 (setq form0 form)
8628 ;; Insert the references to fields in same row
8629 (while (string-match "\\$\\([0-9]+\\)" form)
8630 (setq n (string-to-number (match-string 1 form))
8631 x (nth (1- (if (= n 0) n0 n)) fields))
8632 (unless x (error "Invalid field specifier \"%s\""
8633 (match-string 0 form)))
8634 (setq form (replace-match
8635 (save-match-data
8636 (org-table-make-reference x nil numbers lispp))
8637 t t form)))
8639 (if lispp
8640 (setq ev (condition-case nil
8641 (eval (eval (read form)))
8642 (error "#ERROR"))
8643 ev (if (numberp ev) (number-to-string ev) ev))
8644 (or (fboundp 'calc-eval)
8645 (error "Calc does not seem to be installed, and is needed to evaluate the formula"))
8646 (setq ev (calc-eval (cons form modes)
8647 (if numbers 'num))))
8649 (when org-table-formula-debug
8650 (with-output-to-temp-buffer "*Substitution History*"
8651 (princ (format "Substitution history of formula
8652 Orig: %s
8653 $xyz-> %s
8654 @r$c-> %s
8655 $1-> %s\n" orig formula form0 form))
8656 (if (listp ev)
8657 (princ (format " %s^\nError: %s"
8658 (make-string (car ev) ?\-) (nth 1 ev)))
8659 (princ (format "Result: %s\nFormat: %s\nFinal: %s"
8660 ev (or fmt "NONE")
8661 (if fmt (format fmt (string-to-number ev)) ev)))))
8662 (setq bw (get-buffer-window "*Substitution History*"))
8663 (shrink-window-if-larger-than-buffer bw)
8664 (unless (and (interactive-p) (not ndown))
8665 (unless (let (inhibit-redisplay)
8666 (y-or-n-p "Debugging Formula. Continue to next? "))
8667 (org-table-align)
8668 (error "Abort"))
8669 (delete-window bw)
8670 (message "")))
8671 (if (listp ev) (setq fmt nil ev "#ERROR"))
8672 (org-table-justify-field-maybe
8673 (if fmt (format fmt (string-to-number ev)) ev))
8674 (if (and down (> ndown 0) (looking-at ".*\n[ \t]*|[^-]"))
8675 (call-interactively 'org-return)
8676 (setq ndown 0)))
8677 (and down (org-table-maybe-recalculate-line))
8678 (or suppress-align (and org-table-may-need-update
8679 (org-table-align))))))
8681 (defun org-table-put-field-property (prop value)
8682 (save-excursion
8683 (put-text-property (progn (skip-chars-backward "^|") (point))
8684 (progn (skip-chars-forward "^|") (point))
8685 prop value)))
8687 (defun org-table-get-range (desc &optional tbeg col highlight)
8688 "Get a calc vector from a column, accorting to descriptor DESC.
8689 Optional arguments TBEG and COL can give the beginning of the table and
8690 the current column, to avoid unnecessary parsing.
8691 HIGHLIGHT means, just highlight the range."
8692 (if (not (equal (string-to-char desc) ?@))
8693 (setq desc (concat "@" desc)))
8694 (save-excursion
8695 (or tbeg (setq tbeg (org-table-begin)))
8696 (or col (setq col (org-table-current-column)))
8697 (let ((thisline (org-current-line))
8698 beg end c1 c2 r1 r2 rangep tmp)
8699 (unless (string-match org-table-range-regexp desc)
8700 (error "Invalid table range specifier `%s'" desc))
8701 (setq rangep (match-end 3)
8702 r1 (and (match-end 1) (match-string 1 desc))
8703 r2 (and (match-end 4) (match-string 4 desc))
8704 c1 (and (match-end 2) (substring (match-string 2 desc) 1))
8705 c2 (and (match-end 5) (substring (match-string 5 desc) 1)))
8707 (and c1 (setq c1 (+ (string-to-number c1)
8708 (if (memq (string-to-char c1) '(?- ?+)) col 0))))
8709 (and c2 (setq c2 (+ (string-to-number c2)
8710 (if (memq (string-to-char c2) '(?- ?+)) col 0))))
8711 (if (equal r1 "") (setq r1 nil))
8712 (if (equal r2 "") (setq r2 nil))
8713 (if r1 (setq r1 (org-table-get-descriptor-line r1)))
8714 (if r2 (setq r2 (org-table-get-descriptor-line r2)))
8715 ; (setq r2 (or r2 r1) c2 (or c2 c1))
8716 (if (not r1) (setq r1 thisline))
8717 (if (not r2) (setq r2 thisline))
8718 (if (not c1) (setq c1 col))
8719 (if (not c2) (setq c2 col))
8720 (if (or (not rangep) (and (= r1 r2) (= c1 c2)))
8721 ;; just one field
8722 (progn
8723 (goto-line r1)
8724 (while (not (looking-at org-table-dataline-regexp))
8725 (beginning-of-line 2))
8726 (prog1 (org-table-get-field c1)
8727 (if highlight (org-table-highlight-rectangle (point) (point)))))
8728 ;; A range, return a vector
8729 ;; First sort the numbers to get a regular ractangle
8730 (if (< r2 r1) (setq tmp r1 r1 r2 r2 tmp))
8731 (if (< c2 c1) (setq tmp c1 c1 c2 c2 tmp))
8732 (goto-line r1)
8733 (while (not (looking-at org-table-dataline-regexp))
8734 (beginning-of-line 2))
8735 (org-table-goto-column c1)
8736 (setq beg (point))
8737 (goto-line r2)
8738 (while (not (looking-at org-table-dataline-regexp))
8739 (beginning-of-line 0))
8740 (org-table-goto-column c2)
8741 (setq end (point))
8742 (if highlight
8743 (org-table-highlight-rectangle
8744 beg (progn (skip-chars-forward "^|\n") (point))))
8745 ;; return string representation of calc vector
8746 (apply 'append (org-table-copy-region beg end))))))
8748 (defun org-table-get-descriptor-line (desc &optional cline bline table)
8749 "Analyze descriptor DESC and retrieve the corresponding line number.
8750 The cursor is currently in line CLINE, the table begins in line BLINE,
8751 and TABLE is a vector with line types."
8752 (if (string-match "^[0-9]+$" desc)
8753 (aref org-table-dlines (string-to-number desc))
8754 (setq cline (or cline (org-current-line))
8755 bline (or bline org-table-current-begin-line)
8756 table (or table org-table-current-line-types))
8757 (if (or
8758 (not (string-match "^\\(\\([-+]\\)?\\(I+\\)\\)?\\(\\([-+]\\)?\\([0-9]+\\)\\)?" desc))
8759 ;; 1 2 3 4 5 6
8760 (and (not (match-end 3)) (not (match-end 6)))
8761 (and (match-end 3) (match-end 6) (not (match-end 5))))
8762 (error "invalid row descriptor `%s'" desc))
8763 (let* ((hdir (and (match-end 2) (match-string 2 desc)))
8764 (hn (if (match-end 3) (- (match-end 3) (match-beginning 3)) nil))
8765 (odir (and (match-end 5) (match-string 5 desc)))
8766 (on (if (match-end 6) (string-to-number (match-string 6 desc))))
8767 (i (- cline bline))
8768 (rel (and (match-end 6)
8769 (or (and (match-end 1) (not (match-end 3)))
8770 (match-end 5)))))
8771 (if (and hn (not hdir))
8772 (progn
8773 (setq i 0 hdir "+")
8774 (if (eq (aref table 0) 'hline) (setq hn (1- hn)))))
8775 (if (and (not hn) on (not odir))
8776 (error "should never happen");;(aref org-table-dlines on)
8777 (if (and hn (> hn 0))
8778 (setq i (org-find-row-type table i 'hline (equal hdir "-") nil hn)))
8779 (if on
8780 (setq i (org-find-row-type table i 'dline (equal odir "-") rel on)))
8781 (+ bline i)))))
8783 (defun org-find-row-type (table i type backwards relative n)
8784 (let ((l (length table)))
8785 (while (> n 0)
8786 (while (and (setq i (+ i (if backwards -1 1)))
8787 (>= i 0) (< i l)
8788 (not (eq (aref table i) type))
8789 (if (and relative (eq (aref table i) 'hline))
8790 (progn (setq i (- i (if backwards -1 1)) n 1) nil)
8791 t)))
8792 (setq n (1- n)))
8793 (if (or (< i 0) (>= i l))
8794 (error "Row descriptior leads outside table")
8795 i)))
8797 (defun org-rewrite-old-row-references (s)
8798 (if (string-match "&[-+0-9I]" s)
8799 (error "Formula contains old &row reference, please rewrite using @-syntax")
8802 (defun org-table-make-reference (elements keep-empty numbers lispp)
8803 "Convert list ELEMENTS to something appropriate to insert into formula.
8804 KEEP-EMPTY indicated to keep empty fields, default is to skip them.
8805 NUMBERS indicates that everything should be converted to numbers.
8806 LISPP means to return something appropriate for a Lisp list."
8807 (if (stringp elements) ; just a single val
8808 (if lispp
8809 (if (eq lispp 'literal)
8810 elements
8811 (prin1-to-string (if numbers (string-to-number elements) elements)))
8812 (if (equal elements "") (setq elements "0"))
8813 (if numbers (number-to-string (string-to-number elements)) elements))
8814 (unless keep-empty
8815 (setq elements
8816 (delq nil
8817 (mapcar (lambda (x) (if (string-match "\\S-" x) x nil))
8818 elements))))
8819 (setq elements (or elements '("0")))
8820 (if lispp
8821 (mapconcat
8822 (lambda (x)
8823 (if (eq lispp 'literal)
8825 (prin1-to-string (if numbers (string-to-number x) x))))
8826 " ")
8827 (concat "[" (mapconcat
8828 (lambda (x)
8829 (if numbers (number-to-string (string-to-number x)) x))
8830 elements
8831 ",") "]"))))
8833 (defun org-table-recalculate (&optional all noalign)
8834 "Recalculate the current table line by applying all stored formulas.
8835 With prefix arg ALL, do this for all lines in the table."
8836 (interactive "P")
8837 (or (memq this-command org-recalc-commands)
8838 (setq org-recalc-commands (cons this-command org-recalc-commands)))
8839 (unless (org-at-table-p) (error "Not at a table"))
8840 (if (equal all '(16))
8841 (org-table-iterate)
8842 (org-table-get-specials)
8843 (let* ((eqlist (sort (org-table-get-stored-formulas)
8844 (lambda (a b) (string< (car a) (car b)))))
8845 (inhibit-redisplay (not debug-on-error))
8846 (line-re org-table-dataline-regexp)
8847 (thisline (org-current-line))
8848 (thiscol (org-table-current-column))
8849 beg end entry eqlnum eqlname eqlname1 eql (cnt 0) eq a name)
8850 ;; Insert constants in all formulas
8851 (setq eqlist
8852 (mapcar (lambda (x)
8853 (setcdr x (org-table-formula-substitute-names (cdr x)))
8855 eqlist))
8856 ;; Split the equation list
8857 (while (setq eq (pop eqlist))
8858 (if (<= (string-to-char (car eq)) ?9)
8859 (push eq eqlnum)
8860 (push eq eqlname)))
8861 (setq eqlnum (nreverse eqlnum) eqlname (nreverse eqlname))
8862 (if all
8863 (progn
8864 (setq end (move-marker (make-marker) (1+ (org-table-end))))
8865 (goto-char (setq beg (org-table-begin)))
8866 (if (re-search-forward org-table-calculate-mark-regexp end t)
8867 ;; This is a table with marked lines, compute selected lines
8868 (setq line-re org-table-recalculate-regexp)
8869 ;; Move forward to the first non-header line
8870 (if (and (re-search-forward org-table-dataline-regexp end t)
8871 (re-search-forward org-table-hline-regexp end t)
8872 (re-search-forward org-table-dataline-regexp end t))
8873 (setq beg (match-beginning 0))
8874 nil))) ;; just leave beg where it is
8875 (setq beg (point-at-bol)
8876 end (move-marker (make-marker) (1+ (point-at-eol)))))
8877 (goto-char beg)
8878 (and all (message "Re-applying formulas to full table..."))
8880 ;; First find the named fields, and mark them untouchanble
8881 (remove-text-properties beg end '(org-untouchable t))
8882 (while (setq eq (pop eqlname))
8883 (setq name (car eq)
8884 a (assoc name org-table-named-field-locations))
8885 (and (not a)
8886 (string-match "@\\([0-9]+\\)\\$\\([0-9]+\\)" name)
8887 (setq a (list name
8888 (aref org-table-dlines
8889 (string-to-number (match-string 1 name)))
8890 (string-to-number (match-string 2 name)))))
8891 (when (and a (or all (equal (nth 1 a) thisline)))
8892 (message "Re-applying formula to field: %s" name)
8893 (goto-line (nth 1 a))
8894 (org-table-goto-column (nth 2 a))
8895 (push (append a (list (cdr eq))) eqlname1)
8896 ;; FIXME (org-table-eval-formula nil (cdr eq) 'noalign 'nocst
8897 ;; FIXME 'nostore 'noanalysis)
8898 (org-table-put-field-property :org-untouchable t)))
8900 ;; Now evauluate the column formulas, but skip fields covered by
8901 ;; field formulas
8902 (goto-char beg)
8903 (while (re-search-forward line-re end t)
8904 (unless (string-match "^ *[_^!$/] *$" (org-table-get-field 1))
8905 ;; Unprotected line, recalculate
8906 (and all (message "Re-applying formulas to full table...(line %d)"
8907 (setq cnt (1+ cnt))))
8908 (setq org-last-recalc-line (org-current-line))
8909 (setq eql eqlnum)
8910 (while (setq entry (pop eql))
8911 (goto-line org-last-recalc-line)
8912 (org-table-goto-column (string-to-number (car entry)) nil 'force)
8913 (unless (get-text-property (point) :org-untouchable)
8914 (org-table-eval-formula nil (cdr entry)
8915 'noalign 'nocst 'nostore 'noanalysis)))))
8917 ;; Now evaluate the field formulas
8918 (while (setq eq (pop eqlname1))
8919 (message "Re-applying formula to field: %s" (car eq))
8920 (goto-line (nth 1 eq))
8921 (org-table-goto-column (nth 2 eq))
8922 (org-table-eval-formula nil (nth 3 eq) 'noalign 'nocst
8923 'nostore 'noanalysis))
8925 (goto-line thisline)
8926 (org-table-goto-column thiscol)
8927 (remove-text-properties (point-min) (point-max) '(org-untouchable t))
8928 (or noalign (and org-table-may-need-update (org-table-align))
8929 (and all (message "Re-applying formulas to %d lines...done" cnt)))
8931 ;; back to initial position
8932 (message "Re-applying formulas...done")
8933 (goto-line thisline)
8934 (org-table-goto-column thiscol)
8935 (or noalign (and org-table-may-need-update (org-table-align))
8936 (and all (message "Re-applying formulas...done"))))))
8938 (defun org-table-iterate (&optional arg)
8939 "Recalculate the table until it does not change anymore."
8940 (interactive "P")
8941 (let ((imax (if arg (prefix-numeric-value arg) 10))
8942 (i 0)
8943 (lasttbl (buffer-substring (org-table-begin) (org-table-end)))
8944 thistbl)
8945 (catch 'exit
8946 (while (< i imax)
8947 (setq i (1+ i))
8948 (org-table-recalculate 'all)
8949 (setq thistbl (buffer-substring (org-table-begin) (org-table-end)))
8950 (if (not (string= lasttbl thistbl))
8951 (setq lasttbl thistbl)
8952 (if (> i 1)
8953 (message "Convergence after %d iterations" i)
8954 (message "Table was already stable"))
8955 (throw 'exit t)))
8956 (error "No convergence after %d iterations" i))))
8958 (defun org-table-formula-substitute-names (f)
8959 "Replace $const with values in string F."
8960 (let ((start 0) a (f1 f))
8961 ;; First, check for column names
8962 (while (setq start (string-match org-table-column-name-regexp f start))
8963 (setq start (1+ start))
8964 (setq a (assoc (match-string 1 f) org-table-column-names))
8965 (setq f (replace-match (concat "$" (cdr a)) t t f)))
8966 ;; Parameters and constants
8967 (setq start 0)
8968 (while (setq start (string-match "\\$\\([a-zA-Z][_a-zA-Z0-9]*\\)" f start))
8969 (setq start (1+ start))
8970 (if (setq a (save-match-data
8971 (org-table-get-constant (match-string 1 f))))
8972 (setq f (replace-match (concat "(" a ")") t t f))))
8973 (if org-table-formula-debug
8974 (put-text-property 0 (length f) :orig-formula f1 f))
8977 (defun org-table-get-constant (const)
8978 "Find the value for a parameter or constant in a formula.
8979 Parameters get priority."
8980 (or (cdr (assoc const org-table-local-parameters))
8981 (cdr (assoc const org-table-formula-constants-local))
8982 (cdr (assoc const org-table-formula-constants))
8983 (and (fboundp 'constants-get) (constants-get const))
8984 (and (string= (substring const 0 (min 5 (length const))) "PROP_")
8985 (org-entry-get nil (substring const 5) 'inherit))
8986 "#UNDEFINED_NAME"))
8988 (defvar org-table-fedit-map (make-sparse-keymap))
8989 (org-defkey org-table-fedit-map "\C-x\C-s" 'org-table-fedit-finish)
8990 (org-defkey org-table-fedit-map "\C-c\C-s" 'org-table-fedit-finish)
8991 (org-defkey org-table-fedit-map "\C-c\C-c" 'org-table-fedit-finish)
8992 (org-defkey org-table-fedit-map "\C-c\C-q" 'org-table-fedit-abort)
8993 (org-defkey org-table-fedit-map "\C-c?" 'org-table-show-reference)
8994 (org-defkey org-table-fedit-map [(meta shift up)] 'org-table-fedit-line-up)
8995 (org-defkey org-table-fedit-map [(meta shift down)] 'org-table-fedit-line-down)
8996 (org-defkey org-table-fedit-map [(shift up)] 'org-table-fedit-ref-up)
8997 (org-defkey org-table-fedit-map [(shift down)] 'org-table-fedit-ref-down)
8998 (org-defkey org-table-fedit-map [(shift left)] 'org-table-fedit-ref-left)
8999 (org-defkey org-table-fedit-map [(shift right)] 'org-table-fedit-ref-right)
9000 (org-defkey org-table-fedit-map [(meta up)] 'org-table-fedit-scroll-down)
9001 (org-defkey org-table-fedit-map [(meta down)] 'org-table-fedit-scroll)
9002 (org-defkey org-table-fedit-map [(meta tab)] 'lisp-complete-symbol)
9003 (org-defkey org-table-fedit-map "\M-\C-i" 'lisp-complete-symbol)
9004 (org-defkey org-table-fedit-map [(tab)] 'org-table-fedit-lisp-indent)
9005 (org-defkey org-table-fedit-map "\C-i" 'org-table-fedit-lisp-indent)
9006 (org-defkey org-table-fedit-map "\C-c\C-r" 'org-table-fedit-toggle-ref-type)
9007 (org-defkey org-table-fedit-map "\C-c}" 'org-table-fedit-toggle-coordinates)
9009 (easy-menu-define org-table-fedit-menu org-table-fedit-map "Org Edit Formulas Menu"
9010 '("Edit-Formulas"
9011 ["Finish and Install" org-table-fedit-finish t]
9012 ["Finish, Install, and Apply" (org-table-fedit-finish t) :keys "C-u C-c C-c"]
9013 ["Abort" org-table-fedit-abort t]
9014 "--"
9015 ["Pretty-Print Lisp Formula" org-table-fedit-lisp-indent t]
9016 ["Complete Lisp Symbol" lisp-complete-symbol t]
9017 "--"
9018 "Shift Reference at Point"
9019 ["Up" org-table-fedit-ref-up t]
9020 ["Down" org-table-fedit-ref-down t]
9021 ["Left" org-table-fedit-ref-left t]
9022 ["Right" org-table-fedit-ref-right t]
9024 "Change Test Row for Column Formulas"
9025 ["Up" org-table-fedit-line-up t]
9026 ["Down" org-table-fedit-line-down t]
9027 "--"
9028 ["Scroll Table Window" org-table-fedit-scroll t]
9029 ["Scroll Table Window down" org-table-fedit-scroll-down t]
9030 ["Show Table Grid" org-table-fedit-toggle-coordinates
9031 :style toggle :selected (with-current-buffer (marker-buffer org-pos)
9032 org-table-overlay-coordinates)]
9033 "--"
9034 ["Standard Refs (B3 instead of @3$2)" org-table-fedit-toggle-ref-type
9035 :style toggle :selected org-table-buffer-is-an]))
9037 (defvar org-pos)
9039 (defun org-table-edit-formulas ()
9040 "Edit the formulas of the current table in a separate buffer."
9041 (interactive)
9042 (when (save-excursion (beginning-of-line 1) (looking-at "#\\+TBLFM"))
9043 (beginning-of-line 0))
9044 (unless (org-at-table-p) (error "Not at a table"))
9045 (org-table-get-specials)
9046 (let ((key (org-table-current-field-formula 'key 'noerror))
9047 (eql (sort (org-table-get-stored-formulas 'noerror)
9048 'org-table-formula-less-p))
9049 (pos (move-marker (make-marker) (point)))
9050 (startline 1)
9051 (wc (current-window-configuration))
9052 (titles '((column . "# Column Formulas\n")
9053 (field . "# Field Formulas\n")
9054 (named . "# Named Field Formulas\n")))
9055 entry s type title)
9056 (switch-to-buffer-other-window "*Edit Formulas*")
9057 (erase-buffer)
9058 ;; Keep global-font-lock-mode from turning on font-lock-mode
9059 (let ((font-lock-global-modes '(not fundamental-mode)))
9060 (fundamental-mode))
9061 (org-set-local 'font-lock-global-modes (list 'not major-mode))
9062 (org-set-local 'org-pos pos)
9063 (org-set-local 'org-window-configuration wc)
9064 (use-local-map org-table-fedit-map)
9065 (org-add-hook 'post-command-hook 'org-table-fedit-post-command t t)
9066 (easy-menu-add org-table-fedit-menu)
9067 (setq startline (org-current-line))
9068 (while (setq entry (pop eql))
9069 (setq type (cond
9070 ((equal (string-to-char (car entry)) ?@) 'field)
9071 ((string-match "^[0-9]" (car entry)) 'column)
9072 (t 'named)))
9073 (when (setq title (assq type titles))
9074 (or (bobp) (insert "\n"))
9075 (insert (org-add-props (cdr title) nil 'face font-lock-comment-face))
9076 (setq titles (delq title titles)))
9077 (if (equal key (car entry)) (setq startline (org-current-line)))
9078 (setq s (concat (if (equal (string-to-char (car entry)) ?@) "" "$")
9079 (car entry) " = " (cdr entry) "\n"))
9080 (remove-text-properties 0 (length s) '(face nil) s)
9081 (insert s))
9082 (if (eq org-table-use-standard-references t)
9083 (org-table-fedit-toggle-ref-type))
9084 (goto-line startline)
9085 (message "Edit formulas and finish with `C-c C-c'. See menu for more commands.")))
9087 (defun org-table-fedit-post-command ()
9088 (when (not (memq this-command '(lisp-complete-symbol)))
9089 (let ((win (selected-window)))
9090 (save-excursion
9091 (condition-case nil
9092 (org-table-show-reference)
9093 (error nil))
9094 (select-window win)))))
9096 (defun org-table-formula-to-user (s)
9097 "Convert a formula from internal to user representation."
9098 (if (eq org-table-use-standard-references t)
9099 (org-table-convert-refs-to-an s)
9102 (defun org-table-formula-from-user (s)
9103 "Convert a formula from user to internal representation."
9104 (if org-table-use-standard-references
9105 (org-table-convert-refs-to-rc s)
9108 (defun org-table-convert-refs-to-rc (s)
9109 "Convert spreadsheet references from AB7 to @7$28.
9110 Works for single references, but also for entire formulas and even the
9111 full TBLFM line."
9112 (let ((start 0))
9113 (while (string-match "\\<\\([a-zA-Z]+\\)\\([0-9]+\\>\\|&\\)\\|\\(;[^\r\n:]+\\)" s start)
9114 (cond
9115 ((match-end 3)
9116 ;; format match, just advance
9117 (setq start (match-end 0)))
9118 ((and (> (match-beginning 0) 0)
9119 (equal ?. (aref s (max (1- (match-beginning 0)) 0))))
9120 ;; 3.e5 or something like this. FIXME: is this ok????
9121 (setq start (match-end 0)))
9123 (setq start (match-beginning 0)
9124 s (replace-match
9125 (if (equal (match-string 2 s) "&")
9126 (format "$%d" (org-letters-to-number (match-string 1 s)))
9127 (format "@%d$%d"
9128 (string-to-number (match-string 2 s))
9129 (org-letters-to-number (match-string 1 s))))
9130 t t s)))))
9133 (defun org-table-convert-refs-to-an (s)
9134 "Convert spreadsheet references from to @7$28 to AB7.
9135 Works for single references, but also for entire formulas and even the
9136 full TBLFM line."
9137 (while (string-match "@\\([0-9]+\\)$\\([0-9]+\\)" s)
9138 (setq s (replace-match
9139 (format "%s%d"
9140 (org-number-to-letters
9141 (string-to-number (match-string 2 s)))
9142 (string-to-number (match-string 1 s)))
9143 t t s)))
9144 (while (string-match "\\(^\\|[^0-9a-zA-Z]\\)\\$\\([0-9]+\\)" s)
9145 (setq s (replace-match (concat "\\1"
9146 (org-number-to-letters
9147 (string-to-number (match-string 2 s))) "&")
9148 t nil s)))
9151 (defun org-letters-to-number (s)
9152 "Convert a base 26 number represented by letters into an integer.
9153 For example: AB -> 28."
9154 (let ((n 0))
9155 (setq s (upcase s))
9156 (while (> (length s) 0)
9157 (setq n (+ (* n 26) (string-to-char s) (- ?A) 1)
9158 s (substring s 1)))
9161 (defun org-number-to-letters (n)
9162 "Convert an integer into a base 26 number represented by letters.
9163 For example: 28 -> AB."
9164 (let ((s ""))
9165 (while (> n 0)
9166 (setq s (concat (char-to-string (+ (mod (1- n) 26) ?A)) s)
9167 n (/ (1- n) 26)))
9170 (defun org-table-fedit-convert-buffer (function)
9171 "Convert all references in this buffer, using FUNTION."
9172 (let ((line (org-current-line)))
9173 (goto-char (point-min))
9174 (while (not (eobp))
9175 (insert (funcall function (buffer-substring (point) (point-at-eol))))
9176 (delete-region (point) (point-at-eol))
9177 (or (eobp) (forward-char 1)))
9178 (goto-line line)))
9180 (defun org-table-fedit-toggle-ref-type ()
9181 "Convert all references in the buffer from B3 to @3$2 and back."
9182 (interactive)
9183 (org-set-local 'org-table-buffer-is-an (not org-table-buffer-is-an))
9184 (org-table-fedit-convert-buffer
9185 (if org-table-buffer-is-an
9186 'org-table-convert-refs-to-an 'org-table-convert-refs-to-rc))
9187 (message "Reference type switched to %s"
9188 (if org-table-buffer-is-an "A1 etc" "@row$column")))
9190 (defun org-table-fedit-ref-up ()
9191 "Shift the reference at point one row/hline up."
9192 (interactive)
9193 (org-table-fedit-shift-reference 'up))
9194 (defun org-table-fedit-ref-down ()
9195 "Shift the reference at point one row/hline down."
9196 (interactive)
9197 (org-table-fedit-shift-reference 'down))
9198 (defun org-table-fedit-ref-left ()
9199 "Shift the reference at point one field to the left."
9200 (interactive)
9201 (org-table-fedit-shift-reference 'left))
9202 (defun org-table-fedit-ref-right ()
9203 "Shift the reference at point one field to the right."
9204 (interactive)
9205 (org-table-fedit-shift-reference 'right))
9207 (defun org-table-fedit-shift-reference (dir)
9208 (cond
9209 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\)&")
9210 (if (memq dir '(left right))
9211 (org-rematch-and-replace 1 (eq dir 'left))
9212 (error "Cannot shift reference in this direction")))
9213 ((org-at-regexp-p "\\(\\<[a-zA-Z]\\{1,2\\}\\)\\([0-9]+\\)")
9214 ;; A B3-like reference
9215 (if (memq dir '(up down))
9216 (org-rematch-and-replace 2 (eq dir 'up))
9217 (org-rematch-and-replace 1 (eq dir 'left))))
9218 ((org-at-regexp-p
9219 "\\(@\\|\\.\\.\\)\\([-+]?\\(I+\\>\\|[0-9]+\\)\\)\\(\\$\\([-+]?[0-9]+\\)\\)?")
9220 ;; An internal reference
9221 (if (memq dir '(up down))
9222 (org-rematch-and-replace 2 (eq dir 'up) (match-end 3))
9223 (org-rematch-and-replace 5 (eq dir 'left))))))
9225 (defun org-rematch-and-replace (n &optional decr hline)
9226 "Re-match the group N, and replace it with the shifted refrence."
9227 (or (match-end n) (error "Cannot shift reference in this direction"))
9228 (goto-char (match-beginning n))
9229 (and (looking-at (regexp-quote (match-string n)))
9230 (replace-match (org-shift-refpart (match-string 0) decr hline)
9231 t t)))
9233 (defun org-shift-refpart (ref &optional decr hline)
9234 "Shift a refrence part REF.
9235 If DECR is set, decrease the references row/column, else increase.
9236 If HLINE is set, this may be a hline reference, it certainly is not
9237 a translation reference."
9238 (save-match-data
9239 (let* ((sign (string-match "^[-+]" ref)) n)
9241 (if sign (setq sign (substring ref 0 1) ref (substring ref 1)))
9242 (cond
9243 ((and hline (string-match "^I+" ref))
9244 (setq n (string-to-number (concat sign (number-to-string (length ref)))))
9245 (setq n (+ n (if decr -1 1)))
9246 (if (= n 0) (setq n (+ n (if decr -1 1))))
9247 (if sign
9248 (setq sign (if (< n 0) "-" "+") n (abs n))
9249 (setq n (max 1 n)))
9250 (concat sign (make-string n ?I)))
9252 ((string-match "^[0-9]+" ref)
9253 (setq n (string-to-number (concat sign ref)))
9254 (setq n (+ n (if decr -1 1)))
9255 (if sign
9256 (concat (if (< n 0) "-" "+") (number-to-string (abs n)))
9257 (number-to-string (max 1 n))))
9259 ((string-match "^[a-zA-Z]+" ref)
9260 (org-number-to-letters
9261 (max 1 (+ (org-letters-to-number ref) (if decr -1 1)))))
9263 (t (error "Cannot shift reference"))))))
9265 (defun org-table-fedit-toggle-coordinates ()
9266 "Toggle the display of coordinates in the refrenced table."
9267 (interactive)
9268 (let ((pos (marker-position org-pos)))
9269 (with-current-buffer (marker-buffer org-pos)
9270 (save-excursion
9271 (goto-char pos)
9272 (org-table-toggle-coordinate-overlays)))))
9274 (defun org-table-fedit-finish (&optional arg)
9275 "Parse the buffer for formula definitions and install them.
9276 With prefix ARG, apply the new formulas to the table."
9277 (interactive "P")
9278 (org-table-remove-rectangle-highlight)
9279 (if org-table-use-standard-references
9280 (progn
9281 (org-table-fedit-convert-buffer 'org-table-convert-refs-to-rc)
9282 (setq org-table-buffer-is-an nil)))
9283 (let ((pos org-pos) eql var form)
9284 (goto-char (point-min))
9285 (while (re-search-forward
9286 "^\\(@[0-9]+\\$[0-9]+\\|\\$\\([a-zA-Z0-9]+\\)\\) *= *\\(.*\\(\n[ \t]+.*$\\)*\\)"
9287 nil t)
9288 (setq var (if (match-end 2) (match-string 2) (match-string 1))
9289 form (match-string 3))
9290 (setq form (org-trim form))
9291 (when (not (equal form ""))
9292 (while (string-match "[ \t]*\n[ \t]*" form)
9293 (setq form (replace-match " " t t form)))
9294 (when (assoc var eql)
9295 (error "Double formulas for %s" var))
9296 (push (cons var form) eql)))
9297 (setq org-pos nil)
9298 (set-window-configuration org-window-configuration)
9299 (select-window (get-buffer-window (marker-buffer pos)))
9300 (goto-char pos)
9301 (unless (org-at-table-p)
9302 (error "Lost table position - cannot install formulae"))
9303 (org-table-store-formulas eql)
9304 (move-marker pos nil)
9305 (kill-buffer "*Edit Formulas*")
9306 (if arg
9307 (org-table-recalculate 'all)
9308 (message "New formulas installed - press C-u C-c C-c to apply."))))
9310 (defun org-table-fedit-abort ()
9311 "Abort editing formulas, without installing the changes."
9312 (interactive)
9313 (org-table-remove-rectangle-highlight)
9314 (let ((pos org-pos))
9315 (set-window-configuration org-window-configuration)
9316 (select-window (get-buffer-window (marker-buffer pos)))
9317 (goto-char pos)
9318 (move-marker pos nil)
9319 (message "Formula editing aborted without installing changes")))
9321 (defun org-table-fedit-lisp-indent ()
9322 "Pretty-print and re-indent Lisp expressions in the Formula Editor."
9323 (interactive)
9324 (let ((pos (point)) beg end ind)
9325 (beginning-of-line 1)
9326 (cond
9327 ((looking-at "[ \t]")
9328 (goto-char pos)
9329 (call-interactively 'lisp-indent-line))
9330 ((looking-at "[$@0-9a-zA-Z]+ *= *[^ \t\n']") (goto-char pos))
9331 ((not (fboundp 'pp-buffer))
9332 (error "Cannot pretty-print. Command `pp-buffer' is not available."))
9333 ((looking-at "[$@0-9a-zA-Z]+ *= *'(")
9334 (goto-char (- (match-end 0) 2))
9335 (setq beg (point))
9336 (setq ind (make-string (current-column) ?\ ))
9337 (condition-case nil (forward-sexp 1)
9338 (error
9339 (error "Cannot pretty-print Lisp expression: Unbalanced parenthesis")))
9340 (setq end (point))
9341 (save-restriction
9342 (narrow-to-region beg end)
9343 (if (eq last-command this-command)
9344 (progn
9345 (goto-char (point-min))
9346 (setq this-command nil)
9347 (while (re-search-forward "[ \t]*\n[ \t]*" nil t)
9348 (replace-match " ")))
9349 (pp-buffer)
9350 (untabify (point-min) (point-max))
9351 (goto-char (1+ (point-min)))
9352 (while (re-search-forward "^." nil t)
9353 (beginning-of-line 1)
9354 (insert ind))
9355 (goto-char (point-max))
9356 (backward-delete-char 1)))
9357 (goto-char beg))
9358 (t nil))))
9360 (defvar org-show-positions nil)
9362 (defun org-table-show-reference (&optional local)
9363 "Show the location/value of the $ expression at point."
9364 (interactive)
9365 (org-table-remove-rectangle-highlight)
9366 (catch 'exit
9367 (let ((pos (if local (point) org-pos))
9368 (face2 'highlight)
9369 (org-inhibit-highlight-removal t)
9370 (win (selected-window))
9371 (org-show-positions nil)
9372 var name e what match dest)
9373 (if local (org-table-get-specials))
9374 (setq what (cond
9375 ((or (org-at-regexp-p org-table-range-regexp2)
9376 (org-at-regexp-p org-table-translate-regexp)
9377 (org-at-regexp-p org-table-range-regexp))
9378 (setq match
9379 (save-match-data
9380 (org-table-convert-refs-to-rc (match-string 0))))
9381 'range)
9382 ((org-at-regexp-p "\\$[a-zA-Z][a-zA-Z0-9]*") 'name)
9383 ((org-at-regexp-p "\\$[0-9]+") 'column)
9384 ((not local) nil)
9385 (t (error "No reference at point")))
9386 match (and what (or match (match-string 0))))
9387 (when (and match (not (equal (match-beginning 0) (point-at-bol))))
9388 (org-table-add-rectangle-overlay (match-beginning 0) (match-end 0)
9389 'secondary-selection))
9390 (org-add-hook 'before-change-functions
9391 'org-table-remove-rectangle-highlight)
9392 (if (eq what 'name) (setq var (substring match 1)))
9393 (when (eq what 'range)
9394 (or (equal (string-to-char match) ?@) (setq match (concat "@" match)))
9395 (setq match (org-table-formula-substitute-names match)))
9396 (unless local
9397 (save-excursion
9398 (end-of-line 1)
9399 (re-search-backward "^\\S-" nil t)
9400 (beginning-of-line 1)
9401 (when (looking-at "\\(\\$[0-9a-zA-Z]+\\|@[0-9]+\\$[0-9]+\\|[a-zA-Z]+\\([0-9]+\\|&\\)\\) *=")
9402 (setq dest
9403 (save-match-data
9404 (org-table-convert-refs-to-rc (match-string 1))))
9405 (org-table-add-rectangle-overlay
9406 (match-beginning 1) (match-end 1) face2))))
9407 (if (and (markerp pos) (marker-buffer pos))
9408 (if (get-buffer-window (marker-buffer pos))
9409 (select-window (get-buffer-window (marker-buffer pos)))
9410 (switch-to-buffer-other-window (get-buffer-window
9411 (marker-buffer pos)))))
9412 (goto-char pos)
9413 (org-table-force-dataline)
9414 (when dest
9415 (setq name (substring dest 1))
9416 (cond
9417 ((string-match "^\\$[a-zA-Z][a-zA-Z0-9]*" dest)
9418 (setq e (assoc name org-table-named-field-locations))
9419 (goto-line (nth 1 e))
9420 (org-table-goto-column (nth 2 e)))
9421 ((string-match "^@\\([0-9]+\\)\\$\\([0-9]+\\)" dest)
9422 (let ((l (string-to-number (match-string 1 dest)))
9423 (c (string-to-number (match-string 2 dest))))
9424 (goto-line (aref org-table-dlines l))
9425 (org-table-goto-column c)))
9426 (t (org-table-goto-column (string-to-number name))))
9427 (move-marker pos (point))
9428 (org-table-highlight-rectangle nil nil face2))
9429 (cond
9430 ((equal dest match))
9431 ((not match))
9432 ((eq what 'range)
9433 (condition-case nil
9434 (save-excursion
9435 (org-table-get-range match nil nil 'highlight))
9436 (error nil)))
9437 ((setq e (assoc var org-table-named-field-locations))
9438 (goto-line (nth 1 e))
9439 (org-table-goto-column (nth 2 e))
9440 (org-table-highlight-rectangle (point) (point))
9441 (message "Named field, column %d of line %d" (nth 2 e) (nth 1 e)))
9442 ((setq e (assoc var org-table-column-names))
9443 (org-table-goto-column (string-to-number (cdr e)))
9444 (org-table-highlight-rectangle (point) (point))
9445 (goto-char (org-table-begin))
9446 (if (re-search-forward (concat "^[ \t]*| *! *.*?| *\\(" var "\\) *|")
9447 (org-table-end) t)
9448 (progn
9449 (goto-char (match-beginning 1))
9450 (org-table-highlight-rectangle)
9451 (message "Named column (column %s)" (cdr e)))
9452 (error "Column name not found")))
9453 ((eq what 'column)
9454 ;; column number
9455 (org-table-goto-column (string-to-number (substring match 1)))
9456 (org-table-highlight-rectangle (point) (point))
9457 (message "Column %s" (substring match 1)))
9458 ((setq e (assoc var org-table-local-parameters))
9459 (goto-char (org-table-begin))
9460 (if (re-search-forward (concat "^[ \t]*| *\\$ *.*?| *\\(" var "=\\)") nil t)
9461 (progn
9462 (goto-char (match-beginning 1))
9463 (org-table-highlight-rectangle)
9464 (message "Local parameter."))
9465 (error "Parameter not found")))
9467 (cond
9468 ((not var) (error "No reference at point"))
9469 ((setq e (assoc var org-table-formula-constants-local))
9470 (message "Local Constant: $%s=%s in #+CONSTANTS line."
9471 var (cdr e)))
9472 ((setq e (assoc var org-table-formula-constants))
9473 (message "Constant: $%s=%s in `org-table-formula-constants'."
9474 var (cdr e)))
9475 ((setq e (and (fboundp 'constants-get) (constants-get var)))
9476 (message "Constant: $%s=%s, from `constants.el'%s."
9477 var e (format " (%s units)" constants-unit-system)))
9478 (t (error "Undefined name $%s" var)))))
9479 (goto-char pos)
9480 (when (and org-show-positions
9481 (not (memq this-command '(org-table-fedit-scroll
9482 org-table-fedit-scroll-down))))
9483 (push pos org-show-positions)
9484 (push org-table-current-begin-pos org-show-positions)
9485 (let ((min (apply 'min org-show-positions))
9486 (max (apply 'max org-show-positions)))
9487 (goto-char min) (recenter 0)
9488 (goto-char max)
9489 (or (pos-visible-in-window-p max) (recenter -1))))
9490 (select-window win))))
9492 (defun org-table-force-dataline ()
9493 "Make sure the cursor is in a dataline in a table."
9494 (unless (save-excursion
9495 (beginning-of-line 1)
9496 (looking-at org-table-dataline-regexp))
9497 (let* ((re org-table-dataline-regexp)
9498 (p1 (save-excursion (re-search-forward re nil 'move)))
9499 (p2 (save-excursion (re-search-backward re nil 'move))))
9500 (cond ((and p1 p2)
9501 (goto-char (if (< (abs (- p1 (point))) (abs (- p2 (point))))
9502 p1 p2)))
9503 ((or p1 p2) (goto-char (or p1 p2)))
9504 (t (error "No table dataline around here"))))))
9506 (defun org-table-fedit-line-up ()
9507 "Move cursor one line up in the window showing the table."
9508 (interactive)
9509 (org-table-fedit-move 'previous-line))
9511 (defun org-table-fedit-line-down ()
9512 "Move cursor one line down in the window showing the table."
9513 (interactive)
9514 (org-table-fedit-move 'next-line))
9516 (defun org-table-fedit-move (command)
9517 "Move the cursor in the window shoinw the table.
9518 Use COMMAND to do the motion, repeat if necessary to end up in a data line."
9519 (let ((org-table-allow-automatic-line-recalculation nil)
9520 (pos org-pos) (win (selected-window)) p)
9521 (select-window (get-buffer-window (marker-buffer org-pos)))
9522 (setq p (point))
9523 (call-interactively command)
9524 (while (and (org-at-table-p)
9525 (org-at-table-hline-p))
9526 (call-interactively command))
9527 (or (org-at-table-p) (goto-char p))
9528 (move-marker pos (point))
9529 (select-window win)))
9531 (defun org-table-fedit-scroll (N)
9532 (interactive "p")
9533 (let ((other-window-scroll-buffer (marker-buffer org-pos)))
9534 (scroll-other-window N)))
9536 (defun org-table-fedit-scroll-down (N)
9537 (interactive "p")
9538 (org-table-fedit-scroll (- N)))
9540 (defvar org-table-rectangle-overlays nil)
9542 (defun org-table-add-rectangle-overlay (beg end &optional face)
9543 "Add a new overlay."
9544 (let ((ov (org-make-overlay beg end)))
9545 (org-overlay-put ov 'face (or face 'secondary-selection))
9546 (push ov org-table-rectangle-overlays)))
9548 (defun org-table-highlight-rectangle (&optional beg end face)
9549 "Highlight rectangular region in a table."
9550 (setq beg (or beg (point)) end (or end (point)))
9551 (let ((b (min beg end))
9552 (e (max beg end))
9553 l1 c1 l2 c2 tmp)
9554 (and (boundp 'org-show-positions)
9555 (setq org-show-positions (cons b (cons e org-show-positions))))
9556 (goto-char (min beg end))
9557 (setq l1 (org-current-line)
9558 c1 (org-table-current-column))
9559 (goto-char (max beg end))
9560 (setq l2 (org-current-line)
9561 c2 (org-table-current-column))
9562 (if (> c1 c2) (setq tmp c1 c1 c2 c2 tmp))
9563 (goto-line l1)
9564 (beginning-of-line 1)
9565 (loop for line from l1 to l2 do
9566 (when (looking-at org-table-dataline-regexp)
9567 (org-table-goto-column c1)
9568 (skip-chars-backward "^|\n") (setq beg (point))
9569 (org-table-goto-column c2)
9570 (skip-chars-forward "^|\n") (setq end (point))
9571 (org-table-add-rectangle-overlay beg end face))
9572 (beginning-of-line 2))
9573 (goto-char b))
9574 (add-hook 'before-change-functions 'org-table-remove-rectangle-highlight))
9576 (defun org-table-remove-rectangle-highlight (&rest ignore)
9577 "Remove the rectangle overlays."
9578 (unless org-inhibit-highlight-removal
9579 (remove-hook 'before-change-functions 'org-table-remove-rectangle-highlight)
9580 (mapc 'org-delete-overlay org-table-rectangle-overlays)
9581 (setq org-table-rectangle-overlays nil)))
9583 (defvar org-table-coordinate-overlays nil
9584 "Collects the cooordinate grid overlays, so that they can be removed.")
9585 (make-variable-buffer-local 'org-table-coordinate-overlays)
9587 (defun org-table-overlay-coordinates ()
9588 "Add overlays to the table at point, to show row/column coordinates."
9589 (interactive)
9590 (mapc 'org-delete-overlay org-table-coordinate-overlays)
9591 (setq org-table-coordinate-overlays nil)
9592 (save-excursion
9593 (let ((id 0) (ih 0) hline eol s1 s2 str ic ov beg)
9594 (goto-char (org-table-begin))
9595 (while (org-at-table-p)
9596 (setq eol (point-at-eol))
9597 (setq ov (org-make-overlay (point-at-bol) (1+ (point-at-bol))))
9598 (push ov org-table-coordinate-overlays)
9599 (setq hline (looking-at org-table-hline-regexp))
9600 (setq str (if hline (format "I*%-2d" (setq ih (1+ ih)))
9601 (format "%4d" (setq id (1+ id)))))
9602 (org-overlay-before-string ov str 'org-special-keyword 'evaporate)
9603 (when hline
9604 (setq ic 0)
9605 (while (re-search-forward "[+|]\\(-+\\)" eol t)
9606 (setq beg (1+ (match-beginning 0))
9607 ic (1+ ic)
9608 s1 (concat "$" (int-to-string ic))
9609 s2 (org-number-to-letters ic)
9610 str (if (eq org-table-use-standard-references t) s2 s1))
9611 (setq ov (org-make-overlay beg (+ beg (length str))))
9612 (push ov org-table-coordinate-overlays)
9613 (org-overlay-display ov str 'org-special-keyword 'evaporate)))
9614 (beginning-of-line 2)))))
9616 (defun org-table-toggle-coordinate-overlays ()
9617 "Toggle the display of Row/Column numbers in tables."
9618 (interactive)
9619 (setq org-table-overlay-coordinates (not org-table-overlay-coordinates))
9620 (message "Row/Column number display turned %s"
9621 (if org-table-overlay-coordinates "on" "off"))
9622 (if (and (org-at-table-p) org-table-overlay-coordinates)
9623 (org-table-align))
9624 (unless org-table-overlay-coordinates
9625 (mapc 'org-delete-overlay org-table-coordinate-overlays)
9626 (setq org-table-coordinate-overlays nil)))
9628 (defun org-table-toggle-formula-debugger ()
9629 "Toggle the formula debugger in tables."
9630 (interactive)
9631 (setq org-table-formula-debug (not org-table-formula-debug))
9632 (message "Formula debugging has been turned %s"
9633 (if org-table-formula-debug "on" "off")))
9635 ;;; The orgtbl minor mode
9637 ;; Define a minor mode which can be used in other modes in order to
9638 ;; integrate the org-mode table editor.
9640 ;; This is really a hack, because the org-mode table editor uses several
9641 ;; keys which normally belong to the major mode, for example the TAB and
9642 ;; RET keys. Here is how it works: The minor mode defines all the keys
9643 ;; necessary to operate the table editor, but wraps the commands into a
9644 ;; function which tests if the cursor is currently inside a table. If that
9645 ;; is the case, the table editor command is executed. However, when any of
9646 ;; those keys is used outside a table, the function uses `key-binding' to
9647 ;; look up if the key has an associated command in another currently active
9648 ;; keymap (minor modes, major mode, global), and executes that command.
9649 ;; There might be problems if any of the keys used by the table editor is
9650 ;; otherwise used as a prefix key.
9652 ;; Another challenge is that the key binding for TAB can be tab or \C-i,
9653 ;; likewise the binding for RET can be return or \C-m. Orgtbl-mode
9654 ;; addresses this by checking explicitly for both bindings.
9656 ;; The optimized version (see variable `orgtbl-optimized') takes over
9657 ;; all keys which are bound to `self-insert-command' in the *global map*.
9658 ;; Some modes bind other commands to simple characters, for example
9659 ;; AUCTeX binds the double quote to `Tex-insert-quote'. With orgtbl-mode
9660 ;; active, this binding is ignored inside tables and replaced with a
9661 ;; modified self-insert.
9663 (defvar orgtbl-mode nil
9664 "Variable controlling `orgtbl-mode', a minor mode enabling the `org-mode'
9665 table editor in arbitrary modes.")
9666 (make-variable-buffer-local 'orgtbl-mode)
9668 (defvar orgtbl-mode-map (make-keymap)
9669 "Keymap for `orgtbl-mode'.")
9671 ;;;###autoload
9672 (defun turn-on-orgtbl ()
9673 "Unconditionally turn on `orgtbl-mode'."
9674 (orgtbl-mode 1))
9676 (defvar org-old-auto-fill-inhibit-regexp nil
9677 "Local variable used by `orgtbl-mode'")
9679 (defconst orgtbl-line-start-regexp "[ \t]*\\(|\\|#\\+\\(TBLFM\\|ORGTBL\\):\\)"
9680 "Matches a line belonging to an orgtbl.")
9682 (defconst orgtbl-extra-font-lock-keywords
9683 (list (list (concat "^" orgtbl-line-start-regexp ".*")
9684 0 (quote 'org-table) 'prepend))
9685 "Extra font-lock-keywords to be added when orgtbl-mode is active.")
9687 ;;;###autoload
9688 (defun orgtbl-mode (&optional arg)
9689 "The `org-mode' table editor as a minor mode for use in other modes."
9690 (interactive)
9691 (if (org-mode-p)
9692 ;; Exit without error, in case some hook functions calls this
9693 ;; by accident in org-mode.
9694 (message "Orgtbl-mode is not useful in org-mode, command ignored")
9695 (setq orgtbl-mode
9696 (if arg (> (prefix-numeric-value arg) 0) (not orgtbl-mode)))
9697 (if orgtbl-mode
9698 (progn
9699 (and (orgtbl-setup) (defun orgtbl-setup () nil))
9700 ;; Make sure we are first in minor-mode-map-alist
9701 (let ((c (assq 'orgtbl-mode minor-mode-map-alist)))
9702 (and c (setq minor-mode-map-alist
9703 (cons c (delq c minor-mode-map-alist)))))
9704 (org-set-local (quote org-table-may-need-update) t)
9705 (org-add-hook 'before-change-functions 'org-before-change-function
9706 nil 'local)
9707 (org-set-local 'org-old-auto-fill-inhibit-regexp
9708 auto-fill-inhibit-regexp)
9709 (org-set-local 'auto-fill-inhibit-regexp
9710 (if auto-fill-inhibit-regexp
9711 (concat orgtbl-line-start-regexp "\\|"
9712 auto-fill-inhibit-regexp)
9713 orgtbl-line-start-regexp))
9714 (org-add-to-invisibility-spec '(org-cwidth))
9715 (when (fboundp 'font-lock-add-keywords)
9716 (font-lock-add-keywords nil orgtbl-extra-font-lock-keywords)
9717 (org-restart-font-lock))
9718 (easy-menu-add orgtbl-mode-menu)
9719 (run-hooks 'orgtbl-mode-hook))
9720 (setq auto-fill-inhibit-regexp org-old-auto-fill-inhibit-regexp)
9721 (org-cleanup-narrow-column-properties)
9722 (org-remove-from-invisibility-spec '(org-cwidth))
9723 (remove-hook 'before-change-functions 'org-before-change-function t)
9724 (when (fboundp 'font-lock-remove-keywords)
9725 (font-lock-remove-keywords nil orgtbl-extra-font-lock-keywords)
9726 (org-restart-font-lock))
9727 (easy-menu-remove orgtbl-mode-menu)
9728 (force-mode-line-update 'all))))
9730 (defun org-cleanup-narrow-column-properties ()
9731 "Remove all properties related to narrow-column invisibility."
9732 (let ((s 1))
9733 (while (setq s (text-property-any s (point-max)
9734 'display org-narrow-column-arrow))
9735 (remove-text-properties s (1+ s) '(display t)))
9736 (setq s 1)
9737 (while (setq s (text-property-any s (point-max) 'org-cwidth 1))
9738 (remove-text-properties s (1+ s) '(org-cwidth t)))
9739 (setq s 1)
9740 (while (setq s (text-property-any s (point-max) 'invisible 'org-cwidth))
9741 (remove-text-properties s (1+ s) '(invisible t)))))
9743 ;; Install it as a minor mode.
9744 (put 'orgtbl-mode :included t)
9745 (put 'orgtbl-mode :menu-tag "Org Table Mode")
9746 (add-minor-mode 'orgtbl-mode " OrgTbl" orgtbl-mode-map)
9748 (defun orgtbl-make-binding (fun n &rest keys)
9749 "Create a function for binding in the table minor mode.
9750 FUN is the command to call inside a table. N is used to create a unique
9751 command name. KEYS are keys that should be checked in for a command
9752 to execute outside of tables."
9753 (eval
9754 (list 'defun
9755 (intern (concat "orgtbl-hijacker-command-" (int-to-string n)))
9756 '(arg)
9757 (concat "In tables, run `" (symbol-name fun) "'.\n"
9758 "Outside of tables, run the binding of `"
9759 (mapconcat (lambda (x) (format "%s" x)) keys "' or `")
9760 "'.")
9761 '(interactive "p")
9762 (list 'if
9763 '(org-at-table-p)
9764 (list 'call-interactively (list 'quote fun))
9765 (list 'let '(orgtbl-mode)
9766 (list 'call-interactively
9767 (append '(or)
9768 (mapcar (lambda (k)
9769 (list 'key-binding k))
9770 keys)
9771 '('orgtbl-error))))))))
9773 (defun orgtbl-error ()
9774 "Error when there is no default binding for a table key."
9775 (interactive)
9776 (error "This key is has no function outside tables"))
9778 (defun orgtbl-setup ()
9779 "Setup orgtbl keymaps."
9780 (let ((nfunc 0)
9781 (bindings
9782 (list
9783 '([(meta shift left)] org-table-delete-column)
9784 '([(meta left)] org-table-move-column-left)
9785 '([(meta right)] org-table-move-column-right)
9786 '([(meta shift right)] org-table-insert-column)
9787 '([(meta shift up)] org-table-kill-row)
9788 '([(meta shift down)] org-table-insert-row)
9789 '([(meta up)] org-table-move-row-up)
9790 '([(meta down)] org-table-move-row-down)
9791 '("\C-c\C-w" org-table-cut-region)
9792 '("\C-c\M-w" org-table-copy-region)
9793 '("\C-c\C-y" org-table-paste-rectangle)
9794 '("\C-c-" org-table-insert-hline)
9795 '("\C-c}" org-table-toggle-coordinate-overlays)
9796 '("\C-c{" org-table-toggle-formula-debugger)
9797 '("\C-m" org-table-next-row)
9798 '([(shift return)] org-table-copy-down)
9799 '("\C-c\C-q" org-table-wrap-region)
9800 '("\C-c?" org-table-field-info)
9801 '("\C-c " org-table-blank-field)
9802 '("\C-c+" org-table-sum)
9803 '("\C-c=" org-table-eval-formula)
9804 '("\C-c'" org-table-edit-formulas)
9805 '("\C-c`" org-table-edit-field)
9806 '("\C-c*" org-table-recalculate)
9807 '("\C-c|" org-table-create-or-convert-from-region)
9808 '("\C-c^" org-table-sort-lines)
9809 '([(control ?#)] org-table-rotate-recalc-marks)))
9810 elt key fun cmd)
9811 (while (setq elt (pop bindings))
9812 (setq nfunc (1+ nfunc))
9813 (setq key (org-key (car elt))
9814 fun (nth 1 elt)
9815 cmd (orgtbl-make-binding fun nfunc key))
9816 (org-defkey orgtbl-mode-map key cmd))
9818 ;; Special treatment needed for TAB and RET
9819 (org-defkey orgtbl-mode-map [(return)]
9820 (orgtbl-make-binding 'orgtbl-ret 100 [(return)] "\C-m"))
9821 (org-defkey orgtbl-mode-map "\C-m"
9822 (orgtbl-make-binding 'orgtbl-ret 101 "\C-m" [(return)]))
9824 (org-defkey orgtbl-mode-map [(tab)]
9825 (orgtbl-make-binding 'orgtbl-tab 102 [(tab)] "\C-i"))
9826 (org-defkey orgtbl-mode-map "\C-i"
9827 (orgtbl-make-binding 'orgtbl-tab 103 "\C-i" [(tab)]))
9829 (org-defkey orgtbl-mode-map [(shift tab)]
9830 (orgtbl-make-binding 'org-table-previous-field 104
9831 [(shift tab)] [(tab)] "\C-i"))
9833 (org-defkey orgtbl-mode-map "\M-\C-m"
9834 (orgtbl-make-binding 'org-table-wrap-region 105
9835 "\M-\C-m" [(meta return)]))
9836 (org-defkey orgtbl-mode-map [(meta return)]
9837 (orgtbl-make-binding 'org-table-wrap-region 106
9838 [(meta return)] "\M-\C-m"))
9840 (org-defkey orgtbl-mode-map "\C-c\C-c" 'orgtbl-ctrl-c-ctrl-c)
9841 (when orgtbl-optimized
9842 ;; If the user wants maximum table support, we need to hijack
9843 ;; some standard editing functions
9844 (org-remap orgtbl-mode-map
9845 'self-insert-command 'orgtbl-self-insert-command
9846 'delete-char 'org-delete-char
9847 'delete-backward-char 'org-delete-backward-char)
9848 (org-defkey orgtbl-mode-map "|" 'org-force-self-insert))
9849 (easy-menu-define orgtbl-mode-menu orgtbl-mode-map "OrgTbl menu"
9850 '("OrgTbl"
9851 ["Align" org-ctrl-c-ctrl-c :active (org-at-table-p) :keys "C-c C-c"]
9852 ["Next Field" org-cycle :active (org-at-table-p) :keys "TAB"]
9853 ["Previous Field" org-shifttab :active (org-at-table-p) :keys "S-TAB"]
9854 ["Next Row" org-return :active (org-at-table-p) :keys "RET"]
9855 "--"
9856 ["Blank Field" org-table-blank-field :active (org-at-table-p) :keys "C-c SPC"]
9857 ["Edit Field" org-table-edit-field :active (org-at-table-p) :keys "C-c ` "]
9858 ["Copy Field from Above"
9859 org-table-copy-down :active (org-at-table-p) :keys "S-RET"]
9860 "--"
9861 ("Column"
9862 ["Move Column Left" org-metaleft :active (org-at-table-p) :keys "M-<left>"]
9863 ["Move Column Right" org-metaright :active (org-at-table-p) :keys "M-<right>"]
9864 ["Delete Column" org-shiftmetaleft :active (org-at-table-p) :keys "M-S-<left>"]
9865 ["Insert Column" org-shiftmetaright :active (org-at-table-p) :keys "M-S-<right>"])
9866 ("Row"
9867 ["Move Row Up" org-metaup :active (org-at-table-p) :keys "M-<up>"]
9868 ["Move Row Down" org-metadown :active (org-at-table-p) :keys "M-<down>"]
9869 ["Delete Row" org-shiftmetaup :active (org-at-table-p) :keys "M-S-<up>"]
9870 ["Insert Row" org-shiftmetadown :active (org-at-table-p) :keys "M-S-<down>"]
9871 ["Sort lines in region" org-table-sort-lines (org-at-table-p) :keys "C-c ^"]
9872 "--"
9873 ["Insert Hline" org-table-insert-hline :active (org-at-table-p) :keys "C-c -"])
9874 ("Rectangle"
9875 ["Copy Rectangle" org-copy-special :active (org-at-table-p)]
9876 ["Cut Rectangle" org-cut-special :active (org-at-table-p)]
9877 ["Paste Rectangle" org-paste-special :active (org-at-table-p)]
9878 ["Fill Rectangle" org-table-wrap-region :active (org-at-table-p)])
9879 "--"
9880 ("Radio tables"
9881 ["Insert table template" orgtbl-insert-radio-table
9882 (assq major-mode orgtbl-radio-table-templates)]
9883 ["Comment/uncomment table" orgtbl-toggle-comment t])
9884 "--"
9885 ["Set Column Formula" org-table-eval-formula :active (org-at-table-p) :keys "C-c ="]
9886 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
9887 ["Edit Formulas" org-table-edit-formulas :active (org-at-table-p) :keys "C-c '"]
9888 ["Recalculate line" org-table-recalculate :active (org-at-table-p) :keys "C-c *"]
9889 ["Recalculate all" (org-table-recalculate '(4)) :active (org-at-table-p) :keys "C-u C-c *"]
9890 ["Iterate all" (org-table-recalculate '(16)) :active (org-at-table-p) :keys "C-u C-u C-c *"]
9891 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks :active (org-at-table-p) :keys "C-c #"]
9892 ["Sum Column/Rectangle" org-table-sum
9893 :active (or (org-at-table-p) (org-region-active-p)) :keys "C-c +"]
9894 ["Which Column?" org-table-current-column :active (org-at-table-p) :keys "C-c ?"]
9895 ["Debug Formulas"
9896 org-table-toggle-formula-debugger :active (org-at-table-p)
9897 :keys "C-c {"
9898 :style toggle :selected org-table-formula-debug]
9899 ["Show Col/Row Numbers"
9900 org-table-toggle-coordinate-overlays :active (org-at-table-p)
9901 :keys "C-c }"
9902 :style toggle :selected org-table-overlay-coordinates]
9906 (defun orgtbl-ctrl-c-ctrl-c (arg)
9907 "If the cursor is inside a table, realign the table.
9908 It it is a table to be sent away to a receiver, do it.
9909 With prefix arg, also recompute table."
9910 (interactive "P")
9911 (let ((pos (point)) action)
9912 (save-excursion
9913 (beginning-of-line 1)
9914 (setq action (cond ((looking-at "#\\+ORGTBL:.*\n[ \t]*|") (match-end 0))
9915 ((looking-at "[ \t]*|") pos)
9916 ((looking-at "#\\+TBLFM:") 'recalc))))
9917 (cond
9918 ((integerp action)
9919 (goto-char action)
9920 (org-table-maybe-eval-formula)
9921 (if arg
9922 (call-interactively 'org-table-recalculate)
9923 (org-table-maybe-recalculate-line))
9924 (call-interactively 'org-table-align)
9925 (orgtbl-send-table 'maybe))
9926 ((eq action 'recalc)
9927 (save-excursion
9928 (beginning-of-line 1)
9929 (skip-chars-backward " \r\n\t")
9930 (if (org-at-table-p)
9931 (org-call-with-arg 'org-table-recalculate t))))
9932 (t (let (orgtbl-mode)
9933 (call-interactively (key-binding "\C-c\C-c")))))))
9935 (defun orgtbl-tab (arg)
9936 "Justification and field motion for `orgtbl-mode'."
9937 (interactive "P")
9938 (if arg (org-table-edit-field t)
9939 (org-table-justify-field-maybe)
9940 (org-table-next-field)))
9942 (defun orgtbl-ret ()
9943 "Justification and field motion for `orgtbl-mode'."
9944 (interactive)
9945 (org-table-justify-field-maybe)
9946 (org-table-next-row))
9948 (defun orgtbl-self-insert-command (N)
9949 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
9950 If the cursor is in a table looking at whitespace, the whitespace is
9951 overwritten, and the table is not marked as requiring realignment."
9952 (interactive "p")
9953 (if (and (org-at-table-p)
9955 (and org-table-auto-blank-field
9956 (member last-command
9957 '(orgtbl-hijacker-command-100
9958 orgtbl-hijacker-command-101
9959 orgtbl-hijacker-command-102
9960 orgtbl-hijacker-command-103
9961 orgtbl-hijacker-command-104
9962 orgtbl-hijacker-command-105))
9963 (org-table-blank-field))
9965 (eq N 1)
9966 (looking-at "[^|\n]* +|"))
9967 (let (org-table-may-need-update)
9968 (goto-char (1- (match-end 0)))
9969 (delete-backward-char 1)
9970 (goto-char (match-beginning 0))
9971 (self-insert-command N))
9972 (setq org-table-may-need-update t)
9973 (let (orgtbl-mode)
9974 (call-interactively (key-binding (vector last-input-event))))))
9976 (defun org-force-self-insert (N)
9977 "Needed to enforce self-insert under remapping."
9978 (interactive "p")
9979 (self-insert-command N))
9981 (defvar orgtbl-exp-regexp "^\\([-+]?[0-9][0-9.]*\\)[eE]\\([-+]?[0-9]+\\)$"
9982 "Regula expression matching exponentials as produced by calc.")
9984 (defvar org-table-clean-did-remove-column nil)
9986 (defun orgtbl-export (table target)
9987 (let ((func (intern (concat "orgtbl-to-" (symbol-name target))))
9988 (lines (org-split-string table "[ \t]*\n[ \t]*"))
9989 org-table-last-alignment org-table-last-column-widths
9990 maxcol column)
9991 (if (not (fboundp func))
9992 (error "Cannot export orgtbl table to %s" target))
9993 (setq lines (org-table-clean-before-export lines))
9994 (setq table
9995 (mapcar
9996 (lambda (x)
9997 (if (string-match org-table-hline-regexp x)
9998 'hline
9999 (org-split-string (org-trim x) "\\s-*|\\s-*")))
10000 lines))
10001 (setq maxcol (apply 'max (mapcar (lambda (x) (if (listp x) (length x) 0))
10002 table)))
10003 (loop for i from (1- maxcol) downto 0 do
10004 (setq column (mapcar (lambda (x) (if (listp x) (nth i x) nil)) table))
10005 (setq column (delq nil column))
10006 (push (apply 'max (mapcar 'string-width column)) org-table-last-column-widths)
10007 (push (> (/ (apply '+ (mapcar (lambda (x) (if (string-match org-table-number-regexp x) 1 0)) column)) maxcol) org-table-number-fraction) org-table-last-alignment))
10008 (funcall func table nil)))
10010 (defun orgtbl-send-table (&optional maybe)
10011 "Send a tranformed version of this table to the receiver position.
10012 With argument MAYBE, fail quietly if no transformation is defined for
10013 this table."
10014 (interactive)
10015 (catch 'exit
10016 (unless (org-at-table-p) (error "Not at a table"))
10017 ;; when non-interactive, we assume align has just happened.
10018 (when (interactive-p) (org-table-align))
10019 (save-excursion
10020 (goto-char (org-table-begin))
10021 (beginning-of-line 0)
10022 (unless (looking-at "#\\+ORGTBL: *SEND +\\([a-zA-Z0-9_]+\\) +\\([^ \t\r\n]+\\)\\( +.*\\)?")
10023 (if maybe
10024 (throw 'exit nil)
10025 (error "Don't know how to transform this table."))))
10026 (let* ((name (match-string 1))
10028 (transform (intern (match-string 2)))
10029 (params (if (match-end 3) (read (concat "(" (match-string 3) ")"))))
10030 (skip (plist-get params :skip))
10031 (skipcols (plist-get params :skipcols))
10032 (txt (buffer-substring-no-properties
10033 (org-table-begin) (org-table-end)))
10034 (lines (nthcdr (or skip 0) (org-split-string txt "[ \t]*\n[ \t]*")))
10035 (lines (org-table-clean-before-export lines))
10036 (i0 (if org-table-clean-did-remove-column 2 1))
10037 (table (mapcar
10038 (lambda (x)
10039 (if (string-match org-table-hline-regexp x)
10040 'hline
10041 (org-remove-by-index
10042 (org-split-string (org-trim x) "\\s-*|\\s-*")
10043 skipcols i0)))
10044 lines))
10045 (fun (if (= i0 2) 'cdr 'identity))
10046 (org-table-last-alignment
10047 (org-remove-by-index (funcall fun org-table-last-alignment)
10048 skipcols i0))
10049 (org-table-last-column-widths
10050 (org-remove-by-index (funcall fun org-table-last-column-widths)
10051 skipcols i0)))
10053 (unless (fboundp transform)
10054 (error "No such transformation function %s" transform))
10055 (setq txt (funcall transform table params))
10056 ;; Find the insertion place
10057 (save-excursion
10058 (goto-char (point-min))
10059 (unless (re-search-forward
10060 (concat "BEGIN RECEIVE ORGTBL +" name "\\([ \t]\\|$\\)") nil t)
10061 (error "Don't know where to insert translated table"))
10062 (goto-char (match-beginning 0))
10063 (beginning-of-line 2)
10064 (setq beg (point))
10065 (unless (re-search-forward (concat "END RECEIVE ORGTBL +" name) nil t)
10066 (error "Cannot find end of insertion region"))
10067 (beginning-of-line 1)
10068 (delete-region beg (point))
10069 (goto-char beg)
10070 (insert txt "\n"))
10071 (message "Table converted and installed at receiver location"))))
10073 (defun org-remove-by-index (list indices &optional i0)
10074 "Remove the elements in LIST with indices in INDICES.
10075 First element has index 0, or I0 if given."
10076 (if (not indices)
10077 list
10078 (if (integerp indices) (setq indices (list indices)))
10079 (setq i0 (1- (or i0 0)))
10080 (delq :rm (mapcar (lambda (x)
10081 (setq i0 (1+ i0))
10082 (if (memq i0 indices) :rm x))
10083 list))))
10085 (defun orgtbl-toggle-comment ()
10086 "Comment or uncomment the orgtbl at point."
10087 (interactive)
10088 (let* ((re1 (concat "^" (regexp-quote comment-start) orgtbl-line-start-regexp))
10089 (re2 (concat "^" orgtbl-line-start-regexp))
10090 (commented (save-excursion (beginning-of-line 1)
10091 (cond ((looking-at re1) t)
10092 ((looking-at re2) nil)
10093 (t (error "Not at an org table")))))
10094 (re (if commented re1 re2))
10095 beg end)
10096 (save-excursion
10097 (beginning-of-line 1)
10098 (while (looking-at re) (beginning-of-line 0))
10099 (beginning-of-line 2)
10100 (setq beg (point))
10101 (while (looking-at re) (beginning-of-line 2))
10102 (setq end (point)))
10103 (comment-region beg end (if commented '(4) nil))))
10105 (defun orgtbl-insert-radio-table ()
10106 "Insert a radio table template appropriate for this major mode."
10107 (interactive)
10108 (let* ((e (assq major-mode orgtbl-radio-table-templates))
10109 (txt (nth 1 e))
10110 name pos)
10111 (unless e (error "No radio table setup defined for %s" major-mode))
10112 (setq name (read-string "Table name: "))
10113 (while (string-match "%n" txt)
10114 (setq txt (replace-match name t t txt)))
10115 (or (bolp) (insert "\n"))
10116 (setq pos (point))
10117 (insert txt)
10118 (goto-char pos)))
10120 (defun org-get-param (params header i sym &optional hsym)
10121 "Get parameter value for symbol SYM.
10122 If this is a header line, actually get the value for the symbol with an
10123 additional \"h\" inserted after the colon.
10124 If the value is a protperty list, get the element for the current column.
10125 Assumes variables VAL, PARAMS, HEAD and I to be scoped into the function."
10126 (let ((val (plist-get params sym)))
10127 (and hsym header (setq val (or (plist-get params hsym) val)))
10128 (if (consp val) (plist-get val i) val)))
10130 (defun orgtbl-to-generic (table params)
10131 "Convert the orgtbl-mode TABLE to some other format.
10132 This generic routine can be used for many standard cases.
10133 TABLE is a list, each entry either the symbol `hline' for a horizontal
10134 separator line, or a list of fields for that line.
10135 PARAMS is a property list of parameters that can influence the conversion.
10136 For the generic converter, some parameters are obligatory: You need to
10137 specify either :lfmt, or all of (:lstart :lend :sep). If you do not use
10138 :splice, you must have :tstart and :tend.
10140 Valid parameters are
10142 :tstart String to start the table. Ignored when :splice is t.
10143 :tend String to end the table. Ignored when :splice is t.
10145 :splice When set to t, return only table body lines, don't wrap
10146 them into :tstart and :tend. Default is nil.
10148 :hline String to be inserted on horizontal separation lines.
10149 May be nil to ignore hlines.
10151 :lstart String to start a new table line.
10152 :lend String to end a table line
10153 :sep Separator between two fields
10154 :lfmt Format for entire line, with enough %s to capture all fields.
10155 If this is present, :lstart, :lend, and :sep are ignored.
10156 :fmt A format to be used to wrap the field, should contain
10157 %s for the original field value. For example, to wrap
10158 everything in dollars, you could use :fmt \"$%s$\".
10159 This may also be a property list with column numbers and
10160 formats. for example :fmt (2 \"$%s$\" 4 \"%s%%\")
10162 :hlstart :hlend :hlsep :hlfmt :hfmt
10163 Same as above, specific for the header lines in the table.
10164 All lines before the first hline are treated as header.
10165 If any of these is not present, the data line value is used.
10167 :efmt Use this format to print numbers with exponentials.
10168 The format should have %s twice for inserting mantissa
10169 and exponent, for example \"%s\\\\times10^{%s}\". This
10170 may also be a property list with column numbers and
10171 formats. :fmt will still be applied after :efmt.
10173 In addition to this, the parameters :skip and :skipcols are always handled
10174 directly by `orgtbl-send-table'. See manual."
10175 (interactive)
10176 (let* ((p params)
10177 (splicep (plist-get p :splice))
10178 (hline (plist-get p :hline))
10179 rtn line i fm efm lfmt h)
10181 ;; Do we have a header?
10182 (if (and (not splicep) (listp (car table)) (memq 'hline table))
10183 (setq h t))
10185 ;; Put header
10186 (unless splicep
10187 (push (or (plist-get p :tstart) "ERROR: no :tstart") rtn))
10189 ;; Now loop over all lines
10190 (while (setq line (pop table))
10191 (if (eq line 'hline)
10192 ;; A horizontal separator line
10193 (progn (if hline (push hline rtn))
10194 (setq h nil)) ; no longer in header
10195 ;; A normal line. Convert the fields, push line onto the result list
10196 (setq i 0)
10197 (setq line
10198 (mapcar
10199 (lambda (f)
10200 (setq i (1+ i)
10201 fm (org-get-param p h i :fmt :hfmt)
10202 efm (org-get-param p h i :efmt))
10203 (if (and efm (string-match orgtbl-exp-regexp f))
10204 (setq f (format
10205 efm (match-string 1 f) (match-string 2 f))))
10206 (if fm (setq f (format fm f)))
10208 line))
10209 (if (setq lfmt (org-get-param p h i :lfmt :hlfmt))
10210 (push (apply 'format lfmt line) rtn)
10211 (push (concat
10212 (org-get-param p h i :lstart :hlstart)
10213 (mapconcat 'identity line (org-get-param p h i :sep :hsep))
10214 (org-get-param p h i :lend :hlend))
10215 rtn))))
10217 (unless splicep
10218 (push (or (plist-get p :tend) "ERROR: no :tend") rtn))
10220 (mapconcat 'identity (nreverse rtn) "\n")))
10222 (defun orgtbl-to-latex (table params)
10223 "Convert the orgtbl-mode TABLE to LaTeX.
10224 TABLE is a list, each entry either the symbol `hline' for a horizontal
10225 separator line, or a list of fields for that line.
10226 PARAMS is a property list of parameters that can influence the conversion.
10227 Supports all parameters from `orgtbl-to-generic'. Most important for
10228 LaTeX are:
10230 :splice When set to t, return only table body lines, don't wrap
10231 them into a tabular environment. Default is nil.
10233 :fmt A format to be used to wrap the field, should contain %s for the
10234 original field value. For example, to wrap everything in dollars,
10235 use :fmt \"$%s$\". This may also be a property list with column
10236 numbers and formats. for example :fmt (2 \"$%s$\" 4 \"%s%%\")
10238 :efmt Format for transforming numbers with exponentials. The format
10239 should have %s twice for inserting mantissa and exponent, for
10240 example \"%s\\\\times10^{%s}\". LaTeX default is \"%s\\\\,(%s)\".
10241 This may also be a property list with column numbers and formats.
10243 The general parameters :skip and :skipcols have already been applied when
10244 this function is called."
10245 (let* ((alignment (mapconcat (lambda (x) (if x "r" "l"))
10246 org-table-last-alignment ""))
10247 (params2
10248 (list
10249 :tstart (concat "\\begin{tabular}{" alignment "}")
10250 :tend "\\end{tabular}"
10251 :lstart "" :lend " \\\\" :sep " & "
10252 :efmt "%s\\,(%s)" :hline "\\hline")))
10253 (orgtbl-to-generic table (org-combine-plists params2 params))))
10255 (defun orgtbl-to-html (table params)
10256 "Convert the orgtbl-mode TABLE to LaTeX.
10257 TABLE is a list, each entry either the symbol `hline' for a horizontal
10258 separator line, or a list of fields for that line.
10259 PARAMS is a property list of parameters that can influence the conversion.
10260 Currently this function recognizes the following parameters:
10262 :splice When set to t, return only table body lines, don't wrap
10263 them into a <table> environment. Default is nil.
10265 The general parameters :skip and :skipcols have already been applied when
10266 this function is called. The function does *not* use `orgtbl-to-generic',
10267 so you cannot specify parameters for it."
10268 (let* ((splicep (plist-get params :splice))
10269 html)
10270 ;; Just call the formatter we already have
10271 ;; We need to make text lines for it, so put the fields back together.
10272 (setq html (org-format-org-table-html
10273 (mapcar
10274 (lambda (x)
10275 (if (eq x 'hline)
10276 "|----+----|"
10277 (concat "| " (mapconcat 'identity x " | ") " |")))
10278 table)
10279 splicep))
10280 (if (string-match "\n+\\'" html)
10281 (setq html (replace-match "" t t html)))
10282 html))
10284 (defun orgtbl-to-texinfo (table params)
10285 "Convert the orgtbl-mode TABLE to TeXInfo.
10286 TABLE is a list, each entry either the symbol `hline' for a horizontal
10287 separator line, or a list of fields for that line.
10288 PARAMS is a property list of parameters that can influence the conversion.
10289 Supports all parameters from `orgtbl-to-generic'. Most important for
10290 TeXInfo are:
10292 :splice nil/t When set to t, return only table body lines, don't wrap
10293 them into a multitable environment. Default is nil.
10295 :fmt fmt A format to be used to wrap the field, should contain
10296 %s for the original field value. For example, to wrap
10297 everything in @kbd{}, you could use :fmt \"@kbd{%s}\".
10298 This may also be a property list with column numbers and
10299 formats. for example :fmt (2 \"@kbd{%s}\" 4 \"@code{%s}\").
10301 :cf \"f1 f2..\" The column fractions for the table. Bye default these
10302 are computed automatically from the width of the columns
10303 under org-mode.
10305 The general parameters :skip and :skipcols have already been applied when
10306 this function is called."
10307 (let* ((total (float (apply '+ org-table-last-column-widths)))
10308 (colfrac (or (plist-get params :cf)
10309 (mapconcat
10310 (lambda (x) (format "%.3f" (/ (float x) total)))
10311 org-table-last-column-widths " ")))
10312 (params2
10313 (list
10314 :tstart (concat "@multitable @columnfractions " colfrac)
10315 :tend "@end multitable"
10316 :lstart "@item " :lend "" :sep " @tab "
10317 :hlstart "@headitem ")))
10318 (orgtbl-to-generic table (org-combine-plists params2 params))))
10320 ;;;; Link Stuff
10322 ;;; Link abbreviations
10324 (defun org-link-expand-abbrev (link)
10325 "Apply replacements as defined in `org-link-abbrev-alist."
10326 (if (string-match "^\\([a-zA-Z]+\\)\\(::?\\(.*\\)\\)?$" link)
10327 (let* ((key (match-string 1 link))
10328 (as (or (assoc key org-link-abbrev-alist-local)
10329 (assoc key org-link-abbrev-alist)))
10330 (tag (and (match-end 2) (match-string 3 link)))
10331 rpl)
10332 (if (not as)
10333 link
10334 (setq rpl (cdr as))
10335 (cond
10336 ((symbolp rpl) (funcall rpl tag))
10337 ((string-match "%s" rpl) (replace-match (or tag "") t t rpl))
10338 (t (concat rpl tag)))))
10339 link))
10341 ;;; Storing and inserting links
10343 (defvar org-insert-link-history nil
10344 "Minibuffer history for links inserted with `org-insert-link'.")
10346 (defvar org-stored-links nil
10347 "Contains the links stored with `org-store-link'.")
10349 (defvar org-store-link-plist nil
10350 "Plist with info about the most recently link created with `org-store-link'.")
10352 ;;;###autoload
10353 (defun org-store-link (arg)
10354 "\\<org-mode-map>Store an org-link to the current location.
10355 This link can later be inserted into an org-buffer with
10356 \\[org-insert-link].
10357 For some link types, a prefix arg is interpreted:
10358 For links to usenet articles, arg negates `org-usenet-links-prefer-google'.
10359 For file links, arg negates `org-context-in-file-links'."
10360 (interactive "P")
10361 (setq org-store-link-plist nil) ; reset
10362 (let (link cpltxt desc description search txt)
10363 (cond
10365 ((eq major-mode 'bbdb-mode)
10366 (let ((name (bbdb-record-name (bbdb-current-record)))
10367 (company (bbdb-record-getprop (bbdb-current-record) 'company)))
10368 (setq cpltxt (concat "bbdb:" (or name company))
10369 link (org-make-link cpltxt))
10370 (org-store-link-props :type "bbdb" :name name :company company)))
10372 ((eq major-mode 'Info-mode)
10373 (setq link (org-make-link "info:"
10374 (file-name-nondirectory Info-current-file)
10375 ":" Info-current-node))
10376 (setq cpltxt (concat (file-name-nondirectory Info-current-file)
10377 ":" Info-current-node))
10378 (org-store-link-props :type "info" :file Info-current-file
10379 :node Info-current-node))
10381 ((eq major-mode 'calendar-mode)
10382 (let ((cd (calendar-cursor-to-date)))
10383 (setq link
10384 (format-time-string
10385 (car org-time-stamp-formats)
10386 (apply 'encode-time
10387 (list 0 0 0 (nth 1 cd) (nth 0 cd) (nth 2 cd)
10388 nil nil nil))))
10389 (org-store-link-props :type "calendar" :date cd)))
10391 ((or (eq major-mode 'vm-summary-mode)
10392 (eq major-mode 'vm-presentation-mode))
10393 (and (eq major-mode 'vm-presentation-mode) (vm-summarize))
10394 (vm-follow-summary-cursor)
10395 (save-excursion
10396 (vm-select-folder-buffer)
10397 (let* ((message (car vm-message-pointer))
10398 (folder buffer-file-name)
10399 (subject (vm-su-subject message))
10400 (to (vm-get-header-contents message "To"))
10401 (from (vm-get-header-contents message "From"))
10402 (message-id (vm-su-message-id message)))
10403 (org-store-link-props :type "vm" :from from :to to :subject subject
10404 :message-id message-id)
10405 (setq message-id (org-remove-angle-brackets message-id))
10406 (setq folder (abbreviate-file-name folder))
10407 (if (string-match (concat "^" (regexp-quote vm-folder-directory))
10408 folder)
10409 (setq folder (replace-match "" t t folder)))
10410 (setq cpltxt (org-email-link-description))
10411 (setq link (org-make-link "vm:" folder "#" message-id)))))
10413 ((eq major-mode 'wl-summary-mode)
10414 (let* ((msgnum (wl-summary-message-number))
10415 (message-id (elmo-message-field wl-summary-buffer-elmo-folder
10416 msgnum 'message-id))
10417 (wl-message-entity
10418 (if (fboundp 'elmo-message-entity)
10419 (elmo-message-entity
10420 wl-summary-buffer-elmo-folder msgnum)
10421 (elmo-msgdb-overview-get-entity
10422 msgnum (wl-summary-buffer-msgdb))))
10423 (from (wl-summary-line-from))
10424 (to (car (elmo-message-entity-field wl-message-entity 'to)))
10425 (subject (let (wl-thr-indent-string wl-parent-message-entity)
10426 (wl-summary-line-subject))))
10427 (org-store-link-props :type "wl" :from from :to to
10428 :subject subject :message-id message-id)
10429 (setq message-id (org-remove-angle-brackets message-id))
10430 (setq cpltxt (org-email-link-description))
10431 (setq link (org-make-link "wl:" wl-summary-buffer-folder-name
10432 "#" message-id))))
10434 ((or (equal major-mode 'mh-folder-mode)
10435 (equal major-mode 'mh-show-mode))
10436 (let ((from (org-mhe-get-header "From:"))
10437 (to (org-mhe-get-header "To:"))
10438 (message-id (org-mhe-get-header "Message-Id:"))
10439 (subject (org-mhe-get-header "Subject:")))
10440 (org-store-link-props :type "mh" :from from :to to
10441 :subject subject :message-id message-id)
10442 (setq cpltxt (org-email-link-description))
10443 (setq link (org-make-link "mhe:" (org-mhe-get-message-real-folder) "#"
10444 (org-remove-angle-brackets message-id)))))
10446 ((eq major-mode 'rmail-mode)
10447 (save-excursion
10448 (save-restriction
10449 (rmail-narrow-to-non-pruned-header)
10450 (let ((folder buffer-file-name)
10451 (message-id (mail-fetch-field "message-id"))
10452 (from (mail-fetch-field "from"))
10453 (to (mail-fetch-field "to"))
10454 (subject (mail-fetch-field "subject")))
10455 (org-store-link-props
10456 :type "rmail" :from from :to to
10457 :subject subject :message-id message-id)
10458 (setq message-id (org-remove-angle-brackets message-id))
10459 (setq cpltxt (org-email-link-description))
10460 (setq link (org-make-link "rmail:" folder "#" message-id))))))
10462 ((eq major-mode 'gnus-group-mode)
10463 (let ((group (cond ((fboundp 'gnus-group-group-name) ; depending on Gnus
10464 (gnus-group-group-name)) ; version
10465 ((fboundp 'gnus-group-name)
10466 (gnus-group-name))
10467 (t "???"))))
10468 (unless group (error "Not on a group"))
10469 (org-store-link-props :type "gnus" :group group)
10470 (setq cpltxt (concat
10471 (if (org-xor arg org-usenet-links-prefer-google)
10472 "http://groups.google.com/groups?group="
10473 "gnus:")
10474 group)
10475 link (org-make-link cpltxt))))
10477 ((memq major-mode '(gnus-summary-mode gnus-article-mode))
10478 (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary))
10479 (let* ((group gnus-newsgroup-name)
10480 (article (gnus-summary-article-number))
10481 (header (gnus-summary-article-header article))
10482 (from (mail-header-from header))
10483 (message-id (mail-header-id header))
10484 (date (mail-header-date header))
10485 (subject (gnus-summary-subject-string)))
10486 (org-store-link-props :type "gnus" :from from :subject subject
10487 :message-id message-id :group group)
10488 (setq cpltxt (org-email-link-description))
10489 (if (org-xor arg org-usenet-links-prefer-google)
10490 (setq link
10491 (concat
10492 cpltxt "\n "
10493 (format "http://groups.google.com/groups?as_umsgid=%s"
10494 (org-fixup-message-id-for-http message-id))))
10495 (setq link (org-make-link "gnus:" group
10496 "#" (number-to-string article))))))
10498 ((eq major-mode 'w3-mode)
10499 (setq cpltxt (url-view-url t)
10500 link (org-make-link cpltxt))
10501 (org-store-link-props :type "w3" :url (url-view-url t)))
10503 ((eq major-mode 'w3m-mode)
10504 (setq cpltxt (or w3m-current-title w3m-current-url)
10505 link (org-make-link w3m-current-url))
10506 (org-store-link-props :type "w3m" :url (url-view-url t)))
10508 ((setq search (run-hook-with-args-until-success
10509 'org-create-file-search-functions))
10510 (setq link (concat "file:" (abbreviate-file-name buffer-file-name)
10511 "::" search))
10512 (setq cpltxt (or description link)))
10514 ((eq major-mode 'image-mode)
10515 (setq cpltxt (concat "file:"
10516 (abbreviate-file-name buffer-file-name))
10517 link (org-make-link cpltxt))
10518 (org-store-link-props :type "image" :file buffer-file-name))
10520 ((eq major-mode 'dired-mode)
10521 ;; link to the file in the current line
10522 (setq cpltxt (concat "file:"
10523 (abbreviate-file-name
10524 (expand-file-name
10525 (dired-get-filename nil t))))
10526 link (org-make-link cpltxt)))
10528 ((and buffer-file-name (org-mode-p))
10529 ;; Just link to current headline
10530 (setq cpltxt (concat "file:"
10531 (abbreviate-file-name buffer-file-name)))
10532 ;; Add a context search string
10533 (when (org-xor org-context-in-file-links arg)
10534 ;; Check if we are on a target
10535 (if (org-in-regexp "<<\\(.*?\\)>>")
10536 (setq cpltxt (concat cpltxt "::" (match-string 1)))
10537 (setq txt (cond
10538 ((org-on-heading-p) nil)
10539 ((org-region-active-p)
10540 (buffer-substring (region-beginning) (region-end)))
10541 (t (buffer-substring (point-at-bol) (point-at-eol)))))
10542 (when (or (null txt) (string-match "\\S-" txt))
10543 (setq cpltxt
10544 (concat cpltxt "::" (org-make-org-heading-search-string txt))
10545 desc "NONE"))))
10546 (if (string-match "::\\'" cpltxt)
10547 (setq cpltxt (substring cpltxt 0 -2)))
10548 (setq link (org-make-link cpltxt)))
10550 (buffer-file-name
10551 ;; Just link to this file here.
10552 (setq cpltxt (concat "file:"
10553 (abbreviate-file-name buffer-file-name)))
10554 ;; Add a context string
10555 (when (org-xor org-context-in-file-links arg)
10556 (setq txt (if (org-region-active-p)
10557 (buffer-substring (region-beginning) (region-end))
10558 (buffer-substring (point-at-bol) (point-at-eol))))
10559 ;; Only use search option if there is some text.
10560 (when (string-match "\\S-" txt)
10561 (setq cpltxt
10562 (concat cpltxt "::" (org-make-org-heading-search-string txt))
10563 desc "NONE")))
10564 (setq link (org-make-link cpltxt)))
10566 ((interactive-p)
10567 (error "Cannot link to a buffer which is not visiting a file"))
10569 (t (setq link nil)))
10571 (if (consp link) (setq cpltxt (car link) link (cdr link)))
10572 (setq link (or link cpltxt)
10573 desc (or desc cpltxt))
10574 (if (equal desc "NONE") (setq desc nil))
10576 (if (and (interactive-p) link)
10577 (progn
10578 (setq org-stored-links
10579 (cons (list cpltxt link desc) org-stored-links))
10580 (message "Stored: %s" (or cpltxt link)))
10581 (org-make-link-string link desc))))
10583 (defun org-store-link-props (&rest plist)
10584 "Store link properties, extract names and addresses."
10585 (let (x adr)
10586 (when (setq x (plist-get plist :from))
10587 (setq adr (mail-extract-address-components x))
10588 (plist-put plist :fromname (car adr))
10589 (plist-put plist :fromaddress (nth 1 adr)))
10590 (when (setq x (plist-get plist :to))
10591 (setq adr (mail-extract-address-components x))
10592 (plist-put plist :toname (car adr))
10593 (plist-put plist :toaddress (nth 1 adr))))
10594 (let ((from (plist-get plist :from))
10595 (to (plist-get plist :to)))
10596 (when (and from to org-from-is-user-regexp)
10597 (plist-put plist :fromto
10598 (if (string-match org-from-is-user-regexp from)
10599 (concat "to %t")
10600 (concat "from %f")))))
10601 (setq org-store-link-plist plist))
10603 (defun org-email-link-description (&optional fmt)
10604 "Return the description part of an email link.
10605 This takes information from `org-store-link-plist' and formats it
10606 according to FMT (default from `org-email-link-description-format')."
10607 (setq fmt (or fmt org-email-link-description-format))
10608 (let* ((p org-store-link-plist)
10609 (to (plist-get p :toaddress))
10610 (from (plist-get p :fromaddress))
10611 (table
10612 (list
10613 (cons "%c" (plist-get p :fromto))
10614 (cons "%F" (plist-get p :from))
10615 (cons "%f" (or (plist-get p :fromname) (plist-get p :fromaddress) "?"))
10616 (cons "%T" (plist-get p :to))
10617 (cons "%t" (or (plist-get p :toname) (plist-get p :toaddress) "?"))
10618 (cons "%s" (plist-get p :subject))
10619 (cons "%m" (plist-get p :message-id)))))
10620 (when (string-match "%c" fmt)
10621 ;; Check if the user wrote this message
10622 (if (and org-from-is-user-regexp from to
10623 (save-match-data (string-match org-from-is-user-regexp from)))
10624 (setq fmt (replace-match "to %t" t t fmt))
10625 (setq fmt (replace-match "from %f" t t fmt))))
10626 (org-replace-escapes fmt table)))
10628 (defun org-make-org-heading-search-string (&optional string heading)
10629 "Make search string for STRING or current headline."
10630 (interactive)
10631 (let ((s (or string (org-get-heading))))
10632 (unless (and string (not heading))
10633 ;; We are using a headline, clean up garbage in there.
10634 (if (string-match org-todo-regexp s)
10635 (setq s (replace-match "" t t s)))
10636 (if (string-match (org-re ":[[:alnum:]_@:]+:[ \t]*$") s)
10637 (setq s (replace-match "" t t s)))
10638 (setq s (org-trim s))
10639 (if (string-match (concat "^\\(" org-quote-string "\\|"
10640 org-comment-string "\\)") s)
10641 (setq s (replace-match "" t t s)))
10642 (while (string-match org-ts-regexp s)
10643 (setq s (replace-match "" t t s))))
10644 (while (string-match "[^a-zA-Z_0-9 \t]+" s)
10645 (setq s (replace-match " " t t s)))
10646 (or string (setq s (concat "*" s))) ; Add * for headlines
10647 (mapconcat 'identity (org-split-string s "[ \t]+") " ")))
10649 (defun org-make-link (&rest strings)
10650 "Concatenate STRINGS, format resulting string with `org-link-format'."
10651 (apply 'concat strings))
10653 (defun org-make-link-string (link &optional description)
10654 "Make a link with brackets, consisting of LINK and DESCRIPTION."
10655 (when (stringp description)
10656 ;; Remove brackets from the description, they are fatal.
10657 (while (string-match "\\[\\|\\]" description)
10658 (setq description (replace-match "" t t description))))
10659 (when (equal (org-link-escape link) description)
10660 ;; No description needed, it is identical
10661 (setq description nil))
10662 (when (and (not description)
10663 (not (equal link (org-link-escape link))))
10664 (setq description link))
10665 (concat "[[" (org-link-escape link) "]"
10666 (if description (concat "[" description "]") "")
10667 "]"))
10669 (defconst org-link-escape-chars '(("[" . "%5B") ("]" . "%5D") (" " . "%20"))
10670 "Association list of escapes for some characters problematic in links.")
10672 (defun org-link-escape (text)
10673 "Escape charaters in TEXT that are problematic for links."
10674 (when text
10675 (let ((re (mapconcat (lambda (x) (regexp-quote (car x)))
10676 org-link-escape-chars "\\|")))
10677 (while (string-match re text)
10678 (setq text
10679 (replace-match
10680 (cdr (assoc (match-string 0 text) org-link-escape-chars))
10681 t t text)))
10682 text)))
10684 (defun org-link-unescape (text)
10685 "Reverse the action of `org-link-escape'."
10686 (when text
10687 (let ((re (mapconcat (lambda (x) (regexp-quote (cdr x)))
10688 org-link-escape-chars "\\|")))
10689 (while (string-match re text)
10690 (setq text
10691 (replace-match
10692 (car (rassoc (match-string 0 text) org-link-escape-chars))
10693 t t text)))
10694 text)))
10696 (defun org-xor (a b)
10697 "Exclusive or."
10698 (if a (not b) b))
10700 (defun org-get-header (header)
10701 "Find a header field in the current buffer."
10702 (save-excursion
10703 (goto-char (point-min))
10704 (let ((case-fold-search t) s)
10705 (cond
10706 ((eq header 'from)
10707 (if (re-search-forward "^From:\\s-+\\(.*\\)" nil t)
10708 (setq s (match-string 1)))
10709 (while (string-match "\"" s)
10710 (setq s (replace-match "" t t s)))
10711 (if (string-match "[<(].*" s)
10712 (setq s (replace-match "" t t s))))
10713 ((eq header 'message-id)
10714 (if (re-search-forward "^message-id:\\s-+\\(.*\\)" nil t)
10715 (setq s (match-string 1))))
10716 ((eq header 'subject)
10717 (if (re-search-forward "^subject:\\s-+\\(.*\\)" nil t)
10718 (setq s (match-string 1)))))
10719 (if (string-match "\\`[ \t\]+" s) (setq s (replace-match "" t t s)))
10720 (if (string-match "[ \t\]+\\'" s) (setq s (replace-match "" t t s)))
10721 s)))
10724 (defun org-fixup-message-id-for-http (s)
10725 "Replace special characters in a message id, so it can be used in an http query."
10726 (while (string-match "<" s)
10727 (setq s (replace-match "%3C" t t s)))
10728 (while (string-match ">" s)
10729 (setq s (replace-match "%3E" t t s)))
10730 (while (string-match "@" s)
10731 (setq s (replace-match "%40" t t s)))
10734 (defun org-insert-link (&optional complete-file)
10735 "Insert a link. At the prompt, enter the link.
10737 Completion can be used to select a link previously stored with
10738 `org-store-link'. When the empty string is entered (i.e. if you just
10739 press RET at the prompt), the link defaults to the most recently
10740 stored link. As SPC triggers completion in the minibuffer, you need to
10741 use M-SPC or C-q SPC to force the insertion of a space character.
10743 You will also be prompted for a description, and if one is given, it will
10744 be displayed in the buffer instead of the link.
10746 If there is already a link at point, this command will allow you to edit link
10747 and description parts.
10749 With a \\[universal-argument] prefix, prompts for a file to link to. The file name can be
10750 selected using completion. The path to the file will be relative to
10751 the current directory if the file is in the current directory or a
10752 subdirectory. Otherwise, the link will be the absolute path as
10753 completed in the minibuffer (i.e. normally ~/path/to/file).
10755 With two \\[universal-argument] prefixes, enforce an absolute path even if the file
10756 is in the current directory or below.
10757 With three \\[universal-argument] prefixes, negate the meaning of
10758 `org-keep-stored-link-after-insertion'."
10759 (interactive "P")
10760 (let ((wcf (current-window-configuration))
10761 (region (if (org-region-active-p)
10762 (prog1 (buffer-substring (region-beginning) (region-end))
10763 (delete-region (region-beginning) (region-end)))))
10764 tmphist ; byte-compile incorrectly complains about this
10765 link desc entry remove file)
10766 (cond
10767 ((org-in-regexp org-bracket-link-regexp 1)
10768 ;; We do have a link at point, and we are going to edit it.
10769 (setq remove (list (match-beginning 0) (match-end 0)))
10770 (setq desc (if (match-end 3) (org-match-string-no-properties 3)))
10771 (setq link (read-string "Link: "
10772 (org-link-unescape
10773 (org-match-string-no-properties 1)))))
10774 ((or (org-in-regexp org-angle-link-re)
10775 (org-in-regexp org-plain-link-re))
10776 ;; Convert to bracket link
10777 (setq remove (list (match-beginning 0) (match-end 0))
10778 link (read-string "Link: "
10779 (org-remove-angle-brackets (match-string 0)))))
10780 ((equal complete-file '(4))
10781 ;; Completing read for file names.
10782 (setq file (read-file-name "File: "))
10783 (let ((pwd (file-name-as-directory (expand-file-name ".")))
10784 (pwd1 (file-name-as-directory (abbreviate-file-name
10785 (expand-file-name ".")))))
10786 (cond
10787 ((equal complete-file '(16))
10788 (setq link (org-make-link
10789 "file:"
10790 (abbreviate-file-name (expand-file-name file)))))
10791 ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
10792 (setq link (org-make-link "file:" (match-string 1 file))))
10793 ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
10794 (expand-file-name file))
10795 (setq link (org-make-link
10796 "file:" (match-string 1 (expand-file-name file)))))
10797 (t (setq link (org-make-link "file:" file))))))
10799 ;; Read link, with completion for stored links.
10800 (with-output-to-temp-buffer "*Org Links*"
10801 (princ "Insert a link. Use TAB to complete valid link prefixes.\n")
10802 (when org-stored-links
10803 (princ "\nStored links are available with <up>/<down> (most recent with RET):\n\n")
10804 (princ (mapconcat 'car (reverse org-stored-links) "\n"))))
10805 (let ((cw (selected-window)))
10806 (select-window (get-buffer-window "*Org Links*"))
10807 (shrink-window-if-larger-than-buffer)
10808 (setq truncate-lines t)
10809 (select-window cw))
10810 ;; Fake a link history, containing the stored links.
10811 (setq tmphist (append (mapcar 'car org-stored-links)
10812 org-insert-link-history))
10813 (unwind-protect
10814 (setq link (org-completing-read
10815 "Link: "
10816 (append
10817 (mapcar (lambda (x) (concat (car x) ":"))
10818 (append org-link-abbrev-alist-local org-link-abbrev-alist))
10819 (mapcar (lambda (x) (concat x ":")) org-link-types))
10820 nil nil nil
10821 'tmphist
10822 (or (car (car org-stored-links)))))
10823 (set-window-configuration wcf)
10824 (kill-buffer "*Org Links*"))
10825 (setq entry (assoc link org-stored-links))
10826 (or entry (push link org-insert-link-history))
10827 (if (funcall (if (equal complete-file '(64)) 'not 'identity)
10828 (not org-keep-stored-link-after-insertion))
10829 (setq org-stored-links (delq (assoc link org-stored-links)
10830 org-stored-links)))
10831 (setq link (if entry (nth 1 entry) link)
10832 desc (or region desc (nth 2 entry)))))
10834 (if (string-match org-plain-link-re link)
10835 ;; URL-like link, normalize the use of angular brackets.
10836 (setq link (org-make-link (org-remove-angle-brackets link))))
10838 ;; Check if we are linking to the current file with a search option
10839 ;; If yes, simplify the link by using only the search option.
10840 (when (and buffer-file-name
10841 (string-match "\\<file:\\(.+?\\)::\\([^>]+\\)" link))
10842 (let* ((path (match-string 1 link))
10843 (case-fold-search nil)
10844 (search (match-string 2 link)))
10845 (save-match-data
10846 (if (equal (file-truename buffer-file-name) (file-truename path))
10847 ;; We are linking to this same file, with a search option
10848 (setq link search)))))
10850 ;; Check if we can/should use a relative path. If yes, simplify the link
10851 (when (string-match "\\<file:\\(.*\\)" link)
10852 (let* ((path (match-string 1 link))
10853 (case-fold-search nil))
10854 (cond
10855 ((eq org-link-file-path-type 'absolute)
10856 (setq path (abbreviate-file-name (expand-file-name path))))
10857 ((eq org-link-file-path-type 'noabbrev)
10858 (setq path (expand-file-name path)))
10859 ((eq org-link-file-path-type 'relative)
10860 (setq path (file-relative-name path)))
10862 (save-match-data
10863 (if (string-match (concat "^" (regexp-quote
10864 (file-name-as-directory
10865 (expand-file-name "."))))
10866 (expand-file-name path))
10867 ;; We are linking a file with relative path name.
10868 (setq path (substring (expand-file-name path)
10869 (match-end 0)))))))
10870 (setq link (concat "file:" path))))
10872 (setq desc (read-string "Description: " desc))
10873 (unless (string-match "\\S-" desc) (setq desc nil))
10874 (if remove (apply 'delete-region remove))
10875 (insert (org-make-link-string link desc))))
10877 (defun org-completing-read (&rest args)
10878 (let ((minibuffer-local-completion-map
10879 (copy-keymap minibuffer-local-completion-map)))
10880 (org-defkey minibuffer-local-completion-map " " 'self-insert-command)
10881 (apply 'completing-read args)))
10883 ;;; Opening/following a link
10884 (defvar org-link-search-failed nil)
10886 (defun org-next-link ()
10887 "Move forward to the next link.
10888 If the link is in hidden text, expose it."
10889 (interactive)
10890 (when (and org-link-search-failed (eq this-command last-command))
10891 (goto-char (point-min))
10892 (message "Link search wrapped back to beginning of buffer"))
10893 (setq org-link-search-failed nil)
10894 (let* ((pos (point))
10895 (ct (org-context))
10896 (a (assoc :link ct)))
10897 (if a (goto-char (nth 2 a)))
10898 (if (re-search-forward org-any-link-re nil t)
10899 (progn
10900 (goto-char (match-beginning 0))
10901 (if (org-invisible-p) (org-show-context)))
10902 (goto-char pos)
10903 (setq org-link-search-failed t)
10904 (error "No further link found"))))
10906 (defun org-previous-link ()
10907 "Move backward to the previous link.
10908 If the link is in hidden text, expose it."
10909 (interactive)
10910 (when (and org-link-search-failed (eq this-command last-command))
10911 (goto-char (point-max))
10912 (message "Link search wrapped back to end of buffer"))
10913 (setq org-link-search-failed nil)
10914 (let* ((pos (point))
10915 (ct (org-context))
10916 (a (assoc :link ct)))
10917 (if a (goto-char (nth 1 a)))
10918 (if (re-search-backward org-any-link-re nil t)
10919 (progn
10920 (goto-char (match-beginning 0))
10921 (if (org-invisible-p) (org-show-context)))
10922 (goto-char pos)
10923 (setq org-link-search-failed t)
10924 (error "No further link found"))))
10926 (defun org-find-file-at-mouse (ev)
10927 "Open file link or URL at mouse."
10928 (interactive "e")
10929 (mouse-set-point ev)
10930 (org-open-at-point 'in-emacs))
10932 (defun org-open-at-mouse (ev)
10933 "Open file link or URL at mouse."
10934 (interactive "e")
10935 (mouse-set-point ev)
10936 (org-open-at-point))
10938 (defvar org-window-config-before-follow-link nil
10939 "The window configuration before following a link.
10940 This is saved in case the need arises to restore it.")
10942 (defvar org-open-link-marker (make-marker)
10943 "Marker pointing to the location where `org-open-at-point; was called.")
10945 (defun org-open-at-point (&optional in-emacs)
10946 "Open link at or after point.
10947 If there is no link at point, this function will search forward up to
10948 the end of the current subtree.
10949 Normally, files will be opened by an appropriate application. If the
10950 optional argument IN-EMACS is non-nil, Emacs will visit the file."
10951 (interactive "P")
10952 (move-marker org-open-link-marker (point))
10953 (setq org-window-config-before-follow-link (current-window-configuration))
10954 (org-remove-occur-highlights nil nil t)
10955 (if (org-at-timestamp-p t)
10956 (org-follow-timestamp-link)
10957 (let (type path link line search (pos (point)))
10958 (catch 'match
10959 (save-excursion
10960 (skip-chars-forward "^]\n\r")
10961 (when (org-in-regexp org-bracket-link-regexp)
10962 (setq link (org-link-unescape (org-match-string-no-properties 1)))
10963 (while (string-match " *\n *" link)
10964 (setq link (replace-match " " t t link)))
10965 (setq link (org-link-expand-abbrev link))
10966 (if (string-match org-link-re-with-space2 link)
10967 (setq type (match-string 1 link) path (match-string 2 link))
10968 (setq type "thisfile" path link))
10969 (throw 'match t)))
10971 (when (get-text-property (point) 'org-linked-text)
10972 (setq type "thisfile"
10973 pos (if (get-text-property (1+ (point)) 'org-linked-text)
10974 (1+ (point)) (point))
10975 path (buffer-substring
10976 (previous-single-property-change pos 'org-linked-text)
10977 (next-single-property-change pos 'org-linked-text)))
10978 (throw 'match t))
10980 (save-excursion
10981 (when (or (org-in-regexp org-angle-link-re)
10982 (org-in-regexp org-plain-link-re))
10983 (setq type (match-string 1) path (match-string 2))
10984 (throw 'match t)))
10985 (when (org-in-regexp "\\<\\([^><\n]+\\)\\>")
10986 (setq type "tree-match"
10987 path (match-string 1))
10988 (throw 'match t))
10989 (save-excursion
10990 (when (org-in-regexp (org-re "\\(:[[:alnum:]_@:]+\\):[ \t]*$"))
10991 (setq type "tags"
10992 path (match-string 1))
10993 (while (string-match ":" path)
10994 (setq path (replace-match "+" t t path)))
10995 (throw 'match t))))
10996 (unless path
10997 (error "No link found"))
10998 ;; Remove any trailing spaces in path
10999 (if (string-match " +\\'" path)
11000 (setq path (replace-match "" t t path)))
11002 (cond
11004 ((equal type "mailto")
11005 (let ((cmd (car org-link-mailto-program))
11006 (args (cdr org-link-mailto-program)) args1
11007 (address path) (subject "") a)
11008 (if (string-match "\\(.*\\)::\\(.*\\)" path)
11009 (setq address (match-string 1 path)
11010 subject (org-link-escape (match-string 2 path))))
11011 (while args
11012 (cond
11013 ((not (stringp (car args))) (push (pop args) args1))
11014 (t (setq a (pop args))
11015 (if (string-match "%a" a)
11016 (setq a (replace-match address t t a)))
11017 (if (string-match "%s" a)
11018 (setq a (replace-match subject t t a)))
11019 (push a args1))))
11020 (apply cmd (nreverse args1))))
11022 ((member type '("http" "https" "ftp" "news"))
11023 (browse-url (concat type ":" path)))
11025 ((string= type "tags")
11026 (org-tags-view in-emacs path))
11027 ((string= type "thisfile")
11028 (if in-emacs
11029 (switch-to-buffer-other-window
11030 (org-get-buffer-for-internal-link (current-buffer)))
11031 (org-mark-ring-push))
11032 (let ((cmd `(org-link-search
11033 ,path
11034 ,(cond ((equal in-emacs '(4)) 'occur)
11035 ((equal in-emacs '(16)) 'org-occur)
11036 (t nil))
11037 ,pos)))
11038 (condition-case nil (eval cmd)
11039 (error (progn (widen) (eval cmd))))))
11041 ((string= type "tree-match")
11042 (org-occur (concat "\\[" (regexp-quote path) "\\]")))
11044 ((string= type "file")
11045 (if (string-match "::\\([0-9]+\\)\\'" path)
11046 (setq line (string-to-number (match-string 1 path))
11047 path (substring path 0 (match-beginning 0)))
11048 (if (string-match "::\\(.+\\)\\'" path)
11049 (setq search (match-string 1 path)
11050 path (substring path 0 (match-beginning 0)))))
11051 (org-open-file path in-emacs line search))
11053 ((string= type "news")
11054 (org-follow-gnus-link path))
11056 ((string= type "bbdb")
11057 (org-follow-bbdb-link path))
11059 ((string= type "info")
11060 (org-follow-info-link path))
11062 ((string= type "gnus")
11063 (let (group article)
11064 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
11065 (error "Error in Gnus link"))
11066 (setq group (match-string 1 path)
11067 article (match-string 3 path))
11068 (org-follow-gnus-link group article)))
11070 ((string= type "vm")
11071 (let (folder article)
11072 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
11073 (error "Error in VM link"))
11074 (setq folder (match-string 1 path)
11075 article (match-string 3 path))
11076 ;; in-emacs is the prefix arg, will be interpreted as read-only
11077 (org-follow-vm-link folder article in-emacs)))
11079 ((string= type "wl")
11080 (let (folder article)
11081 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
11082 (error "Error in Wanderlust link"))
11083 (setq folder (match-string 1 path)
11084 article (match-string 3 path))
11085 (org-follow-wl-link folder article)))
11087 ((string= type "mhe")
11088 (let (folder article)
11089 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
11090 (error "Error in MHE link"))
11091 (setq folder (match-string 1 path)
11092 article (match-string 3 path))
11093 (org-follow-mhe-link folder article)))
11095 ((string= type "rmail")
11096 (let (folder article)
11097 (if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
11098 (error "Error in RMAIL link"))
11099 (setq folder (match-string 1 path)
11100 article (match-string 3 path))
11101 (org-follow-rmail-link folder article)))
11103 ((string= type "shell")
11104 (let ((cmd path))
11105 ;; FIXME: the following is only for backward compatibility
11106 (while (string-match "@{" cmd) (setq cmd (replace-match "<" t t cmd)))
11107 (while (string-match "@}" cmd) (setq cmd (replace-match ">" t t cmd)))
11108 (if (or (not org-confirm-shell-link-function)
11109 (funcall org-confirm-shell-link-function
11110 (format "Execute \"%s\" in shell? "
11111 (org-add-props cmd nil
11112 'face 'org-warning))))
11113 (progn
11114 (message "Executing %s" cmd)
11115 (shell-command cmd))
11116 (error "Abort"))))
11118 ((string= type "elisp")
11119 (let ((cmd path))
11120 (if (or (not org-confirm-elisp-link-function)
11121 (funcall org-confirm-elisp-link-function
11122 (format "Execute \"%s\" as elisp? "
11123 (org-add-props cmd nil
11124 'face 'org-warning))))
11125 (message "%s => %s" cmd (eval (read cmd)))
11126 (error "Abort"))))
11129 (browse-url-at-point)))))
11130 (move-marker org-open-link-marker nil))
11133 ;;; File search
11135 (defvar org-create-file-search-functions nil
11136 "List of functions to construct the right search string for a file link.
11137 These functions are called in turn with point at the location to
11138 which the link should point.
11140 A function in the hook should first test if it would like to
11141 handle this file type, for example by checking the major-mode or
11142 the file extension. If it decides not to handle this file, it
11143 should just return nil to give other functions a chance. If it
11144 does handle the file, it must return the search string to be used
11145 when following the link. The search string will be part of the
11146 file link, given after a double colon, and `org-open-at-point'
11147 will automatically search for it. If special measures must be
11148 taken to make the search successful, another function should be
11149 added to the companion hook `org-execute-file-search-functions',
11150 which see.
11152 A function in this hook may also use `setq' to set the variable
11153 `description' to provide a suggestion for the descriptive text to
11154 be used for this link when it gets inserted into an Org-mode
11155 buffer with \\[org-insert-link].")
11157 (defvar org-execute-file-search-functions nil
11158 "List of functions to execute a file search triggered by a link.
11160 Functions added to this hook must accept a single argument, the
11161 search string that was part of the file link, the part after the
11162 double colon. The function must first check if it would like to
11163 handle this search, for example by checking the major-mode or the
11164 file extension. If it decides not to handle this search, it
11165 should just return nil to give other functions a chance. If it
11166 does handle the search, it must return a non-nil value to keep
11167 other functions from trying.
11169 Each function can access the current prefix argument through the
11170 variable `current-prefix-argument'. Note that a single prefix is
11171 used to force opening a link in Emacs, so it may be good to only
11172 use a numeric or double prefix to guide the search function.
11174 In case this is needed, a function in this hook can also restore
11175 the window configuration before `org-open-at-point' was called using:
11177 (set-window-configuration org-window-config-before-follow-link)")
11179 (defun org-link-search (s &optional type avoid-pos)
11180 "Search for a link search option.
11181 If S is surrounded by forward slashes, it is interpreted as a
11182 regular expression. In org-mode files, this will create an `org-occur'
11183 sparse tree. In ordinary files, `occur' will be used to list matches.
11184 If the current buffer is in `dired-mode', grep will be used to search
11185 in all files. If AVOID-POS is given, ignore matches near that position."
11186 (let ((case-fold-search t)
11187 (s0 (mapconcat 'identity (org-split-string s "[ \t\r\n]+") " "))
11188 (markers (concat "\\(?:" (mapconcat (lambda (x) (regexp-quote (car x)))
11189 (append '(("") (" ") ("\t") ("\n"))
11190 org-emphasis-alist)
11191 "\\|") "\\)"))
11192 (pos (point))
11193 (pre "") (post "")
11194 words re0 re1 re2 re3 re4 re5 re2a reall)
11195 (cond
11196 ;; First check if there are any special
11197 ((run-hook-with-args-until-success 'org-execute-file-search-functions s))
11198 ;; Now try the builtin stuff
11199 ((save-excursion
11200 (goto-char (point-min))
11201 (and
11202 (re-search-forward
11203 (concat "<<" (regexp-quote s0) ">>") nil t)
11204 (setq pos (match-beginning 0))))
11205 ;; There is an exact target for this
11206 (goto-char pos))
11207 ((string-match "^/\\(.*\\)/$" s)
11208 ;; A regular expression
11209 (cond
11210 ((org-mode-p)
11211 (org-occur (match-string 1 s)))
11212 ;;((eq major-mode 'dired-mode)
11213 ;; (grep (concat "grep -n -e '" (match-string 1 s) "' *")))
11214 (t (org-do-occur (match-string 1 s)))))
11216 ;; A normal search strings
11217 (when (equal (string-to-char s) ?*)
11218 ;; Anchor on headlines, post may include tags.
11219 (setq pre "^\\*+[ \t]+\\(?:\\sw+\\)?[ \t]*"
11220 post (org-re "[ \t]*\\(?:[ \t]+:[[:alnum:]_@:+]:[ \t]*\\)?$")
11221 s (substring s 1)))
11222 (remove-text-properties
11223 0 (length s)
11224 '(face nil mouse-face nil keymap nil fontified nil) s)
11225 ;; Make a series of regular expressions to find a match
11226 (setq words (org-split-string s "[ \n\r\t]+")
11227 re0 (concat "\\(<<" (regexp-quote s0) ">>\\)")
11228 re2 (concat markers "\\(" (mapconcat 'downcase words "[ \t]+")
11229 "\\)" markers)
11230 re2a (concat "[ \t\r\n]\\(" (mapconcat 'downcase words "[ \t\r\n]+") "\\)[ \t\r\n]")
11231 re4 (concat "[^a-zA-Z_]\\(" (mapconcat 'downcase words "[^a-zA-Z_\r\n]+") "\\)[^a-zA-Z_]")
11232 re1 (concat pre re2 post)
11233 re3 (concat pre re4 post)
11234 re5 (concat pre ".*" re4)
11235 re2 (concat pre re2)
11236 re2a (concat pre re2a)
11237 re4 (concat pre re4)
11238 reall (concat "\\(" re0 "\\)\\|\\(" re1 "\\)\\|\\(" re2
11239 "\\)\\|\\(" re3 "\\)\\|\\(" re4 "\\)\\|\\("
11240 re5 "\\)"
11242 (cond
11243 ((eq type 'org-occur) (org-occur reall))
11244 ((eq type 'occur) (org-do-occur (downcase reall) 'cleanup))
11245 (t (goto-char (point-min))
11246 (if (or (org-search-not-self 1 re0 nil t)
11247 (org-search-not-self 1 re1 nil t)
11248 (org-search-not-self 1 re2 nil t)
11249 (org-search-not-self 1 re2a nil t)
11250 (org-search-not-self 1 re3 nil t)
11251 (org-search-not-self 1 re4 nil t)
11252 (org-search-not-self 1 re5 nil t)
11254 (goto-char (match-beginning 1))
11255 (goto-char pos)
11256 (error "No match")))))
11258 ;; Normal string-search
11259 (goto-char (point-min))
11260 (if (search-forward s nil t)
11261 (goto-char (match-beginning 0))
11262 (error "No match"))))
11263 (and (org-mode-p) (org-show-context 'link-search))))
11265 (defun org-search-not-self (group &rest args)
11266 "Execute `re-search-forward', but only accept matches that do not
11267 enclose the position of `org-open-link-marker'."
11268 (let ((m org-open-link-marker))
11269 (catch 'exit
11270 (while (apply 're-search-forward args)
11271 (unless (get-text-property (match-end group) 'intangible) ; Emacs 21
11272 (goto-char (match-end group))
11273 (if (and (or (not (eq (marker-buffer m) (current-buffer)))
11274 (> (match-beginning 0) (marker-position m))
11275 (< (match-end 0) (marker-position m)))
11276 (save-match-data
11277 (or (not (org-in-regexp
11278 org-bracket-link-analytic-regexp 1))
11279 (not (match-end 4)) ; no description
11280 (and (<= (match-beginning 4) (point))
11281 (>= (match-end 4) (point))))))
11282 (throw 'exit (point))))))))
11284 (defun org-get-buffer-for-internal-link (buffer)
11285 "Return a buffer to be used for displaying the link target of internal links."
11286 (cond
11287 ((not org-display-internal-link-with-indirect-buffer)
11288 buffer)
11289 ((string-match "(Clone)$" (buffer-name buffer))
11290 (message "Buffer is already a clone, not making another one")
11291 ;; we also do not modify visibility in this case
11292 buffer)
11293 (t ; make a new indirect buffer for displaying the link
11294 (let* ((bn (buffer-name buffer))
11295 (ibn (concat bn "(Clone)"))
11296 (ib (or (get-buffer ibn) (make-indirect-buffer buffer ibn 'clone))))
11297 (with-current-buffer ib (org-overview))
11298 ib))))
11300 (defun org-do-occur (regexp &optional cleanup)
11301 "Call the Emacs command `occur'.
11302 If CLEANUP is non-nil, remove the printout of the regular expression
11303 in the *Occur* buffer. This is useful if the regex is long and not useful
11304 to read."
11305 (occur regexp)
11306 (when cleanup
11307 (let ((cwin (selected-window)) win beg end)
11308 (when (setq win (get-buffer-window "*Occur*"))
11309 (select-window win))
11310 (goto-char (point-min))
11311 (when (re-search-forward "match[a-z]+" nil t)
11312 (setq beg (match-end 0))
11313 (if (re-search-forward "^[ \t]*[0-9]+" nil t)
11314 (setq end (1- (match-beginning 0)))))
11315 (and beg end (let ((buffer-read-only)) (delete-region beg end)))
11316 (goto-char (point-min))
11317 (select-window cwin))))
11319 ;;; The mark ring for links jumps
11321 (defvar org-mark-ring nil
11322 "Mark ring for positions before jumps in Org-mode.")
11323 (defvar org-mark-ring-last-goto nil
11324 "Last position in the mark ring used to go back.")
11325 ;; Fill and close the ring
11326 (setq org-mark-ring nil org-mark-ring-last-goto nil) ;; in case file is reloaded
11327 (loop for i from 1 to org-mark-ring-length do
11328 (push (make-marker) org-mark-ring))
11329 (setcdr (nthcdr (1- org-mark-ring-length) org-mark-ring)
11330 org-mark-ring)
11332 (defun org-mark-ring-push (&optional pos buffer)
11333 "Put the current position or POS into the mark ring and rotate it."
11334 (interactive)
11335 (setq pos (or pos (point)))
11336 (setq org-mark-ring (nthcdr (1- org-mark-ring-length) org-mark-ring))
11337 (move-marker (car org-mark-ring)
11338 (or pos (point))
11339 (or buffer (current-buffer)))
11340 (message
11341 (substitute-command-keys
11342 "Position saved to mark ring, go back with \\[org-mark-ring-goto].")))
11344 (defun org-mark-ring-goto (&optional n)
11345 "Jump to the previous position in the mark ring.
11346 With prefix arg N, jump back that many stored positions. When
11347 called several times in succession, walk through the entire ring.
11348 Org-mode commands jumping to a different position in the current file,
11349 or to another Org-mode file, automatically push the old position
11350 onto the ring."
11351 (interactive "p")
11352 (let (p m)
11353 (if (eq last-command this-command)
11354 (setq p (nthcdr n (or org-mark-ring-last-goto org-mark-ring)))
11355 (setq p org-mark-ring))
11356 (setq org-mark-ring-last-goto p)
11357 (setq m (car p))
11358 (switch-to-buffer (marker-buffer m))
11359 (goto-char m)
11360 (if (or (org-invisible-p) (org-invisible-p2)) (org-show-context 'mark-goto))))
11362 (defun org-remove-angle-brackets (s)
11363 (if (equal (substring s 0 1) "<") (setq s (substring s 1)))
11364 (if (equal (substring s -1) ">") (setq s (substring s 0 -1)))
11366 (defun org-add-angle-brackets (s)
11367 (if (equal (substring s 0 1) "<") nil (setq s (concat "<" s)))
11368 (if (equal (substring s -1) ">") nil (setq s (concat s ">")))
11371 ;;; Following specific links
11373 (defun org-follow-timestamp-link ()
11374 (cond
11375 ((org-at-date-range-p t)
11376 (let ((org-agenda-start-on-weekday)
11377 (t1 (match-string 1))
11378 (t2 (match-string 2)))
11379 (setq t1 (time-to-days (org-time-string-to-time t1))
11380 t2 (time-to-days (org-time-string-to-time t2)))
11381 (org-agenda-list nil t1 (1+ (- t2 t1)))))
11382 ((org-at-timestamp-p t)
11383 (org-agenda-list nil (time-to-days (org-time-string-to-time
11384 (substring (match-string 1) 0 10)))
11386 (t (error "This should not happen"))))
11389 (defun org-follow-bbdb-link (name)
11390 "Follow a BBDB link to NAME."
11391 (require 'bbdb)
11392 (let ((inhibit-redisplay (not debug-on-error))
11393 (bbdb-electric-p nil))
11394 (catch 'exit
11395 ;; Exact match on name
11396 (bbdb-name (concat "\\`" name "\\'") nil)
11397 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
11398 ;; Exact match on name
11399 (bbdb-company (concat "\\`" name "\\'") nil)
11400 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
11401 ;; Partial match on name
11402 (bbdb-name name nil)
11403 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
11404 ;; Partial match on company
11405 (bbdb-company name nil)
11406 (if (< 0 (buffer-size (get-buffer "*BBDB*"))) (throw 'exit nil))
11407 ;; General match including network address and notes
11408 (bbdb name nil)
11409 (when (= 0 (buffer-size (get-buffer "*BBDB*")))
11410 (delete-window (get-buffer-window "*BBDB*"))
11411 (error "No matching BBDB record")))))
11413 (defun org-follow-info-link (name)
11414 "Follow an info file & node link to NAME."
11415 (if (or (string-match "\\(.*\\)::?\\(.*\\)" name)
11416 (string-match "\\(.*\\)" name))
11417 (progn
11418 (require 'info)
11419 (if (match-string 2 name) ; If there isn't a node, choose "Top"
11420 (Info-find-node (match-string 1 name) (match-string 2 name))
11421 (Info-find-node (match-string 1 name) "Top")))
11422 (message (concat "Could not open: " name))))
11424 (defun org-follow-gnus-link (&optional group article)
11425 "Follow a Gnus link to GROUP and ARTICLE."
11426 (require 'gnus)
11427 (funcall (cdr (assq 'gnus org-link-frame-setup)))
11428 (if gnus-other-frame-object (select-frame gnus-other-frame-object))
11429 (cond ((and group article)
11430 (gnus-group-read-group 1 nil group)
11431 (gnus-summary-goto-article (string-to-number article) nil t))
11432 (group (gnus-group-jump-to-group group))))
11434 (defun org-follow-vm-link (&optional folder article readonly)
11435 "Follow a VM link to FOLDER and ARTICLE."
11436 (require 'vm)
11437 (setq article (org-add-angle-brackets article))
11438 (if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
11439 ;; ange-ftp or efs or tramp access
11440 (let ((user (or (match-string 1 folder) (user-login-name)))
11441 (host (match-string 2 folder))
11442 (file (match-string 3 folder)))
11443 (cond
11444 ((featurep 'tramp)
11445 ;; use tramp to access the file
11446 (if (featurep 'xemacs)
11447 (setq folder (format "[%s@%s]%s" user host file))
11448 (setq folder (format "/%s@%s:%s" user host file))))
11450 ;; use ange-ftp or efs
11451 (require (if (featurep 'xemacs) 'efs 'ange-ftp))
11452 (setq folder (format "/%s@%s:%s" user host file))))))
11453 (when folder
11454 (funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
11455 (sit-for 0.1)
11456 (when article
11457 (vm-select-folder-buffer)
11458 (widen)
11459 (let ((case-fold-search t))
11460 (goto-char (point-min))
11461 (if (not (re-search-forward
11462 (concat "^" "message-id: *" (regexp-quote article))))
11463 (error "Could not find the specified message in this folder"))
11464 (vm-isearch-update)
11465 (vm-isearch-narrow)
11466 (vm-beginning-of-message)
11467 (vm-summarize)))))
11469 (defun org-follow-wl-link (folder article)
11470 "Follow a Wanderlust link to FOLDER and ARTICLE."
11471 (if (and (string= folder "%")
11472 article
11473 (string-match "^\\([^#]+\\)\\(#\\(.*\\)\\)?" article))
11474 ;; XXX: imap-uw supports folders starting with '#' such as "#mh/inbox".
11475 ;; Thus, we recompose folder and article ids.
11476 (setq folder (format "%s#%s" folder (match-string 1 article))
11477 article (match-string 3 article)))
11478 (if (not (elmo-folder-exists-p (wl-folder-get-elmo-folder folder)))
11479 (error "No such folder: %s" folder))
11480 (wl-summary-goto-folder-subr folder 'no-sync t nil t nil nil)
11481 (and article
11482 (wl-summary-jump-to-msg-by-message-id (org-add-angle-brackets article))
11483 (wl-summary-redisplay)))
11485 (defun org-follow-rmail-link (folder article)
11486 "Follow an RMAIL link to FOLDER and ARTICLE."
11487 (setq article (org-add-angle-brackets article))
11488 (let (message-number)
11489 (save-excursion
11490 (save-window-excursion
11491 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
11492 (setq message-number
11493 (save-restriction
11494 (widen)
11495 (goto-char (point-max))
11496 (if (re-search-backward
11497 (concat "^Message-ID:\\s-+" (regexp-quote
11498 (or article "")))
11499 nil t)
11500 (rmail-what-message))))))
11501 (if message-number
11502 (progn
11503 (rmail (if (string= folder "RMAIL") rmail-file-name folder))
11504 (rmail-show-message message-number)
11505 message-number)
11506 (error "Message not found"))))
11508 ;;; mh-e integration based on planner-mode
11509 (defun org-mhe-get-message-real-folder ()
11510 "Return the name of the current message real folder, so if you use
11511 sequences, it will now work."
11512 (save-excursion
11513 (let* ((folder
11514 (if (equal major-mode 'mh-folder-mode)
11515 mh-current-folder
11516 ;; Refer to the show buffer
11517 mh-show-folder-buffer))
11518 (end-index
11519 (if (boundp 'mh-index-folder)
11520 (min (length mh-index-folder) (length folder))))
11522 ;; a simple test on mh-index-data does not work, because
11523 ;; mh-index-data is always nil in a show buffer.
11524 (if (and (boundp 'mh-index-folder)
11525 (string= mh-index-folder (substring folder 0 end-index)))
11526 (if (equal major-mode 'mh-show-mode)
11527 (save-window-excursion
11528 (when (buffer-live-p (get-buffer folder))
11529 (progn
11530 (pop-to-buffer folder)
11531 (org-mhe-get-message-folder-from-index)
11534 (org-mhe-get-message-folder-from-index)
11536 folder
11540 (defun org-mhe-get-message-folder-from-index ()
11541 "Returns the name of the message folder in a index folder buffer."
11542 (save-excursion
11543 (mh-index-previous-folder)
11544 (re-search-forward "^\\(+.*\\)$" nil t)
11545 (message (match-string 1))))
11547 (defun org-mhe-get-message-folder ()
11548 "Return the name of the current message folder. Be careful if you
11549 use sequences."
11550 (save-excursion
11551 (if (equal major-mode 'mh-folder-mode)
11552 mh-current-folder
11553 ;; Refer to the show buffer
11554 mh-show-folder-buffer)))
11556 (defun org-mhe-get-message-num ()
11557 "Return the number of the current message. Be careful if you
11558 use sequences."
11559 (save-excursion
11560 (if (equal major-mode 'mh-folder-mode)
11561 (mh-get-msg-num nil)
11562 ;; Refer to the show buffer
11563 (mh-show-buffer-message-number))))
11565 (defun org-mhe-get-header (header)
11566 "Return a header of the message in folder mode. This will create a
11567 show buffer for the corresponding message. If you have a more clever
11568 idea..."
11569 (let* ((folder (org-mhe-get-message-folder))
11570 (num (org-mhe-get-message-num))
11571 (buffer (get-buffer-create (concat "show-" folder)))
11572 (header-field))
11573 (with-current-buffer buffer
11574 (mh-display-msg num folder)
11575 (if (equal major-mode 'mh-folder-mode)
11576 (mh-header-display)
11577 (mh-show-header-display))
11578 (set-buffer buffer)
11579 (setq header-field (mh-get-header-field header))
11580 (if (equal major-mode 'mh-folder-mode)
11581 (mh-show)
11582 (mh-show-show))
11583 header-field)))
11585 (defun org-follow-mhe-link (folder article)
11586 "Follow an MHE link to FOLDER and ARTICLE.
11587 If ARTICLE is nil FOLDER is shown. If the configuration variable
11588 `org-mhe-search-all-folders' is t and `mh-searcher' is pick,
11589 ARTICLE is searched in all folders. Indexed searches (swish++,
11590 namazu, and others supported by MH-E) will always search in all
11591 folders."
11592 (require 'mh-e)
11593 (require 'mh-search)
11594 (require 'mh-utils)
11595 (mh-find-path)
11596 (if (not article)
11597 (mh-visit-folder (mh-normalize-folder-name folder))
11598 (setq article (org-add-angle-brackets article))
11599 (mh-search-choose)
11600 (if (equal mh-searcher 'pick)
11601 (progn
11602 (mh-search folder (list "--message-id" article))
11603 (when (and org-mhe-search-all-folders
11604 (not (org-mhe-get-message-real-folder)))
11605 (kill-this-buffer)
11606 (mh-search "+" (list "--message-id" article))))
11607 (mh-search "+" article))
11608 (if (org-mhe-get-message-real-folder)
11609 (mh-show-msg 1)
11610 (kill-this-buffer)
11611 (error "Message not found"))))
11613 ;;; BibTeX links
11615 ;; Use the custom search meachnism to construct and use search strings for
11616 ;; file links to BibTeX database entries.
11618 (defun org-create-file-search-in-bibtex ()
11619 "Create the search string and description for a BibTeX database entry."
11620 (when (eq major-mode 'bibtex-mode)
11621 ;; yes, we want to construct this search string.
11622 ;; Make a good description for this entry, using names, year and the title
11623 ;; Put it into the `description' variable which is dynamically scoped.
11624 (let ((bibtex-autokey-names 1)
11625 (bibtex-autokey-names-stretch 1)
11626 (bibtex-autokey-name-case-convert-function 'identity)
11627 (bibtex-autokey-name-separator " & ")
11628 (bibtex-autokey-additional-names " et al.")
11629 (bibtex-autokey-year-length 4)
11630 (bibtex-autokey-name-year-separator " ")
11631 (bibtex-autokey-titlewords 3)
11632 (bibtex-autokey-titleword-separator " ")
11633 (bibtex-autokey-titleword-case-convert-function 'identity)
11634 (bibtex-autokey-titleword-length 'infty)
11635 (bibtex-autokey-year-title-separator ": "))
11636 (setq description (bibtex-generate-autokey)))
11637 ;; Now parse the entry, get the key and return it.
11638 (save-excursion
11639 (bibtex-beginning-of-entry)
11640 (cdr (assoc "=key=" (bibtex-parse-entry))))))
11642 (defun org-execute-file-search-in-bibtex (s)
11643 "Find the link search string S as a key for a database entry."
11644 (when (eq major-mode 'bibtex-mode)
11645 ;; Yes, we want to do the search in this file.
11646 ;; We construct a regexp that searches for "@entrytype{" followed by the key
11647 (goto-char (point-min))
11648 (and (re-search-forward (concat "@[a-zA-Z]+[ \t\n]*{[ \t\n]*"
11649 (regexp-quote s) "[ \t\n]*,") nil t)
11650 (goto-char (match-beginning 0)))
11651 (if (and (match-beginning 0) (equal current-prefix-arg '(16)))
11652 ;; Use double prefix to indicate that any web link should be browsed
11653 (let ((b (current-buffer)) (p (point)))
11654 ;; Restore the window configuration because we just use the web link
11655 (set-window-configuration org-window-config-before-follow-link)
11656 (save-excursion (set-buffer b) (goto-char p)
11657 (bibtex-url)))
11658 (recenter 0)) ; Move entry start to beginning of window
11659 ;; return t to indicate that the search is done.
11662 ;; Finally add the functions to the right hooks.
11663 (add-hook 'org-create-file-search-functions 'org-create-file-search-in-bibtex)
11664 (add-hook 'org-execute-file-search-functions 'org-execute-file-search-in-bibtex)
11666 ;; end of Bibtex link setup
11668 ;;; Following file links
11670 (defun org-open-file (path &optional in-emacs line search)
11671 "Open the file at PATH.
11672 First, this expands any special file name abbreviations. Then the
11673 configuration variable `org-file-apps' is checked if it contains an
11674 entry for this file type, and if yes, the corresponding command is launched.
11675 If no application is found, Emacs simply visits the file.
11676 With optional argument IN-EMACS, Emacs will visit the file.
11677 Optional LINE specifies a line to go to, optional SEARCH a string to
11678 search for. If LINE or SEARCH is given, the file will always be
11679 opened in Emacs.
11680 If the file does not exist, an error is thrown."
11681 (setq in-emacs (or in-emacs line search))
11682 (let* ((file (if (equal path "")
11683 buffer-file-name
11684 (substitute-in-file-name (expand-file-name path))))
11685 (apps (append org-file-apps (org-default-apps)))
11686 (remp (and (assq 'remote apps) (org-file-remote-p file)))
11687 (dirp (if remp nil (file-directory-p file)))
11688 (dfile (downcase file))
11689 (old-buffer (current-buffer))
11690 (old-pos (point))
11691 (old-mode major-mode)
11692 ext cmd)
11693 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\.gz\\)$" dfile)
11694 (setq ext (match-string 1 dfile))
11695 (if (string-match "^.*\\.\\([a-zA-Z0-9]+\\)$" dfile)
11696 (setq ext (match-string 1 dfile))))
11697 (if in-emacs
11698 (setq cmd 'emacs)
11699 (setq cmd (or (and remp (cdr (assoc 'remote apps)))
11700 (and dirp (cdr (assoc 'directory apps)))
11701 (cdr (assoc ext apps))
11702 (cdr (assoc t apps)))))
11703 (when (eq cmd 'mailcap)
11704 (require 'mailcap)
11705 (mailcap-parse-mailcaps)
11706 (let* ((mime-type (mailcap-extension-to-mime (or ext "")))
11707 (command (mailcap-mime-info mime-type)))
11708 (if (stringp command)
11709 (setq cmd command)
11710 (setq cmd 'emacs))))
11711 (if (and (not (eq cmd 'emacs)) ; Emacs has no problems with non-ex files
11712 (not (file-exists-p file))
11713 (not org-open-non-existing-files))
11714 (error "No such file: %s" file))
11715 (cond
11716 ((and (stringp cmd) (not (string-match "^\\s-*$" cmd)))
11717 ;; Remove quotes around the file name - we'll use shell-quote-argument.
11718 (if (string-match "['\"]%s['\"]" cmd)
11719 (setq cmd (replace-match "%s" t t cmd)))
11720 (setq cmd (format cmd (shell-quote-argument file)))
11721 (save-window-excursion
11722 (shell-command (concat cmd " &"))))
11723 ((or (stringp cmd)
11724 (eq cmd 'emacs))
11725 (funcall (cdr (assq 'file org-link-frame-setup)) file)
11726 (widen)
11727 (if line (goto-line line)
11728 (if search (org-link-search search))))
11729 ((consp cmd)
11730 (eval cmd))
11731 (t (funcall (cdr (assq 'file org-link-frame-setup)) file)))
11732 (and (org-mode-p) (eq old-mode 'org-mode)
11733 (or (not (equal old-buffer (current-buffer)))
11734 (not (equal old-pos (point))))
11735 (org-mark-ring-push old-pos old-buffer))))
11737 (defun org-default-apps ()
11738 "Return the default applications for this operating system."
11739 (cond
11740 ((eq system-type 'darwin)
11741 org-file-apps-defaults-macosx)
11742 ((eq system-type 'windows-nt)
11743 org-file-apps-defaults-windowsnt)
11744 (t org-file-apps-defaults-gnu)))
11746 (defvar ange-ftp-name-format) ; to silence the XEmacs compiler.
11747 (defun org-file-remote-p (file)
11748 "Test whether FILE specifies a location on a remote system.
11749 Return non-nil if the location is indeed remote.
11751 For example, the filename \"/user@host:/foo\" specifies a location
11752 on the system \"/user@host:\"."
11753 (cond ((fboundp 'file-remote-p)
11754 (file-remote-p file))
11755 ((fboundp 'tramp-handle-file-remote-p)
11756 (tramp-handle-file-remote-p file))
11757 ((and (boundp 'ange-ftp-name-format)
11758 (string-match (car ange-ftp-name-format) file))
11760 (t nil)))
11763 ;;;; Hooks for remember.el
11765 ;;;###autoload
11766 (defun org-remember-annotation ()
11767 "Return a link to the current location as an annotation for remember.el.
11768 If you are using Org-mode files as target for data storage with
11769 remember.el, then the annotations should include a link compatible with the
11770 conventions in Org-mode. This function returns such a link."
11771 (org-store-link nil))
11773 (defconst org-remember-help
11774 "Select a destination location for the note.
11775 UP/DOWN=headline TAB=cycle visibility [Q]uit RET/<left>/<right>=Store
11776 RET at beg-of-buf -> Append to file as level 2 headline
11777 RET on headline -> Store as sublevel entry to current headline
11778 <left>/<right> -> before/after current headline, same headings level")
11780 ;;;###autoload
11781 (defun org-remember-apply-template (&optional use-char skip-interactive)
11782 "Initialize *remember* buffer with template, invoke `org-mode'.
11783 This function should be placed into `remember-mode-hook' and in fact requires
11784 to be run from that hook to fucntion properly."
11785 (if org-remember-templates
11787 (let* ((char (or use-char
11788 (if (= (length org-remember-templates) 1)
11789 (caar org-remember-templates)
11790 (message "Select template: %s"
11791 (mapconcat
11792 (lambda (x) (char-to-string (car x)))
11793 org-remember-templates " "))
11794 (read-char-exclusive))))
11795 (entry (cdr (assoc char org-remember-templates)))
11796 (tpl (car entry))
11797 (plist-p (if org-store-link-plist t nil))
11798 (file (if (and (nth 1 entry) (stringp (nth 1 entry))
11799 (string-match "\\S-" (nth 1 entry)))
11800 (nth 1 entry)
11801 org-default-notes-file))
11802 (headline (nth 2 entry))
11803 (v-t (format-time-string (car org-time-stamp-formats) (org-current-time)))
11804 (v-T (format-time-string (cdr org-time-stamp-formats) (org-current-time)))
11805 (v-u (concat "[" (substring v-t 1 -1) "]"))
11806 (v-U (concat "[" (substring v-T 1 -1) "]"))
11807 (v-i initial) ; defined in `remember-mode'
11808 (v-a (if (equal annotation "[[]]") "" annotation)) ; likewise
11809 (v-n user-full-name)
11810 (org-startup-folded nil)
11811 org-time-was-given org-end-time-was-given x prompt char time)
11812 (setq org-store-link-plist
11813 (append (list :annotation v-a :initial v-i)))
11814 (unless tpl (setq tpl "") (message "No template") (ding))
11815 (erase-buffer)
11816 (insert (substitute-command-keys
11817 (format
11818 "## `C-c C-c' to file interactively, `C-u C-c C-c' to file directly.
11819 ## Target file \"%s\", headline \"%s\"
11820 ## To switch templates, use `\\[org-remember]'.\n\n"
11821 (abbreviate-file-name (or file org-default-notes-file))
11822 (or headline ""))))
11823 (insert tpl) (goto-char (point-min))
11824 ;; Simple %-escapes
11825 (while (re-search-forward "%\\([tTuUai]\\)" nil t)
11826 (when (and initial (equal (match-string 0) "%i"))
11827 (save-match-data
11828 (let* ((lead (buffer-substring
11829 (point-at-bol) (match-beginning 0))))
11830 (setq v-i (mapconcat 'identity
11831 (org-split-string initial "\n")
11832 (concat "\n" lead))))))
11833 (replace-match
11834 (or (eval (intern (concat "v-" (match-string 1)))) "")
11835 t t))
11836 ;; From the property list
11837 (when plist-p
11838 (goto-char (point-min))
11839 (while (re-search-forward "%\\(:[-a-zA-Z]+\\)" nil t)
11840 (and (setq x (plist-get org-store-link-plist
11841 (intern (match-string 1))))
11842 (replace-match x t t))))
11843 ;; Turn on org-mode in the remember buffer, set local variables
11844 (org-mode)
11845 (org-set-local 'org-finish-function 'remember-buffer)
11846 (if (and file (string-match "\\S-" file) (not (file-directory-p file)))
11847 (org-set-local 'org-default-notes-file file))
11848 (if (and headline (stringp headline) (string-match "\\S-" headline))
11849 (org-set-local 'org-remember-default-headline headline))
11850 ;; Interactive template entries
11851 (goto-char (point-min))
11852 (while (re-search-forward "%^\\({\\([^}]*\\)}\\)?\\([guUtT]\\)?" nil t)
11853 (setq char (if (match-end 3) (match-string 3))
11854 prompt (if (match-end 2) (match-string 2)))
11855 (goto-char (match-beginning 0))
11856 (replace-match "")
11857 (cond
11858 ((member char '("G" "g"))
11859 (let* ((org-last-tags-completion-table
11860 (org-global-tags-completion-table
11861 (if (equal char "G") (org-agenda-files) (and file (list file)))))
11862 (org-add-colon-after-tag-completion t)
11863 (ins (completing-read
11864 (if prompt (concat prompt ": ") "Tags: ")
11865 'org-tags-completion-function nil nil nil
11866 'org-tags-history)))
11867 (setq ins (mapconcat 'identity
11868 (org-split-string ins (org-re "[^[:alnum:]]+"))
11869 ":"))
11870 (when (string-match "\\S-" ins)
11871 (or (equal (char-before) ?:) (insert ":"))
11872 (insert ins)
11873 (or (equal (char-after) ?:) (insert ":")))))
11874 (char
11875 (setq org-time-was-given (equal (upcase char) char))
11876 (setq time (org-read-date (equal (upcase char) "U") t nil
11877 prompt))
11878 (org-insert-time-stamp time org-time-was-given
11879 (member char '("u" "U"))
11880 nil nil (list org-end-time-was-given)))
11882 (insert (read-string
11883 (if prompt (concat prompt ": ") "Enter string"))))))
11884 (goto-char (point-min))
11885 (if (re-search-forward "%\\?" nil t)
11886 (replace-match "")
11887 (and (re-search-forward "^[^#\n]" nil t) (backward-char 1))))
11888 (org-mode)
11889 (org-set-local 'org-finish-function 'remember-buffer)))
11891 ;;;###autoload
11892 (defun org-remember ()
11893 "Call `remember'. If this is already a remember buffer, re-apply template.
11894 If there is an active region, make sure remember uses it as initial content
11895 of the remember buffer."
11896 (interactive)
11897 (if (eq org-finish-function 'remember-buffer)
11898 (progn
11899 (when (< (length org-remember-templates) 2)
11900 (error "No other template available"))
11901 (erase-buffer)
11902 (let ((annotation (plist-get org-store-link-plist :annotation))
11903 (initial (plist-get org-store-link-plist :initial)))
11904 (org-remember-apply-template))
11905 (message "Press C-c C-c to remember data"))
11906 (if (org-region-active-p)
11907 (remember (buffer-substring (point) (mark)))
11908 (call-interactively 'remember))))
11910 ;;;###autoload
11911 (defun org-remember-handler ()
11912 "Store stuff from remember.el into an org file.
11913 First prompts for an org file. If the user just presses return, the value
11914 of `org-default-notes-file' is used.
11915 Then the command offers the headings tree of the selected file in order to
11916 file the text at a specific location.
11917 You can either immediately press RET to get the note appended to the
11918 file, or you can use vertical cursor motion and visibility cycling (TAB) to
11919 find a better place. Then press RET or <left> or <right> in insert the note.
11921 Key Cursor position Note gets inserted
11922 -----------------------------------------------------------------------------
11923 RET buffer-start as level 2 heading at end of file
11924 RET on headline as sublevel of the heading at cursor
11925 RET no heading at cursor position, level taken from context.
11926 Or use prefix arg to specify level manually.
11927 <left> on headline as same level, before current heading
11928 <right> on headline as same level, after current heading
11930 So the fastest way to store the note is to press RET RET to append it to
11931 the default file. This way your current train of thought is not
11932 interrupted, in accordance with the principles of remember.el. But with
11933 little extra effort, you can push it directly to the correct location.
11935 Before being stored away, the function ensures that the text has a
11936 headline, i.e. a first line that starts with a \"*\". If not, a headline
11937 is constructed from the current date and some additional data.
11939 If the variable `org-adapt-indentation' is non-nil, the entire text is
11940 also indented so that it starts in the same column as the headline
11941 \(i.e. after the stars).
11943 See also the variable `org-reverse-note-order'."
11944 (goto-char (point-min))
11945 (while (looking-at "^[ \t]*\n\\|^##.*\n")
11946 (replace-match ""))
11947 (catch 'quit
11948 (let* ((txt (buffer-substring (point-min) (point-max)))
11949 (fastp (equal current-prefix-arg '(4)))
11950 (file (if fastp org-default-notes-file (org-get-org-file)))
11951 (heading org-remember-default-headline)
11952 (visiting (org-find-base-buffer-visiting file))
11953 (org-startup-folded nil)
11954 (org-startup-align-all-tables nil)
11955 (org-goto-start-pos 1)
11956 spos level indent reversed)
11957 (setq current-prefix-arg nil)
11958 ;; Modify text so that it becomes a nice subtree which can be inserted
11959 ;; into an org tree.
11960 (let* ((lines (split-string txt "\n"))
11961 first)
11962 (setq first (car lines) lines (cdr lines))
11963 (if (string-match "^\\*+ " first)
11964 ;; Is already a headline
11965 (setq indent nil)
11966 ;; We need to add a headline: Use time and first buffer line
11967 (setq lines (cons first lines)
11968 first (concat "* " (current-time-string)
11969 " (" (remember-buffer-desc) ")")
11970 indent " "))
11971 (if (and org-adapt-indentation indent)
11972 (setq lines (mapcar (lambda (x) (concat indent x)) lines)))
11973 (setq txt (concat first "\n"
11974 (mapconcat 'identity lines "\n"))))
11975 ;; Find the file
11976 (if (not visiting) (find-file-noselect file))
11977 (with-current-buffer (or visiting (get-file-buffer file))
11978 (save-excursion
11979 (save-restriction
11980 (widen)
11981 (and (goto-char (point-min))
11982 (not (re-search-forward "^\\* " nil t))
11983 (insert "\n* Notes\n"))
11984 (setq reversed (org-notes-order-reversed-p))
11986 ;; Find the default location
11987 (when (and heading (stringp heading) (string-match "\\S-" heading))
11988 (goto-char (point-min))
11989 (if (re-search-forward
11990 (concat "^\\*+[ \t]+" (regexp-quote heading)
11991 (org-re "\\([ \t]+:[[:alnum:]@_:]*\\)?[ \t]*$"))
11992 nil t)
11993 (setq org-goto-start-pos (match-beginning 0))))
11995 ;; Ask the User for a location
11996 (setq spos (if fastp
11997 org-goto-start-pos
11998 (org-get-location (current-buffer) org-remember-help)))
11999 (if (not spos) (throw 'quit nil)) ; return nil to show we did
12000 ; not handle this note
12001 (goto-char spos)
12002 (cond ((and (bobp) (not reversed))
12003 ;; Put it at the end, one level below level 1
12004 (save-restriction
12005 (widen)
12006 (goto-char (point-max))
12007 (if (not (bolp)) (newline))
12008 (org-paste-subtree (org-get-legal-level 1 1) txt)))
12009 ((and (bobp) reversed)
12010 ;; Put it at the start, as level 1
12011 (save-restriction
12012 (widen)
12013 (goto-char (point-min))
12014 (re-search-forward "^\\*+ " nil t)
12015 (beginning-of-line 1)
12016 (org-paste-subtree 1 txt)))
12017 ((and (org-on-heading-p t) (not current-prefix-arg))
12018 ;; Put it below this entry, at the beg/end of the subtree
12019 (org-back-to-heading t)
12020 (setq level (funcall outline-level))
12021 (if reversed
12022 (outline-next-heading)
12023 (org-end-of-subtree t))
12024 (if (not (bolp)) (newline))
12025 (beginning-of-line 1)
12026 (org-paste-subtree (org-get-legal-level level 1) txt))
12028 ;; Put it right there, with automatic level determined by
12029 ;; org-paste-subtree or from prefix arg
12030 (org-paste-subtree
12031 (if (numberp current-prefix-arg) current-prefix-arg)
12032 txt)))
12033 (when remember-save-after-remembering
12034 (save-buffer)
12035 (if (not visiting) (kill-buffer (current-buffer)))))))))
12036 t) ;; return t to indicate that we took care of this note.
12038 (defun org-get-org-file ()
12039 "Read a filename, with default directory `org-directory'."
12040 (let ((default (or org-default-notes-file remember-data-file)))
12041 (read-file-name (format "File name [%s]: " default)
12042 (file-name-as-directory org-directory)
12043 default)))
12045 (defun org-notes-order-reversed-p ()
12046 "Check if the current file should receive notes in reversed order."
12047 (cond
12048 ((not org-reverse-note-order) nil)
12049 ((eq t org-reverse-note-order) t)
12050 ((not (listp org-reverse-note-order)) nil)
12051 (t (catch 'exit
12052 (let ((all org-reverse-note-order)
12053 entry)
12054 (while (setq entry (pop all))
12055 (if (string-match (car entry) buffer-file-name)
12056 (throw 'exit (cdr entry))))
12057 nil)))))
12059 ;;;; Dynamic blocks
12061 (defun org-find-dblock (name)
12062 "Find the first dynamic block with name NAME in the buffer.
12063 If not found, stay at current position and return nil."
12064 (let (pos)
12065 (save-excursion
12066 (goto-char (point-min))
12067 (setq pos (and (re-search-forward (concat "^#\\+BEGIN:[ \t]+" name "\\>")
12068 nil t)
12069 (match-beginning 0))))
12070 (if pos (goto-char pos))
12071 pos))
12073 (defconst org-dblock-start-re
12074 "^#\\+BEGIN:[ \t]+\\(\\S-+\\)\\([ \t]+\\(.*\\)\\)?"
12075 "Matches the startline of a dynamic block, with parameters.")
12077 (defconst org-dblock-end-re "^#\\+END\\([: \t\r\n]\\|$\\)"
12078 "Matches the end of a dyhamic block.")
12080 (defun org-create-dblock (plist)
12081 "Create a dynamic block section, with parameters taken from PLIST.
12082 PLIST must containe a :name entry which is used as name of the block."
12083 (unless (bolp) (newline))
12084 (let ((name (plist-get plist :name)))
12085 (insert "#+BEGIN: " name)
12086 (while plist
12087 (if (eq (car plist) :name)
12088 (setq plist (cddr plist))
12089 (insert " " (prin1-to-string (pop plist)))))
12090 (insert "\n\n#+END:\n")
12091 (beginning-of-line -2)))
12093 (defun org-prepare-dblock ()
12094 "Prepare dynamic block for refresh.
12095 This empties the block, puts the cursor at the insert position and returns
12096 the property list including an extra property :name with the block name."
12097 (unless (looking-at org-dblock-start-re)
12098 (error "Not at a dynamic block"))
12099 (let* ((begdel (1+ (match-end 0)))
12100 (name (match-string 1))
12101 (params (append (list :name name)
12102 (read (concat "(" (match-string 3) ")")))))
12103 (unless (re-search-forward org-dblock-end-re nil t)
12104 (error "Dynamic block not terminated"))
12105 (delete-region begdel (match-beginning 0))
12106 (goto-char begdel)
12107 (open-line 1)
12108 params))
12110 (defun org-map-dblocks (&optional command)
12111 "Apply COMMAND to all dynamic blocks in the current buffer.
12112 If COMMAND is not given, use `org-update-dblock'."
12113 (let ((cmd (or command 'org-update-dblock))
12114 pos)
12115 (save-excursion
12116 (goto-char (point-min))
12117 (while (re-search-forward org-dblock-start-re nil t)
12118 (goto-char (setq pos (match-beginning 0)))
12119 (condition-case nil
12120 (funcall cmd)
12121 (error (message "Error during update of dynamic block")))
12122 (goto-char pos)
12123 (unless (re-search-forward org-dblock-end-re nil t)
12124 (error "Dynamic block not terminated"))))))
12126 (defun org-dblock-update (&optional arg)
12127 "User command for updating dynamic blocks.
12128 Update the dynamic block at point. With prefix ARG, update all dynamic
12129 blocks in the buffer."
12130 (interactive "P")
12131 (if arg
12132 (org-update-all-dblocks)
12133 (or (looking-at org-dblock-start-re)
12134 (org-beginning-of-dblock))
12135 (org-update-dblock)))
12137 (defun org-update-dblock ()
12138 "Update the dynamic block at point
12139 This means to empty the block, parse for parameters and then call
12140 the correct writing function."
12141 (let* ((pos (point))
12142 (params (org-prepare-dblock))
12143 (name (plist-get params :name))
12144 (cmd (intern (concat "org-dblock-write:" name))))
12145 (funcall cmd params)
12146 (goto-char pos)))
12148 (defun org-beginning-of-dblock ()
12149 "Find the beginning of the dynamic block at point.
12150 Error if there is no scuh block at point."
12151 (let ((pos (point))
12152 beg)
12153 (end-of-line 1)
12154 (if (and (re-search-backward org-dblock-start-re nil t)
12155 (setq beg (match-beginning 0))
12156 (re-search-forward org-dblock-end-re nil t)
12157 (> (match-end 0) pos))
12158 (goto-char beg)
12159 (goto-char pos)
12160 (error "Not in a dynamic block"))))
12162 (defun org-update-all-dblocks ()
12163 "Update all dynamic blocks in the buffer.
12164 This function can be used in a hook."
12165 (when (org-mode-p)
12166 (org-map-dblocks 'org-update-dblock)))
12169 ;;;; Completion
12171 (defun org-complete (&optional arg)
12172 "Perform completion on word at point.
12173 At the beginning of a headline, this completes TODO keywords as given in
12174 `org-todo-keywords'.
12175 If the current word is preceded by a backslash, completes the TeX symbols
12176 that are supported for HTML support.
12177 If the current word is preceded by \"#+\", completes special words for
12178 setting file options.
12179 In the line after \"#+STARTUP:, complete valid keywords.\"
12180 At all other locations, this simply calls `ispell-complete-word'."
12181 (interactive "P")
12182 (catch 'exit
12183 (let* ((end (point))
12184 (beg1 (save-excursion
12185 (skip-chars-backward (org-re "[:alnum:]_@"))
12186 (point)))
12187 (beg (save-excursion
12188 (skip-chars-backward "a-zA-Z0-9_:$")
12189 (point)))
12190 (confirm (lambda (x) (stringp (car x))))
12191 (searchhead (equal (char-before beg) ?*))
12192 (tag (and (equal (char-before beg1) ?:)
12193 (equal (char-after (point-at-bol)) ?*)))
12194 (prop (and (equal (char-before beg1) ?:)
12195 (not (equal (char-after (point-at-bol)) ?*))))
12196 (texp (equal (char-before beg) ?\\))
12197 (link (equal (char-before beg) ?\[))
12198 (opt (equal (buffer-substring (max (point-at-bol) (- beg 2))
12199 beg)
12200 "#+"))
12201 (startup (string-match "^#\\+STARTUP:.*"
12202 (buffer-substring (point-at-bol) (point))))
12203 (completion-ignore-case opt)
12204 (type nil)
12205 (tbl nil)
12206 (table (cond
12207 (opt
12208 (setq type :opt)
12209 (mapcar (lambda (x)
12210 (string-match "^#\\+\\(\\([A-Z_]+:?\\).*\\)" x)
12211 (cons (match-string 2 x) (match-string 1 x)))
12212 (org-split-string (org-get-current-options) "\n")))
12213 (startup
12214 (setq type :startup)
12215 org-startup-options)
12216 (link (append org-link-abbrev-alist-local
12217 org-link-abbrev-alist))
12218 (texp
12219 (setq type :tex)
12220 org-html-entities)
12221 ((string-match "\\`\\*+[ \t]+\\'"
12222 (buffer-substring (point-at-bol) beg))
12223 (setq type :todo)
12224 (mapcar 'list org-todo-keywords-1))
12225 (searchhead
12226 (setq type :searchhead)
12227 (save-excursion
12228 (goto-char (point-min))
12229 (while (re-search-forward org-todo-line-regexp nil t)
12230 (push (list
12231 (org-make-org-heading-search-string
12232 (match-string 3) t))
12233 tbl)))
12234 tbl)
12235 (tag (setq type :tag beg beg1)
12236 (or org-tag-alist (org-get-buffer-tags)))
12237 (prop (setq type :prop beg beg1)
12238 (mapcar 'list (org-buffer-property-keys)))
12239 (t (progn (ispell-complete-word arg) (throw 'exit nil)))))
12240 (pattern (buffer-substring-no-properties beg end))
12241 (completion (try-completion pattern table confirm)))
12242 (cond ((eq completion t)
12243 (if (equal type :opt)
12244 (insert (substring (cdr (assoc (upcase pattern) table))
12245 (length pattern)))
12246 (if (memq type '(:tag :prop)) (insert ":"))))
12247 ((null completion)
12248 (message "Can't find completion for \"%s\"" pattern)
12249 (ding))
12250 ((not (string= pattern completion))
12251 (delete-region beg end)
12252 (if (string-match " +$" completion)
12253 (setq completion (replace-match "" t t completion)))
12254 (insert completion)
12255 (if (get-buffer-window "*Completions*")
12256 (delete-window (get-buffer-window "*Completions*")))
12257 (if (assoc completion table)
12258 (if (eq type :todo) (insert " ")
12259 (if (memq type '(:tag :prop)) (insert ":"))))
12260 (if (and (equal type :opt) (assoc completion table))
12261 (message "%s" (substitute-command-keys
12262 "Press \\[org-complete] again to insert example settings"))))
12264 (message "Making completion list...")
12265 (let ((list (sort (all-completions pattern table confirm)
12266 'string<)))
12267 (with-output-to-temp-buffer "*Completions*"
12268 (condition-case nil
12269 ;; Protection needed for XEmacs and emacs 21
12270 (display-completion-list list pattern)
12271 (error (display-completion-list list)))))
12272 (message "Making completion list...%s" "done"))))))
12274 ;;;; TODO, DEADLINE, Comments
12276 (defun org-toggle-comment ()
12277 "Change the COMMENT state of an entry."
12278 (interactive)
12279 (save-excursion
12280 (org-back-to-heading)
12281 (if (looking-at (concat outline-regexp
12282 "\\( *\\<" org-comment-string "\\>\\)"))
12283 (replace-match "" t t nil 1)
12284 (if (looking-at outline-regexp)
12285 (progn
12286 (goto-char (match-end 0))
12287 (insert org-comment-string " "))))))
12289 (defvar org-last-todo-state-is-todo nil
12290 "This is non-nil when the last TODO state change led to a TODO state.
12291 If the last change removed the TODO tag or switched to DONE, then
12292 this is nil.")
12294 (defun org-todo (&optional arg)
12295 "Change the TODO state of an item.
12296 The state of an item is given by a keyword at the start of the heading,
12297 like
12298 *** TODO Write paper
12299 *** DONE Call mom
12301 The different keywords are specified in the variable `org-todo-keywords'.
12302 By default the available states are \"TODO\" and \"DONE\".
12303 So for this example: when the item starts with TODO, it is changed to DONE.
12304 When it starts with DONE, the DONE is removed. And when neither TODO nor
12305 DONE are present, add TODO at the beginning of the heading.
12307 With C-u prefix arg, use completion to determine the new state.
12308 With numeric prefix arg, switch to that state.
12310 For calling through lisp, arg is also interpreted in the following way:
12311 'none -> empty state
12312 \"\"(empty string) -> switch to empty state
12313 'done -> switch to DONE
12314 'nextset -> switch to the next set of keywords
12315 'previousset -> switch to the previous set of keywords
12316 \"WAITING\" -> switch to the specified keyword, but only if it
12317 really is a member of `org-todo-keywords'."
12318 (interactive "P")
12319 (save-excursion
12320 (org-back-to-heading)
12321 (if (looking-at outline-regexp) (goto-char (1- (match-end 0))))
12322 (or (looking-at (concat " +" org-todo-regexp " *"))
12323 (looking-at " *"))
12324 (let* ((this (match-string 1))
12325 (head (org-get-todo-sequence-head this))
12326 (ass (assoc head org-todo-kwd-alist))
12327 (interpret (nth 1 ass))
12328 (done-word (nth 3 ass))
12329 (final-done-word (nth 4 ass))
12330 (last-state (or this ""))
12331 (completion-ignore-case t)
12332 (member (member this org-todo-keywords-1))
12333 (tail (cdr member))
12334 (state (cond
12335 ((equal arg '(4))
12336 ;; Read a state with completion
12337 (completing-read "State: " (mapcar (lambda(x) (list x))
12338 org-todo-keywords-1)
12339 nil t))
12340 ((eq arg 'right)
12341 (if this
12342 (if tail (car tail) nil)
12343 (car org-todo-keywords-1)))
12344 ((eq arg 'left)
12345 (if (equal member org-todo-keywords-1)
12347 (if this
12348 (nth (- (length org-todo-keywords-1) (length tail) 2)
12349 org-todo-keywords-1)
12350 (org-last org-todo-keywords-1))))
12351 (arg
12352 ;; user or caller requests a specific state
12353 (cond
12354 ((equal arg "") nil)
12355 ((eq arg 'none) nil)
12356 ((eq arg 'done) (or done-word (car org-done-keywords)))
12357 ((eq arg 'nextset)
12358 (or (car (cdr (member head org-todo-heads)))
12359 (car org-todo-heads)))
12360 ((eq arg 'previousset)
12361 (let ((org-todo-heads (reverse org-todo-heads)))
12362 (or (car (cdr (member head org-todo-heads)))
12363 (car org-todo-heads))))
12364 ((car (member arg org-todo-keywords-1)))
12365 ((nth (1- (prefix-numeric-value arg))
12366 org-todo-keywords-1))))
12367 ((null member) (or head (car org-todo-keywords-1)))
12368 ((equal this final-done-word) nil) ;; -> make empty
12369 ((null tail) nil) ;; -> first entry
12370 ((eq interpret 'sequence)
12371 (car tail))
12372 ((memq interpret '(type priority))
12373 (if (eq this-command last-command)
12374 (car tail)
12375 (if (> (length tail) 0)
12376 (or done-word (car org-done-keywords))
12377 nil)))
12378 (t nil)))
12379 (next (if state (concat " " state " ") " "))
12380 dostates)
12381 (replace-match next t t)
12382 (unless head
12383 (setq head (org-get-todo-sequence-head state)
12384 ass (assoc head org-todo-kwd-alist)
12385 interpret (nth 1 ass)
12386 done-word (nth 3 ass)
12387 final-done-word (nth 4 ass)))
12388 (when (memq arg '(nextset previousset))
12389 (message "Keyword set: %s"
12390 (mapconcat 'identity (assoc state org-todo-sets) " ")))
12391 (setq org-last-todo-state-is-todo
12392 (not (member state org-done-keywords)))
12393 (when (and org-log-done (not (memq arg '(nextset previousset))))
12394 (setq dostates (and (eq interpret 'sequence)
12395 (listp org-log-done) (memq 'state org-log-done)))
12396 (cond
12397 ((and state (not this))
12398 (org-add-planning-info nil nil 'closed)
12399 (and dostates (org-add-log-maybe 'state state 'findpos)))
12400 ((and state dostates)
12401 (org-add-log-maybe 'state state 'findpos))
12402 ((member state org-done-keywords)
12403 ;; Planning info calls the note-setting command.
12404 (org-add-planning-info 'closed (org-current-time)
12405 (if (org-get-repeat) nil 'scheduled))
12406 (org-add-log-maybe 'done state 'findpos))))
12407 ;; Fixup tag positioning
12408 (and org-auto-align-tags (org-set-tags nil t))
12409 (run-hooks 'org-after-todo-state-change-hook)
12410 (and (member state org-done-keywords) (org-auto-repeat-maybe))
12411 (if (and arg (not (member state org-done-keywords)))
12412 (setq head (org-get-todo-sequence-head state)))
12413 (put-text-property (point-at-bol) (point-at-eol) 'org-todo-head head)))
12414 ;; Fixup cursor location if close to the keyword
12415 (if (and (outline-on-heading-p)
12416 (not (bolp))
12417 (save-excursion (beginning-of-line 1)
12418 (looking-at org-todo-line-regexp))
12419 (< (point) (+ 2 (or (match-end 2) (match-end 1)))))
12420 (progn
12421 (goto-char (or (match-end 2) (match-end 1)))
12422 (just-one-space))))
12424 (defun org-get-todo-sequence-head (kwd)
12425 "Return the head of the TODO sequence to which KWD belongs.
12426 If KWD is not set, check if there is a text property remembering the
12427 right sequence."
12428 (let (p)
12429 (cond
12430 ((not kwd)
12431 (or (get-text-property (point-at-bol) 'org-todo-head)
12432 (progn
12433 (setq p (next-single-property-change (point-at-bol) 'org-todo-head
12434 nil (point-at-eol)))
12435 (get-text-property p 'org-todo-head))))
12436 ((not (member kwd org-todo-keywords-1))
12437 (car org-todo-keywords-1))
12438 (t (nth 2 (assoc kwd org-todo-kwd-alist))))))
12440 (defun org-get-repeat ()
12441 "Check if tere is a deadline/schedule with repeater in this entry."
12442 (save-match-data
12443 (save-excursion
12444 (org-back-to-heading t)
12445 (if (re-search-forward
12446 org-repeat-re (save-excursion (outline-next-heading) (point)) t)
12447 (match-string 1)))))
12449 (defvar org-last-changed-timestamp)
12450 (defvar org-log-post-message)
12451 (defun org-auto-repeat-maybe ()
12452 "Check if the current headline contains a repeated deadline/schedule.
12453 If yes, set TODO state back to what it was and change the base date
12454 of repeating deadline/scheduled time stamps to new date.
12455 This function should be run in the `org-after-todo-state-change-hook'."
12456 ;; last-state is dynamically scoped into this function
12457 (let* ((repeat (org-get-repeat))
12458 (aa (assoc last-state org-todo-kwd-alist))
12459 (interpret (nth 1 aa))
12460 (head (nth 2 aa))
12461 (done-word (nth 3 aa))
12462 (whata '(("d" . day) ("m" . month) ("y" . year)))
12463 (msg "Entry repeats: ")
12464 (org-log-done)
12465 re type n what ts)
12466 (when repeat
12467 (org-todo (if (eq interpret 'type) last-state head))
12468 (when (and org-log-repeat
12469 (not (memq 'org-add-log-note
12470 (default-value 'post-command-hook))))
12471 ;; Make sure a note is taken
12472 (let ((org-log-done '(done)))
12473 (org-add-log-maybe 'done (or done-word (car org-done-keywords))
12474 'findpos)))
12475 (org-back-to-heading t)
12476 (org-add-planning-info nil nil 'closed)
12477 (setq re (concat "\\(" org-scheduled-time-regexp "\\)\\|\\("
12478 org-deadline-time-regexp "\\)"))
12479 (while (re-search-forward
12480 re (save-excursion (outline-next-heading) (point)) t)
12481 (setq type (if (match-end 1) org-scheduled-string org-deadline-string)
12482 ts (match-string (if (match-end 2) 2 4)))
12483 (when (string-match "\\([-+]?[0-9]+\\)\\([dwmy]\\)" ts)
12484 (setq n (string-to-number (match-string 1 ts))
12485 what (match-string 2 ts))
12486 (if (equal what "w") (setq n (* n 7) what "d"))
12487 (org-timestamp-change n (cdr (assoc what whata))))
12488 (setq msg (concat msg type org-last-changed-timestamp " ")))
12489 (setq org-log-post-message msg)
12490 (message msg))))
12492 (defun org-show-todo-tree (arg)
12493 "Make a compact tree which shows all headlines marked with TODO.
12494 The tree will show the lines where the regexp matches, and all higher
12495 headlines above the match.
12496 With \\[universal-argument] prefix, also show the DONE entries.
12497 With a numeric prefix N, construct a sparse tree for the Nth element
12498 of `org-todo-keywords-1'."
12499 (interactive "P")
12500 (let ((case-fold-search nil)
12501 (kwd-re
12502 (cond ((null arg) org-not-done-regexp)
12503 ((equal arg '(4))
12504 (let ((kwd (completing-read "Keyword (or KWD1|KWD2|...): "
12505 (mapcar 'list org-todo-keywords-1))))
12506 (concat "\\("
12507 (mapconcat 'identity (org-split-string kwd "|") "\\|")
12508 "\\)\\>")))
12509 ((<= (prefix-numeric-value arg) (length org-todo-keywords-1))
12510 (regexp-quote (nth (1- (prefix-numeric-value arg))
12511 org-todo-keywords-1)))
12512 (t (error "Invalid prefix argument: %s" arg)))))
12513 (message "%d TODO entries found"
12514 (org-occur (concat "^" outline-regexp " *" kwd-re )))))
12516 (defun org-deadline ()
12517 "Insert the DEADLINE: string to make a deadline.
12518 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
12519 to modify it to the correct date."
12520 (interactive)
12521 (org-add-planning-info 'deadline nil 'closed))
12523 (defun org-schedule ()
12524 "Insert the SCHEDULED: string to schedule a TODO item.
12525 A timestamp is also inserted - use \\[org-timestamp-up] and \\[org-timestamp-down]
12526 to modify it to the correct date."
12527 (interactive)
12528 (org-add-planning-info 'scheduled nil 'closed))
12530 (defun org-add-planning-info (what &optional time &rest remove)
12531 "Insert new timestamp with keyword in the line directly after the headline.
12532 WHAT indicates what kind of time stamp to add. TIME indicated the time to use.
12533 If non is given, the user is prompted for a date.
12534 REMOVE indicates what kind of entries to remove. An old WHAT entry will also
12535 be removed."
12536 (interactive)
12537 (let (org-time-was-given org-end-time-was-given)
12538 (when what (setq time (or time (org-read-date nil 'to-time))))
12539 (when (and org-insert-labeled-timestamps-at-point
12540 (member what '(scheduled deadline)))
12541 (insert
12542 (if (eq what 'scheduled) org-scheduled-string org-deadline-string) " ")
12543 (org-insert-time-stamp time org-time-was-given
12544 nil nil nil (list org-end-time-was-given))
12545 (setq what nil))
12546 (save-excursion
12547 (save-restriction
12548 (let (col list elt ts buffer-invisibility-spec)
12549 (org-back-to-heading t)
12550 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"))
12551 (goto-char (match-end 1))
12552 (setq col (current-column))
12553 (goto-char (match-end 0))
12554 (if (eobp) (insert "\n"))
12555 (forward-char 1)
12556 (when (looking-at "[ \t]*:PROPERTIES:[ \t]*$")
12557 (goto-char (match-end 0))
12558 (if (eobp) (insert "\n"))
12559 (forward-char 1))
12560 (if (and (not (looking-at outline-regexp))
12561 (looking-at (concat "[^\r\n]*?" org-keyword-time-regexp
12562 "[^\r\n]*"))
12563 (not (equal (match-string 1) org-clock-string)))
12564 (narrow-to-region (match-beginning 0) (match-end 0))
12565 (insert "\n")
12566 (backward-char 1)
12567 (narrow-to-region (point) (point))
12568 (indent-to-column col))
12569 ;; Check if we have to remove something.
12570 (setq list (cons what remove))
12571 (while list
12572 (setq elt (pop list))
12573 (goto-char (point-min))
12574 (when (or (and (eq elt 'scheduled)
12575 (re-search-forward org-scheduled-time-regexp nil t))
12576 (and (eq elt 'deadline)
12577 (re-search-forward org-deadline-time-regexp nil t))
12578 (and (eq elt 'closed)
12579 (re-search-forward org-closed-time-regexp nil t)))
12580 (replace-match "")
12581 (if (looking-at "--+<[^>]+>") (replace-match ""))
12582 (if (looking-at " +") (replace-match ""))))
12583 (goto-char (point-max))
12584 (when what
12585 (insert
12586 (if (not (equal (char-before) ?\ )) " " "")
12587 (cond ((eq what 'scheduled) org-scheduled-string)
12588 ((eq what 'deadline) org-deadline-string)
12589 ((eq what 'closed) org-closed-string)
12590 ((eq what 'archived) org-archived-string))
12591 " ")
12592 (org-insert-time-stamp
12593 time
12594 (or org-time-was-given
12595 (and (eq what 'closed) org-log-done-with-time))
12596 (eq what 'closed)
12597 nil nil (list org-end-time-was-given))
12598 (end-of-line 1))
12599 (goto-char (point-min))
12600 (widen)
12601 (if (looking-at "[ \t]+\r?\n")
12602 (replace-match ""))
12603 ts)))))
12605 (defvar org-log-note-marker (make-marker))
12606 (defvar org-log-note-purpose nil)
12607 (defvar org-log-note-state nil)
12608 (defvar org-log-note-window-configuration nil)
12609 (defvar org-log-note-return-to (make-marker))
12610 (defvar org-log-post-message nil
12611 "Message to be displayed after a log note has been stored.
12612 The auto-repeater uses this.")
12614 (defun org-add-log-maybe (&optional purpose state findpos)
12615 "Set up the post command hook to take a note."
12616 (save-excursion
12617 (when (and (listp org-log-done)
12618 (memq purpose org-log-done))
12619 (when findpos
12620 (org-back-to-heading t)
12621 (looking-at (concat outline-regexp "\\( *\\)[^\r\n]*"
12622 "\\(\n[^\r\n]*?" org-keyword-time-not-clock-regexp
12623 "[^\r\n]*\\)?"))
12624 (goto-char (match-end 0)))
12625 (move-marker org-log-note-marker (point))
12626 (setq org-log-note-purpose purpose)
12627 (setq org-log-note-state state)
12628 (add-hook 'post-command-hook 'org-add-log-note 'append))))
12630 (defun org-add-log-note (&optional purpose)
12631 "Pop up a window for taking a note, and add this note later at point."
12632 (remove-hook 'post-command-hook 'org-add-log-note)
12633 (setq org-log-note-window-configuration (current-window-configuration))
12634 (delete-other-windows)
12635 (move-marker org-log-note-return-to (point))
12636 (switch-to-buffer (marker-buffer org-log-note-marker))
12637 (goto-char org-log-note-marker)
12638 (switch-to-buffer-other-window "*Org Note*")
12639 (erase-buffer)
12640 (let ((org-inhibit-startup t)) (org-mode))
12641 (insert (format "# Insert note for %s, finish with C-c C-c.\n\n"
12642 (cond
12643 ((eq org-log-note-purpose 'clock-out) "stopped clock")
12644 ((eq org-log-note-purpose 'done) "closed todo item")
12645 ((eq org-log-note-purpose 'state) "state change")
12646 (t (error "This should not happen")))))
12647 (org-set-local 'org-finish-function 'org-store-log-note))
12649 (defun org-store-log-note ()
12650 "Finish taking a log note, and insert it to where it belongs."
12651 (let ((txt (buffer-string))
12652 (note (cdr (assq org-log-note-purpose org-log-note-headings)))
12653 lines ind)
12654 (kill-buffer (current-buffer))
12655 (if (string-match "^#.*\n[ \t\n]*" txt)
12656 (setq txt (replace-match "" t t txt)))
12657 (if (string-match "\\s-+\\'" txt)
12658 (setq txt (replace-match "" t t txt)))
12659 (setq lines (org-split-string txt "\n"))
12660 (when (and note (string-match "\\S-" note))
12661 (setq note
12662 (org-replace-escapes
12663 note
12664 (list (cons "%u" (user-login-name))
12665 (cons "%U" user-full-name)
12666 (cons "%t" (format-time-string
12667 (org-time-stamp-format 'long 'inactive)
12668 (current-time)))
12669 (cons "%s" (if org-log-note-state
12670 (concat "\"" org-log-note-state "\"")
12671 "")))))
12672 (if lines (setq note (concat note " \\\\")))
12673 (push note lines))
12674 (when lines
12675 (save-excursion
12676 (set-buffer (marker-buffer org-log-note-marker))
12677 (save-excursion
12678 (goto-char org-log-note-marker)
12679 (move-marker org-log-note-marker nil)
12680 (end-of-line 1)
12681 (if (not (bolp)) (insert "\n")) (indent-relative nil)
12682 (setq ind (concat (buffer-substring (point-at-bol) (point)) " "))
12683 (insert " - " (pop lines))
12684 (while lines
12685 (insert "\n" ind (pop lines)))))))
12686 (set-window-configuration org-log-note-window-configuration)
12687 (with-current-buffer (marker-buffer org-log-note-return-to)
12688 (goto-char org-log-note-return-to))
12689 (move-marker org-log-note-return-to nil)
12690 (and org-log-post-message (message org-log-post-message)))
12692 (defvar org-occur-highlights nil)
12693 (make-variable-buffer-local 'org-occur-highlights)
12695 (defun org-occur (regexp &optional keep-previous callback)
12696 "Make a compact tree which shows all matches of REGEXP.
12697 The tree will show the lines where the regexp matches, and all higher
12698 headlines above the match. It will also show the heading after the match,
12699 to make sure editing the matching entry is easy.
12700 If KEEP-PREVIOUS is non-nil, highlighting and exposing done by a previous
12701 call to `org-occur' will be kept, to allow stacking of calls to this
12702 command.
12703 If CALLBACK is non-nil, it is a function which is called to confirm
12704 that the match should indeed be shown."
12705 (interactive "sRegexp: \nP")
12706 (or keep-previous (org-remove-occur-highlights nil nil t))
12707 (let ((cnt 0))
12708 (save-excursion
12709 (goto-char (point-min))
12710 (if (or (not keep-previous) ; do not want to keep
12711 (not org-occur-highlights)) ; no previous matches
12712 ;; hide everything
12713 (org-overview))
12714 (while (re-search-forward regexp nil t)
12715 (when (or (not callback)
12716 (save-match-data (funcall callback)))
12717 (setq cnt (1+ cnt))
12718 (when org-highlight-sparse-tree-matches
12719 (org-highlight-new-match (match-beginning 0) (match-end 0)))
12720 (org-show-context 'occur-tree))))
12721 (when org-remove-highlights-with-change
12722 (org-add-hook 'before-change-functions 'org-remove-occur-highlights
12723 nil 'local))
12724 (unless org-sparse-tree-open-archived-trees
12725 (org-hide-archived-subtrees (point-min) (point-max)))
12726 (run-hooks 'org-occur-hook)
12727 (if (interactive-p)
12728 (message "%d match(es) for regexp %s" cnt regexp))
12729 cnt))
12731 (defun org-show-context (&optional key)
12732 "Make sure point and context and visible.
12733 How much context is shown depends upon the variables
12734 `org-show-hierarchy-above', `org-show-following-heading'. and
12735 `org-show-siblings'."
12736 (let ((heading-p (org-on-heading-p t))
12737 (hierarchy-p (org-get-alist-option org-show-hierarchy-above key))
12738 (following-p (org-get-alist-option org-show-following-heading key))
12739 (siblings-p (org-get-alist-option org-show-siblings key)))
12740 (catch 'exit
12741 ;; Show heading or entry text
12742 (if heading-p
12743 (org-flag-heading nil) ; only show the heading
12744 (and (or (org-invisible-p) (org-invisible-p2))
12745 (org-show-hidden-entry))) ; show entire entry
12746 (when following-p
12747 ;; Show next sibling, or heading below text
12748 (save-excursion
12749 (and (if heading-p (org-goto-sibling) (outline-next-heading))
12750 (org-flag-heading nil))))
12751 (when siblings-p (org-show-siblings))
12752 (when hierarchy-p
12753 ;; show all higher headings, possibly with siblings
12754 (save-excursion
12755 (while (and (condition-case nil
12756 (progn (org-up-heading-all 1) t)
12757 (error nil))
12758 (not (bobp)))
12759 (org-flag-heading nil)
12760 (when siblings-p (org-show-siblings))))))))
12762 (defun org-reveal (&optional siblings)
12763 "Show current entry, hierarchy above it, and the following headline.
12764 This can be used to show a consistent set of context around locations
12765 exposed with `org-show-hierarchy-above' or `org-show-following-heading'
12766 not t for the search context.
12768 With optional argument SIBLINGS, on each level of the hierarchy all
12769 siblings are shown. This repairs the tree structure to what it would
12770 look like when opened with hierarchical calls to `org-cycle'."
12771 (interactive "P")
12772 (let ((org-show-hierarchy-above t)
12773 (org-show-following-heading t)
12774 (org-show-siblings (if siblings t org-show-siblings)))
12775 (org-show-context nil)))
12777 (defun org-highlight-new-match (beg end)
12778 "Highlight from BEG to END and mark the highlight is an occur headline."
12779 (let ((ov (org-make-overlay beg end)))
12780 (org-overlay-put ov 'face 'secondary-selection)
12781 (push ov org-occur-highlights)))
12783 (defun org-remove-occur-highlights (&optional beg end noremove)
12784 "Remove the occur highlights from the buffer.
12785 BEG and END are ignored. If NOREMOVE is nil, remove this function
12786 from the `before-change-functions' in the current buffer."
12787 (interactive)
12788 (unless org-inhibit-highlight-removal
12789 (mapc 'org-delete-overlay org-occur-highlights)
12790 (setq org-occur-highlights nil)
12791 (unless noremove
12792 (remove-hook 'before-change-functions
12793 'org-remove-occur-highlights 'local))))
12795 ;;;; Priorities
12797 (defvar org-priority-regexp ".*?\\(\\[#\\([A-Z0-9]\\)\\] ?\\)"
12798 "Regular expression matching the priority indicator.")
12800 (defvar org-remove-priority-next-time nil)
12802 (defun org-priority-up ()
12803 "Increase the priority of the current item."
12804 (interactive)
12805 (org-priority 'up))
12807 (defun org-priority-down ()
12808 "Decrease the priority of the current item."
12809 (interactive)
12810 (org-priority 'down))
12812 (defun org-priority (&optional action)
12813 "Change the priority of an item by ARG.
12814 ACTION can be `set', `up', `down', or a character."
12815 (interactive)
12816 (setq action (or action 'set))
12817 (let (current new news have remove)
12818 (save-excursion
12819 (org-back-to-heading)
12820 (if (looking-at org-priority-regexp)
12821 (setq current (string-to-char (match-string 2))
12822 have t)
12823 (setq current org-default-priority))
12824 (cond
12825 ((or (eq action 'set) (integerp action))
12826 (if (integerp action)
12827 (setq new action)
12828 (message "Priority %c-%c, SPC to remove: " org-highest-priority org-lowest-priority)
12829 (setq new (read-char-exclusive)))
12830 (cond ((equal new ?\ ) (setq remove t))
12831 ((or (< (upcase new) org-highest-priority) (> (upcase new) org-lowest-priority))
12832 (error "Priority must be between `%c' and `%c'"
12833 org-highest-priority org-lowest-priority))))
12834 ((eq action 'up)
12835 (setq new (1- current)))
12836 ((eq action 'down)
12837 (setq new (1+ current)))
12838 (t (error "Invalid action")))
12839 (setq new (min (max org-highest-priority (upcase new)) org-lowest-priority))
12840 (setq news (format "%c" new))
12841 (if have
12842 (if remove
12843 (replace-match "" t t nil 1)
12844 (replace-match news t t nil 2))
12845 (if remove
12846 (error "No priority cookie found in line")
12847 (looking-at org-todo-line-regexp)
12848 (if (match-end 2)
12849 (progn
12850 (goto-char (match-end 2))
12851 (insert " [#" news "]"))
12852 (goto-char (match-beginning 3))
12853 (insert "[#" news "] ")))))
12854 (org-preserve-lc (org-set-tags nil 'align))
12855 (if remove
12856 (message "Priority removed")
12857 (message "Priority of current item set to %s" news))))
12860 (defun org-get-priority (s)
12861 "Find priority cookie and return priority."
12862 (save-match-data
12863 (if (not (string-match org-priority-regexp s))
12864 (* 1000 (- org-lowest-priority org-default-priority))
12865 (* 1000 (- org-lowest-priority
12866 (string-to-char (match-string 2 s)))))))
12868 ;;;; Tags
12870 (defun org-scan-tags (action matcher &optional todo-only)
12871 "Scan headline tags with inheritance and produce output ACTION.
12872 ACTION can be `sparse-tree' or `agenda'. MATCHER is a Lisp form to be
12873 evaluated, testing if a given set of tags qualifies a headline for
12874 inclusion. When TODO-ONLY is non-nil, only lines with a TODO keyword
12875 are included in the output."
12876 (let* ((re (concat "[\n\r]" outline-regexp " *\\(\\<\\("
12877 (mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
12878 (org-re
12879 "\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@:]+:\\)?[ \t]*$")))
12880 (props (list 'face nil
12881 'done-face 'org-done
12882 'undone-face nil
12883 'mouse-face 'highlight
12884 'org-not-done-regexp org-not-done-regexp
12885 'org-todo-regexp org-todo-regexp
12886 'keymap org-agenda-keymap
12887 'help-echo
12888 (format "mouse-2 or RET jump to org file %s"
12889 (abbreviate-file-name buffer-file-name))))
12890 (case-fold-search nil)
12891 lspos
12892 tags tags-list tags-alist (llast 0) rtn level category i txt
12893 todo marker entry priority)
12894 (save-excursion
12895 (goto-char (point-min))
12896 (when (eq action 'sparse-tree) (org-overview))
12897 (while (re-search-forward re nil t)
12898 (catch :skip
12899 (setq todo (if (match-end 1) (match-string 2))
12900 tags (if (match-end 4) (match-string 4)))
12901 (goto-char (setq lspos (1+ (match-beginning 0))))
12902 (setq level (org-reduced-level (funcall outline-level))
12903 category (org-get-category))
12904 (setq i llast llast level)
12905 ;; remove tag lists from same and sublevels
12906 (while (>= i level)
12907 (when (setq entry (assoc i tags-alist))
12908 (setq tags-alist (delete entry tags-alist)))
12909 (setq i (1- i)))
12910 ;; add the nex tags
12911 (when tags
12912 (setq tags (mapcar 'downcase (org-split-string tags ":"))
12913 tags-alist
12914 (cons (cons level tags) tags-alist)))
12915 ;; compile tags for current headline
12916 (setq tags-list
12917 (if org-use-tag-inheritance
12918 (apply 'append (mapcar 'cdr tags-alist))
12919 tags))
12920 (when (and (or (not todo-only) (member todo org-not-done-keywords))
12921 (eval matcher)
12922 (or (not org-agenda-skip-archived-trees)
12923 (not (member org-archive-tag tags-list))))
12924 (and (eq action 'agenda) (org-agenda-skip))
12925 ;; list this headline
12926 (if (eq action 'sparse-tree)
12927 (progn
12928 (org-show-context 'tags-tree))
12929 (setq txt (org-format-agenda-item
12931 (concat
12932 (if org-tags-match-list-sublevels
12933 (make-string (1- level) ?.) "")
12934 (org-get-heading))
12935 category tags-list)
12936 priority (org-get-priority txt))
12937 (goto-char lspos)
12938 (setq marker (org-agenda-new-marker))
12939 (org-add-props txt props
12940 'org-marker marker 'org-hd-marker marker 'org-category category
12941 'priority priority 'type "tagsmatch")
12942 (push txt rtn))
12943 ;; if we are to skip sublevels, jump to end of subtree
12944 (or org-tags-match-list-sublevels (org-end-of-subtree t))))))
12945 (when (and (eq action 'sparse-tree)
12946 (not org-sparse-tree-open-archived-trees))
12947 (org-hide-archived-subtrees (point-min) (point-max)))
12948 (nreverse rtn)))
12950 (defvar todo-only) ;; dynamically scoped
12952 (defun org-tags-sparse-tree (&optional todo-only match)
12953 "Create a sparse tree according to tags string MATCH.
12954 MATCH can contain positive and negative selection of tags, like
12955 \"+WORK+URGENT-WITHBOSS\".
12956 If optional argument TODO_ONLY is non-nil, only select lines that are
12957 also TODO lines."
12958 (interactive "P")
12959 (org-scan-tags 'sparse-tree (cdr (org-make-tags-matcher match)) todo-only))
12961 (defvar org-cached-props nil)
12962 (defun org-cached-entry-get (pom property)
12963 (cdr (assoc property (or org-cached-props
12964 (setq org-cached-props
12965 (org-entry-properties pom))))))
12967 (defun org-global-tags-completion-table (&optional files)
12968 "Return the list of all tags in all agenda buffer/files."
12969 (save-excursion
12970 (org-uniquify
12971 (apply 'append
12972 (mapcar
12973 (lambda (file)
12974 (set-buffer (find-file-noselect file))
12975 (org-get-buffer-tags))
12976 (if (and files (car files))
12977 files
12978 (org-agenda-files)))))))
12980 (defun org-make-tags-matcher (match)
12981 "Create the TAGS//TODO matcher form for the selection string MATCH."
12982 ;; todo-only is scoped dynamically into this function, and the function
12983 ;; may change it it the matcher asksk for it.
12984 (unless match
12985 ;; Get a new match request, with completion
12986 (let ((org-last-tags-completion-table
12987 (org-global-tags-completion-table)))
12988 (setq match (completing-read
12989 "Match: " 'org-tags-completion-function nil nil nil
12990 'org-tags-history))))
12992 ;; Parse the string and create a lisp form
12993 (let ((match0 match)
12994 (re (org-re "^&?\\([-+:]\\)?\\({[^}]+}\\|LEVEL=\\([0-9]+\\)\\|\\([[:alnum:]]+\\)=\\({[^}]+}\\|\"[^\"]+\"\\)\\|[[:alnum:]_@]+\\)"))
12995 minus tag mm
12996 tagsmatch todomatch tagsmatcher todomatcher kwd matcher
12997 orterms term orlist re-p level-p prop-p pn pv)
12998 (if (string-match "/+" match)
12999 ;; match contains also a todo-matching request
13000 (progn
13001 (setq tagsmatch (substring match 0 (match-beginning 0))
13002 todomatch (substring match (match-end 0)))
13003 (if (string-match "^!" todomatch)
13004 (setq todo-only t todomatch (substring todomatch 1)))
13005 (if (string-match "^\\s-*$" todomatch)
13006 (setq todomatch nil)))
13007 ;; only matching tags
13008 (setq tagsmatch match todomatch nil))
13010 ;; Make the tags matcher
13011 (if (or (not tagsmatch) (not (string-match "\\S-" tagsmatch)))
13012 (setq tagsmatcher t)
13013 (setq orterms (org-split-string tagsmatch "|") orlist nil)
13014 (while (setq term (pop orterms))
13015 (while (and (equal (substring term -1) "\\") orterms)
13016 (setq term (concat term "|" (pop orterms)))) ; repair bad split
13017 (while (string-match re term)
13018 (setq minus (and (match-end 1)
13019 (equal (match-string 1 term) "-"))
13020 tag (match-string 2 term)
13021 re-p (equal (string-to-char tag) ?{)
13022 level-p (match-end 3)
13023 prop-p (match-end 4)
13024 mm (cond
13025 (re-p `(org-match-any-p ,(substring tag 1 -1) tags-list))
13026 (level-p `(= level ,(string-to-number
13027 (match-string 3 term))))
13028 (prop-p
13029 (setq pn (match-string 4 term)
13030 pv (match-string 5 term)
13031 re-p (equal (string-to-char pv) ?{)
13032 pv (substring pv 1 -1))
13033 (if re-p
13034 `(string-match ,pv (org-cached-entry-get nil ,pn))
13035 `(equal ,pv (org-cached-entry-get nil ,pn))))
13036 (t `(member ,(downcase tag) tags-list)))
13037 mm (if minus (list 'not mm) mm)
13038 term (substring term (match-end 0)))
13039 (push mm tagsmatcher))
13040 (push (if (> (length tagsmatcher) 1)
13041 (cons 'and tagsmatcher)
13042 (car tagsmatcher))
13043 orlist)
13044 (setq tagsmatcher nil))
13045 (setq tagsmatcher (if (> (length orlist) 1) (cons 'or orlist) (car orlist)))
13046 (setq tagsmatcher
13047 (list 'progn '(setq org-cached-props nil) tagsmatcher)))
13049 ;; Make the todo matcher
13050 (if (or (not todomatch) (not (string-match "\\S-" todomatch)))
13051 (setq todomatcher t)
13052 (setq orterms (org-split-string todomatch "|") orlist nil)
13053 (while (setq term (pop orterms))
13054 (while (string-match re term)
13055 (setq minus (and (match-end 1)
13056 (equal (match-string 1 term) "-"))
13057 kwd (match-string 2 term)
13058 re-p (equal (string-to-char kwd) ?{)
13059 term (substring term (match-end 0))
13060 mm (if re-p
13061 `(string-match ,(substring kwd 1 -1) todo)
13062 (list 'equal 'todo kwd))
13063 mm (if minus (list 'not mm) mm))
13064 (push mm todomatcher))
13065 (push (if (> (length todomatcher) 1)
13066 (cons 'and todomatcher)
13067 (car todomatcher))
13068 orlist)
13069 (setq todomatcher nil))
13070 (setq todomatcher (if (> (length orlist) 1)
13071 (cons 'or orlist) (car orlist))))
13073 ;; Return the string and lisp forms of the matcher
13074 (setq matcher (if todomatcher
13075 (list 'and tagsmatcher todomatcher)
13076 tagsmatcher))
13077 (cons match0 matcher)))
13079 (defun org-match-any-p (re list)
13080 "Does re match any element of list?"
13081 (setq list (mapcar (lambda (x) (string-match re x)) list))
13082 (delq nil list))
13084 (defvar org-add-colon-after-tag-completion nil) ;; dynamically skoped param
13085 (defvar org-tags-overlay (org-make-overlay 1 1))
13086 (org-detach-overlay org-tags-overlay)
13088 (defun org-set-tags (&optional arg just-align)
13089 "Set the tags for the current headline.
13090 With prefix ARG, realign all tags in headings in the current buffer."
13091 (interactive "P")
13092 (let* ((re (concat "^" outline-regexp))
13093 (current (org-get-tags))
13094 table current-tags inherited-tags ; computed below when needed
13095 tags p0 c0 c1 rpl)
13096 (if arg
13097 (save-excursion
13098 (goto-char (point-min))
13099 (let ((buffer-invisibility-spec (org-inhibit-invisibility)))
13100 (while (re-search-forward re nil t)
13101 (org-set-tags nil t)
13102 (end-of-line 1)))
13103 (message "All tags realigned to column %d" org-tags-column))
13104 (if just-align
13105 (setq tags current)
13106 ;; Get a new set of tags from the user
13107 (save-excursion
13108 (setq table (or org-tag-alist (org-get-buffer-tags))
13109 org-last-tags-completion-table table
13110 current-tags (org-split-string current ":")
13111 inherited-tags (nreverse
13112 (nthcdr (length current-tags)
13113 (nreverse (org-get-tags-at))))
13114 tags
13115 (if (or (eq t org-use-fast-tag-selection)
13116 (and org-use-fast-tag-selection
13117 (delq nil (mapcar 'cdr table))))
13118 (org-fast-tag-selection current-tags inherited-tags table)
13119 (let ((org-add-colon-after-tag-completion t))
13120 (org-trim
13121 (completing-read "Tags: " 'org-tags-completion-function
13122 nil nil current 'org-tags-history))))))
13123 (while (string-match "[-+&]+" tags)
13124 ;; No boolean logic, just a list
13125 (setq tags (replace-match ":" t t tags))))
13127 (if (string-match "\\`[\t ]*\\'" tags)
13128 (setq tags "")
13129 (unless (string-match ":$" tags) (setq tags (concat tags ":")))
13130 (unless (string-match "^:" tags) (setq tags (concat ":" tags))))
13132 ;; Insert new tags at the correct column
13133 (beginning-of-line 1)
13134 (if (re-search-forward
13135 (concat "\\([ \t]*" (regexp-quote current) "\\)[ \t]*$")
13136 (point-at-eol) t)
13137 (progn
13138 (if (equal tags "")
13139 (setq rpl "")
13140 (goto-char (match-beginning 0))
13141 (setq c0 (current-column) p0 (point)
13142 c1 (max (1+ c0) (if (> org-tags-column 0)
13143 org-tags-column
13144 (- (- org-tags-column) (length tags))))
13145 rpl (concat (make-string (max 0 (- c1 c0)) ?\ ) tags)))
13146 (replace-match rpl t t)
13147 (and (not (featurep 'xemacs)) c0 (tabify p0 (point)))
13148 tags)
13149 (error "Tags alignment failed")))))
13151 (defun org-tags-completion-function (string predicate &optional flag)
13152 (let (s1 s2 rtn (ctable org-last-tags-completion-table)
13153 (confirm (lambda (x) (stringp (car x)))))
13154 (if (string-match "^\\(.*[-+:&|]\\)\\([^-+:&|]*\\)$" string)
13155 (setq s1 (match-string 1 string)
13156 s2 (match-string 2 string))
13157 (setq s1 "" s2 string))
13158 (cond
13159 ((eq flag nil)
13160 ;; try completion
13161 (setq rtn (try-completion s2 ctable confirm))
13162 (if (stringp rtn)
13163 (setq rtn
13164 (concat s1 s2 (substring rtn (length s2))
13165 (if (and org-add-colon-after-tag-completion
13166 (assoc rtn ctable))
13167 ":" ""))))
13168 rtn)
13169 ((eq flag t)
13170 ;; all-completions
13171 (all-completions s2 ctable confirm)
13173 ((eq flag 'lambda)
13174 ;; exact match?
13175 (assoc s2 ctable)))
13178 (defun org-fast-tag-insert (kwd tags face &optional end)
13179 "Insert KDW, and the TAGS, the latter with face FACE. Also inser END."
13180 (insert (format "%-12s" (concat kwd ":"))
13181 (org-add-props (mapconcat 'identity tags " ") nil 'face face)
13182 (or end "")))
13184 (defun org-fast-tag-show-exit (flag)
13185 (save-excursion
13186 (goto-line 3)
13187 (if (re-search-forward "[ \t]+Next change exits" (point-at-eol) t)
13188 (replace-match ""))
13189 (when flag
13190 (end-of-line 1)
13191 (move-to-column (- (window-width) 19) t)
13192 (insert (org-add-props " Next change exits" nil 'face 'org-warning)))))
13194 (defun org-set-current-tags-overlay (current prefix)
13195 (let ((s (concat ":" (mapconcat 'identity current ":") ":")))
13196 (if (featurep 'xemacs)
13197 (org-overlay-display org-tags-overlay (concat prefix s)
13198 'secondary-selection)
13199 (put-text-property 0 (length s) 'face '(secondary-selection org-tag) s)
13200 (org-overlay-display org-tags-overlay (concat prefix s)))))
13202 (defun org-fast-tag-selection (current inherited table)
13203 "Fast tag selection with single keys.
13204 CURRENT is the current list of tags in the headline, INHERITED is the
13205 list of inherited tags, and TABLE is an alist of tags and corresponding keys,
13206 possibly with grouping information.
13207 If the keys are nil, a-z are automatically assigned.
13208 Returns the new tags string, or nil to not change the current settings."
13209 (let* ((maxlen (apply 'max (mapcar
13210 (lambda (x)
13211 (if (stringp (car x)) (string-width (car x)) 0))
13212 table)))
13213 (buf (current-buffer))
13214 (expert (eq org-fast-tag-selection-single-key 'expert))
13215 (buffer-tags nil)
13216 (fwidth (+ maxlen 3 1 3))
13217 (ncol (/ (- (window-width) 4) fwidth))
13218 (i-face 'org-done)
13219 (c-face 'org-todo)
13220 tg cnt e c char c1 c2 ntable tbl rtn
13221 ov-start ov-end ov-prefix
13222 (exit-after-next org-fast-tag-selection-single-key)
13223 groups ingroup)
13224 (save-excursion
13225 (beginning-of-line 1)
13226 (if (looking-at
13227 (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
13228 (setq ov-start (match-beginning 1)
13229 ov-end (match-end 1)
13230 ov-prefix "")
13231 (setq ov-start (1- (point-at-eol))
13232 ov-end (1+ ov-start))
13233 (skip-chars-forward "^\n\r")
13234 (setq ov-prefix
13235 (concat
13236 (buffer-substring (1- (point)) (point))
13237 (if (> (current-column) org-tags-column)
13239 (make-string (- org-tags-column (current-column)) ?\ ))))))
13240 (org-move-overlay org-tags-overlay ov-start ov-end)
13241 (save-window-excursion
13242 (if expert
13243 (set-buffer (get-buffer-create " *Org tags*"))
13244 (delete-other-windows)
13245 (split-window-vertically)
13246 (switch-to-buffer-other-window (get-buffer-create " *Org tags*")))
13247 (erase-buffer)
13248 (org-fast-tag-insert "Inherited" inherited i-face "\n")
13249 (org-fast-tag-insert "Current" current c-face "\n\n")
13250 (org-fast-tag-show-exit exit-after-next)
13251 (org-set-current-tags-overlay current ov-prefix)
13252 (setq tbl table char ?a cnt 0)
13253 (while (setq e (pop tbl))
13254 (cond
13255 ((equal e '(:startgroup))
13256 (push '() groups) (setq ingroup t)
13257 (when (not (= cnt 0))
13258 (setq cnt 0)
13259 (insert "\n"))
13260 (insert "{ "))
13261 ((equal e '(:endgroup))
13262 (setq ingroup nil cnt 0)
13263 (insert "}\n"))
13265 (setq tg (car e) c2 nil)
13266 (if (cdr e)
13267 (setq c (cdr e))
13268 ;; automatically assign a character.
13269 (setq c1 (string-to-char
13270 (downcase (substring
13271 tg (if (= (string-to-char tg) ?@) 1 0)))))
13272 (if (or (rassoc c1 ntable) (rassoc c1 table))
13273 (while (or (rassoc char ntable) (rassoc char table))
13274 (setq char (1+ char)))
13275 (setq c2 c1))
13276 (setq c (or c2 char)))
13277 (if ingroup (push tg (car groups)))
13278 (setq tg (org-add-props tg nil 'face
13279 (cond
13280 ((member tg current) c-face)
13281 ((member tg inherited) i-face)
13282 (t nil))))
13283 (if (and (= cnt 0) (not ingroup)) (insert " "))
13284 (insert "[" c "] " tg (make-string
13285 (- fwidth 4 (length tg)) ?\ ))
13286 (push (cons tg c) ntable)
13287 (when (= (setq cnt (1+ cnt)) ncol)
13288 (insert "\n")
13289 (if ingroup (insert " "))
13290 (setq cnt 0)))))
13291 (setq ntable (nreverse ntable))
13292 (insert "\n")
13293 (goto-char (point-min))
13294 (if (and (not expert) (fboundp 'fit-window-to-buffer))
13295 (fit-window-to-buffer))
13296 (setq rtn
13297 (catch 'exit
13298 (while t
13299 (message "[a-z..]:Toggle [SPC]:clear [RET]:accept [TAB]:free%s%s"
13300 (if groups " [!] no groups" " [!]groups")
13301 (if expert " [C-c]:window" (if exit-after-next " [C-c]:single" " [C-c]:multi")))
13302 (setq c (let ((inhibit-quit t)) (read-char-exclusive)))
13303 (cond
13304 ((= c ?\r) (throw 'exit t))
13305 ((= c ?!)
13306 (setq groups (not groups))
13307 (goto-char (point-min))
13308 (while (re-search-forward "[{}]" nil t) (replace-match " ")))
13309 ((= c ?\C-c)
13310 (if (not expert)
13311 (org-fast-tag-show-exit
13312 (setq exit-after-next (not exit-after-next)))
13313 (setq expert nil)
13314 (delete-other-windows)
13315 (split-window-vertically)
13316 (switch-to-buffer-other-window " *Org tags*")
13317 (and (fboundp 'fit-window-to-buffer)
13318 (fit-window-to-buffer))))
13319 ((or (= c ?\C-g)
13320 (and (= c ?q) (not (rassoc c ntable))))
13321 (org-detach-overlay org-tags-overlay)
13322 (setq quit-flag t))
13323 ((= c ?\ )
13324 (setq current nil)
13325 (if exit-after-next (setq exit-after-next 'now)))
13326 ((= c ?\t)
13327 (condition-case nil
13328 (setq tg (completing-read
13329 "Tag: "
13330 (or buffer-tags
13331 (with-current-buffer buf
13332 (org-get-buffer-tags)))))
13333 (quit (setq tg "")))
13334 (when (string-match "\\S-" tg)
13335 (add-to-list 'buffer-tags (list tg))
13336 (if (member tg current)
13337 (setq current (delete tg current))
13338 (push tg current)))
13339 (if exit-after-next (setq exit-after-next 'now)))
13340 ((setq e (rassoc c ntable) tg (car e))
13341 (if (member tg current)
13342 (setq current (delete tg current))
13343 (loop for g in groups do
13344 (if (member tg g)
13345 (mapcar (lambda (x)
13346 (setq current (delete x current)))
13347 g)))
13348 (push tg current))
13349 (if exit-after-next (setq exit-after-next 'now))))
13351 ;; Create a sorted list
13352 (setq current
13353 (sort current
13354 (lambda (a b)
13355 (assoc b (cdr (memq (assoc a ntable) ntable))))))
13356 (if (eq exit-after-next 'now) (throw 'exit t))
13357 (goto-char (point-min))
13358 (beginning-of-line 2)
13359 (delete-region (point) (point-at-eol))
13360 (org-fast-tag-insert "Current" current c-face)
13361 (org-set-current-tags-overlay current ov-prefix)
13362 (while (re-search-forward
13363 (org-re "\\[.\\] \\([[:alnum:]_@]+\\)") nil t)
13364 (setq tg (match-string 1))
13365 (add-text-properties (match-beginning 1) (match-end 1)
13366 (list 'face
13367 (cond
13368 ((member tg current) c-face)
13369 ((member tg inherited) i-face)
13370 (t nil)))))
13371 (goto-char (point-min)))))
13372 (org-detach-overlay org-tags-overlay)
13373 (if rtn
13374 (mapconcat 'identity current ":")
13375 nil))))
13377 (defun org-get-tags ()
13378 "Get the TAGS string in the current headline."
13379 (unless (org-on-heading-p t)
13380 (error "Not on a heading"))
13381 (save-excursion
13382 (beginning-of-line 1)
13383 (if (looking-at (org-re ".*[ \t]\\(:[[:alnum:]_@:]+:\\)[ \t]*$"))
13384 (org-match-string-no-properties 1)
13385 "")))
13387 (defun org-get-buffer-tags ()
13388 "Get a table of all tags used in the buffer, for completion."
13389 (let (tags)
13390 (save-excursion
13391 (goto-char (point-min))
13392 (while (re-search-forward
13393 (org-re "[ \t]:\\([[:alnum:]_@:]+\\):[ \t\r\n]") nil t)
13394 (when (equal (char-after (point-at-bol 0)) ?*)
13395 (mapc (lambda (x) (add-to-list 'tags x))
13396 (org-split-string (org-match-string-no-properties 1) ":")))))
13397 (mapcar 'list tags)))
13400 ;;;; Properties
13402 ;;; Setting and retrieving properties
13404 (defconst org-special-properties
13405 '("TODO" "TAGS" "ALLTAGS" "DEADLINE" "SCHEDULED"
13406 "CLOCK" "PRIORITY")
13407 "The special properties valid in Org-mode.
13409 These are properties that are not defined in the property drawer,
13410 but in some other way.")
13412 (defconst org-property-start-re "^[ \t]*:PROPERTIES:[ \t]*$"
13413 "Regular expression matching the first line of a property drawer.")
13415 (defconst org-property-end-re "^[ \t]*:END:[ \t]*$"
13416 "Regular expression matching the first line of a property drawer.")
13418 (defun org-property-action ()
13419 "Do an action on properties."
13420 (interactive)
13421 (let (c prop)
13422 (org-at-property-p)
13423 (setq prop (match-string 2))
13424 (message "Property Action: [s]et [d]elete [D]delete globally")
13425 (setq c (read-char-exclusive))
13426 (cond
13427 ((equal c ?s)
13428 (call-interactively 'org-set-property))
13429 ((equal c ?d)
13430 (call-interactively 'org-delete-property))
13431 ((equal c ?D)
13432 (call-interactively 'org-delete-property-globally))
13433 (t (error "No such property action %c" c)))))
13435 (defun org-at-property-p ()
13436 "Is the cursor in a property line?"
13437 ;; FIXME: Does not check if we are actually in the drawer.
13438 ;; FIXME: also returns true on any drawers.....
13439 ;; This is used by C-c C-c for property action.
13440 (save-excursion
13441 (beginning-of-line 1)
13442 (looking-at "^[ \t]*\\(:\\([a-zA-Z_0-9]+\\):\\)[ \t]*\\(.*\\)")))
13444 (defmacro org-with-point-at (pom &rest body)
13445 "Move to buffer and point of point-or-marker POM for the duration of BODY."
13446 (declare (indent 1) (debug t))
13447 `(save-excursion
13448 (if (markerp pom) (set-buffer (marker-buffer pom)))
13449 (save-excursion
13450 (goto-char (or pom (point)))
13451 ,@body)))
13453 (defun org-get-property-block (&optional beg end force)
13454 "Return the (beg . end) range of the body of the property drawer.
13455 BEG and END can be beginning and end of subtree, if not given
13456 they will be found.
13457 If the drawer does not exist and FORCE is non-nil, create the drawer."
13458 (catch 'exit
13459 (save-excursion
13460 (let* ((beg (or beg (progn (org-back-to-heading t) (point))))
13461 (end (or end (progn (outline-next-heading) (point)))))
13462 (goto-char beg)
13463 (if (re-search-forward org-property-start-re end t)
13464 (setq beg (1+ (match-end 0)))
13465 (if force
13466 (save-excursion
13467 (org-insert-property-drawer)
13468 (setq end (progn (outline-next-heading) (point))))
13469 (throw 'exit nil))
13470 (goto-char beg)
13471 (if (re-search-forward org-property-start-re end t)
13472 (setq beg (1+ (match-end 0)))))
13473 (if (re-search-forward org-property-end-re end t)
13474 (setq end (match-beginning 0))
13475 (or force (throw 'exit nil))
13476 (goto-char beg)
13477 (setq end beg)
13478 (org-indent-line-function)
13479 (insert ":END:\n"))
13480 (cons beg end)))))
13482 (defun org-entry-properties (&optional pom which)
13483 "Get all properties of the entry at point-or-marker POM.
13484 This includes the TODO keyword, the tags, time strings for deadline,
13485 scheduled, and clocking, and any additional properties defined in the
13486 entry. The return value is an alist, keys may occur multiple times
13487 if the property key was used several times.
13488 POM may also be nil, in which case the current entry is used.
13489 If WHICH is nil or `all', get all properties. If WHICH is
13490 `special' or `standard', only get that subclass."
13491 (setq which (or which 'all))
13492 (org-with-point-at pom
13493 (let ((clockstr (substring org-clock-string 0 -1))
13494 (excluded '("TODO" "TAGS" "ALLTAGS" "PRIORITY"))
13495 beg end range props sum-props key value)
13496 (save-excursion
13497 (when (condition-case nil (org-back-to-heading t) (error nil))
13498 (setq beg (point))
13499 (setq sum-props (get-text-property (point) 'org-summaries))
13500 (outline-next-heading)
13501 (setq end (point))
13502 (when (memq which '(all special))
13503 ;; Get the special properties, like TODO and tags
13504 (goto-char beg)
13505 (when (and (looking-at org-todo-line-regexp) (match-end 2))
13506 (push (cons "TODO" (org-match-string-no-properties 2)) props))
13507 (when (looking-at org-priority-regexp)
13508 (push (cons "PRIORITY" (org-match-string-no-properties 2)) props))
13509 (when (and (setq value (org-get-tags)) (string-match "\\S-" value))
13510 (push (cons "TAGS" value) props))
13511 (when (setq value (org-get-tags-at))
13512 (push (cons "ALLTAGS" (concat ":" (mapconcat 'identity value ":") ":"))
13513 props))
13514 (while (re-search-forward org-keyword-time-regexp end t)
13515 (setq key (substring (org-match-string-no-properties 1) 0 -1))
13516 (unless (member key excluded) (push key excluded))
13517 (push (cons key
13518 (if (equal key clockstr)
13519 (org-no-properties
13520 (org-trim
13521 (buffer-substring
13522 (match-beginning 2) (point-at-eol))))
13523 (org-match-string-no-properties 2)))
13524 props)))
13525 (when (memq which '(all standard))
13526 ;; Get the standard properties, like :PORP: ...
13527 (setq range (org-get-property-block beg end))
13528 (when range
13529 (goto-char (car range))
13530 (while (re-search-forward
13531 "^[ \t]*:\\([a-zA-Z][a-zA-Z_0-9]*\\):[ \t]*\\(\\S-.*\\)?"
13532 (cdr range) t)
13533 (setq key (org-match-string-no-properties 1)
13534 value (org-trim (or (org-match-string-no-properties 2) "")))
13535 (unless (member key excluded)
13536 (push (cons key (or value "")) props)))))
13537 (append sum-props (nreverse props)))))))
13539 (defun org-entry-get (pom property &optional inherit)
13540 "Get value of PROPERTY for entry at point-or-marker POM.
13541 If INHERIT is non-nil and the entry does not have the property,
13542 then also check higher levels of the hierarchy.
13543 If the property is present but empty, the return value is the empty string.
13544 If the property is not present at all, nil is returned."
13545 (org-with-point-at pom
13546 (if inherit
13547 (org-entry-get-with-inheritance property)
13548 (if (member property org-special-properties)
13549 ;; We need a special property. Use brute force, get all properties.
13550 (cdr (assoc property (org-entry-properties nil 'special)))
13551 (let ((range (org-get-property-block)))
13552 (if (and range
13553 (goto-char (car range))
13554 (re-search-forward
13555 (concat "^[ \t]*:" property ":[ \t]*\\(.*\\S-\\)?")
13556 (cdr range) t))
13557 ;; Found the property, return it.
13558 (if (match-end 1)
13559 (org-match-string-no-properties 1)
13560 "")))))))
13562 (defun org-entry-delete (pom property)
13563 "Delete the property PROPERTY from entry at point-or-marker POM."
13564 (org-with-point-at pom
13565 (if (member property org-special-properties)
13566 nil ; cannot delete these properties.
13567 (let ((range (org-get-property-block)))
13568 (if (and range
13569 (goto-char (car range))
13570 (re-search-forward
13571 (concat "^[ \t]*:" property ":[ \t]*\\(.*\\S-\\)")
13572 (cdr range) t))
13573 (progn
13574 (delete-region (match-beginning 0) (1+ (point-at-eol)))
13576 nil)))))
13578 (defvar org-entry-property-inherited-from (make-marker))
13580 (defun org-entry-get-with-inheritance (property)
13581 "Get entry property, and search higher levels if not present."
13582 (let (tmp)
13583 (save-excursion
13584 (catch 'ex
13585 (while t
13586 (when (setq tmp (org-entry-get nil property))
13587 (org-back-to-heading t)
13588 (move-marker org-entry-property-inherited-from (point))
13589 (throw 'ex tmp))
13590 (condition-case nil
13591 (org-up-heading-all 1)
13592 (error (throw 'ex nil))))))))
13594 (defun org-entry-put (pom property value)
13595 "Set PROPERTY to VALUE for entry at point-or-marker POM."
13596 (org-with-point-at pom
13597 (org-back-to-heading t)
13598 (let ((beg (point)) (end (save-excursion (outline-next-heading) (point)))
13599 range)
13600 (cond
13601 ((equal property "TODO")
13602 (when (and (stringp value) (string-match "\\S-" value)
13603 (not (member value org-todo-keywords-1)))
13604 (error "\"%s\" is not a valid TODO state" value))
13605 (if (or (not value)
13606 (not (string-match "\\S-" value)))
13607 (setq value 'none))
13608 (org-todo value)
13609 (org-set-tags nil 'align))
13610 ((equal property "PRIORITY")
13611 (org-priority (if (and value (stringp value) (string-match "\\S-" value))
13612 (string-to-char value) ?\ ))
13613 (org-set-tags nil 'align))
13614 ((member property org-special-properties)
13615 (error "The %s property can not yet be set with `org-entry-put'"
13616 property))
13617 (t ; a non-special property
13618 (setq range (org-get-property-block beg end 'force))
13619 (goto-char (car range))
13620 (if (re-search-forward
13621 (concat "^[ \t]*:" property ":\\(.*\\)") (cdr range) t)
13622 (progn
13623 (delete-region (match-beginning 1) (match-end 1))
13624 (goto-char (match-beginning 1)))
13625 (goto-char (cdr range))
13626 (insert "\n")
13627 (backward-char 1)
13628 (org-indent-line-function)
13629 (insert ":" property ":"))
13630 (and value (insert " " value))
13631 (org-indent-line-function))))))
13633 (defun org-buffer-property-keys (&optional include-specials)
13634 "Get all property keys in the current buffer."
13635 (let (rtn range)
13636 (save-excursion
13637 (save-restriction
13638 (widen)
13639 (goto-char (point-min))
13640 (while (re-search-forward org-property-start-re nil t)
13641 (setq range (org-get-property-block))
13642 (goto-char (car range))
13643 (while (re-search-forward "^[ \t]*:\\([a-zA-Z0-9]+\\):" (cdr range) t)
13644 (add-to-list 'rtn (org-match-string-no-properties 1)))
13645 (outline-next-heading))))
13646 (when include-specials
13647 (setq rtn (append org-special-properties rtn)))
13648 (sort rtn (lambda (a b) (string< (upcase a) (upcase b))))))
13650 (defun org-insert-property-drawer ()
13651 "Insert a property drawer into the current entry."
13652 (interactive)
13653 (org-back-to-heading t)
13654 (let ((beg (point))
13655 (re (concat "^[ \t]*" org-keyword-time-regexp))
13656 end hiddenp)
13657 (outline-next-heading)
13658 (setq end (point))
13659 (goto-char beg)
13660 (while (re-search-forward re end t))
13661 (setq hiddenp (org-invisible-p))
13662 (end-of-line 1)
13663 (insert "\n:PROPERTIES:\n:END:")
13664 (beginning-of-line 0)
13665 (org-indent-line-function)
13666 (beginning-of-line 2)
13667 (org-indent-line-function)
13668 (beginning-of-line 0)
13669 (if hiddenp
13670 (save-excursion
13671 (org-back-to-heading t)
13672 (hide-entry))
13673 (org-flag-drawer t))))
13675 (defun org-set-property (property value)
13676 "In the current entry, set PROPERTY to VALUE."
13677 (interactive
13678 (let* ((prop (completing-read "Property: "
13679 (mapcar 'list (org-buffer-property-keys))))
13680 (cur (org-entry-get nil prop))
13681 (allowed (org-property-get-allowed-values nil prop 'table))
13682 (val (if allowed
13683 (completing-read "Value: " allowed nil 'req-match)
13684 (read-string
13685 (concat "Value" (if (and cur (string-match "\\S-" cur))
13686 (concat "[" cur "]") "")
13687 ": ")
13688 "" cur))))
13689 (list prop (if (equal val "") cur val))))
13690 (unless (equal (org-entry-get nil property) value)
13691 (org-entry-put nil property value)))
13693 (defun org-delete-property (property)
13694 "In the current entry, delete PROPERTY."
13695 (interactive
13696 (let* ((prop (completing-read
13697 "Property: " (org-entry-properties nil 'standard))))
13698 (list prop)))
13699 (message (concat "Property " property
13700 (if (org-entry-delete nil property)
13701 " deleted"
13702 " was not present in the entry"))))
13704 (defun org-delete-property-globally (property)
13705 "Remove PROPERTY globally, from all entries."
13706 (interactive
13707 (let* ((prop (completing-read
13708 "Globally remove property: "
13709 (mapcar 'list (org-buffer-property-keys)))))
13710 (list prop)))
13711 (save-excursion
13712 (save-restriction
13713 (widen)
13714 (goto-char (point-min))
13715 (let ((cnt 0))
13716 (while (re-search-forward
13717 (concat "^[ \t]*:" (regexp-quote property) ":.*\n?")
13718 nil t)
13719 (setq cnt (1+ cnt))
13720 (replace-match ""))
13721 (message "Property \"%s\" removed from %d entries" property cnt)))))
13723 (defun org-property-get-allowed-values (pom property &optional table)
13724 "Get allowed values for the property PROPERTY.
13725 When TABLE is non-nil, return an alist that can directly be used for
13726 completion."
13727 (let (vals)
13728 (cond
13729 ((equal property "TODO")
13730 (setq vals (org-with-point-at pom
13731 (append org-todo-keywords-1 '("")))))
13732 ((equal property "PRIORITY")
13733 (let ((n org-lowest-priority))
13734 (while (>= n org-highest-priority)
13735 (push (char-to-string n) vals)
13736 (setq n (1- n)))))
13737 ((member property org-special-properties))
13739 (setq vals (org-entry-get pom (concat property "_ALL") 'inherit))
13740 (when (and vals (string-match "\\S-" vals))
13741 (setq vals (car (read-from-string (concat "(" vals ")"))))
13742 (setq vals (mapcar (lambda (x)
13743 (cond ((stringp x) x)
13744 ((numberp x) (number-to-string x))
13745 ((symbolp x) (symbol-name x))
13746 (t "???")))
13747 vals)))))
13748 (if table (mapcar 'list vals) vals)))
13750 ;;; Column View
13752 (defvar org-columns-overlays nil
13753 "Holds the list of current column overlays.")
13755 (defvar org-columns-current-fmt nil
13756 "Local variable, holds the currently active column format.")
13757 (defvar org-columns-current-fmt-compiled nil
13758 "Local variable, holds the currently active column format.
13759 This is the compiled version of the format.")
13760 (defvar org-columns-current-maxwidths nil
13761 "Loval variable, holds the currently active maximum column widths.")
13762 (defvar org-columns-begin-marker (make-marker)
13763 "Points to the position where last a column creation command was called.")
13764 (defvar org-columns-top-level-marker (make-marker)
13765 "Points to the position where current columns region starts.")
13767 (defvar org-columns-map (make-sparse-keymap)
13768 "The keymap valid in column display.")
13770 (defun org-columns-content ()
13771 "Switch to contents view while in columns view."
13772 (interactive)
13773 (org-overview)
13774 (org-content))
13776 (org-defkey org-columns-map "c" 'org-columns-content)
13777 (org-defkey org-columns-map "o" 'org-overview)
13778 (org-defkey org-columns-map "e" 'org-columns-edit-value)
13779 (org-defkey org-columns-map "v" 'org-columns-show-value)
13780 (org-defkey org-columns-map "q" 'org-columns-quit)
13781 (org-defkey org-columns-map "r" 'org-columns-redo)
13782 (org-defkey org-columns-map [left] 'backward-char)
13783 (org-defkey org-columns-map "a" 'org-columns-edit-allowed)
13784 (org-defkey org-columns-map "s" 'org-columns-edit-attributes)
13785 (org-defkey org-columns-map [right] 'forward-char)
13786 (org-defkey org-columns-map [(shift right)] 'org-columns-next-allowed-value)
13787 (org-defkey org-columns-map "\C-c\C-c" 'org-columns-next-allowed-value)
13788 (org-defkey org-columns-map "n" 'org-columns-next-allowed-value)
13789 (org-defkey org-columns-map [(shift left)] 'org-columns-previous-allowed-value)
13790 (org-defkey org-columns-map "p" 'org-columns-previous-allowed-value)
13791 (org-defkey org-columns-map "<" 'org-columns-narrow)
13792 (org-defkey org-columns-map ">" 'org-columns-widen)
13793 (org-defkey org-columns-map [(meta right)] 'org-columns-move-right)
13794 (org-defkey org-columns-map [(meta left)] 'org-columns-move-left)
13795 (org-defkey org-columns-map [(shift meta right)] 'org-columns-new)
13796 (org-defkey org-columns-map [(shift meta left)] 'org-columns-delete)
13798 (easy-menu-define org-columns-menu org-columns-map "Org Column Menu"
13799 '("Column"
13800 ["Edit property" org-columns-edit-value t]
13801 ["Next allowed value" org-columns-next-allowed-value t]
13802 ["Previous allowed value" org-columns-previous-allowed-value t]
13803 ["Show full value" org-columns-show-value t]
13804 ["Edit allowed" org-columns-edit-allowed t]
13805 "--"
13806 ["Edit column attributes" org-columns-edit-attributes t]
13807 ["Increase column width" org-columns-widen t]
13808 ["Decrease column width" org-columns-narrow t]
13809 "--"
13810 ["Move column right" org-columns-move-right t]
13811 ["Move column left" org-columns-move-left t]
13812 ["Add column" org-columns-new t]
13813 ["Delete column" org-columns-delete t]
13814 "--"
13815 ["CONTENTS" org-columns-content t]
13816 ["OVERVIEW" org-overview t]
13817 ["Refresh columns display" org-columns-redo t]
13818 "--"
13819 ["Quit" org-columns-quit t]))
13821 (defun org-columns-new-overlay (beg end &optional string face)
13822 "Create a new column overlay and add it to the list."
13823 (let ((ov (org-make-overlay beg end)))
13824 (org-overlay-put ov 'face (or face 'secondary-selection))
13825 (org-overlay-display ov string face)
13826 (push ov org-columns-overlays)
13827 ov))
13829 (defun org-columns-display-here (&optional props)
13830 "Overlay the current line with column display."
13831 (interactive)
13832 (let* ((fmt org-columns-current-fmt-compiled)
13833 (beg (point-at-bol))
13834 (color (list :foreground
13835 (face-attribute
13836 (or (get-text-property beg 'face) 'default)
13837 :foreground)))
13838 props pom property ass width f string ov column)
13839 ;; Check if the entry is in another buffer.
13840 (unless props
13841 (if (eq major-mode 'org-agenda-mode)
13842 (setq pom (or (get-text-property (point) 'org-hd-marker)
13843 (get-text-property (point) 'org-marker))
13844 props (if pom (org-entry-properties pom) nil))
13845 (setq props (org-entry-properties nil))))
13846 ;; Walk the format
13847 (while (setq column (pop fmt))
13848 (setq property (car column)
13849 ass (if (equal property "ITEM")
13850 (cons "ITEM"
13851 (save-match-data
13852 (org-no-properties
13853 (org-remove-tabs
13854 (buffer-substring-no-properties
13855 (point-at-bol) (point-at-eol))))))
13856 (assoc property props))
13857 width (or (cdr (assoc property org-columns-current-maxwidths))
13858 (nth 2 column))
13859 f (format "%%-%d.%ds | " width width)
13860 string (format f (or (cdr ass) "")))
13861 ;; Create the overlay
13862 (org-unmodified
13863 (setq ov (org-columns-new-overlay
13864 beg (setq beg (1+ beg)) string
13865 (list color 'org-column)))
13866 ;;; (list (get-text-property (point-at-bol) 'face) 'org-column)))
13867 (org-overlay-put ov 'keymap org-columns-map)
13868 (org-overlay-put ov 'org-columns-key property)
13869 (org-overlay-put ov 'org-columns-value (cdr ass))
13870 (org-overlay-put ov 'org-columns-pom pom)
13871 (org-overlay-put ov 'org-columns-format f))
13872 (if (or (not (char-after beg))
13873 (equal (char-after beg) ?\n))
13874 (let ((inhibit-read-only t))
13875 (save-excursion
13876 (goto-char beg)
13877 (insert " ")))))
13878 ;; Make the rest of the line disappear.
13879 (org-unmodified
13880 (setq ov (org-columns-new-overlay beg (point-at-eol)))
13881 (org-overlay-put ov 'invisible t)
13882 (org-overlay-put ov 'keymap org-columns-map)
13883 (push ov org-columns-overlays)
13884 (setq ov (org-make-overlay (1- (point-at-eol)) (1+ (point-at-eol))))
13885 (org-overlay-put ov 'keymap org-columns-map)
13886 (push ov org-columns-overlays)
13887 (let ((inhibit-read-only t))
13888 (put-text-property (1- (point-at-bol))
13889 (min (point-max) (1+ (point-at-eol)))
13890 'read-only "Type `e' to edit property")))))
13892 (defvar org-previous-header-line-format nil
13893 "The header line format before column view was turned on.")
13894 (defvar org-columns-inhibit-recalculation nil
13895 "Inhibit recomputing of columns on column view startup.")
13897 (defvar header-line-format)
13898 (defun org-columns-display-here-title ()
13899 "Overlay the newline before the current line with the table title."
13900 (interactive)
13901 (let ((fmt org-columns-current-fmt-compiled)
13902 string (title "")
13903 property width f column str)
13904 (while (setq column (pop fmt))
13905 (setq property (car column)
13906 str (or (nth 1 column) property)
13907 width (or (cdr (assoc property org-columns-current-maxwidths))
13908 (nth 2 column))
13909 f (format "%%-%d.%ds | " width width)
13910 string (format f str)
13911 title (concat title string)))
13912 (setq title (concat
13913 (org-add-props " " nil 'display '(space :align-to 0))
13914 (org-add-props title nil 'face '(:weight bold :underline t))))
13915 (org-set-local 'org-previous-header-line-format header-line-format)
13916 (setq header-line-format title)))
13918 (defun org-columns-remove-overlays ()
13919 "Remove all currently active column overlays."
13920 (interactive)
13921 (when (marker-buffer org-columns-begin-marker)
13922 (with-current-buffer (marker-buffer org-columns-begin-marker)
13923 (when (local-variable-p 'org-previous-header-line-format)
13924 (setq header-line-format org-previous-header-line-format)
13925 (kill-local-variable 'org-previous-header-line-format))
13926 (move-marker org-columns-begin-marker nil)
13927 (move-marker org-columns-top-level-marker nil)
13928 (org-unmodified
13929 (mapc 'org-delete-overlay org-columns-overlays)
13930 (setq org-columns-overlays nil)
13931 (let ((inhibit-read-only t))
13932 (remove-text-properties (point-min) (point-max) '(read-only t)))))))
13934 (defun org-columns-show-value ()
13935 "Show the full value of the property."
13936 (interactive)
13937 (let ((value (get-char-property (point) 'org-columns-value)))
13938 (message "Value is: %s" (or value ""))))
13940 (defun org-columns-quit ()
13941 "Remove the column overlays and in this way exit column editing."
13942 (interactive)
13943 (org-unmodified
13944 (org-columns-remove-overlays)
13945 (let ((inhibit-read-only t))
13946 ;; FIXME: is this safe???
13947 ;; or are there other reasons why there may be a read-only property????
13948 (remove-text-properties (point-min) (point-max) '(read-only t))))
13949 (when (eq major-mode 'org-agenda-mode)
13950 (message "Modification not yet reflected in Agenda buffer, use `r' to refresh")))
13952 (defun org-columns-edit-value ()
13953 "Edit the value of the property at point in column view.
13954 Where possible, use the standard interface for changing this line."
13955 (interactive)
13956 (let* ((col (current-column))
13957 (key (get-char-property (point) 'org-columns-key))
13958 (value (get-char-property (point) 'org-columns-value))
13959 (bol (point-at-bol)) (eol (point-at-eol))
13960 (pom (or (get-text-property bol 'org-hd-marker)
13961 (point))) ; keep despite of compiler waring
13962 (line-overlays
13963 (delq nil (mapcar (lambda (x)
13964 (and (eq (overlay-buffer x) (current-buffer))
13965 (>= (overlay-start x) bol)
13966 (<= (overlay-start x) eol)
13968 org-columns-overlays)))
13969 nval eval allowed)
13970 (when (equal key "ITEM")
13971 (error "Cannot edit item headline from here"))
13973 (cond
13974 ((equal key "TODO")
13975 (setq eval '(org-with-point-at pom
13976 (let ((current-prefix-arg '(4))) (org-todo '(4))))))
13977 ((equal key "PRIORITY")
13978 (setq eval '(org-with-point-at pom
13979 (call-interactively 'org-priority))))
13980 ((equal key "TAGS")
13981 (setq eval '(org-with-point-at pom
13982 (let ((org-fast-tag-selection-single-key
13983 (if (eq org-fast-tag-selection-single-key 'expert)
13984 t org-fast-tag-selection-single-key)))
13985 (call-interactively 'org-set-tags)))))
13986 ((equal key "DEADLINE")
13987 (setq eval '(org-with-point-at pom
13988 (call-interactively 'org-deadline))))
13989 ((equal key "SCHEDULED")
13990 (setq eval '(org-with-point-at pom
13991 (call-interactively 'org-deadline))))
13993 (setq allowed (org-property-get-allowed-values pom key 'table))
13994 (if allowed
13995 (setq nval (completing-read "Value: " allowed nil t))
13996 (setq nval (read-string "Edit: " value)))
13997 (setq nval (org-trim nval))
13998 (when (not (equal nval value))
13999 (setq eval '(org-entry-put pom key nval)))))
14000 (when eval
14001 (let ((inhibit-read-only t))
14002 (remove-text-properties (1- bol) eol '(read-only t))
14003 (unwind-protect
14004 (progn
14005 (setq org-columns-overlays
14006 (org-delete-all line-overlays org-columns-overlays))
14007 (mapc 'org-delete-overlay line-overlays)
14008 (org-columns-eval eval))
14009 (org-columns-display-here))))
14010 (move-to-column col)
14011 (if (nth 3 (assoc key org-columns-current-fmt-compiled))
14012 (org-columns-update key))))
14014 (defun org-columns-edit-allowed ()
14015 "Edit the list of allowed values for the current property."
14016 (interactive)
14017 (let* ((col (current-column))
14018 (key (get-char-property (point) 'org-columns-key))
14019 (key1 (concat key "_ALL"))
14020 (value (get-char-property (point) 'org-columns-value))
14021 (allowed (org-entry-get (point) key1 t))
14022 nval)
14023 (setq nval (read-string "Allowed: " allowed))
14024 (org-entry-put
14025 (cond ((marker-position org-entry-property-inherited-from)
14026 org-entry-property-inherited-from)
14027 ((marker-position org-columns-top-level-marker)
14028 org-columns-top-level-marker))
14029 key1 nval)))
14031 (defun org-columns-eval (form)
14032 (let (hidep)
14033 (save-excursion
14034 (beginning-of-line 1)
14035 (next-line 1)
14036 (setq hidep (org-on-heading-p 1)))
14037 (eval form)
14038 (and hidep (hide-entry))))
14040 (defun org-columns-previous-allowed-value ()
14041 "Switch to the previous allowed value for this column."
14042 (interactive)
14043 (org-columns-next-allowed-value t))
14045 (defun org-columns-next-allowed-value (&optional previous)
14046 "Switch to the next allowed value for this column."
14047 (interactive)
14048 (let* ((col (current-column))
14049 (key (get-char-property (point) 'org-columns-key))
14050 (value (get-char-property (point) 'org-columns-value))
14051 (bol (point-at-bol)) (eol (point-at-eol))
14052 (pom (or (get-text-property bol 'org-hd-marker)
14053 (point))) ; keep despite of compiler waring
14054 (line-overlays
14055 (delq nil (mapcar (lambda (x)
14056 (and (eq (overlay-buffer x) (current-buffer))
14057 (>= (overlay-start x) bol)
14058 (<= (overlay-start x) eol)
14060 org-columns-overlays)))
14061 (allowed (or (org-property-get-allowed-values pom key)
14062 (and (equal
14063 (nth 4 (assoc key org-columns-current-fmt-compiled))
14064 'checkbox) '("[ ]" "[X]"))))
14065 nval)
14066 (when (equal key "ITEM")
14067 (error "Cannot edit item headline from here"))
14068 (unless allowed
14069 (error "Allowed values for this property have not been defined"))
14070 (if previous (setq allowed (reverse allowed)))
14071 (if (member value allowed)
14072 (setq nval (car (cdr (member value allowed)))))
14073 (setq nval (or nval (car allowed)))
14074 (if (equal nval value)
14075 (error "Only one allowed value for this property"))
14076 (let ((inhibit-read-only t))
14077 (remove-text-properties (1- bol) eol '(read-only t))
14078 (unwind-protect
14079 (progn
14080 (setq org-columns-overlays
14081 (org-delete-all line-overlays org-columns-overlays))
14082 (mapc 'org-delete-overlay line-overlays)
14083 (org-columns-eval '(org-entry-put pom key nval)))
14084 (org-columns-display-here)))
14085 (move-to-column col)
14086 (if (nth 3 (assoc key org-columns-current-fmt-compiled))
14087 (org-columns-update key))))
14089 (defun org-verify-version (task)
14090 (cond
14091 ((eq task 'columns)
14092 (if (or (featurep 'xemacs)
14093 (< emacs-major-version 22))
14094 (error "Emacs 22 is required for the columns feature")))))
14096 (defun org-columns ()
14097 "Turn on column view on an org-mode file."
14098 (interactive)
14099 (org-verify-version 'columns)
14100 (org-columns-remove-overlays)
14101 (move-marker org-columns-begin-marker (point))
14102 (let (beg end fmt cache maxwidths)
14103 (when (condition-case nil (org-back-to-heading) (error nil))
14104 (move-marker org-entry-property-inherited-from nil)
14105 (setq fmt (org-entry-get nil "COLUMNS" t)))
14106 (setq fmt (or fmt org-columns-default-format))
14107 (org-set-local 'org-columns-current-fmt fmt)
14108 (org-columns-compile-format fmt)
14109 (save-excursion
14110 (if (marker-position org-entry-property-inherited-from)
14111 (goto-char org-entry-property-inherited-from))
14112 (setq beg (point))
14113 (move-marker org-columns-top-level-marker (point))
14114 (unless org-columns-inhibit-recalculation
14115 (org-columns-compute-all))
14116 (setq end (or (condition-case nil (org-end-of-subtree t t) (error nil))
14117 (point-max)))
14118 (goto-char beg)
14119 ;; Get and cache the properties
14120 (while (re-search-forward (concat "^" outline-regexp) end t)
14121 (push (cons (org-current-line) (org-entry-properties)) cache))
14122 (when cache
14123 (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
14124 (org-set-local 'org-columns-current-maxwidths maxwidths)
14125 (goto-line (car (org-last cache)))
14126 (org-columns-display-here-title)
14127 (mapc (lambda (x)
14128 (goto-line (car x))
14129 (org-columns-display-here (cdr x)))
14130 cache)))))
14132 (defun org-columns-new (&optional prop title width op fmt)
14133 "Insert a new column, to the leeft o the current column."
14134 (interactive)
14135 (let ((editp (and prop (assoc prop org-columns-current-fmt-compiled)))
14136 cell)
14137 (setq prop (completing-read
14138 "Property: " (mapcar 'list (org-buffer-property-keys t))
14139 nil nil prop))
14140 (setq title (read-string (concat "Column title [" prop "]: ") (or title prop)))
14141 (setq width (read-string "Column width: " (if width (number-to-string width))))
14142 (if (string-match "\\S-" width)
14143 (setq width (string-to-number width))
14144 (setq width nil))
14145 (setq fmt (completing-read "Summary [none]: "
14146 '(("none") ("add_numbers") ("add_times") ("checkbox"))
14147 nil t))
14148 (if (string-match "\\S-" fmt)
14149 (setq fmt (intern fmt))
14150 (setq fmt nil))
14151 (if (eq fmt 'none) (setq fmt nil))
14152 (if editp
14153 (progn
14154 (setcar editp prop)
14155 (setcdr editp (list title width nil fmt)))
14156 (setq cell (nthcdr (1- (current-column))
14157 org-columns-current-fmt-compiled))
14158 (setcdr cell (cons (list prop title width nil fmt)
14159 (cdr cell))))
14160 (org-columns-store-format)
14161 (org-columns-redo)))
14163 (defun org-columns-delete ()
14164 "Delete the column at point from columns view."
14165 (interactive)
14166 (let* ((n (current-column))
14167 (title (nth 1 (nth n org-columns-current-fmt-compiled))))
14168 (when (y-or-n-p
14169 (format "Are you sure you want to remove column \"%s\"? " title))
14170 (setq org-columns-current-fmt-compiled
14171 (delq (nth n org-columns-current-fmt-compiled)
14172 org-columns-current-fmt-compiled))
14173 (org-columns-store-format)
14174 (org-columns-redo)
14175 (if (>= (current-column) (length org-columns-current-fmt-compiled))
14176 (backward-char 1)))))
14178 (defun org-columns-edit-attributes ()
14179 "Edit the attributes of the current column."
14180 (interactive)
14181 (let* ((n (current-column))
14182 (info (nth n org-columns-current-fmt-compiled)))
14183 (apply 'org-columns-new info)))
14185 (defun org-columns-widen (arg)
14186 "Make the column wider by ARG characters."
14187 (interactive "p")
14188 (let* ((n (current-column))
14189 (entry (nth n org-columns-current-fmt-compiled))
14190 (width (or (nth 2 entry)
14191 (cdr (assoc (car entry) org-columns-current-maxwidths)))))
14192 (setq width (max 1 (+ width arg)))
14193 (setcar (nthcdr 2 entry) width)
14194 (org-columns-store-format)
14195 (org-columns-redo)))
14197 (defun org-columns-narrow (arg)
14198 "Make the column nrrower by ARG characters."
14199 (interactive "p")
14200 (org-columns-widen (- arg)))
14202 (defun org-columns-move-right ()
14203 "Swap this column with the one to the right."
14204 (interactive)
14205 (let* ((n (current-column))
14206 (cell (nthcdr n org-columns-current-fmt-compiled))
14208 (when (>= n (1- (length org-columns-current-fmt-compiled)))
14209 (error "Cannot shift this column further to the right"))
14210 (setq e (car cell))
14211 (setcar cell (car (cdr cell)))
14212 (setcdr cell (cons e (cdr (cdr cell))))
14213 (org-columns-store-format)
14214 (org-columns-redo)
14215 (forward-char 1)))
14217 (defun org-columns-move-left ()
14218 "Swap this column with the one to the left."
14219 (interactive)
14220 (let* ((n (current-column)))
14221 (when (= n 0)
14222 (error "Cannot shift this column further to the left"))
14223 (backward-char 1)
14224 (org-columns-move-right)
14225 (backward-char 1)))
14227 (defun org-columns-store-format ()
14228 "Store the text version of the current columns format in appropriate place.
14229 This is either in the COLUMNS property of the node starting the current column
14230 display, or in the #+COLUMNS line of the current buffer."
14231 (let (fmt)
14232 (setq fmt (org-columns-uncompile-format org-columns-current-fmt-compiled))
14233 (if (marker-position org-columns-top-level-marker)
14234 (save-excursion
14235 (goto-char org-columns-top-level-marker)
14236 (if (org-entry-get nil "COLUMNS")
14237 (org-entry-put nil "COLUMNS" fmt)
14238 (goto-char (point-min))
14239 (while (re-search-forward "^#\\+COLUMNS:.*" nil t)
14240 (replace-match (concat "#+COLUMNS: " fmt t t)))))
14241 (setq org-columns-current-fmt fmt))))
14243 (defvar org-overriding-columns-format nil
14244 "When set, overrides any other definition.")
14245 (defvar org-agenda-view-columns-initially nil
14246 "When set, switch to columns view immediately after creating the agenda.")
14248 (defun org-agenda-columns ()
14249 "Turn on column view in the agenda."
14250 (interactive)
14251 (org-verify-version 'columns)
14252 (org-columns-remove-overlays)
14253 (move-marker org-columns-begin-marker (point))
14254 (let (fmt cache maxwidths m)
14255 (cond
14256 ((and (local-variable-p 'org-overriding-columns-format)
14257 org-overriding-columns-format)
14258 (setq fmt org-overriding-columns-format))
14259 ((setq m (get-text-property (point-at-bol) 'org-hd-marker))
14260 (setq fmt (org-entry-get m "COLUMNS" t)))
14261 ((and (boundp 'org-columns-current-fmt)
14262 (local-variable-p 'org-columns-current-fmt)
14263 org-columns-current-fmt)
14264 (setq fmt org-columns-current-fmt))
14265 ((setq m (next-single-property-change (point-min) 'org-hd-marker))
14266 (setq m (get-text-property m 'org-hd-marker))
14267 (setq fmt (org-entry-get m "COLUMNS" t))))
14268 (setq fmt (or fmt org-columns-default-format))
14269 (org-set-local 'org-columns-current-fmt fmt)
14270 (org-columns-compile-format fmt)
14271 (save-excursion
14272 ;; Get and cache the properties
14273 (goto-char (point-min))
14274 (while (not (eobp))
14275 (when (setq m (or (get-text-property (point) 'org-hd-marker)
14276 (get-text-property (point) 'org-marker)))
14277 (push (cons (org-current-line) (org-entry-properties m)) cache))
14278 (beginning-of-line 2))
14279 (when cache
14280 (setq maxwidths (org-columns-get-autowidth-alist fmt cache))
14281 (org-set-local 'org-columns-current-maxwidths maxwidths)
14282 (goto-line (car (org-last cache)))
14283 (org-columns-display-here-title)
14284 (mapc (lambda (x)
14285 (goto-line (car x))
14286 (org-columns-display-here (cdr x)))
14287 cache)))))
14289 (defun org-columns-get-autowidth-alist (s cache)
14290 "Derive the maximum column widths from the format and the cache."
14291 (let ((start 0) rtn)
14292 (while (string-match "%\\([a-zA-Z]\\S-*\\)" s start)
14293 (push (cons (match-string 1 s) 1) rtn)
14294 (setq start (match-end 0)))
14295 (mapc (lambda (x)
14296 (setcdr x (apply 'max
14297 (mapcar
14298 (lambda (y)
14299 (length (or (cdr (assoc (car x) (cdr y))) " ")))
14300 cache))))
14301 rtn)
14302 rtn))
14304 (defun org-columns-compute-all ()
14305 "Compute all columns that have operators defined."
14306 (remove-text-properties (point-min) (point-max) '(org-summaries t))
14307 (let ((columns org-columns-current-fmt-compiled) col)
14308 (while (setq col (pop columns))
14309 (when (nth 3 col)
14310 (save-excursion
14311 (org-columns-compute (car col)))))))
14313 (defun org-columns-update (property)
14314 "Recompute PROPERTY, and update the columns display for it."
14315 (org-columns-compute property)
14316 (let (fmt val pos)
14317 (save-excursion
14318 (mapc (lambda (ov)
14319 (when (equal (org-overlay-get ov 'org-columns-key) property)
14320 (setq pos (org-overlay-start ov))
14321 (goto-char pos)
14322 (when (setq val (cdr (assoc property
14323 (get-text-property (point-at-bol) 'org-summaries))))
14324 (setq fmt (org-overlay-get ov 'org-columns-format))
14325 (org-overlay-put ov 'display (format fmt val)))))
14326 org-columns-overlays))))
14328 (defun org-columns-compute (property)
14329 "Sum the values of property PROPERTY hierarchically, for the entire buffer."
14330 (interactive)
14331 (let* ((re (concat "^" outline-regexp))
14332 (lmax 30) ; Does anyone use deeper levels???
14333 (lsum (make-vector lmax 0))
14334 (level 0)
14335 (ass (assoc property org-columns-current-fmt-compiled))
14336 (format (nth 4 ass))
14337 (beg org-columns-top-level-marker)
14338 last-level val end sumpos sum-alist sum str)
14339 (save-excursion
14340 ;; Find the region to compute
14341 (goto-char beg)
14342 (setq end (condition-case nil (org-end-of-subtree t) (error (point-max))))
14343 (goto-char end)
14344 ;; Walk the tree from the back and do the computations
14345 (while (re-search-backward re beg t)
14346 (setq sumpos (match-beginning 0)
14347 last-level level
14348 level (org-outline-level)
14349 val (org-entry-get nil property))
14350 (cond
14351 ((< level last-level)
14352 ;; put the sum of lower levels here as a property
14353 (setq sum (aref lsum last-level)
14354 str (org-column-number-to-string sum format)
14355 sum-alist (get-text-property sumpos 'org-summaries))
14356 (if (assoc property sum-alist)
14357 (setcdr (assoc property sum-alist) str)
14358 (push (cons property str) sum-alist)
14359 (add-text-properties sumpos (1+ sumpos)
14360 (list 'org-summaries sum-alist)))
14361 (when val
14362 (org-entry-put nil property str))
14363 ;; add current to current level accumulator
14364 (aset lsum level (+ (aref lsum level) sum))
14365 ;; clear accumulators for deeper levels
14366 (loop for l from (1+ level) to (1- lmax) do (aset lsum l 0)))
14367 ((>= level last-level)
14368 ;; add what we have here to the accumulator for this level
14369 (aset lsum level (+ (aref lsum level)
14370 (org-column-string-to-number (or val "0") format))))
14371 (t (error "This should not happen")))))))
14373 (defun org-columns-redo ()
14374 "Construct the column display again."
14375 (interactive)
14376 (message "Recomputing columns...")
14377 (save-excursion
14378 (if (marker-position org-columns-begin-marker)
14379 (goto-char org-columns-begin-marker))
14380 (org-columns-remove-overlays)
14381 (if (org-mode-p)
14382 (call-interactively 'org-columns)
14383 (call-interactively 'org-agenda-columns)))
14384 (message "Recomputing columns...done"))
14386 (defun org-columns-not-in-agenda ()
14387 (if (eq major-mode 'org-agenda-mode)
14388 (error "This command is only allowed in Org-mode buffers")))
14391 (defun org-string-to-number (s)
14392 "Convert string to number, and interpret hh:mm:ss."
14393 (if (not (string-match ":" s))
14394 (string-to-number s)
14395 (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
14396 (while l
14397 (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
14398 sum)))
14400 (defun org-column-number-to-string (n fmt)
14401 "Convert a computed column number to a string value, according to FMT."
14402 (cond
14403 ((eq fmt 'add_times)
14404 (let* ((h (floor n)) (m (floor (+ 0.5 (* 60 (- n h))))))
14405 (format "%d:%02d" h m)))
14406 ((eq fmt 'checkbox)
14407 (cond ((= n (floor n)) "[X]")
14408 ((> n 1.) "[-]")
14409 (t "[ ]")))
14410 (t (number-to-string n))))
14412 (defun org-column-string-to-number (s fmt)
14413 "Convert a column value to a number that can be used for column computing."
14414 (cond
14415 ((string-match ":" s)
14416 (let ((l (nreverse (org-split-string s ":"))) (sum 0.0))
14417 (while l
14418 (setq sum (+ (string-to-number (pop l)) (/ sum 60))))
14419 sum))
14420 ((eq fmt 'checkbox)
14421 (if (equal s "[X]") 1. 0.000001))
14422 (t (string-to-number s))))
14424 (defun org-columns-uncompile-format (cfmt)
14425 "Turn the compiled columns format back into a string representation."
14426 (let ((rtn "") e s prop title op width fmt)
14427 (while (setq e (pop cfmt))
14428 (setq prop (car e)
14429 title (nth 1 e)
14430 width (nth 2 e)
14431 op (nth 3 e)
14432 fmt (nth 4 e))
14433 (cond
14434 ((eq fmt 'add_times) (setq op ":"))
14435 ((eq fmt 'checkbox) (setq op "X"))
14436 ((eq fmt 'add_numbers) (setq op "+")))
14437 (if (equal title prop) (setq title nil))
14438 (setq s (concat "%" (if width (number-to-string width))
14439 prop
14440 (if title (concat "(" title ")"))
14441 (if op (concat "{" op "}"))))
14442 (setq rtn (concat rtn " " s)))
14443 (org-trim rtn)))
14445 (defun org-columns-compile-format (fmt)
14446 "FIXME"
14447 (let ((start 0) width prop title op f)
14448 (setq org-columns-current-fmt-compiled nil)
14449 (while (string-match "%\\([0-9]+\\)?\\([a-zA-Z_0-9]+\\)\\(?:(\\([^)]+\\))\\)?\\(?:{\\([^}]+\\)}\\)?\\s-*"
14450 fmt start)
14451 (setq start (match-end 0)
14452 width (match-string 1 fmt)
14453 prop (match-string 2 fmt)
14454 title (or (match-string 3 fmt) prop)
14455 op (match-string 4 fmt)
14456 f nil)
14457 (if width (setq width (string-to-number width)))
14458 (cond
14459 ((equal op "+") (setq f 'add_numbers))
14460 ((equal op ":") (setq f 'add_times))
14461 ((equal op "X") (setq f 'checkbox)))
14462 (push (list prop title width op f) org-columns-current-fmt-compiled))
14463 (setq org-columns-current-fmt-compiled
14464 (nreverse org-columns-current-fmt-compiled))))
14466 ;;;; Timestamps
14468 (defvar org-last-changed-timestamp nil)
14469 (defvar org-time-was-given) ; dynamically scoped parameter
14470 (defvar org-end-time-was-given) ; dynamically scoped parameter
14471 (defvar org-ts-what) ; dynamically scoped parameter
14473 (defun org-time-stamp (arg)
14474 "Prompt for a date/time and insert a time stamp.
14475 If the user specifies a time like HH:MM, or if this command is called
14476 with a prefix argument, the time stamp will contain date and time.
14477 Otherwise, only the date will be included. All parts of a date not
14478 specified by the user will be filled in from the current date/time.
14479 So if you press just return without typing anything, the time stamp
14480 will represent the current date/time. If there is already a timestamp
14481 at the cursor, it will be modified."
14482 (interactive "P")
14483 (let (org-time-was-given org-end-time-was-given time)
14484 (cond
14485 ((and (org-at-timestamp-p)
14486 (eq last-command 'org-time-stamp)
14487 (eq this-command 'org-time-stamp))
14488 (insert "--")
14489 (setq time (let ((this-command this-command))
14490 (org-read-date arg 'totime)))
14491 (org-insert-time-stamp time (or org-time-was-given arg)))
14492 ((org-at-timestamp-p)
14493 (setq time (let ((this-command this-command))
14494 (org-read-date arg 'totime)))
14495 (when (org-at-timestamp-p) ; just to get the match data
14496 (replace-match "")
14497 (setq org-last-changed-timestamp
14498 (org-insert-time-stamp
14499 time (or org-time-was-given arg)
14500 nil nil nil (list org-end-time-was-given))))
14501 (message "Timestamp updated"))
14503 (setq time (let ((this-command this-command))
14504 (org-read-date arg 'totime)))
14505 (org-insert-time-stamp time (or org-time-was-given arg)
14506 nil nil nil (list org-end-time-was-given))))))
14508 (defun org-time-stamp-inactive (&optional arg)
14509 "Insert an inactive time stamp.
14510 An inactive time stamp is enclosed in square brackets instead of angle
14511 brackets. It is inactive in the sense that it does not trigger agenda entries,
14512 does not link to the calendar and cannot be changed with the S-cursor keys.
14513 So these are more for recording a certain time/date."
14514 (interactive "P")
14515 (let (org-time-was-given org-end-time-was-given time)
14516 (setq time (org-read-date arg 'totime))
14517 (org-insert-time-stamp time (or org-time-was-given arg) 'inactive
14518 nil nil (list org-end-time-was-given))))
14520 (defvar org-date-ovl (org-make-overlay 1 1))
14521 (org-overlay-put org-date-ovl 'face 'org-warning)
14522 (org-detach-overlay org-date-ovl)
14524 (defvar org-ans1) ; dynamically scoped parameter
14525 (defvar org-ans2) ; dynamically scoped parameter
14527 (defvar org-plain-time-of-day-regexp) ; defined below
14528 (defun org-read-date (&optional with-time to-time from-string prompt)
14529 "Read a date and make things smooth for the user.
14530 The prompt will suggest to enter an ISO date, but you can also enter anything
14531 which will at least partially be understood by `parse-time-string'.
14532 Unrecognized parts of the date will default to the current day, month, year,
14533 hour and minute. For example,
14534 3-2-5 --> 2003-02-05
14535 feb 15 --> currentyear-02-15
14536 sep 12 9 --> 2009-09-12
14537 12:45 --> today 12:45
14538 22 sept 0:34 --> currentyear-09-22 0:34
14539 12 --> currentyear-currentmonth-12
14540 Fri --> nearest Friday (today or later)
14541 +4 --> four days from today (only if +N is the only thing given)
14542 etc.
14543 The function understands only English month and weekday abbreviations,
14544 but this can be configured with the variables `parse-time-months' and
14545 `parse-time-weekdays'.
14547 While prompting, a calendar is popped up - you can also select the
14548 date with the mouse (button 1). The calendar shows a period of three
14549 months. To scroll it to other months, use the keys `>' and `<'.
14550 If you don't like the calendar, turn it off with
14551 \(setq org-popup-calendar-for-date-prompt nil)
14553 With optional argument TO-TIME, the date will immediately be converted
14554 to an internal time.
14555 With an optional argument WITH-TIME, the prompt will suggest to also
14556 insert a time. Note that when WITH-TIME is not set, you can still
14557 enter a time, and this function will inform the calling routine about
14558 this change. The calling routine may then choose to change the format
14559 used to insert the time stamp into the buffer to include the time."
14560 (require 'parse-time)
14561 (let* ((org-time-stamp-rounding-minutes
14562 (if (equal with-time '(16)) 0 org-time-stamp-rounding-minutes))
14563 (ct (org-current-time))
14564 (default-time
14565 ;; Default time is either today, or, when entering a range,
14566 ;; the range start.
14567 (if (save-excursion
14568 (re-search-backward
14569 (concat org-ts-regexp "--?-?\\=") ; 1-3 minuses
14570 (- (point) 20) t))
14571 (apply
14572 'encode-time
14573 (mapcar (lambda(x) (or x 0))
14574 (parse-time-string (match-string 1))))
14575 ct))
14576 (calendar-move-hook nil)
14577 (view-diary-entries-initially nil)
14578 (view-calendar-holidays-initially nil)
14579 (timestr (format-time-string
14580 (if with-time "%Y-%m-%d %H:%M" "%Y-%m-%d") default-time))
14581 (prompt (concat (if prompt (concat prompt " ") "")
14582 (format "Date and/or time (default [%s]): " timestr)))
14583 ans (org-ans0 "") org-ans1 org-ans2 (deltadays 0)
14584 second minute hour day month year tl wday wday1 pm)
14586 (cond
14587 (from-string (setq ans from-string))
14588 (org-popup-calendar-for-date-prompt
14589 (save-excursion
14590 (save-window-excursion
14591 (calendar)
14592 (calendar-forward-day (- (time-to-days default-time)
14593 (calendar-absolute-from-gregorian
14594 (calendar-current-date))))
14595 (org-eval-in-calendar nil t)
14596 (let* ((old-map (current-local-map))
14597 (map (copy-keymap calendar-mode-map))
14598 (minibuffer-local-map (copy-keymap minibuffer-local-map)))
14599 (org-defkey map (kbd "RET") 'org-calendar-select)
14600 (org-defkey map (if (featurep 'xemacs) [button1] [mouse-1])
14601 'org-calendar-select-mouse)
14602 (org-defkey map (if (featurep 'xemacs) [button2] [mouse-2])
14603 'org-calendar-select-mouse)
14604 (org-defkey minibuffer-local-map [(meta shift left)]
14605 (lambda () (interactive)
14606 (org-eval-in-calendar '(calendar-backward-month 1))))
14607 (org-defkey minibuffer-local-map [(meta shift right)]
14608 (lambda () (interactive)
14609 (org-eval-in-calendar '(calendar-forward-month 1))))
14610 (org-defkey minibuffer-local-map [(shift up)]
14611 (lambda () (interactive)
14612 (org-eval-in-calendar '(calendar-backward-week 1))))
14613 (org-defkey minibuffer-local-map [(shift down)]
14614 (lambda () (interactive)
14615 (org-eval-in-calendar '(calendar-forward-week 1))))
14616 (org-defkey minibuffer-local-map [(shift left)]
14617 (lambda () (interactive)
14618 (org-eval-in-calendar '(calendar-backward-day 1))))
14619 (org-defkey minibuffer-local-map [(shift right)]
14620 (lambda () (interactive)
14621 (org-eval-in-calendar '(calendar-forward-day 1))))
14622 (org-defkey minibuffer-local-map ">"
14623 (lambda () (interactive)
14624 (org-eval-in-calendar '(scroll-calendar-left 1))))
14625 (org-defkey minibuffer-local-map "<"
14626 (lambda () (interactive)
14627 (org-eval-in-calendar '(scroll-calendar-right 1))))
14628 (unwind-protect
14629 (progn
14630 (use-local-map map)
14631 (setq org-ans0 (read-string prompt "" nil nil))
14632 ;; org-ans0: from prompt
14633 ;; org-ans1: from mouse click
14634 ;; org-ans2: from calendar motion
14635 (setq ans (concat org-ans0 " " (or org-ans1 org-ans2))))
14636 (use-local-map old-map))))))
14637 (t ; Naked prompt only
14638 (setq ans (read-string prompt "" nil timestr))))
14639 (org-detach-overlay org-date-ovl)
14641 (if (string-match "^[ \t]*[-+][0-9]+[ \t]*$" org-ans0)
14642 (setq deltadays (string-to-number ans) ans ""))
14644 ;; Help matching ISO dates with single digit month ot day, like 2006-8-11.
14645 (when (string-match
14646 "^ *\\(\\([0-9]+\\)-\\)?\\([0-1]?[0-9]\\)-\\([0-3]?[0-9]\\)\\([^-0-9]\\|$\\)" ans)
14647 (setq year (if (match-end 2)
14648 (string-to-number (match-string 2 ans))
14649 (string-to-number (format-time-string "%Y")))
14650 month (string-to-number (match-string 3 ans))
14651 day (string-to-number (match-string 4 ans)))
14652 (if (< year 100) (setq year (+ 2000 year)))
14653 (setq ans (replace-match (format "%04d-%02d-%02d\\5" year month day)
14654 t nil ans)))
14655 ;; Help matching am/pm times, because `parse-time-string' does not do that.
14656 ;; If there is a time with am/pm, and *no* time without it, we convert
14657 ;; so that matching will be successful.
14658 ;; FIXME: make this replace twice, so that we catch the end time.
14659 (when (and (not (string-match "[012]?[0-9]:[0-9][0-9]\\([ \t\n]\\|$\\)" ans))
14660 (string-match "\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\(am\\|AM\\|pm\\|PM\\)\\>" ans))
14661 (setq hour (string-to-number (match-string 1 ans))
14662 minute (if (match-end 3) (string-to-number (match-string 3 ans)) 0)
14663 pm (equal ?p (string-to-char (downcase (match-string 4 ans)))))
14664 (if (and (= hour 12) (not pm))
14665 (setq hour 0)
14666 (if (and pm (< hour 12)) (setq hour (+ 12 hour))))
14667 (setq ans (replace-match (format "%02d:%02d" hour minute) t t ans)))
14669 ;; Check if there is a time range
14670 (when (and (boundp 'org-end-time-was-given)
14671 (string-match org-plain-time-of-day-regexp ans)
14672 (match-end 8))
14673 (setq org-end-time-was-given (match-string 8 ans))
14674 (setq ans (concat (substring ans 0 (match-beginning 7))
14675 (substring ans (match-end 7)))))
14677 (setq tl (parse-time-string ans)
14678 year (or (nth 5 tl) (string-to-number (format-time-string "%Y" ct)))
14679 month (or (nth 4 tl) (string-to-number (format-time-string "%m" ct)))
14680 day (or (nth 3 tl) (string-to-number (format-time-string "%d" ct)))
14681 hour (or (nth 2 tl) (string-to-number (format-time-string "%H" ct)))
14682 minute (or (nth 1 tl) (string-to-number (format-time-string "%M" ct)))
14683 second (or (nth 0 tl) 0)
14684 wday (nth 6 tl))
14685 (setq day (+ day deltadays))
14686 (when (and wday (not (nth 3 tl)))
14687 ;; Weekday was given, but no day, so pick that day in the week
14688 ;; on or after the derived date.
14689 (setq wday1 (nth 6 (decode-time (encode-time 0 0 0 day month year))))
14690 (unless (equal wday wday1)
14691 (setq day (+ day (% (- wday wday1 -7) 7)))))
14692 (if (and (boundp 'org-time-was-given)
14693 (nth 2 tl))
14694 (setq org-time-was-given t))
14695 (if (< year 100) (setq year (+ 2000 year)))
14696 (if to-time
14697 (encode-time second minute hour day month year)
14698 (if (or (nth 1 tl) (nth 2 tl))
14699 (format "%04d-%02d-%02d %02d:%02d" year month day hour minute)
14700 (format "%04d-%02d-%02d" year month day)))))
14702 (defun org-eval-in-calendar (form &optional keepdate)
14703 "Eval FORM in the calendar window and return to current window.
14704 Also, store the cursor date in variable org-ans2."
14705 (let ((sw (selected-window)))
14706 (select-window (get-buffer-window "*Calendar*"))
14707 (eval form)
14708 (when (and (not keepdate) (calendar-cursor-to-date))
14709 (let* ((date (calendar-cursor-to-date))
14710 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14711 (setq org-ans2 (format-time-string "%Y-%m-%d" time))))
14712 (org-move-overlay org-date-ovl (1- (point)) (1+ (point)) (current-buffer))
14713 (select-window sw)
14714 ;; Update the prompt to show new default date
14715 (save-excursion
14716 (goto-char (point-min))
14717 (when (and org-ans2
14718 (re-search-forward "\\[[-0-9]+\\]" nil t)
14719 (get-text-property (match-end 0) 'field))
14720 (let ((inhibit-read-only t))
14721 (replace-match (concat "[" org-ans2 "]") t t)
14722 (add-text-properties (point-min) (1+ (match-end 0))
14723 (text-properties-at (1+ (point-min)))))))))
14725 (defun org-calendar-select ()
14726 "Return to `org-read-date' with the date currently selected.
14727 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
14728 (interactive)
14729 (when (calendar-cursor-to-date)
14730 (let* ((date (calendar-cursor-to-date))
14731 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14732 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
14733 (if (active-minibuffer-window) (exit-minibuffer))))
14735 (defun org-insert-time-stamp (time &optional with-hm inactive pre post extra)
14736 "Insert a date stamp for the date given by the internal TIME.
14737 WITH-HM means, use the stamp format that includes the time of the day.
14738 INACTIVE means use square brackets instead of angular ones, so that the
14739 stamp will not contribute to the agenda.
14740 PRE and POST are optional strings to be inserted before and after the
14741 stamp.
14742 The command returns the inserted time stamp."
14743 (let ((fmt (funcall (if with-hm 'cdr 'car) org-time-stamp-formats))
14744 stamp)
14745 (if inactive (setq fmt (concat "[" (substring fmt 1 -1) "]")))
14746 (insert (or pre ""))
14747 (insert (setq stamp (format-time-string fmt time)))
14748 (when (listp extra)
14749 (setq extra (car extra))
14750 (if (and (stringp extra)
14751 (string-match "\\([0-9]+\\):\\([0-9]+\\)" extra))
14752 (setq extra (format "-%02d:%02d"
14753 (string-to-number (match-string 1 extra))
14754 (string-to-number (match-string 2 extra))))
14755 (setq extra nil)))
14756 (when extra
14757 (backward-char 1)
14758 (insert extra)
14759 (forward-char 1))
14760 (insert (or post ""))
14761 stamp))
14763 (defun org-toggle-time-stamp-overlays ()
14764 "Toggle the use of custom time stamp formats."
14765 (interactive)
14766 (setq org-display-custom-times (not org-display-custom-times))
14767 (unless org-display-custom-times
14768 (let ((p (point-min)) (bmp (buffer-modified-p)))
14769 (while (setq p (next-single-property-change p 'display))
14770 (if (and (get-text-property p 'display)
14771 (eq (get-text-property p 'face) 'org-date))
14772 (remove-text-properties
14773 p (setq p (next-single-property-change p 'display))
14774 '(display t))))
14775 (set-buffer-modified-p bmp)))
14776 (if (featurep 'xemacs)
14777 (remove-text-properties (point-min) (point-max) '(end-glyph t)))
14778 (org-restart-font-lock)
14779 (setq org-table-may-need-update t)
14780 (if org-display-custom-times
14781 (message "Time stamps are overlayed with custom format")
14782 (message "Time stamp overlays removed")))
14784 (defun org-display-custom-time (beg end)
14785 "Overlay modified time stamp format over timestamp between BED and END."
14786 (let* ((ts (buffer-substring beg end))
14787 t1 w1 with-hm tf time str w2 (off 0))
14788 (save-match-data
14789 (setq t1 (org-parse-time-string ts t))
14790 (if (string-match "\\(-[0-9]+:[0-9]+\\)?\\( \\+[0-9]+[dwmy]\\)?\\'" ts)
14791 (setq off (- (match-end 0) (match-beginning 0)))))
14792 (setq end (- end off))
14793 (setq w1 (- end beg)
14794 with-hm (and (nth 1 t1) (nth 2 t1))
14795 tf (funcall (if with-hm 'cdr 'car) org-time-stamp-custom-formats)
14796 time (org-fix-decoded-time t1)
14797 str (org-add-props
14798 (format-time-string
14799 (substring tf 1 -1) (apply 'encode-time time))
14800 nil 'mouse-face 'highlight)
14801 w2 (length str))
14802 (if (not (= w2 w1))
14803 (add-text-properties (1+ beg) (+ 2 beg)
14804 (list 'org-dwidth t 'org-dwidth-n (- w1 w2))))
14805 (if (featurep 'xemacs)
14806 (progn
14807 (put-text-property beg end 'invisible t)
14808 (put-text-property beg end 'end-glyph (make-glyph str)))
14809 (put-text-property beg end 'display str))))
14811 (defun org-translate-time (string)
14812 "Translate all timestamps in STRING to custom format.
14813 But do this only if the variable `org-display-custom-times' is set."
14814 (when org-display-custom-times
14815 (save-match-data
14816 (let* ((start 0)
14817 (re org-ts-regexp-both)
14818 t1 with-hm inactive tf time str beg end)
14819 (while (setq start (string-match re string start))
14820 (setq beg (match-beginning 0)
14821 end (match-end 0)
14822 t1 (save-match-data
14823 (org-parse-time-string (substring string beg end) t))
14824 with-hm (and (nth 1 t1) (nth 2 t1))
14825 inactive (equal (substring string beg (1+ beg)) "[")
14826 tf (funcall (if with-hm 'cdr 'car)
14827 org-time-stamp-custom-formats)
14828 time (org-fix-decoded-time t1)
14829 str (format-time-string
14830 (concat
14831 (if inactive "[" "<") (substring tf 1 -1)
14832 (if inactive "]" ">"))
14833 (apply 'encode-time time))
14834 string (replace-match str t t string)
14835 start (+ start (length str)))))))
14836 string)
14838 (defun org-fix-decoded-time (time)
14839 "Set 0 instead of nil for the first 6 elements of time.
14840 Don't touch the rest."
14841 (let ((n 0))
14842 (mapcar (lambda (x) (if (< (setq n (1+ n)) 7) (or x 0) x)) time)))
14844 (defun org-days-to-time (timestamp-string)
14845 "Difference between TIMESTAMP-STRING and now in days."
14846 (- (time-to-days (org-time-string-to-time timestamp-string))
14847 (time-to-days (current-time))))
14849 (defun org-deadline-close (timestamp-string &optional ndays)
14850 "Is the time in TIMESTAMP-STRING close to the current date?"
14851 (and (< (org-days-to-time timestamp-string)
14852 (or ndays org-deadline-warning-days))
14853 (not (org-entry-is-done-p))))
14855 (defun org-calendar-select-mouse (ev)
14856 "Return to `org-read-date' with the date currently selected.
14857 This is used by `org-read-date' in a temporary keymap for the calendar buffer."
14858 (interactive "e")
14859 (mouse-set-point ev)
14860 (when (calendar-cursor-to-date)
14861 (let* ((date (calendar-cursor-to-date))
14862 (time (encode-time 0 0 0 (nth 1 date) (nth 0 date) (nth 2 date))))
14863 (setq org-ans1 (format-time-string "%Y-%m-%d" time)))
14864 (if (active-minibuffer-window) (exit-minibuffer))))
14866 (defun org-check-deadlines (ndays)
14867 "Check if there are any deadlines due or past due.
14868 A deadline is considered due if it happens within `org-deadline-warning-days'
14869 days from today's date. If the deadline appears in an entry marked DONE,
14870 it is not shown. The prefix arg NDAYS can be used to test that many
14871 days. If the prefix is a raw \\[universal-argument] prefix, all deadlines are shown."
14872 (interactive "P")
14873 (let* ((org-warn-days
14874 (cond
14875 ((equal ndays '(4)) 100000)
14876 (ndays (prefix-numeric-value ndays))
14877 (t org-deadline-warning-days)))
14878 (case-fold-search nil)
14879 (regexp (concat "\\<" org-deadline-string " *<\\([^>]+\\)>"))
14880 (callback
14881 (lambda () (org-deadline-close (match-string 1) org-warn-days))))
14883 (message "%d deadlines past-due or due within %d days"
14884 (org-occur regexp nil callback)
14885 org-warn-days)))
14887 (defun org-evaluate-time-range (&optional to-buffer)
14888 "Evaluate a time range by computing the difference between start and end.
14889 Normally the result is just printed in the echo area, but with prefix arg
14890 TO-BUFFER, the result is inserted just after the date stamp into the buffer.
14891 If the time range is actually in a table, the result is inserted into the
14892 next column.
14893 For time difference computation, a year is assumed to be exactly 365
14894 days in order to avoid rounding problems."
14895 (interactive "P")
14897 (org-clock-update-time-maybe)
14898 (save-excursion
14899 (unless (org-at-date-range-p)
14900 (goto-char (point-at-bol))
14901 (re-search-forward org-tr-regexp (point-at-eol) t))
14902 (if (not (org-at-date-range-p))
14903 (error "Not at a time-stamp range, and none found in current line")))
14904 (let* ((ts1 (match-string 1))
14905 (ts2 (match-string 2))
14906 (havetime (or (> (length ts1) 15) (> (length ts2) 15)))
14907 (match-end (match-end 0))
14908 (time1 (org-time-string-to-time ts1))
14909 (time2 (org-time-string-to-time ts2))
14910 (t1 (time-to-seconds time1))
14911 (t2 (time-to-seconds time2))
14912 (diff (abs (- t2 t1)))
14913 (negative (< (- t2 t1) 0))
14914 ;; (ys (floor (* 365 24 60 60)))
14915 (ds (* 24 60 60))
14916 (hs (* 60 60))
14917 (fy "%dy %dd %02d:%02d")
14918 (fy1 "%dy %dd")
14919 (fd "%dd %02d:%02d")
14920 (fd1 "%dd")
14921 (fh "%02d:%02d")
14922 y d h m align)
14923 (if havetime
14924 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
14926 d (floor (/ diff ds)) diff (mod diff ds)
14927 h (floor (/ diff hs)) diff (mod diff hs)
14928 m (floor (/ diff 60)))
14929 (setq ; y (floor (/ diff ys)) diff (mod diff ys)
14931 d (floor (+ (/ diff ds) 0.5))
14932 h 0 m 0))
14933 (if (not to-buffer)
14934 (message (org-make-tdiff-string y d h m))
14935 (when (org-at-table-p)
14936 (goto-char match-end)
14937 (setq align t)
14938 (and (looking-at " *|") (goto-char (match-end 0))))
14939 (if (looking-at
14940 "\\( *-? *[0-9]+y\\)?\\( *[0-9]+d\\)? *[0-9][0-9]:[0-9][0-9]")
14941 (replace-match ""))
14942 (if negative (insert " -"))
14943 (if (> y 0) (insert " " (format (if havetime fy fy1) y d h m))
14944 (if (> d 0) (insert " " (format (if havetime fd fd1) d h m))
14945 (insert " " (format fh h m))))
14946 (if align (org-table-align))
14947 (message "Time difference inserted")))))
14949 (defun org-make-tdiff-string (y d h m)
14950 (let ((fmt "")
14951 (l nil))
14952 (if (> y 0) (setq fmt (concat fmt "%d year" (if (> y 1) "s" "") " ")
14953 l (push y l)))
14954 (if (> d 0) (setq fmt (concat fmt "%d day" (if (> d 1) "s" "") " ")
14955 l (push d l)))
14956 (if (> h 0) (setq fmt (concat fmt "%d hour" (if (> h 1) "s" "") " ")
14957 l (push h l)))
14958 (if (> m 0) (setq fmt (concat fmt "%d minute" (if (> m 1) "s" "") " ")
14959 l (push m l)))
14960 (apply 'format fmt (nreverse l))))
14962 (defun org-time-string-to-time (s)
14963 (apply 'encode-time (org-parse-time-string s)))
14965 (defun org-time-string-to-absolute (s &optional daynr)
14966 "Convert a time stamp to an absolute day number.
14967 If there is a specifyer for a cyclic time stamp, get the closest date to
14968 DATE."
14969 (cond
14970 ((and daynr (string-match "\\`%%\\((.*)\\)" s))
14971 (if (org-diary-sexp-entry (match-string 1 s) "" date)
14972 daynr
14973 (+ daynr 1000)))
14974 ((and daynr (string-match "\\+[0-9]+[dwmy]" s))
14975 (org-closest-date s (if (and (boundp 'daynr) (integerp daynr)) daynr
14976 (time-to-days (current-time))) (match-string 0 s)))
14977 (t (time-to-days (apply 'encode-time (org-parse-time-string s))))))
14979 (defun org-calendar-holiday ()
14980 "List of holidays, for Diary display in Org-mode."
14981 (let ((hl (check-calendar-holidays date)))
14982 (if hl (mapconcat 'identity hl "; "))))
14984 (defun org-diary-sexp-entry (sexp entry date)
14985 "Process a SEXP diary ENTRY for DATE."
14986 (let ((result (if calendar-debug-sexp
14987 (let ((stack-trace-on-error t))
14988 (eval (car (read-from-string sexp))))
14989 (condition-case nil
14990 (eval (car (read-from-string sexp)))
14991 (error
14992 (beep)
14993 (message "Bad sexp at line %d in %s: %s"
14994 (org-current-line)
14995 (buffer-file-name) sexp)
14996 (sleep-for 2))))))
14997 (cond ((stringp result) result)
14998 ((and (consp result)
14999 (stringp (cdr result))) (cdr result))
15000 (result entry)
15001 (t nil))))
15003 (defun org-diary-to-ical-string (frombuf)
15004 "FIXME"
15005 (let* ((tmpdir (if (featurep 'xemacs)
15006 (temp-directory)
15007 temporary-file-directory))
15008 (tmpfile (make-temp-name
15009 (expand-file-name "orgics" tmpdir)))
15010 buf rtn b e)
15011 (save-excursion
15012 (set-buffer frombuf)
15013 (icalendar-export-region (point-min) (point-max) tmpfile)
15014 (setq buf (find-buffer-visiting tmpfile))
15015 (set-buffer buf)
15016 (goto-char (point-min))
15017 (if (re-search-forward "^BEGIN:VEVENT" nil t)
15018 (setq b (match-beginning 0)))
15019 (goto-char (point-max))
15020 (if (re-search-backward "^END:VEVENT" nil t)
15021 (setq e (match-end 0)))
15022 (setq rtn (if (and b e) (concat (buffer-substring b e) "\n") "")))
15023 (kill-buffer buf)
15024 (kill-buffer frombuf)
15025 (delete-file tmpfile)
15026 rtn))
15028 (defun org-closest-date (start current change)
15029 "Find the date closest to CURRENT that is consistent with START and CHANGE."
15030 ;; Make the proper lists from the dates
15031 (catch 'exit
15032 (let ((a1 '(("d" . day) ("w" . week) ("m" . month) ("y" . year)))
15033 dn dw sday cday n1 n2
15034 d m y y1 y2 date1 date2 nmonths nm ny m2)
15036 (setq start (org-date-to-gregorian start)
15037 current (org-date-to-gregorian current)
15038 sday (calendar-absolute-from-gregorian start)
15039 cday (calendar-absolute-from-gregorian current))
15041 (if (<= cday sday) (throw 'exit sday))
15043 (if (string-match "\\(\\+[0-9]+\\)\\([dwmy]\\)" change)
15044 (setq dn (string-to-number (match-string 1 change))
15045 dw (cdr (assoc (match-string 2 change) a1)))
15046 (error "Invalid change specifyer: %s" change))
15047 (if (eq dw 'week) (setq dw 'day dn (* 7 dn)))
15048 (cond
15049 ((eq dw 'day)
15050 (setq n1 (+ sday (* dn (floor (/ (- cday sday) dn))))
15051 n2 (+ n1 dn)))
15052 ((eq dw 'year)
15053 (setq d (nth 1 start) m (car start) y1 (nth 2 start) y2 (nth 2 current))
15054 (setq y1 (+ (* (floor (/ (- y2 y1) dn)) dn) y1))
15055 (setq date1 (list m d y1)
15056 n1 (calendar-absolute-from-gregorian date1)
15057 date2 (list m d (+ y1 (* (if (< n1 cday) 1 -1) dn)))
15058 n2 (calendar-absolute-from-gregorian date2)))
15059 ((eq dw 'month)
15060 ;; approx number of month between the tow dates
15061 (setq nmonths (floor (/ (- cday sday) 30.436875)))
15062 ;; How often does dn fit in there?
15063 (setq d (nth 1 start) m (car start) y (nth 2 start)
15064 nm (* dn (max 0 (1- (floor (/ nmonths dn)))))
15065 m (+ m nm)
15066 ny (floor (/ m 12))
15067 y (+ y ny)
15068 m (- m (* ny 12)))
15069 (while (> m 12) (setq m (- m 12) y (1+ y)))
15070 (setq n1 (calendar-absolute-from-gregorian (list m d y)))
15071 (setq m2 (+ m dn) y2 y)
15072 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
15073 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2)))
15074 (while (< n2 cday)
15075 (setq n1 n2 m m2 y y2)
15076 (setq m2 (+ m dn) y2 y)
15077 (if (> m2 12) (setq y2 (1+ y2) m2 (- m2 12)))
15078 (setq n2 (calendar-absolute-from-gregorian (list m2 d y2))))))
15080 (if (> (abs (- cday n1)) (abs (- cday n2))) n2 n1))))
15082 (defun org-date-to-gregorian (date)
15083 "Turn any specification of DATE into a gregorian date for the calendar."
15084 (cond ((integerp date) (calendar-gregorian-from-absolute date))
15085 ((and (listp date) (= (length date) 3)) date)
15086 ((stringp date)
15087 (setq date (org-parse-time-string date))
15088 (list (nth 4 date) (nth 3 date) (nth 5 date)))
15089 ((listp date)
15090 (list (nth 4 date) (nth 3 date) (nth 5 date)))))
15092 (defun org-parse-time-string (s &optional nodefault)
15093 "Parse the standard Org-mode time string.
15094 This should be a lot faster than the normal `parse-time-string'.
15095 If time is not given, defaults to 0:00. However, with optional NODEFAULT,
15096 hour and minute fields will be nil if not given."
15097 (if (string-match org-ts-regexp0 s)
15098 (list 0
15099 (if (or (match-beginning 8) (not nodefault))
15100 (string-to-number (or (match-string 8 s) "0")))
15101 (if (or (match-beginning 7) (not nodefault))
15102 (string-to-number (or (match-string 7 s) "0")))
15103 (string-to-number (match-string 4 s))
15104 (string-to-number (match-string 3 s))
15105 (string-to-number (match-string 2 s))
15106 nil nil nil)
15107 (make-list 9 0)))
15109 (defun org-timestamp-up (&optional arg)
15110 "Increase the date item at the cursor by one.
15111 If the cursor is on the year, change the year. If it is on the month or
15112 the day, change that.
15113 With prefix ARG, change by that many units."
15114 (interactive "p")
15115 (org-timestamp-change (prefix-numeric-value arg)))
15117 (defun org-timestamp-down (&optional arg)
15118 "Decrease the date item at the cursor by one.
15119 If the cursor is on the year, change the year. If it is on the month or
15120 the day, change that.
15121 With prefix ARG, change by that many units."
15122 (interactive "p")
15123 (org-timestamp-change (- (prefix-numeric-value arg))))
15125 (defun org-timestamp-up-day (&optional arg)
15126 "Increase the date in the time stamp by one day.
15127 With prefix ARG, change that many days."
15128 (interactive "p")
15129 (if (and (not (org-at-timestamp-p t))
15130 (org-on-heading-p))
15131 (org-todo 'up)
15132 (org-timestamp-change (prefix-numeric-value arg) 'day)))
15134 (defun org-timestamp-down-day (&optional arg)
15135 "Decrease the date in the time stamp by one day.
15136 With prefix ARG, change that many days."
15137 (interactive "p")
15138 (if (and (not (org-at-timestamp-p t))
15139 (org-on-heading-p))
15140 (org-todo 'down)
15141 (org-timestamp-change (- (prefix-numeric-value arg)) 'day)))
15143 (defsubst org-pos-in-match-range (pos n)
15144 (and (match-beginning n)
15145 (<= (match-beginning n) pos)
15146 (>= (match-end n) pos)))
15148 (defun org-at-timestamp-p (&optional inactive-ok)
15149 "Determine if the cursor is in or at a timestamp."
15150 (interactive)
15151 (let* ((tsr (if inactive-ok org-ts-regexp3 org-ts-regexp2))
15152 (pos (point))
15153 (ans (or (looking-at tsr)
15154 (save-excursion
15155 (skip-chars-backward "^[<\n\r\t")
15156 (if (> (point) 1) (backward-char 1))
15157 (and (looking-at tsr)
15158 (> (- (match-end 0) pos) -1))))))
15159 (and (boundp 'org-ts-what)
15160 (setq org-ts-what
15161 (cond
15162 ((org-pos-in-match-range pos 2) 'year)
15163 ((org-pos-in-match-range pos 3) 'month)
15164 ((org-pos-in-match-range pos 7) 'hour)
15165 ((org-pos-in-match-range pos 8) 'minute)
15166 ((or (org-pos-in-match-range pos 4)
15167 (org-pos-in-match-range pos 5)) 'day)
15168 ((and (> pos (or (match-end 8) (match-end 5)))
15169 (< pos (match-end 0)))
15170 (- pos (or (match-end 8) (match-end 5))))
15171 (t 'day))))
15172 ans))
15174 (defun org-timestamp-change (n &optional what)
15175 "Change the date in the time stamp at point.
15176 The date will be changed by N times WHAT. WHAT can be `day', `month',
15177 `year', `minute', `second'. If WHAT is not given, the cursor position
15178 in the timestamp determines what will be changed."
15179 (let ((pos (point))
15180 with-hm inactive
15181 org-ts-what
15182 extra
15183 ts time time0)
15184 (if (not (org-at-timestamp-p t))
15185 (error "Not at a timestamp"))
15186 (if (and (not what) (not (eq org-ts-what 'day))
15187 org-display-custom-times
15188 (get-text-property (point) 'display)
15189 (not (get-text-property (1- (point)) 'display)))
15190 (setq org-ts-what 'day))
15191 (setq org-ts-what (or what org-ts-what)
15192 inactive (= (char-after (match-beginning 0)) ?\[)
15193 ts (match-string 0))
15194 (replace-match "")
15195 (if (string-match
15196 "\\(\\(-[012][0-9]:[0-5][0-9]\\)?\\( \\+[0-9]+[dwmy]\\)?\\)[]>]"
15198 (setq extra (match-string 1 ts)))
15199 (if (string-match "^.\\{10\\}.*?[0-9]+:[0-9][0-9]" ts)
15200 (setq with-hm t))
15201 (setq time0 (org-parse-time-string ts))
15202 (setq time
15203 (apply 'encode-time
15204 (append
15205 (list (or (car time0) 0))
15206 (list (+ (if (eq org-ts-what 'minute) n 0) (nth 1 time0)))
15207 (list (+ (if (eq org-ts-what 'hour) n 0) (nth 2 time0)))
15208 (list (+ (if (eq org-ts-what 'day) n 0) (nth 3 time0)))
15209 (list (+ (if (eq org-ts-what 'month) n 0) (nth 4 time0)))
15210 (list (+ (if (eq org-ts-what 'year) n 0) (nth 5 time0)))
15211 (nthcdr 6 time0))))
15212 (when (integerp org-ts-what)
15213 (setq extra (org-modify-ts-extra extra org-ts-what n)))
15214 (if (eq what 'calendar)
15215 (let ((cal-date
15216 (save-excursion
15217 (save-match-data
15218 (set-buffer "*Calendar*")
15219 (calendar-cursor-to-date)))))
15220 (setcar (nthcdr 4 time0) (nth 0 cal-date)) ; month
15221 (setcar (nthcdr 3 time0) (nth 1 cal-date)) ; day
15222 (setcar (nthcdr 5 time0) (nth 2 cal-date)) ; year
15223 (setcar time0 (or (car time0) 0))
15224 (setcar (nthcdr 1 time0) (or (nth 1 time0) 0))
15225 (setcar (nthcdr 2 time0) (or (nth 1 time0) 0))
15226 (setq time (apply 'encode-time time0))))
15227 (setq org-last-changed-timestamp
15228 (org-insert-time-stamp time with-hm inactive nil nil extra))
15229 (org-clock-update-time-maybe)
15230 (goto-char pos)
15231 ;; Try to recenter the calendar window, if any
15232 (if (and org-calendar-follow-timestamp-change
15233 (get-buffer-window "*Calendar*" t)
15234 (memq org-ts-what '(day month year)))
15235 (org-recenter-calendar (time-to-days time)))))
15237 (defun org-modify-ts-extra (s pos n)
15238 "FIXME"
15239 (let ((idx '(("d" . 0) ("w" . 1) ("m" . 2) ("y" . 3) ("d" . -1) ("y" . 4)))
15240 ng h m new)
15241 (when (string-match "\\(-\\([012][0-9]\\):\\([0-5][0-9]\\)\\)?\\( \\+\\([0-9]+\\)\\([dmwy]\\)\\)?" s)
15242 (cond
15243 ((or (org-pos-in-match-range pos 2)
15244 (org-pos-in-match-range pos 3))
15245 (setq m (string-to-number (match-string 3 s))
15246 h (string-to-number (match-string 2 s)))
15247 (if (org-pos-in-match-range pos 2)
15248 (setq h (+ h n))
15249 (setq m (+ m n)))
15250 (if (< m 0) (setq m (+ m 60) h (1- h)))
15251 (if (> m 59) (setq m (- m 60) h (1+ h)))
15252 (setq h (min 24 (max 0 h)))
15253 (setq ng 1 new (format "-%02d:%02d" h m)))
15254 ((org-pos-in-match-range pos 6)
15255 (setq ng 6 new (car (rassoc (+ n (cdr (assoc (match-string 6 s) idx))) idx))))
15256 ((org-pos-in-match-range pos 5)
15257 (setq ng 5 new (format "%d" (max 1 (+ n (string-to-number (match-string 5 s))))))))
15259 (when ng
15260 (setq s (concat
15261 (substring s 0 (match-beginning ng))
15263 (substring s (match-end ng))))))
15266 (defun org-recenter-calendar (date)
15267 "If the calendar is visible, recenter it to DATE."
15268 (let* ((win (selected-window))
15269 (cwin (get-buffer-window "*Calendar*" t))
15270 (calendar-move-hook nil))
15271 (when cwin
15272 (select-window cwin)
15273 (calendar-goto-date (if (listp date) date
15274 (calendar-gregorian-from-absolute date)))
15275 (select-window win))))
15277 (defun org-goto-calendar (&optional arg)
15278 "Go to the Emacs calendar at the current date.
15279 If there is a time stamp in the current line, go to that date.
15280 A prefix ARG can be used to force the current date."
15281 (interactive "P")
15282 (let ((tsr org-ts-regexp) diff
15283 (calendar-move-hook nil)
15284 (view-calendar-holidays-initially nil)
15285 (view-diary-entries-initially nil))
15286 (if (or (org-at-timestamp-p)
15287 (save-excursion
15288 (beginning-of-line 1)
15289 (looking-at (concat ".*" tsr))))
15290 (let ((d1 (time-to-days (current-time)))
15291 (d2 (time-to-days
15292 (org-time-string-to-time (match-string 1)))))
15293 (setq diff (- d2 d1))))
15294 (calendar)
15295 (calendar-goto-today)
15296 (if (and diff (not arg)) (calendar-forward-day diff))))
15298 (defun org-date-from-calendar ()
15299 "Insert time stamp corresponding to cursor date in *Calendar* buffer.
15300 If there is already a time stamp at the cursor position, update it."
15301 (interactive)
15302 (org-timestamp-change 0 'calendar))
15304 ;;; The clock for measuring work time.
15306 (defvar org-mode-line-string "")
15307 (put 'org-mode-line-string 'risky-local-variable t)
15309 (defvar org-mode-line-timer nil)
15310 (defvar org-clock-heading "")
15311 (defvar org-clock-start-time "")
15313 (defun org-update-mode-line ()
15314 (let* ((delta (- (time-to-seconds (current-time))
15315 (time-to-seconds org-clock-start-time)))
15316 (h (floor delta 3600))
15317 (m (floor (- delta (* 3600 h)) 60)))
15318 (setq org-mode-line-string
15319 (propertize (format "-[%d:%02d (%s)]" h m org-clock-heading)
15320 'help-echo "Org-mode clock is running"))
15321 (force-mode-line-update)))
15323 (defvar org-clock-marker (make-marker)
15324 "Marker recording the last clock-in.")
15325 (defvar org-clock-mode-line-entry nil
15326 "Information for the modeline about the running clock.")
15328 (defun org-clock-in ()
15329 "Start the clock on the current item.
15330 If necessary, clock-out of the currently active clock."
15331 (interactive)
15332 (org-clock-out t)
15333 (let (ts)
15334 (save-excursion
15335 (org-back-to-heading t)
15336 (if (looking-at org-todo-line-regexp)
15337 (setq org-clock-heading (match-string 3))
15338 (setq org-clock-heading "???"))
15339 (setq org-clock-heading (propertize org-clock-heading 'face nil))
15340 (beginning-of-line 2)
15341 (when (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
15342 (not (equal (match-string 1) org-clock-string)))
15343 ;; First line hast scheduling info, move one further
15344 (beginning-of-line 2)
15345 (or (bolp) (newline)))
15346 (insert "\n") (backward-char 1)
15347 (indent-relative)
15348 (insert org-clock-string " ")
15349 (setq org-clock-start-time (current-time))
15350 (setq ts (org-insert-time-stamp (current-time) 'with-hm 'inactive))
15351 (move-marker org-clock-marker (point) (buffer-base-buffer))
15352 (or global-mode-string (setq global-mode-string '("")))
15353 (or (memq 'org-mode-line-string global-mode-string)
15354 (setq global-mode-string
15355 (append global-mode-string '(org-mode-line-string))))
15356 (org-update-mode-line)
15357 (setq org-mode-line-timer (run-with-timer 60 60 'org-update-mode-line))
15358 (message "Clock started at %s" ts))))
15360 (defun org-clock-out (&optional fail-quietly)
15361 "Stop the currently running clock.
15362 If there is no running clock, throw an error, unless FAIL-QUIETLY is set."
15363 (interactive)
15364 (catch 'exit
15365 (if (not (marker-buffer org-clock-marker))
15366 (if fail-quietly (throw 'exit t) (error "No active clock")))
15367 (let (ts te s h m)
15368 (save-excursion
15369 (set-buffer (marker-buffer org-clock-marker))
15370 (goto-char org-clock-marker)
15371 (beginning-of-line 1)
15372 (if (and (looking-at (concat "[ \t]*" org-keyword-time-regexp))
15373 (equal (match-string 1) org-clock-string))
15374 (setq ts (match-string 2))
15375 (if fail-quietly (throw 'exit nil) (error "Clock start time is gone")))
15376 (goto-char (match-end 0))
15377 (delete-region (point) (point-at-eol))
15378 (insert "--")
15379 (setq te (org-insert-time-stamp (current-time) 'with-hm 'inactive))
15380 (setq s (- (time-to-seconds (apply 'encode-time (org-parse-time-string te)))
15381 (time-to-seconds (apply 'encode-time (org-parse-time-string ts))))
15382 h (floor (/ s 3600))
15383 s (- s (* 3600 h))
15384 m (floor (/ s 60))
15385 s (- s (* 60 s)))
15386 (insert " => " (format "%2d:%02d" h m))
15387 (move-marker org-clock-marker nil)
15388 (org-add-log-maybe 'clock-out)
15389 (when org-mode-line-timer
15390 (cancel-timer org-mode-line-timer)
15391 (setq org-mode-line-timer nil))
15392 (setq global-mode-string
15393 (delq 'org-mode-line-string global-mode-string))
15394 (force-mode-line-update)
15395 (message "Clock stopped at %s after HH:MM = %d:%02d" te h m)))))
15397 (defun org-clock-cancel ()
15398 "Cancel the running clock be removing the start timestamp."
15399 (interactive)
15400 (if (not (marker-buffer org-clock-marker))
15401 (error "No active clock"))
15402 (save-excursion
15403 (set-buffer (marker-buffer org-clock-marker))
15404 (goto-char org-clock-marker)
15405 (delete-region (1- (point-at-bol)) (point-at-eol)))
15406 (message "Clock canceled"))
15408 (defvar org-clock-file-total-minutes nil
15409 "Holds the file total time in minutes, after a call to `org-clock-sum'.")
15410 (make-variable-buffer-local 'org-clock-file-total-minutes)
15412 (defun org-clock-sum (&optional tstart tend)
15413 "Sum the times for each subtree.
15414 Puts the resulting times in minutes as a text property on each headline."
15415 (interactive)
15416 (let* ((bmp (buffer-modified-p))
15417 (re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*"
15418 org-clock-string
15419 "[ \t]*\\(?:\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)"))
15420 (lmax 30)
15421 (ltimes (make-vector lmax 0))
15422 (t1 0)
15423 (level 0)
15424 ts te dt
15425 time)
15426 (remove-text-properties (point-min) (point-max) '(:org-clock-minutes t))
15427 (save-excursion
15428 (goto-char (point-max))
15429 (while (re-search-backward re nil t)
15430 (cond
15431 ((match-end 2)
15432 ;; Two time stamps
15433 (setq ts (match-string 2)
15434 te (match-string 3)
15435 ts (time-to-seconds
15436 (apply 'encode-time (org-parse-time-string ts)))
15437 te (time-to-seconds
15438 (apply 'encode-time (org-parse-time-string te)))
15439 ts (if tstart (max ts tstart) ts)
15440 te (if tend (min te tend) te)
15441 dt (- te ts)
15442 t1 (if (> dt 0) (+ t1 (floor (/ dt 60))) t1)))
15443 ((match-end 4)
15444 ;; A naket time
15445 (setq t1 (+ t1 (string-to-number (match-string 5))
15446 (* 60 (string-to-number (match-string 4))))))
15447 (t ;; A headline
15448 (setq level (- (match-end 1) (match-beginning 1)))
15449 (when (or (> t1 0) (> (aref ltimes level) 0))
15450 (loop for l from 0 to level do
15451 (aset ltimes l (+ (aref ltimes l) t1)))
15452 (setq t1 0 time (aref ltimes level))
15453 (loop for l from level to (1- lmax) do
15454 (aset ltimes l 0))
15455 (goto-char (match-beginning 0))
15456 (put-text-property (point) (point-at-eol) :org-clock-minutes time)))))
15457 (setq org-clock-file-total-minutes (aref ltimes 0)))
15458 (set-buffer-modified-p bmp)))
15460 (defun org-clock-display (&optional total-only)
15461 "Show subtree times in the entire buffer.
15462 If TOTAL-ONLY is non-nil, only show the total time for the entire file
15463 in the echo area."
15464 (interactive)
15465 (org-remove-clock-overlays)
15466 (let (time h m p)
15467 (org-clock-sum)
15468 (unless total-only
15469 (save-excursion
15470 (goto-char (point-min))
15471 (while (setq p (next-single-property-change (point) :org-clock-minutes))
15472 (goto-char p)
15473 (when (setq time (get-text-property p :org-clock-minutes))
15474 (org-put-clock-overlay time (funcall outline-level))))
15475 (setq h (/ org-clock-file-total-minutes 60)
15476 m (- org-clock-file-total-minutes (* 60 h)))
15477 ;; Arrange to remove the overlays upon next change.
15478 (when org-remove-highlights-with-change
15479 (org-add-hook 'before-change-functions 'org-remove-clock-overlays
15480 nil 'local))))
15481 (message "Total file time: %d:%02d (%d hours and %d minutes)" h m h m)))
15483 (defvar org-clock-overlays nil)
15484 (make-variable-buffer-local 'org-clock-overlays)
15486 (defun org-put-clock-overlay (time &optional level)
15487 "Put an overlays on the current line, displaying TIME.
15488 If LEVEL is given, prefix time with a corresponding number of stars.
15489 This creates a new overlay and stores it in `org-clock-overlays', so that it
15490 will be easy to remove."
15491 (let* ((c 60) (h (floor (/ time 60))) (m (- time (* 60 h)))
15492 (l (if level (org-get-legal-level level 0) 0))
15493 (off 0)
15494 ov tx)
15495 (move-to-column c)
15496 (unless (eolp) (skip-chars-backward "^ \t"))
15497 (skip-chars-backward " \t")
15498 (setq ov (org-make-overlay (1- (point)) (point-at-eol))
15499 tx (concat (buffer-substring (1- (point)) (point))
15500 (make-string (+ off (max 0 (- c (current-column)))) ?.)
15501 (org-add-props (format "%s %2d:%02d%s"
15502 (make-string l ?*) h m
15503 (make-string (- 10 l) ?\ ))
15504 '(face secondary-selection))
15505 ""))
15506 (if (not (featurep 'xemacs))
15507 (org-overlay-put ov 'display tx)
15508 (org-overlay-put ov 'invisible t)
15509 (org-overlay-put ov 'end-glyph (make-glyph tx)))
15510 (push ov org-clock-overlays)))
15512 (defun org-remove-clock-overlays (&optional beg end noremove)
15513 "Remove the occur highlights from the buffer.
15514 BEG and END are ignored. If NOREMOVE is nil, remove this function
15515 from the `before-change-functions' in the current buffer."
15516 (interactive)
15517 (unless org-inhibit-highlight-removal
15518 (mapc 'org-delete-overlay org-clock-overlays)
15519 (setq org-clock-overlays nil)
15520 (unless noremove
15521 (remove-hook 'before-change-functions
15522 'org-remove-clock-overlays 'local))))
15524 (defun org-clock-out-if-current ()
15525 "Clock out if the current entry contains the running clock.
15526 This is used to stop the clock after a TODO entry is marked DONE."
15527 (when (and (member state org-done-keywords)
15528 (equal (marker-buffer org-clock-marker) (current-buffer))
15529 (< (point) org-clock-marker)
15530 (> (save-excursion (outline-next-heading) (point))
15531 org-clock-marker))
15532 ;; Clock out, but don't accept a logging message for this.
15533 (let ((org-log-done (if (and (listp org-log-done)
15534 (member 'clock-out org-log-done))
15535 '(done)
15536 org-log-done)))
15537 (org-clock-out))))
15539 (add-hook 'org-after-todo-state-change-hook
15540 'org-clock-out-if-current)
15542 (defun org-check-running-clock ()
15543 "Check if the current buffer contains the running clock.
15544 If yes, offer to stop it and to save the buffer with the changes."
15545 (when (and (equal (marker-buffer org-clock-marker) (current-buffer))
15546 (y-or-n-p (format "Clock-out in buffer %s before killing it? "
15547 (buffer-name))))
15548 (org-clock-out)
15549 (when (y-or-n-p "Save changed buffer?")
15550 (save-buffer))))
15552 (defun org-clock-report ()
15553 "Create a table containing a report about clocked time.
15554 If the buffer contains lines
15555 #+BEGIN: clocktable :maxlevel 3 :emphasize nil
15557 #+END: clocktable
15558 then the table will be inserted between these lines, replacing whatever
15559 is was there before. If these lines are not in the buffer, the table
15560 is inserted at point, surrounded by the special lines.
15561 The BEGIN line can contain parameters. Allowed are:
15562 :maxlevel The maximum level to be included in the table. Default is 3.
15563 :emphasize t/nil, if levell 1 and level 2 should be bold/italic in the table."
15564 (interactive)
15565 (org-remove-clock-overlays)
15566 (unless (org-find-dblock "clocktable")
15567 (org-create-dblock (list :name "clocktable"
15568 :maxlevel 2 :emphasize nil)))
15569 (org-update-dblock))
15571 (defun org-clock-update-time-maybe ()
15572 "If this is a CLOCK line, update it and return t.
15573 Otherwise, return nil."
15574 (interactive)
15575 (save-excursion
15576 (beginning-of-line 1)
15577 (skip-chars-forward " \t")
15578 (when (looking-at org-clock-string)
15579 (let ((re (concat "[ \t]*" org-clock-string
15580 " *[[<]\\([^]>]+\\)[]>]-+[[<]\\([^]>]+\\)[]>]"
15581 "\\([ \t]*=>.*\\)?"))
15582 ts te h m s)
15583 (if (not (looking-at re))
15585 (and (match-end 3) (delete-region (match-beginning 3) (match-end 3)))
15586 (end-of-line 1)
15587 (setq ts (match-string 1)
15588 te (match-string 2))
15589 (setq s (- (time-to-seconds
15590 (apply 'encode-time (org-parse-time-string te)))
15591 (time-to-seconds
15592 (apply 'encode-time (org-parse-time-string ts))))
15593 h (floor (/ s 3600))
15594 s (- s (* 3600 h))
15595 m (floor (/ s 60))
15596 s (- s (* 60 s)))
15597 (insert " => " (format "%2d:%02d" h m))
15598 t)))))
15600 (defun org-clock-special-range (key &optional time as-strings)
15601 "Return two times bordering a special time range.
15602 Key is a symbol specifying the range and can be one of `today', `yesterday',
15603 `thisweek', `lastweek', `thismonth', `lastmonth', `thisyear', `lastyear'.
15604 A week starts Monday 0:00 and ends Sunday 24:00.
15605 The range is determined relative to TIME. TIME defaults to the current time.
15606 The return value is a cons cell with two internal times like the ones
15607 returned by `current time' or `encode-time'. if AS-STRINGS is non-nil,
15608 the returned times will be formatted strings."
15609 (let* ((tm (decode-time (or time (current-time))))
15610 (s 0) (m (nth 1 tm)) (h (nth 2 tm))
15611 (d (nth 3 tm)) (month (nth 4 tm)) (y (nth 5 tm))
15612 (dow (nth 6 tm))
15613 s1 m1 h1 d1 month1 y1 diff ts te fm)
15614 (cond
15615 ((eq key 'today)
15616 (setq h 0 m 0 h1 24 m1 0))
15617 ((eq key 'yesterday)
15618 (setq d (1- d) h 0 m 0 h1 24 m1 0))
15619 ((eq key 'thisweek)
15620 (setq diff (if (= dow 0) 6 (1- dow))
15621 m 0 h 0 d (- d diff) d1 (+ 7 d)))
15622 ((eq key 'lastweek)
15623 (setq diff (+ 7 (if (= dow 0) 6 (1- dow)))
15624 m 0 h 0 d (- d diff) d1 (+ 7 d)))
15625 ((eq key 'thismonth)
15626 (setq d 1 h 0 m 0 d1 1 month1 (1+ month) h1 0 m1 0))
15627 ((eq key 'lastmonth)
15628 (setq d 1 h 0 m 0 d1 1 month (1- month) month1 (1+ month) h1 0 m1 0))
15629 ((eq key 'thisyear)
15630 (setq m 0 h 0 d 1 month 1 y1 (1+ y)))
15631 ((eq key 'lastyear)
15632 (setq m 0 h 0 d 1 month 1 y (1- y) y1 (1+ y)))
15633 (t (error "No such time block %s" key)))
15634 (setq ts (encode-time s m h d month y)
15635 te (encode-time (or s1 s) (or m1 m) (or h1 h)
15636 (or d1 d) (or month1 month) (or y1 y)))
15637 (setq fm (cdr org-time-stamp-formats))
15638 (if as-strings
15639 (cons (format-time-string fm ts) (format-time-string fm te))
15640 (cons ts te))))
15642 (defun org-dblock-write:clocktable (params)
15643 "Write the standard clocktable."
15644 (let ((hlchars '((1 . "*") (2 . ?/)))
15645 (emph nil)
15646 (ins (make-marker))
15647 ipos time h m p level hlc hdl maxlevel
15648 ts te cc block)
15649 (setq maxlevel (or (plist-get params :maxlevel) 3)
15650 emph (plist-get params :emphasize)
15651 ts (plist-get params :tstart)
15652 te (plist-get params :tend)
15653 block (plist-get params :block))
15654 (when block
15655 (setq cc (org-clock-special-range block nil t)
15656 ts (car cc) te (cdr cc)))
15657 (if ts (setq ts (time-to-seconds
15658 (apply 'encode-time (org-parse-time-string ts)))))
15659 (if te (setq te (time-to-seconds
15660 (apply 'encode-time (org-parse-time-string te)))))
15661 (move-marker ins (point))
15662 (setq ipos (point))
15663 (insert-before-markers "Clock summary at ["
15664 (substring
15665 (format-time-string (cdr org-time-stamp-formats))
15666 1 -1)
15667 "]."
15668 (if block
15669 (format " Considered range is /%s/." block)
15671 "\n\n|L|Headline|Time|\n")
15672 (org-clock-sum ts te)
15673 (setq h (/ org-clock-file-total-minutes 60)
15674 m (- org-clock-file-total-minutes (* 60 h)))
15675 (insert-before-markers "|-\n|0|" "*Total file time*| "
15676 (format "*%d:%02d*" h m)
15677 "|\n")
15678 (goto-char (point-min))
15679 (while (setq p (next-single-property-change (point) :org-clock-minutes))
15680 (goto-char p)
15681 (when (setq time (get-text-property p :org-clock-minutes))
15682 (save-excursion
15683 (beginning-of-line 1)
15684 (when (and (looking-at (org-re "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@:]+:\\)?[ \t]*$"))
15685 (setq level (- (match-end 1) (match-beginning 1)))
15686 (<= level maxlevel))
15687 (setq hlc (if emph (or (cdr (assoc level hlchars)) "") "")
15688 hdl (match-string 2)
15689 h (/ time 60)
15690 m (- time (* 60 h)))
15691 (goto-char ins)
15692 (if (= level 1) (insert-before-markers "|-\n"))
15693 (insert-before-markers
15694 "| " (int-to-string level) "|" hlc hdl hlc " |"
15695 (make-string (1- level) ?|)
15697 (format "%d:%02d" h m)
15699 " |\n")))))
15700 (goto-char ins)
15701 (backward-delete-char 1)
15702 (goto-char ipos)
15703 (skip-chars-forward "^|")
15704 (org-table-align)))
15706 ;; FIXME: I don't think anybody uses this, ask David
15707 (defun org-collect-clock-time-entries ()
15708 "Return an internal list with clocking information.
15709 This list has one entry for each CLOCK interval.
15710 FIXME: describe the elements."
15711 (interactive)
15712 (let ((re (concat "^[ \t]*" org-clock-string
15713 " *\\[\\(.*?\\)\\]--\\[\\(.*?\\)\\]"))
15714 rtn beg end next cont level title total closedp leafp
15715 clockpos titlepos h m donep)
15716 (save-excursion
15717 (org-clock-sum)
15718 (goto-char (point-min))
15719 (while (re-search-forward re nil t)
15720 (setq clockpos (match-beginning 0)
15721 beg (match-string 1) end (match-string 2)
15722 cont (match-end 0))
15723 (setq beg (apply 'encode-time (org-parse-time-string beg))
15724 end (apply 'encode-time (org-parse-time-string end)))
15725 (org-back-to-heading t)
15726 (setq donep (org-entry-is-done-p))
15727 (setq titlepos (point)
15728 total (or (get-text-property (1+ (point)) :org-clock-minutes) 0)
15729 h (/ total 60) m (- total (* 60 h))
15730 total (cons h m))
15731 (looking-at "\\(\\*+\\) +\\(.*\\)")
15732 (setq level (- (match-end 1) (match-beginning 1))
15733 title (org-match-string-no-properties 2))
15734 (save-excursion (outline-next-heading) (setq next (point)))
15735 (setq closedp (re-search-forward org-closed-time-regexp next t))
15736 (goto-char next)
15737 (setq leafp (and (looking-at "^\\*+ ")
15738 (<= (- (match-end 0) (point)) level)))
15739 (push (list beg end clockpos closedp donep
15740 total title titlepos level leafp)
15741 rtn)
15742 (goto-char cont)))
15743 (nreverse rtn)))
15745 ;;;; Agenda, and Diary Integration
15747 ;;; Define the Org-agenda-mode
15749 (defvar org-agenda-mode-map (make-sparse-keymap)
15750 "Keymap for `org-agenda-mode'.")
15752 (defvar org-agenda-menu) ; defined later in this file.
15753 (defvar org-agenda-follow-mode nil)
15754 (defvar org-agenda-show-log nil)
15755 (defvar org-agenda-redo-command nil)
15756 (defvar org-agenda-mode-hook nil)
15757 (defvar org-agenda-type nil)
15758 (defvar org-agenda-force-single-file nil)
15760 (defun org-agenda-mode ()
15761 "Mode for time-sorted view on action items in Org-mode files.
15763 The following commands are available:
15765 \\{org-agenda-mode-map}"
15766 (interactive)
15767 (kill-all-local-variables)
15768 (setq org-agenda-undo-list nil
15769 org-agenda-pending-undo-list nil)
15770 (setq major-mode 'org-agenda-mode)
15771 ;; Keep global-font-lock-mode from turning on font-lock-mode
15772 (org-set-local 'font-lock-global-modes (list 'not major-mode))
15773 (setq mode-name "Org-Agenda")
15774 (use-local-map org-agenda-mode-map)
15775 (easy-menu-add org-agenda-menu)
15776 (if org-startup-truncated (setq truncate-lines t))
15777 (org-add-hook 'post-command-hook 'org-agenda-post-command-hook nil 'local)
15778 (org-add-hook 'pre-command-hook 'org-unhighlight nil 'local)
15779 ;; Make sure properties are removed when copying text
15780 (when (boundp 'buffer-substring-filters)
15781 (org-set-local 'buffer-substring-filters
15782 (cons (lambda (x)
15783 (set-text-properties 0 (length x) nil x) x)
15784 buffer-substring-filters)))
15785 (unless org-agenda-keep-modes
15786 (setq org-agenda-follow-mode org-agenda-start-with-follow-mode
15787 org-agenda-show-log nil))
15788 (easy-menu-change
15789 '("Agenda") "Agenda Files"
15790 (append
15791 (list
15792 (vector
15793 (if (get 'org-agenda-files 'org-restrict)
15794 "Restricted to single file"
15795 "Edit File List")
15796 '(org-edit-agenda-file-list)
15797 (not (get 'org-agenda-files 'org-restrict)))
15798 "--")
15799 (mapcar 'org-file-menu-entry (org-agenda-files))))
15800 (org-agenda-set-mode-name)
15801 (apply
15802 (if (fboundp 'run-mode-hooks) 'run-mode-hooks 'run-hooks)
15803 (list 'org-agenda-mode-hook)))
15805 (substitute-key-definition 'undo 'org-agenda-undo
15806 org-agenda-mode-map global-map)
15807 (org-defkey org-agenda-mode-map "\C-i" 'org-agenda-goto)
15808 (org-defkey org-agenda-mode-map [(tab)] 'org-agenda-goto)
15809 (org-defkey org-agenda-mode-map "\C-m" 'org-agenda-switch-to)
15810 (org-defkey org-agenda-mode-map "\C-k" 'org-agenda-kill)
15811 (org-defkey org-agenda-mode-map "\C-c$" 'org-agenda-archive)
15812 (org-defkey org-agenda-mode-map "\C-c\C-x\C-s" 'org-agenda-archive)
15813 (org-defkey org-agenda-mode-map "$" 'org-agenda-archive)
15814 (org-defkey org-agenda-mode-map "\C-c\C-o" 'org-agenda-open-link)
15815 (org-defkey org-agenda-mode-map " " 'org-agenda-show)
15816 (org-defkey org-agenda-mode-map "\C-c\C-t" 'org-agenda-todo)
15817 (org-defkey org-agenda-mode-map [(control shift right)] 'org-agenda-todo-nextset)
15818 (org-defkey org-agenda-mode-map [(control shift left)] 'org-agenda-todo-previousset)
15819 (org-defkey org-agenda-mode-map "\C-c\C-xb" 'org-agenda-tree-to-indirect-buffer)
15820 (org-defkey org-agenda-mode-map "b" 'org-agenda-tree-to-indirect-buffer)
15821 (org-defkey org-agenda-mode-map "o" 'delete-other-windows)
15822 (org-defkey org-agenda-mode-map "L" 'org-agenda-recenter)
15823 (org-defkey org-agenda-mode-map "t" 'org-agenda-todo)
15824 (org-defkey org-agenda-mode-map "a" 'org-agenda-toggle-archive-tag)
15825 (org-defkey org-agenda-mode-map ":" 'org-agenda-set-tags)
15826 (org-defkey org-agenda-mode-map "." 'org-agenda-goto-today)
15827 (org-defkey org-agenda-mode-map "d" 'org-agenda-day-view)
15828 (org-defkey org-agenda-mode-map "w" 'org-agenda-week-view)
15829 (org-defkey org-agenda-mode-map "m" 'org-agenda-month-view)
15830 (org-defkey org-agenda-mode-map "y" 'org-agenda-year-view)
15831 (org-defkey org-agenda-mode-map [(shift right)] 'org-agenda-date-later)
15832 (org-defkey org-agenda-mode-map [(shift left)] 'org-agenda-date-earlier)
15833 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (right)] 'org-agenda-date-later)
15834 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (left)] 'org-agenda-date-earlier)
15836 (org-defkey org-agenda-mode-map ">" 'org-agenda-date-prompt)
15837 (org-defkey org-agenda-mode-map "\C-c\C-s" 'org-agenda-schedule)
15838 (org-defkey org-agenda-mode-map "\C-c\C-d" 'org-agenda-deadline)
15839 (let ((l '(1 2 3 4 5 6 7 8 9 0)))
15840 (while l (org-defkey org-agenda-mode-map
15841 (int-to-string (pop l)) 'digit-argument)))
15843 (org-defkey org-agenda-mode-map "f" 'org-agenda-follow-mode)
15844 (org-defkey org-agenda-mode-map "l" 'org-agenda-log-mode)
15845 (org-defkey org-agenda-mode-map "D" 'org-agenda-toggle-diary)
15846 (org-defkey org-agenda-mode-map "g" 'org-agenda-toggle-time-grid)
15847 (org-defkey org-agenda-mode-map "r" 'org-agenda-redo)
15848 (org-defkey org-agenda-mode-map "q" 'org-agenda-quit)
15849 (org-defkey org-agenda-mode-map "x" 'org-agenda-exit)
15850 (org-defkey org-agenda-mode-map "\C-x\C-w" 'org-write-agenda)
15851 (org-defkey org-agenda-mode-map "s" 'org-save-all-org-buffers)
15852 (org-defkey org-agenda-mode-map "P" 'org-agenda-show-priority)
15853 (org-defkey org-agenda-mode-map "T" 'org-agenda-show-tags)
15854 (org-defkey org-agenda-mode-map "n" 'next-line)
15855 (org-defkey org-agenda-mode-map "p" 'previous-line)
15856 (org-defkey org-agenda-mode-map "\C-n" 'org-agenda-next-date-line)
15857 (org-defkey org-agenda-mode-map "\C-p" 'org-agenda-previous-date-line)
15858 (org-defkey org-agenda-mode-map "," 'org-agenda-priority)
15859 (org-defkey org-agenda-mode-map "\C-c," 'org-agenda-priority)
15860 (org-defkey org-agenda-mode-map "i" 'org-agenda-diary-entry)
15861 (org-defkey org-agenda-mode-map "c" 'org-agenda-goto-calendar)
15862 (eval-after-load "calendar"
15863 '(org-defkey calendar-mode-map org-calendar-to-agenda-key
15864 'org-calendar-goto-agenda))
15865 (org-defkey org-agenda-mode-map "C" 'org-agenda-convert-date)
15866 (org-defkey org-agenda-mode-map "M" 'org-agenda-phases-of-moon)
15867 (org-defkey org-agenda-mode-map "S" 'org-agenda-sunrise-sunset)
15868 (org-defkey org-agenda-mode-map "h" 'org-agenda-holidays)
15869 (org-defkey org-agenda-mode-map "H" 'org-agenda-holidays)
15870 (org-defkey org-agenda-mode-map "I" 'org-agenda-clock-in)
15871 (org-defkey org-agenda-mode-map "O" 'org-agenda-clock-out)
15872 (org-defkey org-agenda-mode-map "X" 'org-agenda-clock-cancel)
15873 (org-defkey org-agenda-mode-map "+" 'org-agenda-priority-up)
15874 (org-defkey org-agenda-mode-map "-" 'org-agenda-priority-down)
15875 (org-defkey org-agenda-mode-map [(shift up)] 'org-agenda-priority-up)
15876 (org-defkey org-agenda-mode-map [(shift down)] 'org-agenda-priority-down)
15877 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (up)] 'org-agenda-priority-up)
15878 (org-defkey org-agenda-mode-map [?\C-c ?\C-x (down)] 'org-agenda-priority-down)
15879 (org-defkey org-agenda-mode-map [(right)] 'org-agenda-later)
15880 (org-defkey org-agenda-mode-map [(left)] 'org-agenda-earlier)
15881 (org-defkey org-agenda-mode-map "\C-c\C-x\C-c" 'org-agenda-columns)
15883 (defvar org-agenda-keymap (copy-keymap org-agenda-mode-map)
15884 "Local keymap for agenda entries from Org-mode.")
15886 (org-defkey org-agenda-keymap
15887 (if (featurep 'xemacs) [(button2)] [(mouse-2)]) 'org-agenda-goto-mouse)
15888 (org-defkey org-agenda-keymap
15889 (if (featurep 'xemacs) [(button3)] [(mouse-3)]) 'org-agenda-show-mouse)
15890 (when org-agenda-mouse-1-follows-link
15891 (org-defkey org-agenda-keymap [follow-link] 'mouse-face))
15892 (easy-menu-define org-agenda-menu org-agenda-mode-map "Agenda menu"
15893 '("Agenda"
15894 ("Agenda Files")
15895 "--"
15896 ["Show" org-agenda-show t]
15897 ["Go To (other window)" org-agenda-goto t]
15898 ["Go To (this window)" org-agenda-switch-to t]
15899 ["Follow Mode" org-agenda-follow-mode
15900 :style toggle :selected org-agenda-follow-mode :active t]
15901 ["Tree to indirect frame" org-agenda-tree-to-indirect-buffer t]
15902 "--"
15903 ["Cycle TODO" org-agenda-todo t]
15904 ["Archive subtree" org-agenda-archive t]
15905 ["Delete subtree" org-agenda-kill t]
15906 "--"
15907 ["Goto Today" org-agenda-goto-today (org-agenda-check-type nil 'agenda 'timeline)]
15908 ["Next Dates" org-agenda-later (org-agenda-check-type nil 'agenda)]
15909 ["Previous Dates" org-agenda-earlier (org-agenda-check-type nil 'agenda)]
15910 "--"
15911 ("Tags and Properties"
15912 ["Show all Tags" org-agenda-show-tags t]
15913 ["Set Tags" org-agenda-set-tags t]
15914 "--"
15915 ["Column View" org-columns t])
15916 ("Date/Schedule"
15917 ["Schedule" org-agenda-schedule t]
15918 ["Set Deadline" org-agenda-deadline t]
15919 "--"
15920 ["Change Date +1 day" org-agenda-date-later (org-agenda-check-type nil 'agenda 'timeline)]
15921 ["Change Date -1 day" org-agenda-date-earlier (org-agenda-check-type nil 'agenda 'timeline)]
15922 ["Change Date to ..." org-agenda-date-prompt (org-agenda-check-type nil 'agenda 'timeline)])
15923 ("Priority"
15924 ["Set Priority" org-agenda-priority t]
15925 ["Increase Priority" org-agenda-priority-up t]
15926 ["Decrease Priority" org-agenda-priority-down t]
15927 ["Show Priority" org-agenda-show-priority t])
15928 ("Calendar/Diary"
15929 ["New Diary Entry" org-agenda-diary-entry (org-agenda-check-type nil 'agenda 'timeline)]
15930 ["Goto Calendar" org-agenda-goto-calendar (org-agenda-check-type nil 'agenda 'timeline)]
15931 ["Phases of the Moon" org-agenda-phases-of-moon (org-agenda-check-type nil 'agenda 'timeline)]
15932 ["Sunrise/Sunset" org-agenda-sunrise-sunset (org-agenda-check-type nil 'agenda 'timeline)]
15933 ["Holidays" org-agenda-holidays (org-agenda-check-type nil 'agenda 'timeline)]
15934 ["Convert" org-agenda-convert-date (org-agenda-check-type nil 'agenda 'timeline)]
15935 "--"
15936 ["Create iCalendar file" org-export-icalendar-combine-agenda-files t])
15937 "--"
15938 ("View"
15939 ["Day View" org-agenda-day-view :active (org-agenda-check-type nil 'agenda)
15940 :style radio :selected (equal org-agenda-ndays 1)]
15941 ["Week View" org-agenda-week-view :active (org-agenda-check-type nil 'agenda)
15942 :style radio :selected (equal org-agenda-ndays 7)]
15943 ["Month View" org-agenda-month-view :active (org-agenda-check-type nil 'agenda)
15944 :style radio :selected (member org-agenda-ndays '(28 29 30 31))]
15945 ["Year View" org-agenda-year-view :active (org-agenda-check-type nil 'agenda)
15946 :style radio :selected (member org-agenda-ndays '(365 366))]
15947 "--"
15948 ["Show Logbook entries" org-agenda-log-mode
15949 :style toggle :selected org-agenda-show-log :active (org-agenda-check-type nil 'agenda 'timeline)]
15950 ["Include Diary" org-agenda-toggle-diary
15951 :style toggle :selected org-agenda-include-diary :active (org-agenda-check-type nil 'agenda)]
15952 ["Use Time Grid" org-agenda-toggle-time-grid
15953 :style toggle :selected org-agenda-use-time-grid :active (org-agenda-check-type nil 'agenda)])
15954 ["Write view to file" org-write-agenda t]
15955 ["Rebuild buffer" org-agenda-redo t]
15956 ["Save all Org-mode Buffers" org-save-all-org-buffers t]
15957 "--"
15958 ["Undo Remote Editing" org-agenda-undo org-agenda-undo-list]
15959 "--"
15960 ["Quit" org-agenda-quit t]
15961 ["Exit and Release Buffers" org-agenda-exit t]
15964 ;;; Agenda undo
15966 (defvar org-agenda-allow-remote-undo t
15967 "Non-nil means, allow remote undo from the agenda buffer.")
15968 (defvar org-agenda-undo-list nil
15969 "List of undoable operations in the agenda since last refresh.")
15970 (defvar org-agenda-undo-has-started-in nil
15971 "Buffers that have already seen `undo-start' in the current undo sequence.")
15972 (defvar org-agenda-pending-undo-list nil
15973 "In a series of undo commands, this is the list of remaning undo items.")
15975 (defmacro org-if-unprotected (&rest body)
15976 "Execute BODY if ther is no `org-protected' text property at point."
15977 (declare (debug t))
15978 `(unless (get-text-property (point) 'org-protected)
15979 ,@body))
15981 (defmacro org-with-remote-undo (_buffer &rest _body)
15982 "Execute BODY while recording undo information in two buffers."
15983 (declare (indent 1) (debug t))
15984 `(let ((_cline (org-current-line))
15985 (_cmd this-command)
15986 (_buf1 (current-buffer))
15987 (_buf2 ,_buffer)
15988 (_undo1 buffer-undo-list)
15989 (_undo2 (with-current-buffer ,_buffer buffer-undo-list))
15990 _c1 _c2)
15991 ,@_body
15992 (when org-agenda-allow-remote-undo
15993 (setq _c1 (org-verify-change-for-undo
15994 _undo1 (with-current-buffer _buf1 buffer-undo-list))
15995 _c2 (org-verify-change-for-undo
15996 _undo2 (with-current-buffer _buf2 buffer-undo-list)))
15997 (when (or _c1 _c2)
15998 ;; make sure there are undo boundaries
15999 (and _c1 (with-current-buffer _buf1 (undo-boundary)))
16000 (and _c2 (with-current-buffer _buf2 (undo-boundary)))
16001 ;; remember which buffer to undo
16002 (push (list _cmd _cline _buf1 _c1 _buf2 _c2)
16003 org-agenda-undo-list)))))
16005 (defun org-agenda-undo ()
16006 "Undo a remote editing step in the agenda.
16007 This undoes changes both in the agenda buffer and in the remote buffer
16008 that have been changed along."
16009 (interactive)
16010 (or org-agenda-allow-remote-undo
16011 (error "Check the variable `org-agenda-allow-remote-undo' to activate remote undo."))
16012 (if (not (eq this-command last-command))
16013 (setq org-agenda-undo-has-started-in nil
16014 org-agenda-pending-undo-list org-agenda-undo-list))
16015 (if (not org-agenda-pending-undo-list)
16016 (error "No further undo information"))
16017 (let* ((entry (pop org-agenda-pending-undo-list))
16018 buf line cmd rembuf)
16019 (setq cmd (pop entry) line (pop entry))
16020 (setq rembuf (nth 2 entry))
16021 (org-with-remote-undo rembuf
16022 (while (bufferp (setq buf (pop entry)))
16023 (if (pop entry)
16024 (with-current-buffer buf
16025 (let ((last-undo-buffer buf)
16026 buffer-read-only)
16027 (unless (memq buf org-agenda-undo-has-started-in)
16028 (push buf org-agenda-undo-has-started-in)
16029 (make-local-variable 'pending-undo-list)
16030 (undo-start))
16031 (while (and pending-undo-list
16032 (listp pending-undo-list)
16033 (not (car pending-undo-list)))
16034 (pop pending-undo-list))
16035 (undo-more 1))))))
16036 (goto-line line)
16037 (message "`%s' undone (buffer %s)" cmd (buffer-name rembuf))))
16039 (defun org-verify-change-for-undo (l1 l2)
16040 "Verify that a real change occurred between the undo lists L1 and L2."
16041 (while (and l1 (listp l1) (null (car l1))) (pop l1))
16042 (while (and l2 (listp l2) (null (car l2))) (pop l2))
16043 (not (eq l1 l2)))
16045 ;;; Agenda dispatch
16047 (defvar org-agenda-restrict nil)
16048 (defvar org-agenda-restrict-begin (make-marker))
16049 (defvar org-agenda-restrict-end (make-marker))
16050 (defvar org-agenda-last-dispatch-buffer nil)
16052 ;;;###autoload
16053 (defun org-agenda (arg)
16054 "Dispatch agenda commands to collect entries to the agenda buffer.
16055 Prompts for a character to select a command. Any prefix arg will be passed
16056 on to the selected command. The default selections are:
16058 a Call `org-agenda-list' to display the agenda for current day or week.
16059 t Call `org-todo-list' to display the global todo list.
16060 T Call `org-todo-list' to display the global todo list, select only
16061 entries with a specific TODO keyword (the user gets a prompt).
16062 m Call `org-tags-view' to display headlines with tags matching
16063 a condition (the user is prompted for the condition).
16064 M Like `m', but select only TODO entries, no ordinary headlines.
16065 l Create a timeline for the current buffer.
16066 e Export views to associated files.
16068 More commands can be added by configuring the variable
16069 `org-agenda-custom-commands'. In particular, specific tags and TODO keyword
16070 searches can be pre-defined in this way.
16072 If the current buffer is in Org-mode and visiting a file, you can also
16073 first press `1' to indicate that the agenda should be temporarily (until the
16074 next use of \\[org-agenda]) restricted to the current file."
16075 (interactive "P")
16076 (catch 'exit
16077 (let* ((buf (current-buffer))
16078 (bfn (buffer-file-name (buffer-base-buffer)))
16079 (restrict-ok (and bfn (org-mode-p)))
16080 (custom org-agenda-custom-commands)
16081 c entry key type match lprops)
16082 ;; Turn off restriction
16083 (put 'org-agenda-files 'org-restrict nil)
16084 (setq org-agenda-restrict nil)
16085 (move-marker org-agenda-restrict-begin nil)
16086 (move-marker org-agenda-restrict-end nil)
16087 ;; Remember where this call originated
16088 (setq org-agenda-last-dispatch-buffer (current-buffer))
16089 (save-window-excursion
16090 (delete-other-windows)
16091 (switch-to-buffer-other-window " *Agenda Commands*")
16092 (erase-buffer)
16093 (insert (eval-when-compile
16094 (let ((header
16095 "Press key for an agenda command:
16096 -------------------------------- C Configure custom agenda commands
16097 a Agenda for current week or day e Export agenda views
16098 t List of all TODO entries T Entries with special TODO kwd
16099 m Match a TAGS query M Like m, but only TODO entries
16100 L Timeline for current buffer # List stuck projects (!=configure)
16102 (start 0))
16103 (while (string-match "\\(^\\| \\|(\\)\\(\\S-\\)\\( \\|=\\)" header start)
16104 (setq start (match-end 0))
16105 (add-text-properties (match-beginning 2) (match-end 2)
16106 '(face bold) header))
16107 header)))
16108 (while (setq entry (pop custom))
16109 (setq key (car entry) type (nth 1 entry) match (nth 2 entry))
16110 (insert (format "\n%-4s%-14s: %s"
16111 (org-add-props (copy-sequence key)
16112 '(face bold))
16113 (cond
16114 ((stringp type) type)
16115 ((eq type 'agenda) "Agenda for current week or day")
16116 ((eq type 'alltodo) "List of all TODO entries")
16117 ((eq type 'stuck) "List of stuck projects")
16118 ((eq type 'todo) "TODO keyword")
16119 ((eq type 'tags) "Tags query")
16120 ((eq type 'tags-todo) "Tags (TODO)")
16121 ((eq type 'tags-tree) "Tags tree")
16122 ((eq type 'todo-tree) "TODO kwd tree")
16123 ((eq type 'occur-tree) "Occur tree")
16124 ((functionp type) (symbol-name type))
16125 (t "???"))
16126 (if (stringp match)
16127 (org-add-props match nil 'face 'org-warning)
16128 (format "set of %d commands" (length match))))))
16129 (if restrict-ok
16130 (insert "\n"
16131 (org-add-props "1 Restrict call to current buffer 0 Restrict call to region or subtree" nil 'face 'org-table)))
16132 (goto-char (point-min))
16133 (if (fboundp 'fit-window-to-buffer) (fit-window-to-buffer))
16134 (message "Press key for agenda command%s"
16135 (if restrict-ok ", or [1] or [0] to restrict" ""))
16136 (setq c (read-char-exclusive))
16137 (message "")
16138 (when (memq c '(?L ?1 ?0))
16139 (if restrict-ok
16140 (put 'org-agenda-files 'org-restrict (list bfn))
16141 (error "Cannot restrict agenda to current buffer"))
16142 (with-current-buffer " *Agenda Commands*"
16143 (goto-char (point-max))
16144 (delete-region (point-at-bol) (point))
16145 (goto-char (point-min)))
16146 (when (eq c ?0)
16147 (setq org-agenda-restrict t)
16148 (with-current-buffer buf
16149 (if (org-region-active-p)
16150 (progn
16151 (move-marker org-agenda-restrict-begin (region-beginning))
16152 (move-marker org-agenda-restrict-end (region-end)))
16153 (save-excursion
16154 (org-back-to-heading t)
16155 (move-marker org-agenda-restrict-begin (point))
16156 (move-marker org-agenda-restrict-end
16157 (progn (org-end-of-subtree t)))))))
16158 (unless (eq c ?L)
16159 (message "Press key for agenda command%s"
16160 (if restrict-ok " (restricted to current file)" ""))
16161 (setq c (read-char-exclusive)))
16162 (message "")))
16163 (require 'calendar) ; FIXME: can we avoid this for some commands?
16164 ;; For example the todo list should not need it (but does...)
16165 (cond
16166 ((setq entry (assoc (char-to-string c) org-agenda-custom-commands))
16167 (if (symbolp (nth 1 entry))
16168 (progn
16169 (setq type (nth 1 entry) match (nth 2 entry) lprops (nth 3 entry)
16170 lprops (nth 3 entry))
16171 (cond
16172 ((eq type 'agenda)
16173 (org-let lprops '(org-agenda-list current-prefix-arg)))
16174 ((eq type 'alltodo)
16175 (org-let lprops '(org-todo-list current-prefix-arg)))
16176 ((eq type 'stuck)
16177 (org-let lprops '(org-agenda-list-stuck-projects
16178 current-prefix-arg)))
16179 ((eq type 'tags)
16180 (org-let lprops '(org-tags-view current-prefix-arg match)))
16181 ((eq type 'tags-todo)
16182 (org-let lprops '(org-tags-view '(4) match)))
16183 ((eq type 'todo)
16184 (org-let lprops '(org-todo-list match)))
16185 ((eq type 'tags-tree)
16186 (org-check-for-org-mode)
16187 (org-let lprops '(org-tags-sparse-tree current-prefix-arg match)))
16188 ((eq type 'todo-tree)
16189 (org-check-for-org-mode)
16190 (org-let lprops
16191 '(org-occur (concat "^" outline-regexp "[ \t]*"
16192 (regexp-quote match) "\\>"))))
16193 ((eq type 'occur-tree)
16194 (org-check-for-org-mode)
16195 (org-let lprops '(org-occur match)))
16196 ((fboundp type)
16197 (org-let lprops '(funcall type match)))
16198 (t (error "Invalid custom agenda command type %s" type))))
16199 (org-run-agenda-series (nth 1 entry) (cddr entry))))
16200 ((equal c ?C) (customize-variable 'org-agenda-custom-commands))
16201 ((equal c ?a) (call-interactively 'org-agenda-list))
16202 ((equal c ?t) (call-interactively 'org-todo-list))
16203 ((equal c ?T) (org-call-with-arg 'org-todo-list (or arg '(4))))
16204 ((equal c ?m) (call-interactively 'org-tags-view))
16205 ((equal c ?M) (org-call-with-arg 'org-tags-view (or arg '(4))))
16206 ((equal c ?e) (call-interactively 'org-store-agenda-views))
16207 ((equal c ?L)
16208 (unless restrict-ok
16209 (error "This is not an Org-mode file"))
16210 (org-call-with-arg 'org-timeline arg))
16211 ((equal c ?#) (call-interactively 'org-agenda-list-stuck-projects))
16212 ((equal c ?!) (customize-variable 'org-stuck-projects))
16213 (t (error "Invalid key"))))))
16215 (defun org-run-agenda-series (name series)
16216 (org-prepare-agenda name)
16217 (let* ((org-agenda-multi t)
16218 (redo (list 'org-run-agenda-series name (list 'quote series)))
16219 (cmds (car series))
16220 (gprops (nth 1 series))
16221 match ;; The byte compiler incorrectly complains about this. Keep it!
16222 cmd type lprops)
16223 (while (setq cmd (pop cmds))
16224 (setq type (car cmd) match (nth 1 cmd) lprops (nth 2 cmd))
16225 (cond
16226 ((eq type 'agenda)
16227 (org-let2 gprops lprops
16228 '(call-interactively 'org-agenda-list)))
16229 ((eq type 'alltodo)
16230 (org-let2 gprops lprops
16231 '(call-interactively 'org-todo-list)))
16232 ((eq type 'stuck)
16233 (org-let2 gprops lprops
16234 '(call-interactively 'org-agenda-list-stuck-projects)))
16235 ((eq type 'tags)
16236 (org-let2 gprops lprops
16237 '(org-tags-view current-prefix-arg match)))
16238 ((eq type 'tags-todo)
16239 (org-let2 gprops lprops
16240 '(org-tags-view '(4) match)))
16241 ((eq type 'todo)
16242 (org-let2 gprops lprops
16243 '(org-todo-list match)))
16244 ((fboundp type)
16245 (org-let2 gprops lprops
16246 '(funcall type match)))
16247 (t (error "Invalid type in command series"))))
16248 (widen)
16249 (setq org-agenda-redo-command redo)
16250 (goto-char (point-min)))
16251 (org-finalize-agenda))
16253 ;;;###autoload
16254 (defmacro org-batch-agenda (cmd-key &rest parameters)
16255 "Run an agenda command in batch mode and send the result to STDOUT.
16256 If CMD-KEY is a string of length 1, it is used as a key in
16257 `org-agenda-custom-commands' and triggers this command. If it is a
16258 longer string is is used as a tags/todo match string.
16259 Paramters are alternating variable names and values that will be bound
16260 before running the agenda command."
16261 (let (pars)
16262 (while parameters
16263 (push (list (pop parameters) (if parameters (pop parameters))) pars))
16264 (if (> (length cmd-key) 1)
16265 (eval (list 'let (nreverse pars)
16266 (list 'org-tags-view nil cmd-key)))
16267 (flet ((read-char-exclusive () (string-to-char cmd-key)))
16268 (eval (list 'let (nreverse pars) '(org-agenda nil)))))
16269 (set-buffer "*Org Agenda*")
16270 (princ (org-encode-for-stdout (buffer-string)))))
16272 (defun org-encode-for-stdout (string)
16273 (if (fboundp 'encode-coding-string)
16274 (encode-coding-string string buffer-file-coding-system)
16275 string))
16277 (defvar org-agenda-info nil)
16279 ;;;###autoload
16280 (defmacro org-batch-agenda-csv (cmd-key &rest parameters)
16281 "Run an agenda command in batch mode and send the result to STDOUT.
16282 If CMD-KEY is a string of length 1, it is used as a key in
16283 `org-agenda-custom-commands' and triggers this command. If it is a
16284 longer string is is used as a tags/todo match string.
16285 Paramters are alternating variable names and values that will be bound
16286 before running the agenda command.
16288 The output gives a line for each selected agenda item. Each
16289 item is a list of comma-separated values, like this:
16291 category,head,type,todo,tags,date,time,extra,priority-l,priority-n
16293 category The category of the item
16294 head The headline, without TODO kwd, TAGS and PRIORITY
16295 type The type of the agenda entry, can be
16296 todo selected in TODO match
16297 tagsmatch selected in tags match
16298 diary imported from diary
16299 deadline a deadline on given date
16300 scheduled scheduled on given date
16301 timestamp entry has timestamp on given date
16302 closed entry was closed on given date
16303 upcoming-deadline warning about deadline
16304 past-scheduled forwarded scheduled item
16305 block entry has date block including g. date
16306 todo The todo keyword, if any
16307 tags All tags including inherited ones, separated by colons
16308 date The relevant date, like 2007-2-14
16309 time The time, like 15:00-16:50
16310 extra Sting with extra planning info
16311 priority-l The priority letter if any was given
16312 priority-n The computed numerical priority
16313 agenda-day The day in the agenda where this is listed"
16315 (let (pars)
16316 (while parameters
16317 (push (list (pop parameters) (if parameters (pop parameters))) pars))
16318 (push (list 'org-agenda-remove-tags t) pars)
16319 (if (> (length cmd-key) 1)
16320 (eval (list 'let (nreverse pars)
16321 (list 'org-tags-view nil cmd-key)))
16322 (flet ((read-char-exclusive () (string-to-char cmd-key)))
16323 (eval (list 'let (nreverse pars) '(org-agenda nil)))))
16324 (set-buffer "*Org Agenda*")
16325 (let* ((lines (org-split-string (buffer-string) "\n"))
16326 line)
16327 (while (setq line (pop lines))
16328 (catch 'next
16329 (if (not (get-text-property 0 'org-category line)) (throw 'next nil))
16330 (setq org-agenda-info
16331 (org-fix-agenda-info (text-properties-at 0 line)))
16332 (princ
16333 (org-encode-for-stdout
16334 (mapconcat 'org-agenda-export-csv-mapper
16335 '(org-category txt type todo tags date time-of-day extra
16336 priority-letter priority agenda-day)
16337 ",")))
16338 (princ "\n"))))))
16340 (defun org-fix-agenda-info (props)
16341 "FIXME"
16342 (let (tmp re)
16343 (when (setq tmp (plist-get props 'tags))
16344 (setq props (plist-put props 'tags (mapconcat 'identity tmp ":"))))
16345 (when (setq tmp (plist-get props 'date))
16346 (if (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
16347 (let ((calendar-date-display-form '(year "-" month "-" day)))
16348 '((format "%4d, %9s %2s, %4s" dayname monthname day year))
16350 (setq tmp (calendar-date-string tmp)))
16351 (setq props (plist-put props 'date tmp)))
16352 (when (setq tmp (plist-get props 'day))
16353 (if (integerp tmp) (setq tmp (calendar-gregorian-from-absolute tmp)))
16354 (let ((calendar-date-display-form '(year "-" month "-" day)))
16355 (setq tmp (calendar-date-string tmp)))
16356 (setq props (plist-put props 'day tmp))
16357 (setq props (plist-put props 'agenda-day tmp)))
16358 (when (setq tmp (plist-get props 'txt))
16359 (when (string-match "\\[#\\([A-Z0-9]\\)\\] ?" tmp)
16360 (plist-put props 'priority-letter (match-string 1 tmp))
16361 (setq tmp (replace-match "" t t tmp)))
16362 (when (and (setq re (plist-get props 'org-todo-regexp))
16363 (setq re (concat "\\`\\.*" re " ?"))
16364 (string-match re tmp))
16365 (plist-put props 'todo (match-string 1 tmp))
16366 (setq tmp (replace-match "" t t tmp)))
16367 (plist-put props 'txt tmp)))
16368 props)
16370 (defun org-agenda-export-csv-mapper (prop)
16371 (let ((res (plist-get org-agenda-info prop)))
16372 (setq res
16373 (cond
16374 ((not res) "")
16375 ((stringp res) res)
16376 (t (prin1-to-string res))))
16377 (while (string-match "," res)
16378 (setq res (replace-match ";" t t res)))
16379 (org-trim res)))
16382 ;;;###autoload
16383 (defun org-store-agenda-views (&rest parameters)
16384 (interactive)
16385 (eval (list 'org-batch-store-agenda-views)))
16387 (defvar org-agenda-buffer-name)
16389 ;; FIXME, why is this a macro?????
16390 ;;;###autoload
16391 (defmacro org-batch-store-agenda-views (&rest parameters)
16392 "Run all custom agenda commands that have a file argument."
16393 (let ((cmds org-agenda-custom-commands)
16394 (dir (default-directory))
16395 pars cmd thiscmdkey files opts)
16396 (while parameters
16397 (push (list (pop parameters) (if parameters (pop parameters))) pars))
16398 (setq pars (reverse pars))
16399 (save-window-excursion
16400 (while cmds
16401 (setq cmd (pop cmds)
16402 thiscmdkey (car cmd)
16403 opts (nth 3 cmd)
16404 files (org-last cmd))
16405 (if (stringp files) (setq files (list files)))
16406 (when files
16407 (flet ((read-char-exclusive () (string-to-char thiscmdkey)))
16408 (eval (list 'let (append org-agenda-exporter-settings opts pars)
16409 '(org-agenda nil))))
16410 (set-buffer "*Org Agenda*")
16411 (while files
16412 (eval (list 'let (append org-agenda-exporter-settings opts pars)
16413 (list 'org-write-agenda
16414 (expand-file-name (pop files) dir) t)))))
16415 (kill-buffer org-agenda-buffer-name)))))
16417 (defun org-write-agenda (file &optional nosettings)
16418 "Write the current buffer (an agenda view) as a file.
16419 Depending on the extension of the file name, plain text (.txt),
16420 HTML (.html or .htm) or Postscript (.ps) is produced.
16421 If NOSETTINGS is given, do not scope the settings of
16422 `org-agenda-exporter-settings' into the export commands. This is used when
16423 the settings have already been scoped and we do not wish to overrule other,
16424 higher priority settings."
16425 (interactive "FWrite agenda to file: ")
16426 (if (not (file-writable-p file))
16427 (error "Cannot write agenda to file %s" file))
16428 (cond
16429 ((string-match "\\.html?\\'" file) (require 'htmlize))
16430 ((string-match "\\.ps\\'" file) (require 'ps-print)))
16431 (org-let (if nosettings nil org-agenda-exporter-settings)
16432 '(save-excursion
16433 (save-window-excursion
16434 (cond
16435 ((string-match "\\.html?\\'" file)
16436 (set-buffer (htmlize-buffer (current-buffer)))
16438 (when (and org-agenda-export-html-style
16439 (string-match "<style>" org-agenda-export-html-style))
16440 ;; replace <style> section with org-agenda-export-html-style
16441 (goto-char (point-min))
16442 (kill-region (- (search-forward "<style") 6)
16443 (search-forward "</style>"))
16444 (insert org-agenda-export-html-style))
16445 (write-file file)
16446 (kill-buffer (current-buffer))
16447 (message "HTML written to %s" file))
16448 ((string-match "\\.ps\\'" file)
16449 (ps-print-buffer-with-faces file)
16450 (message "Postscript written to %s" file))
16452 (let ((bs (buffer-string)))
16453 (find-file file)
16454 (insert bs)
16455 (save-buffer 0)
16456 (kill-buffer (current-buffer))
16457 (message "Plain text written to %s" file))))))
16458 (set-buffer org-agenda-buffer-name)))
16460 (defmacro org-no-read-only (&rest body)
16461 "Inhibit read-only for BODY."
16462 `(let ((inhibit-read-only t)) ,@body))
16464 (defun org-check-for-org-mode ()
16465 "Make sure current buffer is in org-mode. Error if not."
16466 (or (org-mode-p)
16467 (error "Cannot execute org-mode agenda command on buffer in %s."
16468 major-mode)))
16470 (defun org-fit-agenda-window ()
16471 "Fit the window to the buffer size."
16472 (and (memq org-agenda-window-setup '(reorganize-frame))
16473 (fboundp 'fit-window-to-buffer)
16474 (fit-window-to-buffer nil (/ (* (frame-height) 3) 4)
16475 (/ (frame-height) 2))))
16477 ;;; Agenda file list
16479 (defun org-agenda-files (&optional unrestricted)
16480 "Get the list of agenda files.
16481 Optional UNRESTRICTED means return the full list even if a restriction
16482 is currently in place."
16483 (cond
16484 ((and (not unrestricted) (get 'org-agenda-files 'org-restrict)))
16485 ((stringp org-agenda-files) (org-read-agenda-file-list))
16486 ((listp org-agenda-files) org-agenda-files)
16487 (t (error "Invalid value of `org-agenda-files'"))))
16489 (defun org-edit-agenda-file-list ()
16490 "Edit the list of agenda files.
16491 Depending on setup, this either uses customize to edit the variable
16492 `org-agenda-files', or it visits the file that is holding the list. In the
16493 latter case, the buffer is set up in a way that saving it automatically kills
16494 the buffer and restores the previous window configuration."
16495 (interactive)
16496 (if (stringp org-agenda-files)
16497 (let ((cw (current-window-configuration)))
16498 (find-file org-agenda-files)
16499 (org-set-local 'org-window-configuration cw)
16500 (org-add-hook 'after-save-hook
16501 (lambda ()
16502 (set-window-configuration
16503 (prog1 org-window-configuration
16504 (kill-buffer (current-buffer))))
16505 (org-install-agenda-files-menu)
16506 (message "New agenda file list installed"))
16507 nil 'local)
16508 (message (substitute-command-keys
16509 "Edit list and finish with \\[save-buffer]")))
16510 (customize-variable 'org-agenda-files)))
16512 (defun org-store-new-agenda-file-list (list)
16513 "Set new value for the agenda file list and save it correcly."
16514 (if (stringp org-agenda-files)
16515 (let ((f org-agenda-files) b)
16516 (while (setq b (find-buffer-visiting f)) (kill-buffer b))
16517 (with-temp-file f
16518 (insert (mapconcat 'identity list "\n") "\n")))
16519 (let ((org-mode-hook nil) (default-major-mode 'fundamental-mode))
16520 (setq org-agenda-files list)
16521 (customize-save-variable 'org-agenda-files org-agenda-files))))
16523 (defun org-read-agenda-file-list ()
16524 "Read the list of agenda files from a file."
16525 (when (stringp org-agenda-files)
16526 (with-temp-buffer
16527 (insert-file-contents org-agenda-files)
16528 (org-split-string (buffer-string) "[ \t\r\n]*?[\r\n][ \t\r\n]*"))))
16531 ;;;###autoload
16532 (defun org-cycle-agenda-files ()
16533 "Cycle through the files in `org-agenda-files'.
16534 If the current buffer visits an agenda file, find the next one in the list.
16535 If the current buffer does not, find the first agenda file."
16536 (interactive)
16537 (let* ((fs (org-agenda-files t))
16538 (files (append fs (list (car fs))))
16539 (tcf (if buffer-file-name (file-truename buffer-file-name)))
16540 file)
16541 (unless files (error "No agenda files"))
16542 (catch 'exit
16543 (while (setq file (pop files))
16544 (if (equal (file-truename file) tcf)
16545 (when (car files)
16546 (find-file (car files))
16547 (throw 'exit t))))
16548 (find-file (car fs)))
16549 (if (buffer-base-buffer) (switch-to-buffer (buffer-base-buffer)))))
16551 (defun org-agenda-file-to-front (&optional to-end)
16552 "Move/add the current file to the top of the agenda file list.
16553 If the file is not present in the list, it is added to the front. If it is
16554 present, it is moved there. With optional argument TO-END, add/move to the
16555 end of the list."
16556 (interactive "P")
16557 (let ((file-alist (mapcar (lambda (x)
16558 (cons (file-truename x) x))
16559 (org-agenda-files t)))
16560 (ctf (file-truename buffer-file-name))
16561 x had)
16562 (setq x (assoc ctf file-alist) had x)
16564 (if (not x) (setq x (cons ctf (abbreviate-file-name buffer-file-name))))
16565 (if to-end
16566 (setq file-alist (append (delq x file-alist) (list x)))
16567 (setq file-alist (cons x (delq x file-alist))))
16568 (org-store-new-agenda-file-list (mapcar 'cdr file-alist))
16569 (org-install-agenda-files-menu)
16570 (message "File %s to %s of agenda file list"
16571 (if had "moved" "added") (if to-end "end" "front"))))
16573 (defun org-remove-file (&optional file)
16574 "Remove current file from the list of files in variable `org-agenda-files'.
16575 These are the files which are being checked for agenda entries.
16576 Optional argument FILE means, use this file instead of the current."
16577 (interactive)
16578 (let* ((file (or file buffer-file-name))
16579 (true-file (file-truename file))
16580 (afile (abbreviate-file-name file))
16581 (files (delq nil (mapcar
16582 (lambda (x)
16583 (if (equal true-file
16584 (file-truename x))
16585 nil x))
16586 (org-agenda-files t)))))
16587 (if (not (= (length files) (length (org-agenda-files t))))
16588 (progn
16589 (org-store-new-agenda-file-list files)
16590 (org-install-agenda-files-menu)
16591 (message "Removed file: %s" afile))
16592 (message "File was not in list: %s" afile))))
16594 (defun org-file-menu-entry (file)
16595 (vector file (list 'find-file file) t))
16597 (defun org-check-agenda-file (file)
16598 "Make sure FILE exists. If not, ask user what to do."
16599 (when (not (file-exists-p file))
16600 (message "non-existent file %s. [R]emove from list or [A]bort?"
16601 (abbreviate-file-name file))
16602 (let ((r (downcase (read-char-exclusive))))
16603 (cond
16604 ((equal r ?r)
16605 (org-remove-file file)
16606 (throw 'nextfile t))
16607 (t (error "Abort"))))))
16609 ;;; Agenda prepare and finalize
16611 (defvar org-agenda-multi nil) ; dynammically scoped
16612 (defvar org-agenda-buffer-name "*Org Agenda*")
16613 (defvar org-pre-agenda-window-conf nil)
16614 (defvar org-agenda-name nil)
16615 (defun org-prepare-agenda (&optional name)
16616 (setq org-todo-keywords-for-agenda nil)
16617 (setq org-done-keywords-for-agenda nil)
16618 (if org-agenda-multi
16619 (progn
16620 (setq buffer-read-only nil)
16621 (goto-char (point-max))
16622 (unless (= (point) 1)
16623 (insert "\n" (make-string (window-width) ?=) "\n"))
16624 (narrow-to-region (point) (point-max)))
16625 (org-agenda-maybe-reset-markers 'force)
16626 (org-prepare-agenda-buffers (org-agenda-files))
16627 (setq org-todo-keywords-for-agenda
16628 (org-uniquify org-todo-keywords-for-agenda))
16629 (setq org-done-keywords-for-agenda
16630 (org-uniquify org-done-keywords-for-agenda))
16631 (let* ((abuf (get-buffer-create org-agenda-buffer-name))
16632 (awin (get-buffer-window abuf)))
16633 (cond
16634 ((equal (current-buffer) abuf) nil)
16635 (awin (select-window awin))
16636 ((not (setq org-pre-agenda-window-conf (current-window-configuration))))
16637 ((equal org-agenda-window-setup 'current-window)
16638 (switch-to-buffer abuf))
16639 ((equal org-agenda-window-setup 'other-window)
16640 (switch-to-buffer-other-window abuf))
16641 ((equal org-agenda-window-setup 'other-frame)
16642 (switch-to-buffer-other-frame abuf))
16643 ((equal org-agenda-window-setup 'reorganize-frame)
16644 (delete-other-windows)
16645 (switch-to-buffer-other-window abuf))))
16646 (setq buffer-read-only nil)
16647 (erase-buffer)
16648 (org-agenda-mode)
16649 (and name (not org-agenda-name)
16650 (org-set-local 'org-agenda-name name)))
16651 (setq buffer-read-only nil))
16653 (defun org-finalize-agenda ()
16654 "Finishing touch for the agenda buffer, called just before displaying it."
16655 (unless org-agenda-multi
16656 (save-excursion
16657 (let ((buffer-read-only))
16658 (goto-char (point-min))
16659 (while (org-activate-bracket-links (point-max))
16660 (add-text-properties (match-beginning 0) (match-end 0)
16661 '(face org-link)))
16662 (org-agenda-align-tags)
16663 (unless org-agenda-with-colors
16664 (remove-text-properties (point-min) (point-max) '(face nil))))
16665 (if (and (boundp 'org-overriding-columns-format)
16666 org-overriding-columns-format)
16667 (org-set-local 'org-overriding-columns-format
16668 org-overriding-columns-format))
16669 (if (and (boundp 'org-agenda-view-columns-initially)
16670 org-agenda-view-columns-initially)
16671 (org-agenda-columns))
16672 (run-hooks 'org-finalize-agenda-hook))))
16674 (defun org-prepare-agenda-buffers (files)
16675 "Create buffers for all agenda files, protect archived trees and comments."
16676 (interactive)
16677 (let ((pa '(:org-archived t))
16678 (pc '(:org-comment t))
16679 (pall '(:org-archived t :org-comment t))
16680 (rea (concat ":" org-archive-tag ":"))
16681 bmp file re)
16682 (save-excursion
16683 (save-restriction
16684 (while (setq file (pop files))
16685 (org-check-agenda-file file)
16686 (set-buffer (org-get-agenda-file-buffer file))
16687 (widen)
16688 (setq bmp (buffer-modified-p))
16689 (setq org-todo-keywords-for-agenda
16690 (append org-todo-keywords-for-agenda org-todo-keywords-1))
16691 (setq org-done-keywords-for-agenda
16692 (append org-done-keywords-for-agenda org-done-keywords))
16693 (save-excursion
16694 (remove-text-properties (point-min) (point-max) pall)
16695 (when org-agenda-skip-archived-trees
16696 (goto-char (point-min))
16697 (while (re-search-forward rea nil t)
16698 (if (org-on-heading-p t)
16699 (add-text-properties (point-at-bol) (org-end-of-subtree t) pa))))
16700 (goto-char (point-min))
16701 (setq re (concat "^\\*+ +" org-comment-string "\\>"))
16702 (while (re-search-forward re nil t)
16703 (add-text-properties
16704 (match-beginning 0) (org-end-of-subtree t) pc)))
16705 (set-buffer-modified-p bmp))))))
16707 (defvar org-agenda-skip-function nil
16708 "Function to be called at each match during agenda construction.
16709 If this function return nil, the current match should not be skipped.
16710 Otherwise, the function must return a position from where the search
16711 should be continued.
16712 Never set this variable using `setq' or so, because then it will apply
16713 to all future agenda commands. Instead, bind it with `let' to scope
16714 it dynamically into the agenda-constructing command.")
16716 (defun org-agenda-skip ()
16717 "Throw to `:skip' in places that should be skipped.
16718 Also moves point to the end of the skipped region, so that search can
16719 continue from there."
16720 (let ((p (point-at-bol)) to)
16721 (and org-agenda-skip-archived-trees
16722 (get-text-property p :org-archived)
16723 (org-end-of-subtree t)
16724 (throw :skip t))
16725 (and (get-text-property p :org-comment)
16726 (org-end-of-subtree t)
16727 (throw :skip t))
16728 (if (equal (char-after p) ?#) (throw :skip t))
16729 (when (and (functionp org-agenda-skip-function)
16730 (setq to (save-excursion
16731 (save-match-data
16732 (funcall org-agenda-skip-function)))))
16733 (goto-char to)
16734 (throw :skip t))))
16736 (defvar org-agenda-markers nil
16737 "List of all currently active markers created by `org-agenda'.")
16738 (defvar org-agenda-last-marker-time (time-to-seconds (current-time))
16739 "Creation time of the last agenda marker.")
16741 (defun org-agenda-new-marker (&optional pos)
16742 "Return a new agenda marker.
16743 Org-mode keeps a list of these markers and resets them when they are
16744 no longer in use."
16745 (let ((m (copy-marker (or pos (point)))))
16746 (setq org-agenda-last-marker-time (time-to-seconds (current-time)))
16747 (push m org-agenda-markers)
16750 (defun org-agenda-maybe-reset-markers (&optional force)
16751 "Reset markers created by `org-agenda'. But only if they are old enough."
16752 (if (or (and force (not org-agenda-multi))
16753 (> (- (time-to-seconds (current-time))
16754 org-agenda-last-marker-time)
16756 (while org-agenda-markers
16757 (move-marker (pop org-agenda-markers) nil))))
16759 (defvar org-agenda-new-buffers nil
16760 "Buffers created to visit agenda files.")
16762 (defun org-get-agenda-file-buffer (file)
16763 "Get a buffer visiting FILE. If the buffer needs to be created, add
16764 it to the list of buffers which might be released later."
16765 (let ((buf (org-find-base-buffer-visiting file)))
16766 (if buf
16767 buf ; just return it
16768 ;; Make a new buffer and remember it
16769 (setq buf (find-file-noselect file))
16770 (if buf (push buf org-agenda-new-buffers))
16771 buf)))
16773 (defun org-release-buffers (blist)
16774 "Release all buffers in list, asking the user for confirmation when needed.
16775 When a buffer is unmodified, it is just killed. When modified, it is saved
16776 \(if the user agrees) and then killed."
16777 (let (buf file)
16778 (while (setq buf (pop blist))
16779 (setq file (buffer-file-name buf))
16780 (when (and (buffer-modified-p buf)
16781 file
16782 (y-or-n-p (format "Save file %s? " file)))
16783 (with-current-buffer buf (save-buffer)))
16784 (kill-buffer buf))))
16786 (defvar org-category-table nil)
16787 (defun org-get-category-table ()
16788 "Get the table of categories and positions in current buffer."
16789 (let (tbl)
16790 (save-excursion
16791 (save-restriction
16792 (widen)
16793 (goto-char (point-min))
16794 (while (re-search-forward "^#\\+CATEGORY:[ \t]*\\(.*\\)"
16795 nil t)
16796 (push (cons (match-beginning 1)
16797 (org-trim (match-string 1))) tbl))))
16798 tbl))
16800 (defun org-get-category (&optional pos)
16801 "Get the category applying to position POS."
16802 (if (not org-category-table)
16803 (cond
16804 ((null org-category)
16805 (setq org-category
16806 (if buffer-file-name
16807 (file-name-sans-extension
16808 (file-name-nondirectory buffer-file-name))
16809 "???")))
16810 ((symbolp org-category) (symbol-name org-category))
16811 (t org-category))
16812 (let ((tbl org-category-table)
16813 (pos (or pos (point))))
16814 (while (and tbl (> (caar tbl) pos))
16815 (pop tbl))
16816 (or (cdar tbl) (cdr (nth (1- (length org-category-table))
16817 org-category-table))))))
16818 ;;; Agenda timeline
16820 (defun org-timeline (&optional include-all)
16821 "Show a time-sorted view of the entries in the current org file.
16822 Only entries with a time stamp of today or later will be listed. With
16823 \\[universal-argument] prefix, all unfinished TODO items will also be shown,
16824 under the current date.
16825 If the buffer contains an active region, only check the region for
16826 dates."
16827 (interactive "P")
16828 (require 'calendar)
16829 (org-compile-prefix-format 'timeline)
16830 (org-set-sorting-strategy 'timeline)
16831 (let* ((dopast t)
16832 (dotodo include-all)
16833 (doclosed org-agenda-show-log)
16834 (entry buffer-file-name)
16835 (date (calendar-current-date))
16836 (beg (if (org-region-active-p) (region-beginning) (point-min)))
16837 (end (if (org-region-active-p) (region-end) (point-max)))
16838 (day-numbers (org-get-all-dates beg end 'no-ranges
16839 t doclosed ; always include today
16840 org-timeline-show-empty-dates))
16841 (today (time-to-days (current-time)))
16842 (past t)
16843 args
16844 s e rtn d emptyp)
16845 (setq org-agenda-redo-command
16846 (list 'progn
16847 (list 'switch-to-buffer-other-window (current-buffer))
16848 (list 'org-timeline (list 'quote include-all))))
16849 (if (not dopast)
16850 ;; Remove past dates from the list of dates.
16851 (setq day-numbers (delq nil (mapcar (lambda(x)
16852 (if (>= x today) x nil))
16853 day-numbers))))
16854 (org-prepare-agenda (concat "Timeline "
16855 (file-name-nondirectory buffer-file-name)))
16856 (if doclosed (push :closed args))
16857 (push :timestamp args)
16858 (push :sexp args)
16859 (if dotodo (push :todo args))
16860 (while (setq d (pop day-numbers))
16861 (if (and (listp d) (eq (car d) :omitted))
16862 (progn
16863 (setq s (point))
16864 (insert (format "\n[... %d empty days omitted]\n\n" (cdr d)))
16865 (put-text-property s (1- (point)) 'face 'org-agenda-structure))
16866 (if (listp d) (setq d (car d) emptyp t) (setq emptyp nil))
16867 (if (and (>= d today)
16868 dopast
16869 past)
16870 (progn
16871 (setq past nil)
16872 (insert (make-string 79 ?-) "\n")))
16873 (setq date (calendar-gregorian-from-absolute d))
16874 (setq s (point))
16875 (setq rtn (and (not emptyp)
16876 (apply 'org-agenda-get-day-entries
16877 entry date args)))
16878 (if (or rtn (equal d today) org-timeline-show-empty-dates)
16879 (progn
16880 (insert (calendar-day-name date) " "
16881 (number-to-string (extract-calendar-day date)) " "
16882 (calendar-month-name (extract-calendar-month date)) " "
16883 (number-to-string (extract-calendar-year date)) "\n")
16884 ; FIXME: this gives a timezone problem
16885 ; (insert (format-time-string org-agenda-date-format
16886 ; (calendar-time-from-absolute d 0))
16887 ; "\n")
16888 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
16889 (put-text-property s (1- (point)) 'org-date-line t)
16890 (if (equal d today)
16891 (put-text-property s (1- (point)) 'org-today t))
16892 (and rtn (insert (org-finalize-agenda-entries rtn) "\n"))
16893 (put-text-property s (1- (point)) 'day d)))))
16894 (goto-char (point-min))
16895 (goto-char (or (text-property-any (point-min) (point-max) 'org-today t)
16896 (point-min)))
16897 (add-text-properties (point-min) (point-max) '(org-agenda-type timeline))
16898 (org-finalize-agenda)
16899 (setq buffer-read-only t)))
16901 (defun org-get-all-dates (beg end &optional no-ranges force-today inactive empty)
16902 "Return a list of all relevant day numbers from BEG to END buffer positions.
16903 If NO-RANGES is non-nil, include only the start and end dates of a range,
16904 not every single day in the range. If FORCE-TODAY is non-nil, make
16905 sure that TODAY is included in the list. If INACTIVE is non-nil, also
16906 inactive time stamps (those in square brackets) are included.
16907 When EMPTY is non-nil, also include days without any entries."
16908 (let ((re (if inactive org-ts-regexp-both org-ts-regexp))
16909 dates dates1 date day day1 day2 ts1 ts2)
16910 (if force-today
16911 (setq dates (list (time-to-days (current-time)))))
16912 (save-excursion
16913 (goto-char beg)
16914 (while (re-search-forward re end t)
16915 (setq day (time-to-days (org-time-string-to-time
16916 (substring (match-string 1) 0 10))))
16917 (or (memq day dates) (push day dates)))
16918 (unless no-ranges
16919 (goto-char beg)
16920 (while (re-search-forward org-tr-regexp end t)
16921 (setq ts1 (substring (match-string 1) 0 10)
16922 ts2 (substring (match-string 2) 0 10)
16923 day1 (time-to-days (org-time-string-to-time ts1))
16924 day2 (time-to-days (org-time-string-to-time ts2)))
16925 (while (< (setq day1 (1+ day1)) day2)
16926 (or (memq day1 dates) (push day1 dates)))))
16927 (setq dates (sort dates '<))
16928 (when empty
16929 (while (setq day (pop dates))
16930 (setq day2 (car dates))
16931 (push day dates1)
16932 (when (and day2 empty)
16933 (if (or (eq empty t)
16934 (and (numberp empty) (<= (- day2 day) empty)))
16935 (while (< (setq day (1+ day)) day2)
16936 (push (list day) dates1))
16937 (push (cons :omitted (- day2 day)) dates1))))
16938 (setq dates (nreverse dates1)))
16939 dates)))
16941 ;;; Agenda Daily/Weekly
16943 (defvar org-agenda-overriding-arguments nil) ; dynamically scoped parameter
16944 (defvar org-agenda-start-day nil) ; dynamically scoped parameter
16945 (defvar org-agenda-last-arguments nil
16946 "The arguments of the previous call to org-agenda")
16947 (defvar org-starting-day nil) ; local variable in the agenda buffer
16948 (defvar org-agenda-span nil) ; local variable in the agenda buffer
16949 (defvar org-include-all-loc nil) ; local variable
16952 ;;;###autoload
16953 (defun org-agenda-list (&optional include-all start-day ndays)
16954 "Produce a weekly view from all files in variable `org-agenda-files'.
16955 The view will be for the current week, but from the overview buffer you
16956 will be able to go to other weeks.
16957 With one \\[universal-argument] prefix argument INCLUDE-ALL, all unfinished TODO items will
16958 also be shown, under the current date.
16959 With two \\[universal-argument] prefix argument INCLUDE-ALL, all TODO entries marked DONE
16960 on the days are also shown. See the variable `org-log-done' for how
16961 to turn on logging.
16962 START-DAY defaults to TODAY, or to the most recent match for the weekday
16963 given in `org-agenda-start-on-weekday'.
16964 NDAYS defaults to `org-agenda-ndays'."
16965 (interactive "P")
16966 (setq ndays (or ndays org-agenda-ndays)
16967 start-day (or start-day org-agenda-start-day))
16968 (if org-agenda-overriding-arguments
16969 (setq include-all (car org-agenda-overriding-arguments)
16970 start-day (nth 1 org-agenda-overriding-arguments)
16971 ndays (nth 2 org-agenda-overriding-arguments)))
16972 (if (stringp start-day)
16973 ;; Convert to an absolute day number
16974 (setq start-day (time-to-days (org-read-date nil t start-day))))
16975 (setq org-agenda-last-arguments (list include-all start-day ndays))
16976 (org-compile-prefix-format 'agenda)
16977 (org-set-sorting-strategy 'agenda)
16978 (require 'calendar)
16979 (let* ((org-agenda-start-on-weekday
16980 (if (or (equal ndays 7) (and (null ndays) (equal 7 org-agenda-ndays)))
16981 org-agenda-start-on-weekday nil))
16982 (thefiles (org-agenda-files))
16983 (files thefiles)
16984 (today (time-to-days (current-time)))
16985 (sd (or start-day today))
16986 (start (if (or (null org-agenda-start-on-weekday)
16987 (< org-agenda-ndays 7))
16989 (let* ((nt (calendar-day-of-week
16990 (calendar-gregorian-from-absolute sd)))
16991 (n1 org-agenda-start-on-weekday)
16992 (d (- nt n1)))
16993 (- sd (+ (if (< d 0) 7 0) d)))))
16994 (day-numbers (list start))
16995 (inhibit-redisplay (not debug-on-error))
16996 s e rtn rtnall file date d start-pos end-pos todayp nd)
16997 (setq org-agenda-redo-command
16998 (list 'org-agenda-list (list 'quote include-all) start-day ndays))
16999 ;; Make the list of days
17000 (setq ndays (or ndays org-agenda-ndays)
17001 nd ndays)
17002 (while (> ndays 1)
17003 (push (1+ (car day-numbers)) day-numbers)
17004 (setq ndays (1- ndays)))
17005 (setq day-numbers (nreverse day-numbers))
17006 (org-prepare-agenda "Day/Week")
17007 (org-set-local 'org-starting-day (car day-numbers))
17008 (org-set-local 'org-include-all-loc include-all)
17009 (org-set-local 'org-agenda-span
17010 (org-agenda-ndays-to-span nd))
17011 (when (and (or include-all org-agenda-include-all-todo)
17012 (member today day-numbers))
17013 (setq files thefiles
17014 rtnall nil)
17015 (while (setq file (pop files))
17016 (catch 'nextfile
17017 (org-check-agenda-file file)
17018 (setq date (calendar-gregorian-from-absolute today)
17019 rtn (org-agenda-get-day-entries
17020 file date :todo))
17021 (setq rtnall (append rtnall rtn))))
17022 (when rtnall
17023 (insert "ALL CURRENTLY OPEN TODO ITEMS:\n")
17024 (add-text-properties (point-min) (1- (point))
17025 (list 'face 'org-agenda-structure))
17026 (insert (org-finalize-agenda-entries rtnall) "\n")))
17027 (setq s (point))
17028 (insert (capitalize (symbol-name (org-agenda-ndays-to-span nd)))
17029 "-agenda:\n")
17030 (add-text-properties s (1- (point)) (list 'face 'org-agenda-structure
17031 'org-date-line t))
17032 (while (setq d (pop day-numbers))
17033 (setq date (calendar-gregorian-from-absolute d)
17034 s (point))
17035 (if (or (setq todayp (= d today))
17036 (and (not start-pos) (= d sd)))
17037 (setq start-pos (point))
17038 (if (and start-pos (not end-pos))
17039 (setq end-pos (point))))
17040 (setq files thefiles
17041 rtnall nil)
17042 (while (setq file (pop files))
17043 (catch 'nextfile
17044 (org-check-agenda-file file)
17045 (if org-agenda-show-log
17046 (setq rtn (org-agenda-get-day-entries
17047 file date
17048 :deadline :scheduled :timestamp :sexp :closed))
17049 (setq rtn (org-agenda-get-day-entries
17050 file date
17051 :deadline :scheduled :sexp :timestamp)))
17052 (setq rtnall (append rtnall rtn))))
17053 (if org-agenda-include-diary
17054 (progn
17055 (require 'diary-lib)
17056 (setq rtn (org-get-entries-from-diary date))
17057 (setq rtnall (append rtnall rtn))))
17058 (if (or rtnall org-agenda-show-all-dates)
17059 (progn
17060 (insert (format "%-9s %2d %s %4d\n"
17061 (calendar-day-name date)
17062 (extract-calendar-day date)
17063 (calendar-month-name (extract-calendar-month date))
17064 (extract-calendar-year date)))
17065 ; FIXME: this gives a timezone problem
17066 ; (insert (format-time-string org-agenda-date-format
17067 ; (calendar-time-from-absolute d 0)) "\n")
17068 (put-text-property s (1- (point)) 'face 'org-agenda-structure)
17069 (put-text-property s (1- (point)) 'org-date-line t)
17070 (if todayp (put-text-property s (1- (point)) 'org-today t))
17071 (if rtnall (insert
17072 (org-finalize-agenda-entries
17073 (org-agenda-add-time-grid-maybe
17074 rtnall nd todayp))
17075 "\n"))
17076 (put-text-property s (1- (point)) 'day d))))
17077 (goto-char (point-min))
17078 (org-fit-agenda-window)
17079 (unless (and (pos-visible-in-window-p (point-min))
17080 (pos-visible-in-window-p (point-max)))
17081 (goto-char (1- (point-max)))
17082 (recenter -1)
17083 (if (not (pos-visible-in-window-p (or start-pos 1)))
17084 (progn
17085 (goto-char (or start-pos 1))
17086 (recenter 1))))
17087 (goto-char (or start-pos 1))
17088 (add-text-properties (point-min) (point-max) '(org-agenda-type agenda))
17089 (org-finalize-agenda)
17090 (setq buffer-read-only t)
17091 (message "")))
17093 (defun org-agenda-ndays-to-span (n)
17094 (cond ((< n 7) 'day) ((= n 7) 'week) ((< n 32) 'month) (t 'year)))
17096 ;;; Agenda TODO list
17098 (defvar org-select-this-todo-keyword nil)
17099 (defvar org-last-arg nil)
17101 ;;;###autoload
17102 (defun org-todo-list (arg)
17103 "Show all TODO entries from all agenda file in a single list.
17104 The prefix arg can be used to select a specific TODO keyword and limit
17105 the list to these. When using \\[universal-argument], you will be prompted
17106 for a keyword. A numeric prefix directly selects the Nth keyword in
17107 `org-todo-keywords-1'."
17108 (interactive "P")
17109 (require 'calendar)
17110 (org-compile-prefix-format 'todo)
17111 (org-set-sorting-strategy 'todo)
17112 (org-prepare-agenda "TODO")
17113 (let* ((today (time-to-days (current-time)))
17114 (date (calendar-gregorian-from-absolute today))
17115 (kwds org-todo-keywords-for-agenda)
17116 (completion-ignore-case t)
17117 (org-select-this-todo-keyword
17118 (if (stringp arg) arg
17119 (and arg (integerp arg) (> arg 0)
17120 (nth (1- arg) kwds))))
17121 rtn rtnall files file pos)
17122 (when (equal arg '(4))
17123 (setq org-select-this-todo-keyword
17124 (completing-read "Keyword (or KWD1|K2D2|...): "
17125 (mapcar 'list kwds) nil nil)))
17126 (and (equal 0 arg) (setq org-select-this-todo-keyword nil))
17127 (org-set-local 'org-last-arg arg)
17128 (setq org-agenda-redo-command
17129 '(org-todo-list (or current-prefix-arg org-last-arg)))
17130 (setq files (org-agenda-files)
17131 rtnall nil)
17132 (while (setq file (pop files))
17133 (catch 'nextfile
17134 (org-check-agenda-file file)
17135 (setq rtn (org-agenda-get-day-entries file date :todo))
17136 (setq rtnall (append rtnall rtn))))
17137 (if org-agenda-overriding-header
17138 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
17139 nil 'face 'org-agenda-structure) "\n")
17140 (insert "Global list of TODO items of type: ")
17141 (add-text-properties (point-min) (1- (point))
17142 (list 'face 'org-agenda-structure))
17143 (setq pos (point))
17144 (insert (or org-select-this-todo-keyword "ALL") "\n")
17145 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
17146 (setq pos (point))
17147 (unless org-agenda-multi
17148 (insert "Available with `N r': (0)ALL")
17149 (let ((n 0) s)
17150 (mapc (lambda (x)
17151 (setq s (format "(%d)%s" (setq n (1+ n)) x))
17152 (if (> (+ (current-column) (string-width s) 1) (frame-width))
17153 (insert "\n "))
17154 (insert " " s))
17155 kwds))
17156 (insert "\n"))
17157 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
17158 (when rtnall
17159 (insert (org-finalize-agenda-entries rtnall) "\n"))
17160 (goto-char (point-min))
17161 (org-fit-agenda-window)
17162 (add-text-properties (point-min) (point-max) '(org-agenda-type todo))
17163 (org-finalize-agenda)
17164 (setq buffer-read-only t)))
17166 ;;; Agenda tags match
17168 ;;;###autoload
17169 (defun org-tags-view (&optional todo-only match)
17170 "Show all headlines for all `org-agenda-files' matching a TAGS criterion.
17171 The prefix arg TODO-ONLY limits the search to TODO entries."
17172 (interactive "P")
17173 (org-compile-prefix-format 'tags)
17174 (org-set-sorting-strategy 'tags)
17175 (let* ((org-tags-match-list-sublevels
17176 (if todo-only t org-tags-match-list-sublevels))
17177 (completion-ignore-case t)
17178 rtn rtnall files file pos matcher
17179 buffer)
17180 (setq matcher (org-make-tags-matcher match)
17181 match (car matcher) matcher (cdr matcher))
17182 (org-prepare-agenda (concat "TAGS " match))
17183 (setq org-agenda-redo-command
17184 (list 'org-tags-view (list 'quote todo-only)
17185 (list 'if 'current-prefix-arg nil match)))
17186 (setq files (org-agenda-files)
17187 rtnall nil)
17188 (while (setq file (pop files))
17189 (catch 'nextfile
17190 (org-check-agenda-file file)
17191 (setq buffer (if (file-exists-p file)
17192 (org-get-agenda-file-buffer file)
17193 (error "No such file %s" file)))
17194 (if (not buffer)
17195 ;; If file does not exist, merror message to agenda
17196 (setq rtn (list
17197 (format "ORG-AGENDA-ERROR: No such org-file %s" file))
17198 rtnall (append rtnall rtn))
17199 (with-current-buffer buffer
17200 (unless (org-mode-p)
17201 (error "Agenda file %s is not in `org-mode'" file))
17202 (setq org-category-table (org-get-category-table))
17203 (save-excursion
17204 (save-restriction
17205 (if org-agenda-restrict
17206 (narrow-to-region org-agenda-restrict-begin
17207 org-agenda-restrict-end)
17208 (widen))
17209 (setq rtn (org-scan-tags 'agenda matcher todo-only))
17210 (setq rtnall (append rtnall rtn))))))))
17211 (if org-agenda-overriding-header
17212 (insert (org-add-props (copy-sequence org-agenda-overriding-header)
17213 nil 'face 'org-agenda-structure) "\n")
17214 (insert "Headlines with TAGS match: ")
17215 (add-text-properties (point-min) (1- (point))
17216 (list 'face 'org-agenda-structure))
17217 (setq pos (point))
17218 (insert match "\n")
17219 (add-text-properties pos (1- (point)) (list 'face 'org-warning))
17220 (setq pos (point))
17221 (unless org-agenda-multi
17222 (insert "Press `C-u r' to search again with new search string\n"))
17223 (add-text-properties pos (1- (point)) (list 'face 'org-agenda-structure)))
17224 (when rtnall
17225 (insert (org-finalize-agenda-entries rtnall) "\n"))
17226 (goto-char (point-min))
17227 (org-fit-agenda-window)
17228 (add-text-properties (point-min) (point-max) '(org-agenda-type tags))
17229 (org-finalize-agenda)
17230 (setq buffer-read-only t)))
17232 ;;; Agenda Finding stuck projects
17234 (defvar org-agenda-skip-regexp nil
17235 "Regular expression used in skipping subtrees for the agenda.
17236 This is basically a temporary global variable that can be set and then
17237 used by user-defined selections using `org-agenda-skip-function'.")
17239 (defvar org-agenda-overriding-header nil
17240 "When this is set during todo and tags searches, will replace header.")
17242 (defun org-agenda-skip-subtree-when-regexp-matches ()
17243 "Checks if the current subtree contains match for `org-agenda-skip-regexp'.
17244 If yes, it returns the end position of this tree, causing agenda commands
17245 to skip this subtree. This is a function that can be put into
17246 `org-agenda-skip-function' for the duration of a command."
17247 (save-match-data
17248 (let ((end (save-excursion (org-end-of-subtree t)))
17249 skip)
17250 (save-excursion
17251 (setq skip (re-search-forward org-agenda-skip-regexp end t)))
17252 (and skip end))))
17254 (defun org-agenda-list-stuck-projects (&rest ignore)
17255 "Create agenda view for projects that are stuck.
17256 Stuck projects are project that have no next actions. For the definitions
17257 of what a project is and how to check if it stuck, customize the variable
17258 `org-stuck-projects'.
17259 MATCH is being ignored."
17260 (interactive)
17261 (let* ((org-agenda-skip-function 'org-agenda-skip-subtree-when-regexp-matches)
17262 (org-agenda-overriding-header "List of stuck projects: ")
17263 (matcher (nth 0 org-stuck-projects))
17264 (todo (nth 1 org-stuck-projects))
17265 (todo-wds (if (member "*" todo)
17266 (progn
17267 (org-prepare-agenda-buffers (org-agenda-files))
17268 (org-delete-all
17269 org-done-keywords-for-agenda
17270 (copy-sequence org-todo-keywords-for-agenda)))
17271 todo))
17272 (todo-re (concat "^\\*+[ \t]+\\("
17273 (mapconcat 'identity todo-wds "\\|")
17274 "\\)\\>"))
17275 (tags (nth 2 org-stuck-projects))
17276 (tags-re (if (member "*" tags)
17277 (org-re "^\\*+ .*:[[:alnum:]_@]+:[ \t]*$")
17278 (concat "^\\*+ .*:\\("
17279 (mapconcat 'identity tags "\\|")
17280 (org-re "\\):[[:alnum:]_@:]*[ \t]*$"))))
17281 (gen-re (nth 3 org-stuck-projects))
17282 (re-list
17283 (delq nil
17284 (list
17285 (if todo todo-re)
17286 (if tags tags-re)
17287 (and gen-re (stringp gen-re) (string-match "\\S-" gen-re)
17288 gen-re)))))
17289 (setq org-agenda-skip-regexp
17290 (if re-list
17291 (mapconcat 'identity re-list "\\|")
17292 (error "No information how to identify unstuck projects")))
17293 (org-tags-view nil matcher)
17294 (with-current-buffer org-agenda-buffer-name
17295 (setq org-agenda-redo-command
17296 '(org-agenda-list-stuck-projects
17297 (or current-prefix-arg org-last-arg))))))
17299 ;;; Diary integration
17301 (defvar org-disable-agenda-to-diary nil) ;Dynamically-scoped param.
17303 (defun org-get-entries-from-diary (date)
17304 "Get the (Emacs Calendar) diary entries for DATE."
17305 (let* ((fancy-diary-buffer "*temporary-fancy-diary-buffer*")
17306 (diary-display-hook '(fancy-diary-display))
17307 (list-diary-entries-hook
17308 (cons 'org-diary-default-entry list-diary-entries-hook))
17309 (diary-file-name-prefix-function nil) ; turn this feature off
17310 (diary-modify-entry-list-string-function 'org-modify-diary-entry-string)
17311 entries
17312 (org-disable-agenda-to-diary t))
17313 (save-excursion
17314 (save-window-excursion
17315 (list-diary-entries date 1))) ;; Keep this name for now, compatibility
17316 (if (not (get-buffer fancy-diary-buffer))
17317 (setq entries nil)
17318 (with-current-buffer fancy-diary-buffer
17319 (setq buffer-read-only nil)
17320 (if (= (point-max) 1)
17321 ;; No entries
17322 (setq entries nil)
17323 ;; Omit the date and other unnecessary stuff
17324 (org-agenda-cleanup-fancy-diary)
17325 ;; Add prefix to each line and extend the text properties
17326 (if (= (point-max) 1)
17327 (setq entries nil)
17328 (setq entries (buffer-substring (point-min) (- (point-max) 1)))))
17329 (set-buffer-modified-p nil)
17330 (kill-buffer fancy-diary-buffer)))
17331 (when entries
17332 (setq entries (org-split-string entries "\n"))
17333 (setq entries
17334 (mapcar
17335 (lambda (x)
17336 (setq x (org-format-agenda-item "" x "Diary" nil 'time))
17337 ;; Extend the text properties to the beginning of the line
17338 (org-add-props x (text-properties-at (1- (length x)) x)
17339 'type "diary" 'date date))
17340 entries)))))
17342 (defun org-agenda-cleanup-fancy-diary ()
17343 "Remove unwanted stuff in buffer created by `fancy-diary-display'.
17344 This gets rid of the date, the underline under the date, and
17345 the dummy entry installed by `org-mode' to ensure non-empty diary for each
17346 date. It also removes lines that contain only whitespace."
17347 (goto-char (point-min))
17348 (if (looking-at ".*?:[ \t]*")
17349 (progn
17350 (replace-match "")
17351 (re-search-forward "\n=+$" nil t)
17352 (replace-match "")
17353 (while (re-search-backward "^ +\n?" nil t) (replace-match "")))
17354 (re-search-forward "\n=+$" nil t)
17355 (delete-region (point-min) (min (point-max) (1+ (match-end 0)))))
17356 (goto-char (point-min))
17357 (while (re-search-forward "^ +\n" nil t)
17358 (replace-match ""))
17359 (goto-char (point-min))
17360 (if (re-search-forward "^Org-mode dummy\n?" nil t)
17361 (replace-match "")))
17363 ;; Make sure entries from the diary have the right text properties.
17364 (eval-after-load "diary-lib"
17365 '(if (boundp 'diary-modify-entry-list-string-function)
17366 ;; We can rely on the hook, nothing to do
17368 ;; Hook not avaiable, must use advice to make this work
17369 (defadvice add-to-diary-list (before org-mark-diary-entry activate)
17370 "Make the position visible."
17371 (if (and org-disable-agenda-to-diary ;; called from org-agenda
17372 (stringp string)
17373 buffer-file-name)
17374 (setq string (org-modify-diary-entry-string string))))))
17376 (defun org-modify-diary-entry-string (string)
17377 "Add text properties to string, allowing org-mode to act on it."
17378 (org-add-props string nil
17379 'mouse-face 'highlight
17380 'keymap org-agenda-keymap
17381 'help-echo (if buffer-file-name
17382 (format "mouse-2 or RET jump to diary file %s"
17383 (abbreviate-file-name buffer-file-name))
17385 'org-agenda-diary-link t
17386 'org-marker (org-agenda-new-marker (point-at-bol))))
17388 (defun org-diary-default-entry ()
17389 "Add a dummy entry to the diary.
17390 Needed to avoid empty dates which mess up holiday display."
17391 ;; Catch the error if dealing with the new add-to-diary-alist
17392 (when org-disable-agenda-to-diary
17393 (condition-case nil
17394 (add-to-diary-list original-date "Org-mode dummy" "")
17395 (error
17396 (add-to-diary-list original-date "Org-mode dummy" "" nil)))))
17398 ;;;###autoload
17399 (defun org-diary (&rest args)
17400 "Return diary information from org-files.
17401 This function can be used in a \"sexp\" diary entry in the Emacs calendar.
17402 It accesses org files and extracts information from those files to be
17403 listed in the diary. The function accepts arguments specifying what
17404 items should be listed. The following arguments are allowed:
17406 :timestamp List the headlines of items containing a date stamp or
17407 date range matching the selected date. Deadlines will
17408 also be listed, on the expiration day.
17410 :sexp FIXME
17412 :deadline List any deadlines past due, or due within
17413 `org-deadline-warning-days'. The listing occurs only
17414 in the diary for *today*, not at any other date. If
17415 an entry is marked DONE, it is no longer listed.
17417 :scheduled List all items which are scheduled for the given date.
17418 The diary for *today* also contains items which were
17419 scheduled earlier and are not yet marked DONE.
17421 :todo List all TODO items from the org-file. This may be a
17422 long list - so this is not turned on by default.
17423 Like deadlines, these entries only show up in the
17424 diary for *today*, not at any other date.
17426 The call in the diary file should look like this:
17428 &%%(org-diary) ~/path/to/some/orgfile.org
17430 Use a separate line for each org file to check. Or, if you omit the file name,
17431 all files listed in `org-agenda-files' will be checked automatically:
17433 &%%(org-diary)
17435 If you don't give any arguments (as in the example above), the default
17436 arguments (:deadline :scheduled :timestamp :sexp) are used.
17437 So the example above may also be written as
17439 &%%(org-diary :deadline :timestamp :sexp :scheduled)
17441 The function expects the lisp variables `entry' and `date' to be provided
17442 by the caller, because this is how the calendar works. Don't use this
17443 function from a program - use `org-agenda-get-day-entries' instead."
17444 (org-agenda-maybe-reset-markers)
17445 (org-compile-prefix-format 'agenda)
17446 (org-set-sorting-strategy 'agenda)
17447 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
17448 (let* ((files (if (and entry (stringp entry) (string-match "\\S-" entry))
17449 (list entry)
17450 (org-agenda-files t)))
17451 file rtn results)
17452 (org-prepare-agenda-buffers files)
17453 ;; If this is called during org-agenda, don't return any entries to
17454 ;; the calendar. Org Agenda will list these entries itself.
17455 (if org-disable-agenda-to-diary (setq files nil))
17456 (while (setq file (pop files))
17457 (setq rtn (apply 'org-agenda-get-day-entries file date args))
17458 (setq results (append results rtn)))
17459 (if results
17460 (concat (org-finalize-agenda-entries results) "\n"))))
17462 ;;; Agenda entry finders
17464 (defun org-agenda-get-day-entries (file date &rest args)
17465 "Does the work for `org-diary' and `org-agenda'.
17466 FILE is the path to a file to be checked for entries. DATE is date like
17467 the one returned by `calendar-current-date'. ARGS are symbols indicating
17468 which kind of entries should be extracted. For details about these, see
17469 the documentation of `org-diary'."
17470 (setq args (or args '(:deadline :scheduled :timestamp :sexp)))
17471 (let* ((org-startup-folded nil)
17472 (org-startup-align-all-tables nil)
17473 (buffer (if (file-exists-p file)
17474 (org-get-agenda-file-buffer file)
17475 (error "No such file %s" file)))
17476 arg results rtn)
17477 (if (not buffer)
17478 ;; If file does not exist, make sure an error message ends up in diary
17479 (list (format "ORG-AGENDA-ERROR: No such org-file %s" file))
17480 (with-current-buffer buffer
17481 (unless (org-mode-p)
17482 (error "Agenda file %s is not in `org-mode'" file))
17483 (setq org-category-table (org-get-category-table))
17484 (let ((case-fold-search nil))
17485 (save-excursion
17486 (save-restriction
17487 (if org-agenda-restrict
17488 (narrow-to-region org-agenda-restrict-begin
17489 org-agenda-restrict-end)
17490 (widen))
17491 ;; The way we repeatedly append to `results' makes it O(n^2) :-(
17492 (while (setq arg (pop args))
17493 (cond
17494 ((and (eq arg :todo)
17495 (equal date (calendar-current-date)))
17496 (setq rtn (org-agenda-get-todos))
17497 (setq results (append results rtn)))
17498 ((eq arg :timestamp)
17499 (setq rtn (org-agenda-get-blocks))
17500 (setq results (append results rtn))
17501 (setq rtn (org-agenda-get-timestamps))
17502 (setq results (append results rtn)))
17503 ((eq arg :sexp)
17504 (setq rtn (org-agenda-get-sexps))
17505 (setq results (append results rtn)))
17506 ((eq arg :scheduled)
17507 (setq rtn (org-agenda-get-scheduled))
17508 (setq results (append results rtn)))
17509 ((eq arg :closed)
17510 (setq rtn (org-agenda-get-closed))
17511 (setq results (append results rtn)))
17512 ((and (eq arg :deadline)
17513 (equal date (calendar-current-date)))
17514 (setq rtn (org-agenda-get-deadlines))
17515 (setq results (append results rtn))))))))
17516 results))))
17518 ;; FIXME: this works only if the cursor is not at the
17519 ;; beginning of the entry
17520 (defun org-entry-is-done-p ()
17521 "Is the current entry marked DONE?"
17522 (save-excursion
17523 (and (re-search-backward "[\r\n]\\* " nil t)
17524 (looking-at org-nl-done-regexp))))
17526 (defun org-at-date-range-p (&optional inactive-ok)
17527 "Is the cursor inside a date range?"
17528 (interactive)
17529 (save-excursion
17530 (catch 'exit
17531 (let ((pos (point)))
17532 (skip-chars-backward "^[<\r\n")
17533 (skip-chars-backward "<[")
17534 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
17535 (>= (match-end 0) pos)
17536 (throw 'exit t))
17537 (skip-chars-backward "^<[\r\n")
17538 (skip-chars-backward "<[")
17539 (and (looking-at (if inactive-ok org-tr-regexp-both org-tr-regexp))
17540 (>= (match-end 0) pos)
17541 (throw 'exit t)))
17542 nil)))
17544 (defun org-agenda-get-todos ()
17545 "Return the TODO information for agenda display."
17546 (let* ((props (list 'face nil
17547 'done-face 'org-done
17548 'org-not-done-regexp org-not-done-regexp
17549 'org-todo-regexp org-todo-regexp
17550 'mouse-face 'highlight
17551 'keymap org-agenda-keymap
17552 'help-echo
17553 (format "mouse-2 or RET jump to org file %s"
17554 (abbreviate-file-name buffer-file-name))))
17555 ;; FIXME: get rid of the \n at some point but watch out
17556 (regexp (concat "\n\\*+[ \t]+\\("
17557 (if org-select-this-todo-keyword
17558 (if (equal org-select-this-todo-keyword "*")
17559 org-todo-regexp
17560 (concat "\\<\\("
17561 (mapconcat 'identity (org-split-string org-select-this-todo-keyword "|") "\\|")
17562 "\\)\\>"))
17563 org-not-done-regexp)
17564 "[^\n\r]*\\)"))
17565 marker priority category tags
17566 ee txt beg end)
17567 (goto-char (point-min))
17568 (while (re-search-forward regexp nil t)
17569 (catch :skip
17570 (save-match-data
17571 (beginning-of-line)
17572 (setq beg (point) end (progn (outline-next-heading) (point)))
17573 (when (or (and org-agenda-todo-ignore-scheduled (goto-char beg)
17574 (re-search-forward org-scheduled-time-regexp end t))
17575 (and org-agenda-todo-ignore-deadlines (goto-char beg)
17576 (re-search-forward org-deadline-time-regexp end t)
17577 (org-deadline-close (match-string 1))))
17578 (goto-char beg)
17579 (or org-agenda-todo-list-sublevels (org-end-of-subtree 'invisible))
17580 (throw :skip nil)))
17581 (goto-char beg)
17582 (org-agenda-skip)
17583 (goto-char (match-beginning 1))
17584 (setq marker (org-agenda-new-marker (1+ (match-beginning 0)))
17585 category (org-get-category)
17586 tags (org-get-tags-at (point))
17587 txt (org-format-agenda-item "" (match-string 1) category tags)
17588 priority (1+ (org-get-priority txt)))
17589 (org-add-props txt props
17590 'org-marker marker 'org-hd-marker marker
17591 'priority priority 'org-category category
17592 'type "todo")
17593 (push txt ee)
17594 (if org-agenda-todo-list-sublevels
17595 (goto-char (match-end 1))
17596 (org-end-of-subtree 'invisible))))
17597 (nreverse ee)))
17599 (defconst org-agenda-no-heading-message
17600 "No heading for this item in buffer or region.")
17602 (defun org-agenda-get-timestamps ()
17603 "Return the date stamp information for agenda display."
17604 (let* ((props (list 'face nil
17605 'org-not-done-regexp org-not-done-regexp
17606 'org-todo-regexp org-todo-regexp
17607 'mouse-face 'highlight
17608 'keymap org-agenda-keymap
17609 'help-echo
17610 (format "mouse-2 or RET jump to org file %s"
17611 (abbreviate-file-name buffer-file-name))))
17612 ;???? (regexp (regexp-quote
17613 ; (substring
17614 ; (format-time-string
17615 ; (car org-time-stamp-formats)
17616 ; (apply 'encode-time ; DATE bound by calendar
17617 ; (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
17618 ; 0 11)))
17619 (d1 (calendar-absolute-from-gregorian date))
17620 (regexp
17621 (concat
17622 (regexp-quote
17623 (substring
17624 (format-time-string
17625 (car org-time-stamp-formats)
17626 (apply 'encode-time ; DATE bound by calendar
17627 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
17628 0 11))
17629 "\\|\\(<[0-9]+-[0-9]+-[0-9]+[^>\n]+?\\+[0-9]+[dwmy]>\\)"
17630 "\\|\\(<%%\\(([^>\n]+)\\)>\\)"))
17631 marker hdmarker deadlinep scheduledp donep tmp priority category
17632 ee txt timestr tags b0 b3 e3)
17633 (goto-char (point-min))
17634 (while (re-search-forward regexp nil t)
17635 (setq b0 (match-beginning 0)
17636 b3 (match-beginning 3) e3 (match-end 3))
17637 (catch :skip
17638 (and (org-at-date-range-p) (throw :skip nil))
17639 (org-agenda-skip)
17640 (if (and (match-end 1)
17641 (not (= d1 (org-time-string-to-absolute (match-string 1) d1))))
17642 (throw :skip nil))
17643 (if (and e3
17644 (not (org-diary-sexp-entry (buffer-substring b3 e3) "" date)))
17645 (throw :skip nil))
17646 (setq marker (org-agenda-new-marker b0)
17647 category (org-get-category b0)
17648 tmp (buffer-substring (max (point-min)
17649 (- b0 org-ds-keyword-length))
17651 timestr (if b3 "" (buffer-substring b0 (point-at-eol)))
17652 deadlinep (string-match org-deadline-regexp tmp)
17653 scheduledp (string-match org-scheduled-regexp tmp)
17654 donep (org-entry-is-done-p))
17655 (and org-agenda-skip-scheduled-if-done
17656 scheduledp donep
17657 (throw :skip t))
17658 (and org-agenda-skip-deadline-if-done
17659 deadlinep donep
17660 (throw :skip t))
17661 (if (string-match ">" timestr)
17662 ;; substring should only run to end of time stamp
17663 (setq timestr (substring timestr 0 (match-end 0))))
17664 (save-excursion
17665 (if (re-search-backward "^\\*+ " nil t)
17666 (progn
17667 (goto-char (match-beginning 0))
17668 (setq hdmarker (org-agenda-new-marker)
17669 tags (org-get-tags-at))
17670 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
17671 (setq txt (org-format-agenda-item
17672 (format "%s%s"
17673 (if deadlinep "Deadline: " "")
17674 (if scheduledp "Scheduled: " ""))
17675 (match-string 1) category tags timestr)))
17676 (setq txt org-agenda-no-heading-message))
17677 (setq priority (org-get-priority txt))
17678 (org-add-props txt props
17679 'org-marker marker 'org-hd-marker hdmarker)
17680 (if deadlinep
17681 (org-add-props txt nil
17682 'face (if donep 'org-done 'org-warning)
17683 'type "deadline" 'date date
17684 'undone-face 'org-warning 'done-face 'org-done
17685 'org-category category 'priority (+ 100 priority))
17686 (if scheduledp
17687 (org-add-props txt nil
17688 'face 'org-scheduled-today
17689 'type "scheduled" 'date date
17690 'undone-face 'org-scheduled-today 'done-face 'org-done
17691 'org-category category 'priority (+ 99 priority))
17692 (org-add-props txt nil 'priority priority
17693 'org-category category 'date date
17694 'type "timestamp")))
17695 (push txt ee))
17696 (outline-next-heading)))
17697 (nreverse ee)))
17699 (defun org-agenda-get-sexps ()
17700 "Return the sexp information for agenda display."
17701 (require 'diary-lib)
17702 (let* ((props (list 'face nil
17703 'mouse-face 'highlight
17704 'keymap org-agenda-keymap
17705 'help-echo
17706 (format "mouse-2 or RET jump to org file %s"
17707 (abbreviate-file-name buffer-file-name))))
17708 (regexp "^&?%%(")
17709 marker category ee txt tags entry result beg b sexp sexp-entry)
17710 (goto-char (point-min))
17711 (while (re-search-forward regexp nil t)
17712 (catch :skip
17713 (org-agenda-skip)
17714 (setq beg (match-beginning 0))
17715 (goto-char (1- (match-end 0)))
17716 (setq b (point))
17717 (forward-sexp 1)
17718 (setq sexp (buffer-substring b (point)))
17719 (setq sexp-entry (if (looking-at "[ \t]*\\(\\S-.*\\)")
17720 (org-trim (match-string 1))
17721 ""))
17722 (setq result (org-diary-sexp-entry sexp sexp-entry date))
17723 (when result
17724 (setq marker (org-agenda-new-marker beg)
17725 category (org-get-category beg))
17727 (if (string-match "\\S-" result)
17728 (setq txt result)
17729 (setq txt "SEXP entry returned empty string"))
17731 (setq txt (org-format-agenda-item
17732 "" txt category tags 'time))
17733 (org-add-props txt props 'org-marker marker)
17734 (org-add-props txt nil
17735 'org-category category 'date date
17736 'type "sexp")
17737 (push txt ee))))
17738 (nreverse ee)))
17740 (defun org-agenda-get-closed ()
17741 "Return the logged TODO entries for agenda display."
17742 (let* ((props (list 'mouse-face 'highlight
17743 'org-not-done-regexp org-not-done-regexp
17744 'org-todo-regexp org-todo-regexp
17745 'keymap org-agenda-keymap
17746 'help-echo
17747 (format "mouse-2 or RET jump to org file %s"
17748 (abbreviate-file-name buffer-file-name))))
17749 (regexp (concat
17750 "\\<\\(" org-closed-string "\\|" org-clock-string "\\) *\\["
17751 (regexp-quote
17752 (substring
17753 (format-time-string
17754 (car org-time-stamp-formats)
17755 (apply 'encode-time ; DATE bound by calendar
17756 (list 0 0 0 (nth 1 date) (car date) (nth 2 date))))
17757 1 11))))
17758 marker hdmarker priority category tags closedp
17759 ee txt timestr)
17760 (goto-char (point-min))
17761 (while (re-search-forward regexp nil t)
17762 (catch :skip
17763 (org-agenda-skip)
17764 (setq marker (org-agenda-new-marker (match-beginning 0))
17765 closedp (equal (match-string 1) org-closed-string)
17766 category (org-get-category (match-beginning 0))
17767 timestr (buffer-substring (match-beginning 0) (point-at-eol))
17768 ;; donep (org-entry-is-done-p)
17770 (if (string-match "\\]" timestr)
17771 ;; substring should only run to end of time stamp
17772 (setq timestr (substring timestr 0 (match-end 0))))
17773 (save-excursion
17774 (if (re-search-backward "^\\*+ " nil t)
17775 (progn
17776 (goto-char (match-beginning 0))
17777 (setq hdmarker (org-agenda-new-marker)
17778 tags (org-get-tags-at))
17779 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
17780 (setq txt (org-format-agenda-item
17781 (if closedp "Closed: " "Clocked: ")
17782 (match-string 1) category tags timestr)))
17783 (setq txt org-agenda-no-heading-message))
17784 (setq priority 100000)
17785 (org-add-props txt props
17786 'org-marker marker 'org-hd-marker hdmarker 'face 'org-done
17787 'priority priority 'org-category category
17788 'type "closed" 'date date
17789 'undone-face 'org-warning 'done-face 'org-done)
17790 (push txt ee))
17791 (outline-next-heading)))
17792 (nreverse ee)))
17794 (defun org-agenda-get-deadlines ()
17795 "Return the deadline information for agenda display."
17796 (let* ((wdays org-deadline-warning-days)
17797 (props (list 'mouse-face 'highlight
17798 'org-not-done-regexp org-not-done-regexp
17799 'org-todo-regexp org-todo-regexp
17800 'keymap org-agenda-keymap
17801 'help-echo
17802 (format "mouse-2 or RET jump to org file %s"
17803 (abbreviate-file-name buffer-file-name))))
17804 (regexp org-deadline-time-regexp)
17805 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
17806 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
17807 d2 diff pos pos1 category tags
17808 ee txt head face)
17809 (goto-char (point-min))
17810 (while (re-search-forward regexp nil t)
17811 (catch :skip
17812 (org-agenda-skip)
17813 (setq pos (1- (match-beginning 1))
17814 ;??? d2 (time-to-days
17815 ;??? (org-time-string-to-time (match-string 1)))
17816 d2 (org-time-string-to-absolute (match-string 1) d1)
17817 diff (- d2 d1))
17818 ;; When to show a deadline in the calendar:
17819 ;; If the expiration is within wdays warning time.
17820 ;; Past-due deadlines are only shown on the current date
17821 (if (and (< diff wdays) todayp (not (= diff 0)))
17822 (save-excursion
17823 (setq category (org-get-category))
17824 (if (re-search-backward "^\\*+[ \t]+" nil t)
17825 (progn
17826 (goto-char (match-end 0))
17827 (setq pos1 (match-beginning 0))
17828 (setq tags (org-get-tags-at pos1))
17829 (setq head (buffer-substring-no-properties
17830 (point)
17831 (progn (skip-chars-forward "^\r\n")
17832 (point))))
17833 (if (string-match org-looking-at-done-regexp head)
17834 (setq txt nil)
17835 (setq txt (org-format-agenda-item
17836 (format "In %3d d.: " diff) head category tags))))
17837 (setq txt org-agenda-no-heading-message))
17838 (when txt
17839 (setq face (cond ((<= diff 0) 'org-warning)
17840 ((<= diff 5) 'org-upcoming-deadline)
17841 (t nil)))
17842 (org-add-props txt props
17843 'org-marker (org-agenda-new-marker pos)
17844 'org-hd-marker (org-agenda-new-marker pos1)
17845 'priority (+ (- 10 diff) (org-get-priority txt))
17846 'org-category category
17847 'type "upcoming-deadline" 'date d2
17848 'face face 'undone-face face 'done-face 'org-done)
17849 (push txt ee))))))
17850 ee))
17852 (defun org-agenda-get-scheduled ()
17853 "Return the scheduled information for agenda display."
17854 (let* ((props (list 'face 'org-scheduled-previously
17855 'org-not-done-regexp org-not-done-regexp
17856 'org-todo-regexp org-todo-regexp
17857 'undone-face 'org-scheduled-previously
17858 'done-face 'org-done
17859 'mouse-face 'highlight
17860 'keymap org-agenda-keymap
17861 'help-echo
17862 (format "mouse-2 or RET jump to org file %s"
17863 (abbreviate-file-name buffer-file-name))))
17864 (regexp org-scheduled-time-regexp)
17865 (todayp (equal date (calendar-current-date))) ; DATE bound by calendar
17866 (d1 (calendar-absolute-from-gregorian date)) ; DATE bound by calendar
17867 d2 diff pos pos1 category tags
17868 ee txt head)
17869 (goto-char (point-min))
17870 (while (re-search-forward regexp nil t)
17871 (catch :skip
17872 (org-agenda-skip)
17873 (setq pos (1- (match-beginning 1))
17874 d2 (org-time-string-to-absolute (match-string 1) d1)
17875 ;??? d2 (time-to-days
17876 ;??? (org-time-string-to-time (match-string 1)))
17877 diff (- d2 d1))
17878 ;; When to show a scheduled item in the calendar:
17879 ;; If it is on or past the date.
17880 (if (and (< diff 0) todayp)
17881 (save-excursion
17882 (setq category (org-get-category))
17883 (if (re-search-backward "^\\*+[ \t]+" nil t)
17884 (progn
17885 (goto-char (match-end 0))
17886 (setq pos1 (match-beginning 0))
17887 (setq tags (org-get-tags-at))
17888 (setq head (buffer-substring-no-properties
17889 (point)
17890 (progn (skip-chars-forward "^\r\n") (point))))
17891 (if (string-match org-looking-at-done-regexp head)
17892 (setq txt nil)
17893 (setq txt (org-format-agenda-item
17894 (format "Sched.%2dx: " (- 1 diff)) head
17895 category tags))))
17896 (setq txt org-agenda-no-heading-message))
17897 (when txt
17898 (org-add-props txt props
17899 'org-marker (org-agenda-new-marker pos)
17900 'org-hd-marker (org-agenda-new-marker pos1)
17901 'type "past-scheduled" 'date d2
17902 'priority (+ (- 5 diff) (org-get-priority txt))
17903 'org-category category)
17904 (push txt ee))))))
17905 ee))
17907 (defun org-agenda-get-blocks ()
17908 "Return the date-range information for agenda display."
17909 (let* ((props (list 'face nil
17910 'org-not-done-regexp org-not-done-regexp
17911 'org-todo-regexp org-todo-regexp
17912 'mouse-face 'highlight
17913 'keymap org-agenda-keymap
17914 'help-echo
17915 (format "mouse-2 or RET jump to org file %s"
17916 (abbreviate-file-name buffer-file-name))))
17917 (regexp org-tr-regexp)
17918 (d0 (calendar-absolute-from-gregorian date))
17919 marker hdmarker ee txt d1 d2 s1 s2 timestr category tags pos)
17920 (goto-char (point-min))
17921 (while (re-search-forward regexp nil t)
17922 (catch :skip
17923 (org-agenda-skip)
17924 (setq pos (point))
17925 (setq timestr (match-string 0)
17926 s1 (match-string 1)
17927 s2 (match-string 2)
17928 d1 (time-to-days (org-time-string-to-time s1))
17929 d2 (time-to-days (org-time-string-to-time s2)))
17930 (if (and (> (- d0 d1) -1) (> (- d2 d0) -1))
17931 ;; Only allow days between the limits, because the normal
17932 ;; date stamps will catch the limits.
17933 (save-excursion
17934 (setq marker (org-agenda-new-marker (point)))
17935 (setq category (org-get-category))
17936 (if (re-search-backward "^\\*+ " nil t)
17937 (progn
17938 (goto-char (match-beginning 0))
17939 (setq hdmarker (org-agenda-new-marker (point)))
17940 (setq tags (org-get-tags-at))
17941 (looking-at "\\*+[ \t]+\\([^\r\n]+\\)")
17942 (setq txt (org-format-agenda-item
17943 (format (if (= d1 d2) "" "(%d/%d): ")
17944 (1+ (- d0 d1)) (1+ (- d2 d1)))
17945 (match-string 1) category tags
17946 (if (= d0 d1) timestr))))
17947 (setq txt org-agenda-no-heading-message))
17948 (org-add-props txt props
17949 'org-marker marker 'org-hd-marker hdmarker
17950 'type "block" 'date date
17951 'priority (org-get-priority txt) 'org-category category)
17952 (push txt ee)))
17953 (goto-char pos)))
17954 ;; Sort the entries by expiration date.
17955 (nreverse ee)))
17957 ;;; Agenda presentation and sorting
17959 (defconst org-plain-time-of-day-regexp
17960 (concat
17961 "\\(\\<[012]?[0-9]"
17962 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
17963 "\\(--?"
17964 "\\(\\<[012]?[0-9]"
17965 "\\(\\(:\\([0-5][0-9]\\([AaPp][Mm]\\)?\\)\\)\\|\\([AaPp][Mm]\\)\\)\\>\\)"
17966 "\\)?")
17967 "Regular expression to match a plain time or time range.
17968 Examples: 11:45 or 8am-13:15 or 2:45-2:45pm. After a match, the following
17969 groups carry important information:
17970 0 the full match
17971 1 the first time, range or not
17972 8 the second time, if it is a range.")
17974 (defconst org-stamp-time-of-day-regexp
17975 (concat
17976 "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} +\\sw+ +\\)"
17977 "\\([012][0-9]:[0-5][0-9]\\(-\\([012][0-9]:[0-5][0-9]\\)\\)?[^\n\r>]*?\\)>"
17978 "\\(--?"
17979 "<\\1\\([012][0-9]:[0-5][0-9]\\)>\\)?")
17980 "Regular expression to match a timestamp time or time range.
17981 After a match, the following groups carry important information:
17982 0 the full match
17983 1 date plus weekday, for backreferencing to make sure both times on same day
17984 2 the first time, range or not
17985 4 the second time, if it is a range.")
17987 (defvar org-prefix-has-time nil
17988 "A flag, set by `org-compile-prefix-format'.
17989 The flag is set if the currently compiled format contains a `%t'.")
17990 (defvar org-prefix-has-tag nil
17991 "A flag, set by `org-compile-prefix-format'.
17992 The flag is set if the currently compiled format contains a `%T'.")
17994 (defun org-format-agenda-item (extra txt &optional category tags dotime
17995 noprefix)
17996 "Format TXT to be inserted into the agenda buffer.
17997 In particular, it adds the prefix and corresponding text properties. EXTRA
17998 must be a string and replaces the `%s' specifier in the prefix format.
17999 CATEGORY (string, symbol or nil) may be used to overrule the default
18000 category taken from local variable or file name. It will replace the `%c'
18001 specifier in the format. DOTIME, when non-nil, indicates that a
18002 time-of-day should be extracted from TXT for sorting of this entry, and for
18003 the `%t' specifier in the format. When DOTIME is a string, this string is
18004 searched for a time before TXT is. NOPREFIX is a flag and indicates that
18005 only the correctly processes TXT should be returned - this is used by
18006 `org-agenda-change-all-lines'. TAGS can be the tags of the headline."
18007 (save-match-data
18008 ;; Diary entries sometimes have extra whitespace at the beginning
18009 (if (string-match "^ +" txt) (setq txt (replace-match "" nil nil txt)))
18010 (let* ((category (or category
18011 org-category
18012 (if buffer-file-name
18013 (file-name-sans-extension
18014 (file-name-nondirectory buffer-file-name))
18015 "")))
18016 (tag (if tags (nth (1- (length tags)) tags) ""))
18017 time ; time and tag are needed for the eval of the prefix format
18018 (ts (if dotime (concat (if (stringp dotime) dotime "") txt)))
18019 (time-of-day (and dotime (org-get-time-of-day ts)))
18020 stamp plain s0 s1 s2 rtn srp)
18021 (when (and dotime time-of-day org-prefix-has-time)
18022 ;; Extract starting and ending time and move them to prefix
18023 (when (or (setq stamp (string-match org-stamp-time-of-day-regexp ts))
18024 (setq plain (string-match org-plain-time-of-day-regexp ts)))
18025 (setq s0 (match-string 0 ts)
18026 srp (and stamp (match-end 3))
18027 s1 (match-string (if plain 1 2) ts)
18028 s2 (match-string (if plain 8 (if srp 4 6)) ts))
18030 ;; If the times are in TXT (not in DOTIMES), and the prefix will list
18031 ;; them, we might want to remove them there to avoid duplication.
18032 ;; The user can turn this off with a variable.
18033 (if (and org-agenda-remove-times-when-in-prefix (or stamp plain)
18034 (string-match (concat (regexp-quote s0) " *") txt)
18035 (if (eq org-agenda-remove-times-when-in-prefix 'beg)
18036 (= (match-beginning 0) 0)
18038 (setq txt (replace-match "" nil nil txt))))
18039 ;; Normalize the time(s) to 24 hour
18040 (if s1 (setq s1 (org-get-time-of-day s1 'string t)))
18041 (if s2 (setq s2 (org-get-time-of-day s2 'string t))))
18043 (when (and s1 (not s2) org-agenda-default-appointment-duration
18044 (string-match "\\([0-9]+\\):\\([0-9]+\\)" s1))
18045 (let ((m (+ (string-to-number (match-string 2 s1))
18046 (* 60 (string-to-number (match-string 1 s1)))
18047 org-agenda-default-appointment-duration))
18049 (setq h (/ m 60) m (- m (* h 60)))
18050 (setq s2 (format "%02d:%02d" h m))))
18052 (when (string-match (org-re "\\([ \t]+\\)\\(:[[:alnum:]_@:]+:\\)[ \t]*$")
18053 txt)
18054 ;; Tags are in the string
18055 (if (or (eq org-agenda-remove-tags t)
18056 (and org-agenda-remove-tags
18057 org-prefix-has-tag))
18058 (setq txt (replace-match "" t t txt))
18059 (setq txt (replace-match
18060 (concat (make-string (max (- 50 (length txt)) 1) ?\ )
18061 (match-string 2 txt))
18062 t t txt))))
18064 ;; Create the final string
18065 (if noprefix
18066 (setq rtn txt)
18067 ;; Prepare the variables needed in the eval of the compiled format
18068 (setq time (cond (s2 (concat s1 "-" s2))
18069 (s1 (concat s1 "......"))
18070 (t ""))
18071 extra (or extra "")
18072 category (if (symbolp category) (symbol-name category) category))
18073 ;; Evaluate the compiled format
18074 (setq rtn (concat (eval org-prefix-format-compiled) txt)))
18076 ;; And finally add the text properties
18077 (org-add-props rtn nil
18078 'org-category (downcase category) 'tags tags
18079 'prefix-length (- (length rtn) (length txt))
18080 'time-of-day time-of-day
18081 'txt txt
18082 'time time
18083 'extra extra
18084 'dotime dotime))))
18086 (defvar org-agenda-sorting-strategy) ;; FIXME: can be removed?
18087 (defvar org-agenda-sorting-strategy-selected nil)
18089 (defun org-agenda-add-time-grid-maybe (list ndays todayp)
18090 (catch 'exit
18091 (cond ((not org-agenda-use-time-grid) (throw 'exit list))
18092 ((and todayp (member 'today (car org-agenda-time-grid))))
18093 ((and (= ndays 1) (member 'daily (car org-agenda-time-grid))))
18094 ((member 'weekly (car org-agenda-time-grid)))
18095 (t (throw 'exit list)))
18096 (let* ((have (delq nil (mapcar
18097 (lambda (x) (get-text-property 1 'time-of-day x))
18098 list)))
18099 (string (nth 1 org-agenda-time-grid))
18100 (gridtimes (nth 2 org-agenda-time-grid))
18101 (req (car org-agenda-time-grid))
18102 (remove (member 'remove-match req))
18103 new time)
18104 (if (and (member 'require-timed req) (not have))
18105 ;; don't show empty grid
18106 (throw 'exit list))
18107 (while (setq time (pop gridtimes))
18108 (unless (and remove (member time have))
18109 (setq time (int-to-string time))
18110 (push (org-format-agenda-item
18111 nil string "" nil
18112 (concat (substring time 0 -2) ":" (substring time -2)))
18113 new)
18114 (put-text-property
18115 1 (length (car new)) 'face 'org-time-grid (car new))))
18116 (if (member 'time-up org-agenda-sorting-strategy-selected)
18117 (append new list)
18118 (append list new)))))
18120 (defun org-compile-prefix-format (key)
18121 "Compile the prefix format into a Lisp form that can be evaluated.
18122 The resulting form is returned and stored in the variable
18123 `org-prefix-format-compiled'."
18124 (setq org-prefix-has-time nil org-prefix-has-tag nil)
18125 (let ((s (cond
18126 ((stringp org-agenda-prefix-format)
18127 org-agenda-prefix-format)
18128 ((assq key org-agenda-prefix-format)
18129 (cdr (assq key org-agenda-prefix-format)))
18130 (t " %-12:c%?-12t% s")))
18131 (start 0)
18132 varform vars var e c f opt)
18133 (while (string-match "%\\(\\?\\)?\\([-+]?[0-9.]*\\)\\([ .;,:!?=|/<>]?\\)\\([cts]\\)"
18134 s start)
18135 (setq var (cdr (assoc (match-string 4 s)
18136 '(("c" . category) ("t" . time) ("s" . extra)
18137 ("T" . tag))))
18138 c (or (match-string 3 s) "")
18139 opt (match-beginning 1)
18140 start (1+ (match-beginning 0)))
18141 (if (equal var 'time) (setq org-prefix-has-time t))
18142 (if (equal var 'tag) (setq org-prefix-has-tag t))
18143 (setq f (concat "%" (match-string 2 s) "s"))
18144 (if opt
18145 (setq varform
18146 `(if (equal "" ,var)
18148 (format ,f (if (equal "" ,var) "" (concat ,var ,c)))))
18149 (setq varform `(format ,f (if (equal ,var "") "" (concat ,var ,c)))))
18150 (setq s (replace-match "%s" t nil s))
18151 (push varform vars))
18152 (setq vars (nreverse vars))
18153 (setq org-prefix-format-compiled `(format ,s ,@vars))))
18155 (defun org-set-sorting-strategy (key)
18156 (if (symbolp (car org-agenda-sorting-strategy))
18157 ;; the old format
18158 (setq org-agenda-sorting-strategy-selected org-agenda-sorting-strategy)
18159 (setq org-agenda-sorting-strategy-selected
18160 (or (cdr (assq key org-agenda-sorting-strategy))
18161 (cdr (assq 'agenda org-agenda-sorting-strategy))
18162 '(time-up category-keep priority-down)))))
18164 (defun org-get-time-of-day (s &optional string mod24)
18165 "Check string S for a time of day.
18166 If found, return it as a military time number between 0 and 2400.
18167 If not found, return nil.
18168 The optional STRING argument forces conversion into a 5 character wide string
18169 HH:MM."
18170 (save-match-data
18171 (when
18173 (string-match
18174 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)\\([AaPp][Mm]\\)?\\> *" s)
18175 (string-match
18176 "\\<\\([012]?[0-9]\\)\\(:\\([0-5][0-9]\\)\\)?\\([AaPp][Mm]\\)\\> *" s))
18177 (let* ((h (string-to-number (match-string 1 s)))
18178 (m (if (match-end 3) (string-to-number (match-string 3 s)) 0))
18179 (ampm (if (match-end 4) (downcase (match-string 4 s))))
18180 (am-p (equal ampm "am"))
18181 (h1 (cond ((not ampm) h)
18182 ((= h 12) (if am-p 0 12))
18183 (t (+ h (if am-p 0 12)))))
18184 (h2 (if (and string mod24 (not (and (= m 0) (= h1 24))))
18185 (mod h1 24) h1))
18186 (t0 (+ (* 100 h2) m))
18187 (t1 (concat (if (>= h1 24) "+" " ")
18188 (if (< t0 100) "0" "")
18189 (if (< t0 10) "0" "")
18190 (int-to-string t0))))
18191 (if string (concat (substring t1 -4 -2) ":" (substring t1 -2)) t0)))))
18193 (defun org-finalize-agenda-entries (list &optional nosort)
18194 "Sort and concatenate the agenda items."
18195 (setq list (mapcar 'org-agenda-highlight-todo list))
18196 (if nosort
18197 list
18198 (mapconcat 'identity (sort list 'org-entries-lessp) "\n")))
18200 (defun org-agenda-highlight-todo (x)
18201 (let (re pl)
18202 (if (eq x 'line)
18203 (save-excursion
18204 (beginning-of-line 1)
18205 (setq re (get-text-property (point) 'org-not-done-regexp))
18206 (goto-char (+ (point) (or (get-text-property (point) 'prefix-length) 0)))
18207 (and (looking-at (concat "[ \t]*\\.*" re))
18208 (add-text-properties (match-beginning 0) (match-end 0)
18209 '(face org-todo))))
18210 (setq re (concat (get-text-property 0 'org-not-done-regexp x))
18211 pl (get-text-property 0 'prefix-length x))
18212 (and re (equal (string-match (concat "\\(\\.*\\)" re) x (or pl 0)) pl)
18213 (add-text-properties (or (match-end 1) (match-end 0)) (match-end 0)
18214 '(face org-todo) x))
18215 x)))
18217 (defsubst org-cmp-priority (a b)
18218 "Compare the priorities of string A and B."
18219 (let ((pa (or (get-text-property 1 'priority a) 0))
18220 (pb (or (get-text-property 1 'priority b) 0)))
18221 (cond ((> pa pb) +1)
18222 ((< pa pb) -1)
18223 (t nil))))
18225 (defsubst org-cmp-category (a b)
18226 "Compare the string values of categories of strings A and B."
18227 (let ((ca (or (get-text-property 1 'category a) ""))
18228 (cb (or (get-text-property 1 'category b) "")))
18229 (cond ((string-lessp ca cb) -1)
18230 ((string-lessp cb ca) +1)
18231 (t nil))))
18233 (defsubst org-cmp-tag (a b)
18234 "Compare the string values of categories of strings A and B."
18235 (let ((ta (car (last (get-text-property 1 'tags a))))
18236 (tb (car (last (get-text-property 1 'tags b)))))
18237 (cond ((not ta) +1)
18238 ((not tb) -1)
18239 ((string-lessp ta tb) -1)
18240 ((string-lessp tb ta) +1)
18241 (t nil))))
18243 (defsubst org-cmp-time (a b)
18244 "Compare the time-of-day values of strings A and B."
18245 (let* ((def (if org-sort-agenda-notime-is-late 9901 -1))
18246 (ta (or (get-text-property 1 'time-of-day a) def))
18247 (tb (or (get-text-property 1 'time-of-day b) def)))
18248 (cond ((< ta tb) -1)
18249 ((< tb ta) +1)
18250 (t nil))))
18252 (defun org-entries-lessp (a b)
18253 "Predicate for sorting agenda entries."
18254 ;; The following variables will be used when the form is evaluated.
18255 ;; So even though the compiler complains, keep them.
18256 (let* ((time-up (org-cmp-time a b))
18257 (time-down (if time-up (- time-up) nil))
18258 (priority-up (org-cmp-priority a b))
18259 (priority-down (if priority-up (- priority-up) nil))
18260 (category-up (org-cmp-category a b))
18261 (category-down (if category-up (- category-up) nil))
18262 (category-keep (if category-up +1 nil))
18263 (tag-up (org-cmp-tag a b))
18264 (tag-down (if tag-up (- tag-up) nil)))
18265 (cdr (assoc
18266 (eval (cons 'or org-agenda-sorting-strategy-selected))
18267 '((-1 . t) (1 . nil) (nil . nil))))))
18269 ;;; Agenda commands
18271 (defun org-agenda-check-type (error &rest types)
18272 "Check if agenda buffer is of allowed type.
18273 If ERROR is non-nil, throw an error, otherwise just return nil."
18274 (if (memq org-agenda-type types)
18276 (if error
18277 (error "Not allowed in %s-type agenda buffers" org-agenda-type)
18278 nil)))
18280 (defun org-agenda-quit ()
18281 "Exit agenda by removing the window or the buffer."
18282 (interactive)
18283 (let ((buf (current-buffer)))
18284 (if (not (one-window-p)) (delete-window))
18285 (kill-buffer buf)
18286 (org-agenda-maybe-reset-markers 'force)
18287 (org-columns-remove-overlays))
18288 ;; Maybe restore the pre-agenda window configuration.
18289 (and org-agenda-restore-windows-after-quit
18290 (not (eq org-agenda-window-setup 'other-frame))
18291 org-pre-agenda-window-conf
18292 (set-window-configuration org-pre-agenda-window-conf)))
18294 (defun org-agenda-exit ()
18295 "Exit agenda by removing the window or the buffer.
18296 Also kill all Org-mode buffers which have been loaded by `org-agenda'.
18297 Org-mode buffers visited directly by the user will not be touched."
18298 (interactive)
18299 (org-release-buffers org-agenda-new-buffers)
18300 (setq org-agenda-new-buffers nil)
18301 (org-agenda-quit))
18303 (defun org-save-all-org-buffers ()
18304 "Save all Org-mode buffers without user confirmation."
18305 (interactive)
18306 (message "Saving all Org-mode buffers...")
18307 (save-some-buffers t 'org-mode-p)
18308 (message "Saving all Org-mode buffers... done"))
18310 (defun org-agenda-redo ()
18311 "Rebuild Agenda.
18312 When this is the global TODO list, a prefix argument will be interpreted."
18313 (interactive)
18314 (let* ((org-agenda-keep-modes t)
18315 (line (org-current-line))
18316 (window-line (- line (org-current-line (window-start)))))
18317 (message "Rebuilding agenda buffer...")
18318 (eval org-agenda-redo-command)
18319 (setq org-agenda-undo-list nil
18320 org-agenda-pending-undo-list nil)
18321 (message "Rebuilding agenda buffer...done")
18322 (goto-line line)
18323 (recenter window-line)))
18325 (defun org-agenda-goto-today ()
18326 "Go to today."
18327 (interactive)
18328 (org-agenda-check-type t 'timeline 'agenda)
18329 (let ((tdpos (text-property-any (point-min) (point-max) 'org-today t)))
18330 (cond
18331 (tdpos (goto-char tdpos))
18332 ((eq org-agenda-type 'agenda)
18333 (let* ((sd (time-to-days (current-time)))
18334 (comp (org-agenda-compute-time-span sd org-agenda-span))
18335 (org-agenda-overriding-arguments org-agenda-last-arguments))
18336 (setf (nth 1 org-agenda-overriding-arguments) (car comp))
18337 (setf (nth 2 org-agenda-overriding-arguments) (cdr comp))
18338 (org-agenda-redo)
18339 (org-agenda-find-today-or-agenda)))
18340 (t (error "Cannot find today")))))
18342 (defun org-agenda-find-today-or-agenda ()
18343 (goto-char
18344 (or (text-property-any (point-min) (point-max) 'org-today t)
18345 (text-property-any (point-min) (point-max) 'org-agenda-type 'agenda)
18346 (point-min))))
18348 (defun org-agenda-later (arg)
18349 "Go forward in time by thee current span.
18350 With prefix ARG, go forward that many times the current span."
18351 (interactive "p")
18352 (org-agenda-check-type t 'agenda)
18353 (let* ((span org-agenda-span)
18354 (sd org-starting-day)
18355 (greg (calendar-gregorian-from-absolute sd))
18356 greg2 nd)
18357 (cond
18358 ((eq span 'day)
18359 (setq sd (+ arg sd) nd 1))
18360 ((eq span 'week)
18361 (setq sd (+ (* 7 arg) sd) nd 7))
18362 ((eq span 'month)
18363 (setq greg2 (list (+ (car greg) arg) (nth 1 greg) (nth 2 greg))
18364 sd (calendar-absolute-from-gregorian greg2))
18365 (setcar greg2 (1+ (car greg2)))
18366 (setq nd (- (calendar-absolute-from-gregorian greg2) sd)))
18367 ((eq span 'year)
18368 (setq greg2 (list (car greg) (nth 1 greg) (+ arg (nth 2 greg)))
18369 sd (calendar-absolute-from-gregorian greg2))
18370 (setcar (nthcdr 2 greg2) (1+ (nth 2 greg2)))
18371 (setq nd (- (calendar-absolute-from-gregorian greg2) sd))))
18372 (let ((org-agenda-overriding-arguments
18373 (list (car org-agenda-last-arguments) sd nd t)))
18374 (org-agenda-redo)
18375 (org-agenda-find-today-or-agenda))))
18377 (defun org-agenda-earlier (arg)
18378 "Go backward in time by the current span.
18379 With prefix ARG, go backward that many times the current span."
18380 (interactive "p")
18381 (org-agenda-later (- arg)))
18383 (defun org-agenda-day-view ()
18384 "Switch to daily view for agenda."
18385 (interactive)
18386 (setq org-agenda-ndays 1)
18387 (org-agenda-change-time-span 'day))
18388 (defun org-agenda-week-view ()
18389 "Switch to daily view for agenda."
18390 (interactive)
18391 (setq org-agenda-ndays 7)
18392 (org-agenda-change-time-span 'week))
18393 (defun org-agenda-month-view ()
18394 "Switch to daily view for agenda."
18395 (interactive)
18396 (org-agenda-change-time-span 'month))
18397 (defun org-agenda-year-view ()
18398 "Switch to daily view for agenda."
18399 (interactive)
18400 (if (y-or-n-p "Are you sure you want to compute the agenda for an entire year? ")
18401 (org-agenda-change-time-span 'year)
18402 (error "Abort")))
18404 (defun org-agenda-change-time-span (span)
18405 "Change the agenda view to SPAN.
18406 SPAN may be `day', `week', `month', `year'."
18407 (org-agenda-check-type t 'agenda)
18408 (if (equal org-agenda-span span)
18409 (error "Viewing span is already \"%s\"" span))
18410 (let* ((sd (or (get-text-property (point) 'day)
18411 org-starting-day))
18412 (computed (org-agenda-compute-time-span sd span))
18413 (org-agenda-overriding-arguments
18414 (list (car org-agenda-last-arguments)
18415 (car computed) (cdr computed) t)))
18416 (org-agenda-redo)
18417 (org-agenda-find-today-or-agenda))
18418 (org-agenda-set-mode-name)
18419 (message "Switched to %s view" span))
18421 (defun org-agenda-compute-time-span (sd span)
18422 "Compute starting date and number of days for agenda.
18423 SPAN may be `day', `week', `month', `year'. The return value
18424 is a cons cell with the starting date and the number of days,
18425 so that the date SD will be in that range."
18426 (let* ((greg (calendar-gregorian-from-absolute sd))
18428 (cond
18429 ((eq span 'day)
18430 (setq nd 1))
18431 ((eq span 'week)
18432 (let* ((nt (calendar-day-of-week
18433 (calendar-gregorian-from-absolute sd)))
18434 (d (if org-agenda-start-on-weekday
18435 (- nt org-agenda-start-on-weekday)
18436 0)))
18437 (setq sd (- sd (+ (if (< d 0) 7 0) d)))
18438 (setq nd 7)))
18439 ((eq span 'month)
18440 (setq sd (calendar-absolute-from-gregorian
18441 (list (car greg) 1 (nth 2 greg)))
18442 nd (- (calendar-absolute-from-gregorian
18443 (list (1+ (car greg)) 1 (nth 2 greg)))
18444 sd)))
18445 ((eq span 'year)
18446 (setq sd (calendar-absolute-from-gregorian
18447 (list 1 1 (nth 2 greg)))
18448 nd (- (calendar-absolute-from-gregorian
18449 (list 1 1 (1+ (nth 2 greg))))
18450 sd))))
18451 (cons sd nd)))
18453 ;; FIXME: this no longer works if user make date format that starts with a blank
18454 (defun org-agenda-next-date-line (&optional arg)
18455 "Jump to the next line indicating a date in agenda buffer."
18456 (interactive "p")
18457 (org-agenda-check-type t 'agenda 'timeline)
18458 (beginning-of-line 1)
18459 (if (looking-at "^\\S-") (forward-char 1))
18460 (if (not (re-search-forward "^\\S-" nil t arg))
18461 (progn
18462 (backward-char 1)
18463 (error "No next date after this line in this buffer")))
18464 (goto-char (match-beginning 0)))
18466 (defun org-agenda-previous-date-line (&optional arg)
18467 "Jump to the previous line indicating a date in agenda buffer."
18468 (interactive "p")
18469 (org-agenda-check-type t 'agenda 'timeline)
18470 (beginning-of-line 1)
18471 (if (not (re-search-backward "^\\S-" nil t arg))
18472 (error "No previous date before this line in this buffer")))
18474 ;; Initialize the highlight
18475 (defvar org-hl (org-make-overlay 1 1))
18476 (org-overlay-put org-hl 'face 'highlight)
18478 (defun org-highlight (begin end &optional buffer)
18479 "Highlight a region with overlay."
18480 (funcall (if (featurep 'xemacs) 'set-extent-endpoints 'move-overlay)
18481 org-hl begin end (or buffer (current-buffer))))
18483 (defun org-unhighlight ()
18484 "Detach overlay INDEX."
18485 (funcall (if (featurep 'xemacs) 'detach-extent 'delete-overlay) org-hl))
18487 ;; FIXME this is currently not used.
18488 (defun org-highlight-until-next-command (beg end &optional buffer)
18489 (org-highlight beg end buffer)
18490 (add-hook 'pre-command-hook 'org-unhighlight-once))
18492 (defun org-unhighlight-once ()
18493 (remove-hook 'pre-command-hook 'org-unhighlight-once)
18494 (org-unhighlight))
18496 (defun org-agenda-follow-mode ()
18497 "Toggle follow mode in an agenda buffer."
18498 (interactive)
18499 (setq org-agenda-follow-mode (not org-agenda-follow-mode))
18500 (org-agenda-set-mode-name)
18501 (message "Follow mode is %s"
18502 (if org-agenda-follow-mode "on" "off")))
18504 (defun org-agenda-log-mode ()
18505 "Toggle log mode in an agenda buffer."
18506 (interactive)
18507 (org-agenda-check-type t 'agenda 'timeline)
18508 (setq org-agenda-show-log (not org-agenda-show-log))
18509 (org-agenda-set-mode-name)
18510 (org-agenda-redo)
18511 (message "Log mode is %s"
18512 (if org-agenda-show-log "on" "off")))
18514 (defun org-agenda-toggle-diary ()
18515 "Toggle diary inclusion in an agenda buffer."
18516 (interactive)
18517 (org-agenda-check-type t 'agenda)
18518 (setq org-agenda-include-diary (not org-agenda-include-diary))
18519 (org-agenda-redo)
18520 (org-agenda-set-mode-name)
18521 (message "Diary inclusion turned %s"
18522 (if org-agenda-include-diary "on" "off")))
18524 (defun org-agenda-toggle-time-grid ()
18525 "Toggle time grid in an agenda buffer."
18526 (interactive)
18527 (org-agenda-check-type t 'agenda)
18528 (setq org-agenda-use-time-grid (not org-agenda-use-time-grid))
18529 (org-agenda-redo)
18530 (org-agenda-set-mode-name)
18531 (message "Time-grid turned %s"
18532 (if org-agenda-use-time-grid "on" "off")))
18534 (defun org-agenda-set-mode-name ()
18535 "Set the mode name to indicate all the small mode settings."
18536 (setq mode-name
18537 (concat "Org-Agenda"
18538 (if (equal org-agenda-ndays 1) " Day" "")
18539 (if (equal org-agenda-ndays 7) " Week" "")
18540 (if org-agenda-follow-mode " Follow" "")
18541 (if org-agenda-include-diary " Diary" "")
18542 (if org-agenda-use-time-grid " Grid" "")
18543 (if org-agenda-show-log " Log" "")))
18544 (force-mode-line-update))
18546 (defun org-agenda-post-command-hook ()
18547 (and (eolp) (not (bolp)) (backward-char 1))
18548 (setq org-agenda-type (get-text-property (point) 'org-agenda-type))
18549 (if (and org-agenda-follow-mode
18550 (get-text-property (point) 'org-marker))
18551 (org-agenda-show)))
18553 (defun org-agenda-show-priority ()
18554 "Show the priority of the current item.
18555 This priority is composed of the main priority given with the [#A] cookies,
18556 and by additional input from the age of a schedules or deadline entry."
18557 (interactive)
18558 (let* ((pri (get-text-property (point-at-bol) 'priority)))
18559 (message "Priority is %d" (if pri pri -1000))))
18561 (defun org-agenda-show-tags ()
18562 "Show the tags applicable to the current item."
18563 (interactive)
18564 (let* ((tags (get-text-property (point-at-bol) 'tags)))
18565 (if tags
18566 (message "Tags are :%s:"
18567 (org-no-properties (mapconcat 'identity tags ":")))
18568 (message "No tags associated with this line"))))
18570 (defun org-agenda-goto (&optional highlight)
18571 "Go to the Org-mode file which contains the item at point."
18572 (interactive)
18573 (let* ((marker (or (get-text-property (point) 'org-marker)
18574 (org-agenda-error)))
18575 (buffer (marker-buffer marker))
18576 (pos (marker-position marker)))
18577 (switch-to-buffer-other-window buffer)
18578 (widen)
18579 (goto-char pos)
18580 (when (org-mode-p)
18581 (org-show-context 'agenda)
18582 (save-excursion
18583 (and (outline-next-heading)
18584 (org-flag-heading nil)))) ; show the next heading
18585 (and highlight (org-highlight (point-at-bol) (point-at-eol)))))
18587 (defun org-agenda-kill ()
18588 "Kill the entry or subtree belonging to the current agenda entry."
18589 (interactive)
18590 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
18591 (let* ((marker (or (get-text-property (point) 'org-marker)
18592 (org-agenda-error)))
18593 (buffer (marker-buffer marker))
18594 (pos (marker-position marker))
18595 (type (get-text-property (point) 'type))
18596 dbeg dend (n 0) conf)
18597 (org-with-remote-undo buffer
18598 (with-current-buffer buffer
18599 (save-excursion
18600 (goto-char pos)
18601 (if (and (org-mode-p) (not (member type '("sexp"))))
18602 (setq dbeg (progn (org-back-to-heading t) (point))
18603 dend (org-end-of-subtree t))
18604 (setq dbeg (point-at-bol)
18605 dend (min (point-max) (1+ (point-at-eol)))))
18606 (goto-char dbeg)
18607 (while (re-search-forward "^[ \t]*\\S-" dend t) (setq n (1+ n)))))
18608 (setq conf (or (eq t org-agenda-confirm-kill)
18609 (and (numberp org-agenda-confirm-kill)
18610 (> n org-agenda-confirm-kill))))
18611 (and conf
18612 (not (y-or-n-p
18613 (format "Delete entry with %d lines in buffer \"%s\"? "
18614 n (buffer-name buffer))))
18615 (error "Abort"))
18616 (org-remove-subtree-entries-from-agenda buffer dbeg dend)
18617 (with-current-buffer buffer (delete-region dbeg dend))
18618 (message "Agenda item and source killed"))))
18620 (defun org-agenda-archive ()
18621 "Kill the entry or subtree belonging to the current agenda entry."
18622 (interactive)
18623 (or (eq major-mode 'org-agenda-mode) (error "Not in agenda"))
18624 (let* ((marker (or (get-text-property (point) 'org-marker)
18625 (org-agenda-error)))
18626 (buffer (marker-buffer marker))
18627 (pos (marker-position marker)))
18628 (org-with-remote-undo buffer
18629 (with-current-buffer buffer
18630 (if (org-mode-p)
18631 (save-excursion
18632 (goto-char pos)
18633 (org-remove-subtree-entries-from-agenda)
18634 (org-back-to-heading t)
18635 (org-archive-subtree))
18636 (error "Archiving works only in Org-mode files"))))))
18638 (defun org-remove-subtree-entries-from-agenda (&optional buf beg end)
18639 "Remove all lines in the agenda that correspond to a given subtree.
18640 The subtree is the one in buffer BUF, starting at BEG and ending at END.
18641 If this information is not given, the function uses the tree at point."
18642 (let ((buf (or buf (current-buffer))) m p)
18643 (save-excursion
18644 (unless (and beg end)
18645 (org-back-to-heading t)
18646 (setq beg (point))
18647 (org-end-of-subtree t)
18648 (setq end (point)))
18649 (set-buffer (get-buffer org-agenda-buffer-name))
18650 (save-excursion
18651 (goto-char (point-max))
18652 (beginning-of-line 1)
18653 (while (not (bobp))
18654 (when (and (setq m (get-text-property (point) 'org-marker))
18655 (equal buf (marker-buffer m))
18656 (setq p (marker-position m))
18657 (>= p beg)
18658 (<= p end))
18659 (let (buffer-read-only)
18660 (delete-region (point-at-bol) (1+ (point-at-eol)))))
18661 (beginning-of-line 0))))))
18663 (defun org-agenda-open-link ()
18664 "Follow the link in the current line, if any."
18665 (interactive)
18666 (let ((eol (point-at-eol)))
18667 (save-excursion
18668 (if (or (re-search-forward org-bracket-link-regexp eol t)
18669 (re-search-forward org-angle-link-re eol t)
18670 (re-search-forward org-plain-link-re eol t))
18671 (call-interactively 'org-open-at-point)
18672 (error "No link in current line")))))
18674 (defun org-agenda-switch-to (&optional delete-other-windows)
18675 "Go to the Org-mode file which contains the item at point."
18676 (interactive)
18677 (let* ((marker (or (get-text-property (point) 'org-marker)
18678 (org-agenda-error)))
18679 (buffer (marker-buffer marker))
18680 (pos (marker-position marker)))
18681 (switch-to-buffer buffer)
18682 (and delete-other-windows (delete-other-windows))
18683 (widen)
18684 (goto-char pos)
18685 (when (org-mode-p)
18686 (org-show-context 'agenda)
18687 (save-excursion
18688 (and (outline-next-heading)
18689 (org-flag-heading nil)))))) ; show the next heading
18691 (defun org-agenda-goto-mouse (ev)
18692 "Go to the Org-mode file which contains the item at the mouse click."
18693 (interactive "e")
18694 (mouse-set-point ev)
18695 (org-agenda-goto))
18697 (defun org-agenda-show ()
18698 "Display the Org-mode file which contains the item at point."
18699 (interactive)
18700 (let ((win (selected-window)))
18701 (org-agenda-goto t)
18702 (select-window win)))
18704 (defun org-agenda-recenter (arg)
18705 "Display the Org-mode file which contains the item at point and recenter."
18706 (interactive "P")
18707 (let ((win (selected-window)))
18708 (org-agenda-goto t)
18709 (recenter arg)
18710 (select-window win)))
18712 (defun org-agenda-show-mouse (ev)
18713 "Display the Org-mode file which contains the item at the mouse click."
18714 (interactive "e")
18715 (mouse-set-point ev)
18716 (org-agenda-show))
18718 (defun org-agenda-check-no-diary ()
18719 "Check if the entry is a diary link and abort if yes."
18720 (if (get-text-property (point) 'org-agenda-diary-link)
18721 (org-agenda-error)))
18723 (defun org-agenda-error ()
18724 (error "Command not allowed in this line"))
18726 (defun org-agenda-tree-to-indirect-buffer ()
18727 "Show the subtree corresponding to the current entry in an indirect buffer.
18728 This calls the command `org-tree-to-indirect-buffer' from the original
18729 Org-mode buffer.
18730 With numerical prefix arg ARG, go up to this level and then take that tree.
18731 With a C-u prefix, make a separate frame for this tree (i.e. don't use the
18732 dedicated frame)."
18733 (interactive)
18734 (org-agenda-check-no-diary)
18735 (let* ((marker (or (get-text-property (point) 'org-marker)
18736 (org-agenda-error)))
18737 (buffer (marker-buffer marker))
18738 (pos (marker-position marker)))
18739 (with-current-buffer buffer
18740 (save-excursion
18741 (goto-char pos)
18742 (call-interactively 'org-tree-to-indirect-buffer)))))
18744 (defvar org-last-heading-marker (make-marker)
18745 "Marker pointing to the headline that last changed its TODO state
18746 by a remote command from the agenda.")
18748 (defun org-agenda-todo-nextset ()
18749 "Switch TODO entry to next sequence."
18750 (interactive)
18751 (org-agenda-todo 'nextset))
18753 (defun org-agenda-todo-previousset ()
18754 "Switch TODO entry to previous sequence."
18755 (interactive)
18756 (org-agenda-todo 'previousset))
18758 (defun org-agenda-todo (&optional arg)
18759 "Cycle TODO state of line at point, also in Org-mode file.
18760 This changes the line at point, all other lines in the agenda referring to
18761 the same tree node, and the headline of the tree node in the Org-mode file."
18762 (interactive "P")
18763 (org-agenda-check-no-diary)
18764 (let* ((col (current-column))
18765 (marker (or (get-text-property (point) 'org-marker)
18766 (org-agenda-error)))
18767 (buffer (marker-buffer marker))
18768 (pos (marker-position marker))
18769 (hdmarker (get-text-property (point) 'org-hd-marker))
18770 (buffer-read-only nil)
18771 newhead)
18772 (org-with-remote-undo buffer
18773 (with-current-buffer buffer
18774 (widen)
18775 (goto-char pos)
18776 (org-show-context 'agenda)
18777 (save-excursion
18778 (and (outline-next-heading)
18779 (org-flag-heading nil))) ; show the next heading
18780 (org-todo arg)
18781 (and (bolp) (forward-char 1))
18782 (setq newhead (org-get-heading))
18783 (save-excursion
18784 (org-back-to-heading)
18785 (move-marker org-last-heading-marker (point))))
18786 (beginning-of-line 1)
18787 (save-excursion
18788 (org-agenda-change-all-lines newhead hdmarker 'fixface))
18789 (move-to-column col))))
18791 (defun org-agenda-change-all-lines (newhead hdmarker &optional fixface)
18792 "Change all lines in the agenda buffer which match HDMARKER.
18793 The new content of the line will be NEWHEAD (as modified by
18794 `org-format-agenda-item'). HDMARKER is checked with
18795 `equal' against all `org-hd-marker' text properties in the file.
18796 If FIXFACE is non-nil, the face of each item is modified acording to
18797 the new TODO state."
18798 (let* ((buffer-read-only nil)
18799 props m pl undone-face done-face finish new dotime cat tags)
18800 (save-excursion
18801 (goto-char (point-max))
18802 (beginning-of-line 1)
18803 (while (not finish)
18804 (setq finish (bobp))
18805 (when (and (setq m (get-text-property (point) 'org-hd-marker))
18806 (equal m hdmarker))
18807 (setq props (text-properties-at (point))
18808 dotime (get-text-property (point) 'dotime)
18809 cat (get-text-property (point) 'org-category)
18810 tags (get-text-property (point) 'tags)
18811 new (org-format-agenda-item "x" newhead cat tags dotime 'noprefix)
18812 pl (get-text-property (point) 'prefix-length)
18813 undone-face (get-text-property (point) 'undone-face)
18814 done-face (get-text-property (point) 'done-face))
18815 (move-to-column pl)
18816 (cond
18817 ((equal new "")
18818 (beginning-of-line 1)
18819 (and (looking-at ".*\n?") (replace-match "")))
18820 ((looking-at ".*")
18821 (replace-match new t t)
18822 (beginning-of-line 1)
18823 (add-text-properties (point-at-bol) (point-at-eol) props)
18824 (when fixface
18825 (add-text-properties
18826 (point-at-bol) (point-at-eol)
18827 (list 'face
18828 (if org-last-todo-state-is-todo
18829 undone-face done-face))))
18830 (org-agenda-highlight-todo 'line)
18831 (beginning-of-line 1))
18832 (t (error "Line update did not work"))))
18833 (beginning-of-line 0)))
18834 (org-finalize-agenda)))
18836 ;; FIXME: allow negative value for org-agenda-align-tags-to-column
18837 ;; See the code in set-tags for the way to do this.
18838 (defun org-agenda-align-tags (&optional line)
18839 "Align all tags in agenda items to `org-agenda-align-tags-to-column'."
18840 (let ((buffer-read-only))
18841 (save-excursion
18842 (goto-char (if line (point-at-bol) (point-min)))
18843 (while (re-search-forward (org-re "\\([ \t]+\\):[[:alnum:]_@:]+:[ \t]*$")
18844 (if line (point-at-eol) nil) t)
18845 (delete-region (match-beginning 1) (match-end 1))
18846 (goto-char (match-beginning 1))
18847 (insert (org-add-props
18848 (make-string (max 1 (- org-agenda-align-tags-to-column
18849 (current-column))) ?\ )
18850 (text-properties-at (point))))))))
18852 (defun org-agenda-priority-up ()
18853 "Increase the priority of line at point, also in Org-mode file."
18854 (interactive)
18855 (org-agenda-priority 'up))
18857 (defun org-agenda-priority-down ()
18858 "Decrease the priority of line at point, also in Org-mode file."
18859 (interactive)
18860 (org-agenda-priority 'down))
18862 (defun org-agenda-priority (&optional force-direction)
18863 "Set the priority of line at point, also in Org-mode file.
18864 This changes the line at point, all other lines in the agenda referring to
18865 the same tree node, and the headline of the tree node in the Org-mode file."
18866 (interactive)
18867 (org-agenda-check-no-diary)
18868 (let* ((marker (or (get-text-property (point) 'org-marker)
18869 (org-agenda-error)))
18870 (buffer (marker-buffer marker))
18871 (pos (marker-position marker))
18872 (hdmarker (get-text-property (point) 'org-hd-marker))
18873 (buffer-read-only nil)
18874 newhead)
18875 (org-with-remote-undo buffer
18876 (with-current-buffer buffer
18877 (widen)
18878 (goto-char pos)
18879 (org-show-context 'agenda)
18880 (save-excursion
18881 (and (outline-next-heading)
18882 (org-flag-heading nil))) ; show the next heading
18883 (funcall 'org-priority force-direction)
18884 (end-of-line 1)
18885 (setq newhead (org-get-heading)))
18886 (org-agenda-change-all-lines newhead hdmarker)
18887 (beginning-of-line 1))))
18889 (defun org-get-tags-at (&optional pos)
18890 "Get a list of all headline tags applicable at POS.
18891 POS defaults to point. If tags are inherited, the list contains
18892 the targets in the same sequence as the headlines appear, i.e.
18893 the tags of the current headline come last."
18894 (interactive)
18895 (let (tags)
18896 (save-excursion
18897 (save-restriction
18898 (widen)
18899 (goto-char (or pos (point)))
18900 (save-match-data
18901 (org-back-to-heading t)
18902 (condition-case nil
18903 (while t
18904 (if (looking-at (org-re "[^\r\n]+?:\\([[:alnum:]_@:]+\\):[ \t]*$"))
18905 (setq tags (append (org-split-string
18906 (org-match-string-no-properties 1) ":")
18907 tags)))
18908 (or org-use-tag-inheritance (error ""))
18909 (org-up-heading-all 1))
18910 (error nil))))
18911 tags)))
18913 ;; FIXME: should fix the tags property of the agenda line.
18914 (defun org-agenda-set-tags ()
18915 "Set tags for the current headline."
18916 (interactive)
18917 (org-agenda-check-no-diary)
18918 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
18919 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
18920 (org-agenda-error)))
18921 (buffer (marker-buffer hdmarker))
18922 (pos (marker-position hdmarker))
18923 (buffer-read-only nil)
18924 newhead)
18925 (org-with-remote-undo buffer
18926 (with-current-buffer buffer
18927 (widen)
18928 (goto-char pos)
18929 (save-excursion
18930 (org-show-context 'agenda))
18931 (save-excursion
18932 (and (outline-next-heading)
18933 (org-flag-heading nil))) ; show the next heading
18934 (goto-char pos)
18935 (call-interactively 'org-set-tags)
18936 (end-of-line 1)
18937 (setq newhead (org-get-heading)))
18938 (org-agenda-change-all-lines newhead hdmarker)
18939 (beginning-of-line 1))))
18941 (defun org-agenda-toggle-archive-tag ()
18942 "Toggle the archive tag for the current entry."
18943 (interactive)
18944 (org-agenda-check-no-diary)
18945 (org-agenda-show) ;;; FIXME This is a stupid hack and should not be needed
18946 (let* ((hdmarker (or (get-text-property (point) 'org-hd-marker)
18947 (org-agenda-error)))
18948 (buffer (marker-buffer hdmarker))
18949 (pos (marker-position hdmarker))
18950 (buffer-read-only nil)
18951 newhead)
18952 (org-with-remote-undo buffer
18953 (with-current-buffer buffer
18954 (widen)
18955 (goto-char pos)
18956 (org-show-context 'agenda)
18957 (save-excursion
18958 (and (outline-next-heading)
18959 (org-flag-heading nil))) ; show the next heading
18960 (call-interactively 'org-toggle-archive-tag)
18961 (end-of-line 1)
18962 (setq newhead (org-get-heading)))
18963 (org-agenda-change-all-lines newhead hdmarker)
18964 (beginning-of-line 1))))
18966 (defun org-agenda-date-later (arg &optional what)
18967 "Change the date of this item to one day later."
18968 (interactive "p")
18969 (org-agenda-check-type t 'agenda 'timeline)
18970 (org-agenda-check-no-diary)
18971 (let* ((marker (or (get-text-property (point) 'org-marker)
18972 (org-agenda-error)))
18973 (buffer (marker-buffer marker))
18974 (pos (marker-position marker)))
18975 (org-with-remote-undo buffer
18976 (with-current-buffer buffer
18977 (widen)
18978 (goto-char pos)
18979 (if (not (org-at-timestamp-p))
18980 (error "Cannot find time stamp"))
18981 (org-timestamp-change arg (or what 'day)))
18982 (org-agenda-show-new-time marker org-last-changed-timestamp))
18983 (message "Time stamp changed to %s" org-last-changed-timestamp)))
18985 (defun org-agenda-date-earlier (arg &optional what)
18986 "Change the date of this item to one day earlier."
18987 (interactive "p")
18988 (org-agenda-date-later (- arg) what))
18990 (defun org-agenda-show-new-time (marker stamp)
18991 "Show new date stamp via text properties."
18992 ;; We use text properties to make this undoable
18993 (let ((buffer-read-only nil))
18994 (setq stamp (concat " => " stamp))
18995 (save-excursion
18996 (goto-char (point-max))
18997 (while (not (bobp))
18998 (when (equal marker (get-text-property (point) 'org-marker))
18999 (move-to-column (- (window-width) (length stamp)) t)
19000 (if (featurep 'xemacs)
19001 ;; Use `duplicable' property to trigger undo recording
19002 (let ((ex (make-extent nil nil))
19003 (gl (make-glyph stamp)))
19004 (set-glyph-face gl 'secondary-selection)
19005 (set-extent-properties
19006 ex (list 'invisible t 'end-glyph gl 'duplicable t))
19007 (insert-extent ex (1- (point)) (point-at-eol)))
19008 (add-text-properties
19009 (1- (point)) (point-at-eol)
19010 (list 'display (org-add-props stamp nil
19011 'face 'secondary-selection))))
19012 (beginning-of-line 1))
19013 (beginning-of-line 0)))))
19015 (defun org-agenda-date-prompt (arg)
19016 "Change the date of this item. Date is prompted for, with default today.
19017 The prefix ARG is passed to the `org-time-stamp' command and can therefore
19018 be used to request time specification in the time stamp."
19019 (interactive "P")
19020 (org-agenda-check-type t 'agenda 'timeline)
19021 (org-agenda-check-no-diary)
19022 (let* ((marker (or (get-text-property (point) 'org-marker)
19023 (org-agenda-error)))
19024 (buffer (marker-buffer marker))
19025 (pos (marker-position marker)))
19026 (org-with-remote-undo buffer
19027 (with-current-buffer buffer
19028 (widen)
19029 (goto-char pos)
19030 (if (not (org-at-timestamp-p))
19031 (error "Cannot find time stamp"))
19032 (org-time-stamp arg)
19033 (message "Time stamp changed to %s" org-last-changed-timestamp)))))
19035 (defun org-agenda-schedule (arg)
19036 "Schedule the item at point."
19037 (interactive "P")
19038 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
19039 (org-agenda-check-no-diary)
19040 (let* ((marker (or (get-text-property (point) 'org-marker)
19041 (org-agenda-error)))
19042 (buffer (marker-buffer marker))
19043 (pos (marker-position marker))
19044 (org-insert-labeled-timestamps-at-point nil)
19046 (org-with-remote-undo buffer
19047 (with-current-buffer buffer
19048 (widen)
19049 (goto-char pos)
19050 (setq ts (org-schedule))
19051 (message "Item scheduled for %s" ts)))))
19053 (defun org-agenda-deadline (arg)
19054 "Schedule the item at point."
19055 (interactive "P")
19056 (org-agenda-check-type t 'agenda 'timeline 'todo 'tags)
19057 (org-agenda-check-no-diary)
19058 (let* ((marker (or (get-text-property (point) 'org-marker)
19059 (org-agenda-error)))
19060 (buffer (marker-buffer marker))
19061 (pos (marker-position marker))
19062 (org-insert-labeled-timestamps-at-point nil)
19064 (org-with-remote-undo buffer
19065 (with-current-buffer buffer
19066 (widen)
19067 (goto-char pos)
19068 (setq ts (org-deadline))
19069 (message "Deadline for this item set to %s" ts)))))
19071 (defun org-get-heading ()
19072 "Return the heading of the current entry, without the stars."
19073 (save-excursion
19074 (org-back-to-heading t)
19075 (if (looking-at "\\*+[ \t]+\\([^\r\n]*\\)") (match-string 1) "")))
19077 (defun org-agenda-clock-in (&optional arg)
19078 "Start the clock on the currently selected item."
19079 (interactive "P")
19080 (org-agenda-check-no-diary)
19081 (let* ((marker (or (get-text-property (point) 'org-marker)
19082 (org-agenda-error)))
19083 (pos (marker-position marker)))
19084 (org-with-remote-undo (marker-buffer marker)
19085 (with-current-buffer (marker-buffer marker)
19086 (widen)
19087 (goto-char pos)
19088 (org-clock-in)))))
19090 (defun org-agenda-clock-out (&optional arg)
19091 "Stop the currently running clock."
19092 (interactive "P")
19093 (unless (marker-buffer org-clock-marker)
19094 (error "No running clock"))
19095 (org-with-remote-undo (marker-buffer org-clock-marker)
19096 (org-clock-out)))
19098 (defun org-agenda-clock-cancel (&optional arg)
19099 "Cancel the currently running clock."
19100 (interactive "P")
19101 (unless (marker-buffer org-clock-marker)
19102 (error "No running clock"))
19103 (org-with-remote-undo (marker-buffer org-clock-marker)
19104 (org-clock-cancel)))
19106 (defun org-agenda-diary-entry ()
19107 "Make a diary entry, like the `i' command from the calendar.
19108 All the standard commands work: block, weekly etc."
19109 (interactive)
19110 (org-agenda-check-type t 'agenda 'timeline)
19111 (require 'diary-lib)
19112 (let* ((char (progn
19113 (message "Diary entry: [d]ay [w]eekly [m]onthly [y]early [a]nniversary [b]lock [c]yclic")
19114 (read-char-exclusive)))
19115 (cmd (cdr (assoc char
19116 '((?d . insert-diary-entry)
19117 (?w . insert-weekly-diary-entry)
19118 (?m . insert-monthly-diary-entry)
19119 (?y . insert-yearly-diary-entry)
19120 (?a . insert-anniversary-diary-entry)
19121 (?b . insert-block-diary-entry)
19122 (?c . insert-cyclic-diary-entry)))))
19123 (oldf (symbol-function 'calendar-cursor-to-date))
19124 ; (buf (get-file-buffer (substitute-in-file-name diary-file)))
19125 (point (point))
19126 (mark (or (mark t) (point))))
19127 (unless cmd
19128 (error "No command associated with <%c>" char))
19129 (unless (and (get-text-property point 'day)
19130 (or (not (equal ?b char))
19131 (get-text-property mark 'day)))
19132 (error "Don't know which date to use for diary entry"))
19133 ;; We implement this by hacking the `calendar-cursor-to-date' function
19134 ;; and the `calendar-mark-ring' variable. Saves a lot of code.
19135 (let ((calendar-mark-ring
19136 (list (calendar-gregorian-from-absolute
19137 (or (get-text-property mark 'day)
19138 (get-text-property point 'day))))))
19139 (unwind-protect
19140 (progn
19141 (fset 'calendar-cursor-to-date
19142 (lambda (&optional error)
19143 (calendar-gregorian-from-absolute
19144 (get-text-property point 'day))))
19145 (call-interactively cmd))
19146 (fset 'calendar-cursor-to-date oldf)))))
19149 (defun org-agenda-execute-calendar-command (cmd)
19150 "Execute a calendar command from the agenda, with the date associated to
19151 the cursor position."
19152 (org-agenda-check-type t 'agenda 'timeline)
19153 (require 'diary-lib)
19154 (unless (get-text-property (point) 'day)
19155 (error "Don't know which date to use for calendar command"))
19156 (let* ((oldf (symbol-function 'calendar-cursor-to-date))
19157 (point (point))
19158 (date (calendar-gregorian-from-absolute
19159 (get-text-property point 'day)))
19160 ;; the following 3 vars are needed in the calendar
19161 (displayed-day (extract-calendar-day date))
19162 (displayed-month (extract-calendar-month date))
19163 (displayed-year (extract-calendar-year date)))
19164 (unwind-protect
19165 (progn
19166 (fset 'calendar-cursor-to-date
19167 (lambda (&optional error)
19168 (calendar-gregorian-from-absolute
19169 (get-text-property point 'day))))
19170 (call-interactively cmd))
19171 (fset 'calendar-cursor-to-date oldf))))
19173 (defun org-agenda-phases-of-moon ()
19174 "Display the phases of the moon for the 3 months around the cursor date."
19175 (interactive)
19176 (org-agenda-execute-calendar-command 'calendar-phases-of-moon))
19178 (defun org-agenda-holidays ()
19179 "Display the holidays for the 3 months around the cursor date."
19180 (interactive)
19181 (org-agenda-execute-calendar-command 'list-calendar-holidays))
19183 (defun org-agenda-sunrise-sunset (arg)
19184 "Display sunrise and sunset for the cursor date.
19185 Latitude and longitude can be specified with the variables
19186 `calendar-latitude' and `calendar-longitude'. When called with prefix
19187 argument, latitude and longitude will be prompted for."
19188 (interactive "P")
19189 (let ((calendar-longitude (if arg nil calendar-longitude))
19190 (calendar-latitude (if arg nil calendar-latitude))
19191 (calendar-location-name
19192 (if arg "the given coordinates" calendar-location-name)))
19193 (org-agenda-execute-calendar-command 'calendar-sunrise-sunset)))
19195 (defun org-agenda-goto-calendar ()
19196 "Open the Emacs calendar with the date at the cursor."
19197 (interactive)
19198 (org-agenda-check-type t 'agenda 'timeline)
19199 (let* ((day (or (get-text-property (point) 'day)
19200 (error "Don't know which date to open in calendar")))
19201 (date (calendar-gregorian-from-absolute day))
19202 (calendar-move-hook nil)
19203 (view-calendar-holidays-initially nil)
19204 (view-diary-entries-initially nil))
19205 (calendar)
19206 (calendar-goto-date date)))
19208 (defun org-calendar-goto-agenda ()
19209 "Compute the Org-mode agenda for the calendar date displayed at the cursor.
19210 This is a command that has to be installed in `calendar-mode-map'."
19211 (interactive)
19212 (org-agenda-list nil (calendar-absolute-from-gregorian
19213 (calendar-cursor-to-date))
19214 nil))
19216 (defun org-agenda-convert-date ()
19217 (interactive)
19218 (org-agenda-check-type t 'agenda 'timeline)
19219 (let ((day (get-text-property (point) 'day))
19220 date s)
19221 (unless day
19222 (error "Don't know which date to convert"))
19223 (setq date (calendar-gregorian-from-absolute day))
19224 (setq s (concat
19225 "Gregorian: " (calendar-date-string date) "\n"
19226 "ISO: " (calendar-iso-date-string date) "\n"
19227 "Day of Yr: " (calendar-day-of-year-string date) "\n"
19228 "Julian: " (calendar-julian-date-string date) "\n"
19229 "Astron. JD: " (calendar-astro-date-string date)
19230 " (Julian date number at noon UTC)\n"
19231 "Hebrew: " (calendar-hebrew-date-string date) " (until sunset)\n"
19232 "Islamic: " (calendar-islamic-date-string date) " (until sunset)\n"
19233 "French: " (calendar-french-date-string date) "\n"
19234 "Mayan: " (calendar-mayan-date-string date) "\n"
19235 "Coptic: " (calendar-coptic-date-string date) "\n"
19236 "Ethiopic: " (calendar-ethiopic-date-string date) "\n"
19237 "Persian: " (calendar-persian-date-string date) "\n"
19238 "Chinese: " (calendar-chinese-date-string date) "\n"))
19239 (with-output-to-temp-buffer "*Dates*"
19240 (princ s))
19241 (if (fboundp 'fit-window-to-buffer)
19242 (fit-window-to-buffer (get-buffer-window "*Dates*")))))
19245 ;;;; Embedded LaTeX
19247 (defvar org-cdlatex-mode-map (make-sparse-keymap)
19248 "Keymap for the minor `org-cdlatex-mode'.")
19250 (org-defkey org-cdlatex-mode-map "_" 'org-cdlatex-underscore-caret)
19251 (org-defkey org-cdlatex-mode-map "^" 'org-cdlatex-underscore-caret)
19252 (org-defkey org-cdlatex-mode-map "`" 'cdlatex-math-symbol)
19253 (org-defkey org-cdlatex-mode-map "'" 'org-cdlatex-math-modify)
19254 (org-defkey org-cdlatex-mode-map "\C-c{" 'cdlatex-environment)
19256 (defvar org-cdlatex-texmathp-advice-is-done nil
19257 "Flag remembering if we have applied the advice to texmathp already.")
19259 (define-minor-mode org-cdlatex-mode
19260 "Toggle the minor `org-cdlatex-mode'.
19261 This mode supports entering LaTeX environment and math in LaTeX fragments
19262 in Org-mode.
19263 \\{org-cdlatex-mode-map}"
19264 nil " OCDL" nil
19265 (when org-cdlatex-mode (require 'cdlatex))
19266 (unless org-cdlatex-texmathp-advice-is-done
19267 (setq org-cdlatex-texmathp-advice-is-done t)
19268 (defadvice texmathp (around org-math-always-on activate)
19269 "Always return t in org-mode buffers.
19270 This is because we want to insert math symbols without dollars even outside
19271 the LaTeX math segments. If Orgmode thinks that point is actually inside
19272 en embedded LaTeX fragement, let texmathp do its job.
19273 \\[org-cdlatex-mode-map]"
19274 (interactive)
19275 (let (p)
19276 (cond
19277 ((not (org-mode-p)) ad-do-it)
19278 ((eq this-command 'cdlatex-math-symbol)
19279 (setq ad-return-value t
19280 texmathp-why '("cdlatex-math-symbol in org-mode" . 0)))
19282 (let ((p (org-inside-LaTeX-fragment-p)))
19283 (if (and p (member (car p) (plist-get org-format-latex-options :matchers)))
19284 (setq ad-return-value t
19285 texmathp-why '("Org-mode embedded math" . 0))
19286 (if p ad-do-it)))))))))
19288 (defun turn-on-org-cdlatex ()
19289 "Unconditionally turn on `org-cdlatex-mode'."
19290 (org-cdlatex-mode 1))
19292 (defun org-inside-LaTeX-fragment-p ()
19293 "Test if point is inside a LaTeX fragment.
19294 I.e. after a \\begin, \\(, \\[, $, or $$, without the corresponding closing
19295 sequence appearing also before point.
19296 Even though the matchers for math are configurable, this function assumes
19297 that \\begin, \\(, \\[, and $$ are always used. Only the single dollar
19298 delimiters are skipped when they have been removed by customization.
19299 The return value is nil, or a cons cell with the delimiter and
19300 and the position of this delimiter.
19302 This function does a reasonably good job, but can locally be fooled by
19303 for example currency specifications. For example it will assume being in
19304 inline math after \"$22.34\". The LaTeX fragment formatter will only format
19305 fragments that are properly closed, but during editing, we have to live
19306 with the uncertainty caused by missing closing delimiters. This function
19307 looks only before point, not after."
19308 (catch 'exit
19309 (let ((pos (point))
19310 (dodollar (member "$" (plist-get org-format-latex-options :matchers)))
19311 (lim (progn
19312 (re-search-backward (concat "^\\(" paragraph-start "\\)") nil t)
19313 (point)))
19314 dd-on str (start 0) m re)
19315 (goto-char pos)
19316 (when dodollar
19317 (setq str (concat (buffer-substring lim (point)) "\000 X$.")
19318 re (nth 1 (assoc "$" org-latex-regexps)))
19319 (while (string-match re str start)
19320 (cond
19321 ((= (match-end 0) (length str))
19322 (throw 'exit (cons "$" (+ lim (match-beginning 0) 1))))
19323 ((= (match-end 0) (- (length str) 5))
19324 (throw 'exit nil))
19325 (t (setq start (match-end 0))))))
19326 (when (setq m (re-search-backward "\\(\\\\begin{[^}]*}\\|\\\\(\\|\\\\\\[\\)\\|\\(\\\\end{[^}]*}\\|\\\\)\\|\\\\\\]\\)\\|\\(\\$\\$\\)" lim t))
19327 (goto-char pos)
19328 (and (match-beginning 1) (throw 'exit (cons (match-string 1) m)))
19329 (and (match-beginning 2) (throw 'exit nil))
19330 ;; count $$
19331 (while (re-search-backward "\\$\\$" lim t)
19332 (setq dd-on (not dd-on)))
19333 (goto-char pos)
19334 (if dd-on (cons "$$" m))))))
19337 (defun org-try-cdlatex-tab ()
19338 "Check if it makes sense to execute `cdlatex-tab', and do it if yes.
19339 It makes sense to do so if `org-cdlatex-mode' is active and if the cursor is
19340 - inside a LaTeX fragment, or
19341 - after the first word in a line, where an abbreviation expansion could
19342 insert a LaTeX environment."
19343 (when org-cdlatex-mode
19344 (cond
19345 ((save-excursion
19346 (skip-chars-backward "a-zA-Z0-9*")
19347 (skip-chars-backward " \t")
19348 (bolp))
19349 (cdlatex-tab) t)
19350 ((org-inside-LaTeX-fragment-p)
19351 (cdlatex-tab) t)
19352 (t nil))))
19354 (defun org-cdlatex-underscore-caret (&optional arg)
19355 "Execute `cdlatex-sub-superscript' in LaTeX fragments.
19356 Revert to the normal definition outside of these fragments."
19357 (interactive "P")
19358 (if (org-inside-LaTeX-fragment-p)
19359 (call-interactively 'cdlatex-sub-superscript)
19360 (let (org-cdlatex-mode)
19361 (call-interactively (key-binding (vector last-input-event))))))
19363 (defun org-cdlatex-math-modify (&optional arg)
19364 "Execute `cdlatex-math-modify' in LaTeX fragments.
19365 Revert to the normal definition outside of these fragments."
19366 (interactive "P")
19367 (if (org-inside-LaTeX-fragment-p)
19368 (call-interactively 'cdlatex-math-modify)
19369 (let (org-cdlatex-mode)
19370 (call-interactively (key-binding (vector last-input-event))))))
19372 (defvar org-latex-fragment-image-overlays nil
19373 "List of overlays carrying the images of latex fragments.")
19374 (make-variable-buffer-local 'org-latex-fragment-image-overlays)
19376 (defun org-remove-latex-fragment-image-overlays ()
19377 "Remove all overlays with LaTeX fragment images in current buffer."
19378 (mapc 'org-delete-overlay org-latex-fragment-image-overlays)
19379 (setq org-latex-fragment-image-overlays nil))
19381 (defun org-preview-latex-fragment (&optional subtree)
19382 "Preview the LaTeX fragment at point, or all locally or globally.
19383 If the cursor is in a LaTeX fragment, create the image and overlay
19384 it over the source code. If there is no fragment at point, display
19385 all fragments in the current text, from one headline to the next. With
19386 prefix SUBTREE, display all fragments in the current subtree. With a
19387 double prefix `C-u C-u', or when the cursor is before the first headline,
19388 display all fragments in the buffer.
19389 The images can be removed again with \\[org-ctrl-c-ctrl-c]."
19390 (interactive "P")
19391 (org-remove-latex-fragment-image-overlays)
19392 (save-excursion
19393 (save-restriction
19394 (let (beg end at msg)
19395 (cond
19396 ((or (equal subtree '(16))
19397 (not (save-excursion
19398 (re-search-backward (concat "^" outline-regexp) nil t))))
19399 (setq beg (point-min) end (point-max)
19400 msg "Creating images for buffer...%s"))
19401 ((equal subtree '(4))
19402 (org-back-to-heading)
19403 (setq beg (point) end (org-end-of-subtree t)
19404 msg "Creating images for subtree...%s"))
19406 (if (setq at (org-inside-LaTeX-fragment-p))
19407 (goto-char (max (point-min) (- (cdr at) 2)))
19408 (org-back-to-heading))
19409 (setq beg (point) end (progn (outline-next-heading) (point))
19410 msg (if at "Creating image...%s"
19411 "Creating images for entry...%s"))))
19412 (message msg "")
19413 (narrow-to-region beg end)
19414 (goto-char beg)
19415 (org-format-latex
19416 (concat "ltxpng/" (file-name-sans-extension
19417 (file-name-nondirectory
19418 buffer-file-name)))
19419 default-directory 'overlays msg at 'forbuffer)
19420 (message msg "done. Use `C-c C-c' to remove images.")))))
19422 (defvar org-latex-regexps
19423 '(("begin" "^[ \t]*\\(\\\\begin{\\([a-zA-Z0-9\\*]+\\)[^\000]+?\\\\end{\\2}\\)" 1 t)
19424 ;; ("$" "\\([ (]\\|^\\)\\(\\(\\([$]\\)\\([^ \r\n,.$].*?\\(\n.*?\\)\\{0,5\\}[^ \r\n,.$]\\)\\4\\)\\)\\([ .,?;:'\")]\\|$\\)" 2 nil)
19425 ;; \000 in the following regex is needed for org-inside-LaTeX-fragment-p
19426 ("$" "\\([^$]\\)\\(\\(\\$\\([^ \r\n,;.$][^$\n\r]*?\\(\n[^$\n\r]*?\\)\\{0,2\\}[^ \r\n,.$]\\)\\$\\)\\)\\([ .,?;:'\")\000]\\|$\\)" 2 nil)
19427 ("\\(" "\\\\([^\000]*?\\\\)" 0 nil)
19428 ("\\[" "\\\\\\[[^\000]*?\\\\\\]" 0 t)
19429 ("$$" "\\$\\$[^\000]*?\\$\\$" 0 t))
19430 "Regular expressions for matching embedded LaTeX.")
19432 (defun org-format-latex (prefix &optional dir overlays msg at forbuffer)
19433 "Replace LaTeX fragments with links to an image, and produce images."
19434 (if (and overlays (fboundp 'clear-image-cache)) (clear-image-cache))
19435 (let* ((prefixnodir (file-name-nondirectory prefix))
19436 (absprefix (expand-file-name prefix dir))
19437 (todir (file-name-directory absprefix))
19438 (opt org-format-latex-options)
19439 (matchers (plist-get opt :matchers))
19440 (re-list org-latex-regexps)
19441 (cnt 0) txt link beg end re e checkdir
19442 m n block linkfile movefile ov)
19443 ;; Check if there are old images files with this prefix, and remove them
19444 (when (file-directory-p todir)
19445 (mapc 'delete-file
19446 (directory-files
19447 todir 'full
19448 (concat (regexp-quote prefixnodir) "_[0-9]+\\.png$"))))
19449 ;; Check the different regular expressions
19450 (while (setq e (pop re-list))
19451 (setq m (car e) re (nth 1 e) n (nth 2 e)
19452 block (if (nth 3 e) "\n\n" ""))
19453 (when (member m matchers)
19454 (goto-char (point-min))
19455 (while (re-search-forward re nil t)
19456 (when (or (not at) (equal (cdr at) (match-beginning n)))
19457 (setq txt (match-string n)
19458 beg (match-beginning n) end (match-end n)
19459 cnt (1+ cnt)
19460 linkfile (format "%s_%04d.png" prefix cnt)
19461 movefile (format "%s_%04d.png" absprefix cnt)
19462 link (concat block "[[file:" linkfile "]]" block))
19463 (if msg (message msg cnt))
19464 (goto-char beg)
19465 (unless checkdir ; make sure the directory exists
19466 (setq checkdir t)
19467 (or (file-directory-p todir) (make-directory todir)))
19468 (org-create-formula-image
19469 txt movefile opt forbuffer)
19470 (if overlays
19471 (progn
19472 (setq ov (org-make-overlay beg end))
19473 (if (featurep 'xemacs)
19474 (progn
19475 (org-overlay-put ov 'invisible t)
19476 (org-overlay-put
19477 ov 'end-glyph
19478 (make-glyph (vector 'png :file movefile))))
19479 (org-overlay-put
19480 ov 'display
19481 (list 'image :type 'png :file movefile :ascent 'center)))
19482 (push ov org-latex-fragment-image-overlays)
19483 (goto-char end))
19484 (delete-region beg end)
19485 (insert link))))))))
19487 ;; This function borrows from Ganesh Swami's latex2png.el
19488 (defun org-create-formula-image (string tofile options buffer)
19489 (let* ((tmpdir (if (featurep 'xemacs)
19490 (temp-directory)
19491 temporary-file-directory))
19492 (texfilebase (make-temp-name
19493 (expand-file-name "orgtex" tmpdir)))
19494 (texfile (concat texfilebase ".tex"))
19495 (dvifile (concat texfilebase ".dvi"))
19496 (pngfile (concat texfilebase ".png"))
19497 (fnh (face-attribute 'default :height nil))
19498 (scale (or (plist-get options (if buffer :scale :html-scale)) 1.0))
19499 (dpi (number-to-string (* scale (floor (* 0.9 (if buffer fnh 140.))))))
19500 (fg (or (plist-get options (if buffer :foreground :html-foreground))
19501 "Black"))
19502 (bg (or (plist-get options (if buffer :background :html-background))
19503 "Transparent")))
19504 (if (eq fg 'default) (setq fg (org-dvipng-color :foreground)))
19505 (if (eq bg 'default) (setq bg (org-dvipng-color :background)))
19506 (with-temp-file texfile
19507 (insert org-format-latex-header
19508 "\n\\begin{document}\n" string "\n\\end{document}\n"))
19509 (let ((dir default-directory))
19510 (condition-case nil
19511 (progn
19512 (cd tmpdir)
19513 (call-process "latex" nil nil nil texfile))
19514 (error nil))
19515 (cd dir))
19516 (if (not (file-exists-p dvifile))
19517 (progn (message "Failed to create dvi file from %s" texfile) nil)
19518 (call-process "dvipng" nil nil nil
19519 "-E" "-fg" fg "-bg" bg
19520 "-D" dpi
19521 ;;"-x" scale "-y" scale
19522 "-T" "tight"
19523 "-o" pngfile
19524 dvifile)
19525 (if (not (file-exists-p pngfile))
19526 (progn (message "Failed to create png file from %s" texfile) nil)
19527 ;; Use the requested file name and clean up
19528 (copy-file pngfile tofile 'replace)
19529 (loop for e in '(".dvi" ".tex" ".aux" ".log" ".png") do
19530 (delete-file (concat texfilebase e)))
19531 pngfile))))
19533 (defun org-dvipng-color (attr)
19534 "Return an rgb color specification for dvipng."
19535 (apply 'format "rgb %s %s %s"
19536 (mapcar 'org-normalize-color
19537 (color-values (face-attribute 'default attr nil)))))
19539 (defun org-normalize-color (value)
19540 "Return string to be used as color value for an RGB component."
19541 (format "%g" (/ value 65535.0)))
19543 ;;;; Exporting
19545 ;;; Variables, constants, and parameter plists
19547 (defconst org-level-max 20)
19549 (defvar org-export-html-preamble nil
19550 "Preamble, to be inserted just after <body>. Set by publishing functions.")
19551 (defvar org-export-html-postamble nil
19552 "Preamble, to be inserted just before </body>. Set by publishing functions.")
19553 (defvar org-export-html-auto-preamble t
19554 "Should default preamble be inserted? Set by publishing functions.")
19555 (defvar org-export-html-auto-postamble t
19556 "Should default postamble be inserted? Set by publishing functions.")
19557 (defvar org-current-export-file nil) ; dynamically scoped parameter
19558 (defvar org-current-export-dir nil) ; dynamically scoped parameter
19561 (defconst org-export-plist-vars
19562 '((:language . org-export-default-language)
19563 (:customtime . org-display-custom-times)
19564 (:headline-levels . org-export-headline-levels)
19565 (:section-numbers . org-export-with-section-numbers)
19566 (:table-of-contents . org-export-with-toc)
19567 (:preserve-breaks . org-export-preserve-breaks)
19568 (:archived-trees . org-export-with-archived-trees)
19569 (:emphasize . org-export-with-emphasize)
19570 (:sub-superscript . org-export-with-sub-superscripts)
19571 (:footnotes . org-export-with-footnotes)
19572 (:property-drawer . org-export-with-property-drawer)
19573 (:TeX-macros . org-export-with-TeX-macros)
19574 (:LaTeX-fragments . org-export-with-LaTeX-fragments)
19575 (:skip-before-1st-heading . org-export-skip-text-before-1st-heading)
19576 (:fixed-width . org-export-with-fixed-width)
19577 (:timestamps . org-export-with-timestamps)
19578 (:tables . org-export-with-tables)
19579 (:table-auto-headline . org-export-highlight-first-table-line)
19580 (:style . org-export-html-style)
19581 (:agenda-style . org-agenda-export-html-style) ;; FIXME: Does this work????
19582 (:convert-org-links . org-export-html-link-org-files-as-html)
19583 (:inline-images . org-export-html-inline-images)
19584 (:expand-quoted-html . org-export-html-expand)
19585 (:timestamp . org-export-html-with-timestamp)
19586 (:publishing-directory . org-export-publishing-directory)
19587 (:preamble . org-export-html-preamble)
19588 (:postamble . org-export-html-postamble)
19589 (:auto-preamble . org-export-html-auto-preamble)
19590 (:auto-postamble . org-export-html-auto-postamble)
19591 (:author . user-full-name)
19592 (:email . user-mail-address)))
19594 (defun org-default-export-plist ()
19595 "Return the property list with default settings for the export variables."
19596 (let ((l org-export-plist-vars) rtn e)
19597 (while (setq e (pop l))
19598 (setq rtn (cons (car e) (cons (symbol-value (cdr e)) rtn))))
19599 rtn))
19601 (defun org-infile-export-plist ()
19602 "Return the property list with file-local settings for export."
19603 (save-excursion
19604 (goto-char 0)
19605 (let ((re (org-make-options-regexp
19606 '("TITLE" "AUTHOR" "EMAIL" "TEXT" "OPTIONS" "LANGUAGE")))
19607 p key val text options)
19608 (while (re-search-forward re nil t)
19609 (setq key (org-match-string-no-properties 1)
19610 val (org-match-string-no-properties 2))
19611 (cond
19612 ((string-equal key "TITLE") (setq p (plist-put p :title val)))
19613 ((string-equal key "AUTHOR")(setq p (plist-put p :author val)))
19614 ((string-equal key "EMAIL") (setq p (plist-put p :email val)))
19615 ((string-equal key "LANGUAGE") (setq p (plist-put p :language val)))
19616 ((string-equal key "TEXT")
19617 (setq text (if text (concat text "\n" val) val)))
19618 ((string-equal key "OPTIONS") (setq options val))))
19619 (setq p (plist-put p :text text))
19620 (when options
19621 (let ((op '(("H" . :headline-levels)
19622 ("num" . :section-numbers)
19623 ("toc" . :table-of-contents)
19624 ("\\n" . :preserve-breaks)
19625 ("@" . :expand-quoted-html)
19626 (":" . :fixed-width)
19627 ("|" . :tables)
19628 ("^" . :sub-superscript)
19629 ("f" . :footnotes)
19630 ("p" . :property-drawer)
19631 ("*" . :emphasize)
19632 ("TeX" . :TeX-macros)
19633 ("LaTeX" . :LaTeX-fragments)
19634 ("skip" . :skip-before-1st-heading)))
19636 (while (setq o (pop op))
19637 (if (string-match (concat (regexp-quote (car o))
19638 ":\\([^ \t\n\r;,.]*\\)")
19639 options)
19640 (setq p (plist-put p (cdr o)
19641 (car (read-from-string
19642 (match-string 1 options)))))))))
19643 p)))
19645 (defun org-export-directory (type plist)
19646 (let* ((val (plist-get plist :publishing-directory))
19647 (dir (if (listp val)
19648 (or (cdr (assoc type val)) ".")
19649 val)))
19650 dir))
19652 (defun org-skip-comments (lines)
19653 "Skip lines starting with \"#\" and subtrees starting with COMMENT."
19654 (let ((re1 (concat "^\\(\\*+\\)[ \t]+" org-comment-string))
19655 (re2 "^\\(\\*+\\)[ \t\n\r]")
19656 (case-fold-search nil)
19657 rtn line level)
19658 (while (setq line (pop lines))
19659 (cond
19660 ((and (string-match re1 line)
19661 (setq level (- (match-end 1) (match-beginning 1))))
19662 ;; Beginning of a COMMENT subtree. Skip it.
19663 (while (and (setq line (pop lines))
19664 (or (not (string-match re2 line))
19665 (> (- (match-end 1) (match-beginning 1)) level))))
19666 (setq lines (cons line lines)))
19667 ((string-match "^#" line)
19668 ;; an ordinary comment line
19670 ((and org-export-table-remove-special-lines
19671 (string-match "^[ \t]*|" line)
19672 (or (string-match "^[ \t]*| *[!_^] *|" line)
19673 (and (string-match "| *<[0-9]+> *|" line)
19674 (not (string-match "| *[^ <|]" line)))))
19675 ;; a special table line that should be removed
19677 (t (setq rtn (cons line rtn)))))
19678 (nreverse rtn)))
19680 (defun org-export (&optional arg)
19681 (interactive)
19682 (let ((help "[t] insert the export option template
19683 \[v] limit export to visible part of outline tree
19685 \[a] export as ASCII
19686 \[h] export as HTML
19687 \[H] export as HTML to temporary buffer
19688 \[b] export as HTML and browse immediately
19689 \[x] export as XOXO
19691 \[i] export current file as iCalendar file
19692 \[I] export all agenda files as iCalendar files
19693 \[c] export agenda files into combined iCalendar file
19695 \[F] publish current file
19696 \[P] publish current project
19697 \[X] publish... (project will be prompted for)
19698 \[A] publish all projects")
19699 (cmds
19700 '((?t . org-insert-export-options-template)
19701 (?v . org-export-visible)
19702 (?a . org-export-as-ascii)
19703 (?h . org-export-as-html)
19704 (?b . org-export-as-html-and-open)
19705 (?H . org-export-as-html-to-buffer)
19706 (?R . org-export-region-as-html)
19707 (?x . org-export-as-xoxo)
19708 (?i . org-export-icalendar-this-file)
19709 (?I . org-export-icalendar-all-agenda-files)
19710 (?c . org-export-icalendar-combine-agenda-files)
19711 (?F . org-publish-current-file)
19712 (?P . org-publish-current-project)
19713 (?X . org-publish)
19714 (?A . org-publish-all)))
19715 r1 r2 ass)
19716 (save-window-excursion
19717 (delete-other-windows)
19718 (with-output-to-temp-buffer "*Org Export/Publishing Help*"
19719 (princ help))
19720 (message "Select command: ")
19721 (setq r1 (read-char-exclusive)))
19722 (setq r2 (if (< r1 27) (+ r1 96) r1))
19723 (if (setq ass (assq r2 cmds))
19724 (call-interactively (cdr ass))
19725 (error "No command associated with key %c" r1))))
19727 (defconst org-html-entities
19728 '(("nbsp")
19729 ("iexcl")
19730 ("cent")
19731 ("pound")
19732 ("curren")
19733 ("yen")
19734 ("brvbar")
19735 ("vert" . "&#124;")
19736 ("sect")
19737 ("uml")
19738 ("copy")
19739 ("ordf")
19740 ("laquo")
19741 ("not")
19742 ("shy")
19743 ("reg")
19744 ("macr")
19745 ("deg")
19746 ("plusmn")
19747 ("sup2")
19748 ("sup3")
19749 ("acute")
19750 ("micro")
19751 ("para")
19752 ("middot")
19753 ("odot"."o")
19754 ("star"."*")
19755 ("cedil")
19756 ("sup1")
19757 ("ordm")
19758 ("raquo")
19759 ("frac14")
19760 ("frac12")
19761 ("frac34")
19762 ("iquest")
19763 ("Agrave")
19764 ("Aacute")
19765 ("Acirc")
19766 ("Atilde")
19767 ("Auml")
19768 ("Aring") ("AA"."&Aring;")
19769 ("AElig")
19770 ("Ccedil")
19771 ("Egrave")
19772 ("Eacute")
19773 ("Ecirc")
19774 ("Euml")
19775 ("Igrave")
19776 ("Iacute")
19777 ("Icirc")
19778 ("Iuml")
19779 ("ETH")
19780 ("Ntilde")
19781 ("Ograve")
19782 ("Oacute")
19783 ("Ocirc")
19784 ("Otilde")
19785 ("Ouml")
19786 ("times")
19787 ("Oslash")
19788 ("Ugrave")
19789 ("Uacute")
19790 ("Ucirc")
19791 ("Uuml")
19792 ("Yacute")
19793 ("THORN")
19794 ("szlig")
19795 ("agrave")
19796 ("aacute")
19797 ("acirc")
19798 ("atilde")
19799 ("auml")
19800 ("aring")
19801 ("aelig")
19802 ("ccedil")
19803 ("egrave")
19804 ("eacute")
19805 ("ecirc")
19806 ("euml")
19807 ("igrave")
19808 ("iacute")
19809 ("icirc")
19810 ("iuml")
19811 ("eth")
19812 ("ntilde")
19813 ("ograve")
19814 ("oacute")
19815 ("ocirc")
19816 ("otilde")
19817 ("ouml")
19818 ("divide")
19819 ("oslash")
19820 ("ugrave")
19821 ("uacute")
19822 ("ucirc")
19823 ("uuml")
19824 ("yacute")
19825 ("thorn")
19826 ("yuml")
19827 ("fnof")
19828 ("Alpha")
19829 ("Beta")
19830 ("Gamma")
19831 ("Delta")
19832 ("Epsilon")
19833 ("Zeta")
19834 ("Eta")
19835 ("Theta")
19836 ("Iota")
19837 ("Kappa")
19838 ("Lambda")
19839 ("Mu")
19840 ("Nu")
19841 ("Xi")
19842 ("Omicron")
19843 ("Pi")
19844 ("Rho")
19845 ("Sigma")
19846 ("Tau")
19847 ("Upsilon")
19848 ("Phi")
19849 ("Chi")
19850 ("Psi")
19851 ("Omega")
19852 ("alpha")
19853 ("beta")
19854 ("gamma")
19855 ("delta")
19856 ("epsilon")
19857 ("varepsilon"."&epsilon;")
19858 ("zeta")
19859 ("eta")
19860 ("theta")
19861 ("iota")
19862 ("kappa")
19863 ("lambda")
19864 ("mu")
19865 ("nu")
19866 ("xi")
19867 ("omicron")
19868 ("pi")
19869 ("rho")
19870 ("sigmaf") ("varsigma"."&sigmaf;")
19871 ("sigma")
19872 ("tau")
19873 ("upsilon")
19874 ("phi")
19875 ("chi")
19876 ("psi")
19877 ("omega")
19878 ("thetasym") ("vartheta"."&thetasym;")
19879 ("upsih")
19880 ("piv")
19881 ("bull") ("bullet"."&bull;")
19882 ("hellip") ("dots"."&hellip;")
19883 ("prime")
19884 ("Prime")
19885 ("oline")
19886 ("frasl")
19887 ("weierp")
19888 ("image")
19889 ("real")
19890 ("trade")
19891 ("alefsym")
19892 ("larr") ("leftarrow"."&larr;") ("gets"."&larr;")
19893 ("uarr") ("uparrow"."&uarr;")
19894 ("rarr") ("to"."&rarr;") ("rightarrow"."&rarr;")
19895 ("darr")("downarrow"."&darr;")
19896 ("harr") ("leftrightarrow"."&harr;")
19897 ("crarr") ("hookleftarrow"."&crarr;") ; has round hook, not quite CR
19898 ("lArr") ("Leftarrow"."&lArr;")
19899 ("uArr") ("Uparrow"."&uArr;")
19900 ("rArr") ("Rightarrow"."&rArr;")
19901 ("dArr") ("Downarrow"."&dArr;")
19902 ("hArr") ("Leftrightarrow"."&hArr;")
19903 ("forall")
19904 ("part") ("partial"."&part;")
19905 ("exist") ("exists"."&exist;")
19906 ("empty") ("emptyset"."&empty;")
19907 ("nabla")
19908 ("isin") ("in"."&isin;")
19909 ("notin")
19910 ("ni")
19911 ("prod")
19912 ("sum")
19913 ("minus")
19914 ("lowast") ("ast"."&lowast;")
19915 ("radic")
19916 ("prop") ("proptp"."&prop;")
19917 ("infin") ("infty"."&infin;")
19918 ("ang") ("angle"."&ang;")
19919 ("and") ("vee"."&and;")
19920 ("or") ("wedge"."&or;")
19921 ("cap")
19922 ("cup")
19923 ("int")
19924 ("there4")
19925 ("sim")
19926 ("cong") ("simeq"."&cong;")
19927 ("asymp")("approx"."&asymp;")
19928 ("ne") ("neq"."&ne;")
19929 ("equiv")
19930 ("le")
19931 ("ge")
19932 ("sub") ("subset"."&sub;")
19933 ("sup") ("supset"."&sup;")
19934 ("nsub")
19935 ("sube")
19936 ("supe")
19937 ("oplus")
19938 ("otimes")
19939 ("perp")
19940 ("sdot") ("cdot"."&sdot;")
19941 ("lceil")
19942 ("rceil")
19943 ("lfloor")
19944 ("rfloor")
19945 ("lang")
19946 ("rang")
19947 ("loz") ("Diamond"."&loz;")
19948 ("spades") ("spadesuit"."&spades;")
19949 ("clubs") ("clubsuit"."&clubs;")
19950 ("hearts") ("diamondsuit"."&hearts;")
19951 ("diams") ("diamondsuit"."&diams;")
19952 ("quot")
19953 ("amp")
19954 ("lt")
19955 ("gt")
19956 ("OElig")
19957 ("oelig")
19958 ("Scaron")
19959 ("scaron")
19960 ("Yuml")
19961 ("circ")
19962 ("tilde")
19963 ("ensp")
19964 ("emsp")
19965 ("thinsp")
19966 ("zwnj")
19967 ("zwj")
19968 ("lrm")
19969 ("rlm")
19970 ("ndash")
19971 ("mdash")
19972 ("lsquo")
19973 ("rsquo")
19974 ("sbquo")
19975 ("ldquo")
19976 ("rdquo")
19977 ("bdquo")
19978 ("dagger")
19979 ("Dagger")
19980 ("permil")
19981 ("lsaquo")
19982 ("rsaquo")
19983 ("euro")
19985 ("arccos"."arccos")
19986 ("arcsin"."arcsin")
19987 ("arctan"."arctan")
19988 ("arg"."arg")
19989 ("cos"."cos")
19990 ("cosh"."cosh")
19991 ("cot"."cot")
19992 ("coth"."coth")
19993 ("csc"."csc")
19994 ("deg"."deg")
19995 ("det"."det")
19996 ("dim"."dim")
19997 ("exp"."exp")
19998 ("gcd"."gcd")
19999 ("hom"."hom")
20000 ("inf"."inf")
20001 ("ker"."ker")
20002 ("lg"."lg")
20003 ("lim"."lim")
20004 ("liminf"."liminf")
20005 ("limsup"."limsup")
20006 ("ln"."ln")
20007 ("log"."log")
20008 ("max"."max")
20009 ("min"."min")
20010 ("Pr"."Pr")
20011 ("sec"."sec")
20012 ("sin"."sin")
20013 ("sinh"."sinh")
20014 ("sup"."sup")
20015 ("tan"."tan")
20016 ("tanh"."tanh")
20018 "Entities for TeX->HTML translation.
20019 Entries can be like (\"ent\"), in which case \"\\ent\" will be translated to
20020 \"&ent;\". An entry can also be a dotted pair like (\"ent\".\"&other;\").
20021 In that case, \"\\ent\" will be translated to \"&other;\".
20022 The list contains HTML entities for Latin-1, Greek and other symbols.
20023 It is supplemented by a number of commonly used TeX macros with appropriate
20024 translations. There is currently no way for users to extend this.")
20026 ;;; General functions for all backends
20028 (defun org-cleaned-string-for-export (string &rest parameters)
20029 "Cleanup a buffer substring so that links can be created safely."
20030 (interactive)
20031 (let* ((re-radio (and org-target-link-regexp
20032 (concat "\\([^<]\\)\\(" org-target-link-regexp "\\)")))
20033 (re-plain-link (concat "\\([^[<]\\)" org-plain-link-re))
20034 (re-angle-link (concat "\\([^[]\\)" org-angle-link-re))
20035 (re-archive (concat ":" org-archive-tag ":"))
20036 (re-quote (concat "^\\*+[ \t]+" org-quote-string "\\>"))
20037 (htmlp (plist-get parameters :for-html))
20038 (inhibit-read-only t)
20039 (outline-regexp "\\*+ ")
20041 rtn p)
20042 (save-excursion
20043 (set-buffer (get-buffer-create " org-mode-tmp"))
20044 (erase-buffer)
20045 (insert string)
20046 ;; Remove license-to-kill stuff
20047 (while (setq p (text-property-any (point-min) (point-max)
20048 :org-license-to-kill t))
20049 (delete-region p (next-single-property-change p :org-license-to-kill)))
20051 (let ((org-inhibit-startup t)) (org-mode))
20052 (untabify (point-min) (point-max))
20054 ;; Get the correct stuff before the first headline
20055 (when (plist-get parameters :skip-before-1st-heading)
20056 (goto-char (point-min))
20057 (when (re-search-forward "^\\*+[ \t]" nil t)
20058 (delete-region (point-min) (match-beginning 0))
20059 (goto-char (point-min))
20060 (insert "\n")))
20061 (when (plist-get parameters :add-text)
20062 (goto-char (point-min))
20063 (insert (plist-get parameters :add-text) "\n"))
20065 ;; Get rid of archived trees
20066 (when (not (eq org-export-with-archived-trees t))
20067 (goto-char (point-min))
20068 (while (re-search-forward re-archive nil t)
20069 (if (not (org-on-heading-p t))
20070 (org-end-of-subtree t)
20071 (beginning-of-line 1)
20072 (setq a (if org-export-with-archived-trees
20073 (1+ (point-at-eol)) (point))
20074 b (org-end-of-subtree t))
20075 (if (> b a) (delete-region a b)))))
20077 ;; Get rid of property drawers
20078 (unless org-export-with-property-drawer
20079 (goto-char (point-min))
20080 (while (re-search-forward "^[ \t]*:PROPERTIES:[ \t]*\n\\([^@]*?\n\\)?[ \t]*:END:[ \t]*\n" nil t)
20081 (replace-match "")))
20083 ;; Protect stuff from HTML processing
20084 (goto-char (point-min))
20085 (while (re-search-forward "^[ \t]*:.*\\(\n[ \t]*:.*\\)*" nil t)
20086 (add-text-properties (match-beginning 0) (match-end 0)
20087 '(org-protected t)))
20088 (when htmlp
20089 (goto-char (point-min))
20090 (while (re-search-forward "^#\\+HTML:[ \t]*\\(.*\\)" nil t)
20091 (replace-match "\\1" t)
20092 (add-text-properties
20093 (point-at-bol) (min (1+ (point-at-eol)) (point-max))
20094 '(org-protected t))))
20095 (goto-char (point-min))
20096 (while (re-search-forward
20097 "^#\\+BEGIN_HTML\\>.*\\(\\(\n.*\\)*?\n\\)#\\+END_HTML\\>.*\n?" nil t)
20098 (if htmlp
20099 (add-text-properties (match-beginning 1) (1+ (match-end 1))
20100 '(org-protected t))
20101 (delete-region (match-beginning 0) (match-end 0))))
20102 (goto-char (point-min))
20103 (while (re-search-forward re-quote nil t)
20104 (goto-char (match-beginning 0))
20105 (end-of-line 1)
20106 (add-text-properties (point) (org-end-of-subtree t)
20107 '(org-protected t)))
20109 ;; Find targets in comments and move them out of comments,
20110 ;; but mark them as targets that should be invisible
20111 (goto-char (point-min))
20112 (while (re-search-forward "^#.*?\\(<<<?[^>\r\n]+>>>?\\).*" nil t)
20113 (replace-match "\\1(INVISIBLE)"))
20115 ;; Remove comments
20116 (goto-char (point-min))
20117 (while (re-search-forward "^#.*\n?" nil t)
20118 (replace-match ""))
20120 ;; Find matches for radio targets and turn them into internal links
20121 (goto-char (point-min))
20122 (when re-radio
20123 (while (re-search-forward re-radio nil t)
20124 (org-if-unprotected
20125 (replace-match "\\1[[\\2]]"))))
20127 ;; Find all links that contain a newline and put them into a single line
20128 (goto-char (point-min))
20129 (while (re-search-forward "\\(\\(\\[\\|\\]\\)\\[[^]]*?\\)[ \t]*\n[ \t]*\\([^]]*\\]\\(\\[\\|\\]\\)\\)" nil t)
20130 (org-if-unprotected
20131 (replace-match "\\1 \\3")
20132 (goto-char (match-beginning 0))))
20134 ;; Convert LaTeX fragments to images
20135 (when (plist-get parameters :LaTeX-fragments)
20136 (org-format-latex
20137 (concat "ltxpng/" (file-name-sans-extension
20138 (file-name-nondirectory
20139 org-current-export-file)))
20140 org-current-export-dir nil "Creating LaTeX image %s"))
20141 (message "Exporting...")
20143 ;; Normalize links: Convert angle and plain links into bracket links
20144 ;; Expand link abbreviations
20145 (goto-char (point-min))
20146 (while (re-search-forward re-plain-link nil t)
20147 (goto-char (1- (match-end 0)))
20148 (org-if-unprotected
20149 (replace-match
20150 (concat
20151 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
20152 t t)))
20153 (goto-char (point-min))
20154 (while (re-search-forward re-angle-link nil t)
20155 (goto-char (1- (match-end 0)))
20156 (org-if-unprotected
20157 (replace-match
20158 (concat
20159 (match-string 1) "[[" (match-string 2) ":" (match-string 3) "]]")
20160 t t)))
20161 (goto-char (point-min))
20162 (while (re-search-forward org-bracket-link-regexp nil t)
20163 (org-if-unprotected
20164 (replace-match
20165 (concat "[[" (save-match-data
20166 (org-link-expand-abbrev (match-string 1)))
20168 (if (match-end 3)
20169 (match-string 2)
20170 (concat "[" (match-string 1) "]"))
20171 "]")
20172 t t)))
20174 ;; Find multiline emphasis and put them into single line
20175 (when (plist-get parameters :emph-multiline)
20176 (goto-char (point-min))
20177 (while (re-search-forward org-emph-re nil t)
20178 (if (not (= (char-after (match-beginning 3))
20179 (char-after (match-beginning 4))))
20180 (org-if-unprotected
20181 (subst-char-in-region (match-beginning 0) (match-end 0)
20182 ?\n ?\ t)
20183 (goto-char (1- (match-end 0))))
20184 (goto-char (1+ (match-beginning 0))))))
20186 (setq rtn (buffer-string)))
20187 (kill-buffer " org-mode-tmp")
20188 rtn))
20190 (defun org-export-grab-title-from-buffer ()
20191 "Get a title for the current document, from looking at the buffer."
20192 (let (buffer-read-only)
20193 (save-excursion
20194 (goto-char (point-min))
20195 (let ((end (save-excursion (outline-next-heading) (point))))
20196 (when (re-search-forward "^[ \t]*[^|# \t\r\n].*\n" end t)
20197 ;; Mark the line so that it will not be exported as normal text.
20198 (org-unmodified
20199 (add-text-properties (match-beginning 0) (match-end 0)
20200 (list :org-license-to-kill t)))
20201 ;; Return the title string
20202 (org-trim (match-string 0)))))))
20204 (defun org-solidify-link-text (s &optional alist)
20205 "Take link text and make a safe target out of it."
20206 (save-match-data
20207 (let* ((rtn
20208 (mapconcat
20209 'identity
20210 (org-split-string s "[ \t\r\n]+") "--"))
20211 (a (assoc rtn alist)))
20212 (or (cdr a) rtn))))
20214 ;; Variable holding the vector with section numbers
20215 (defvar org-section-numbers (make-vector org-level-max 0))
20217 (defun org-init-section-numbers ()
20218 "Initialize the vector for the section numbers."
20219 (let* ((level -1)
20220 (numbers (nreverse (org-split-string "" "\\.")))
20221 (depth (1- (length org-section-numbers)))
20222 (i depth) number-string)
20223 (while (>= i 0)
20224 (if (> i level)
20225 (aset org-section-numbers i 0)
20226 (setq number-string (or (car numbers) "0"))
20227 (if (string-match "\\`[A-Z]\\'" number-string)
20228 (aset org-section-numbers i
20229 (- (string-to-char number-string) ?A -1))
20230 (aset org-section-numbers i (string-to-number number-string)))
20231 (pop numbers))
20232 (setq i (1- i)))))
20234 (defun org-section-number (&optional level)
20235 "Return a string with the current section number.
20236 When LEVEL is non-nil, increase section numbers on that level."
20237 (let* ((depth (1- (length org-section-numbers))) idx n (string ""))
20238 (when level
20239 (when (> level -1)
20240 (aset org-section-numbers
20241 level (1+ (aref org-section-numbers level))))
20242 (setq idx (1+ level))
20243 (while (<= idx depth)
20244 (if (not (= idx 1))
20245 (aset org-section-numbers idx 0))
20246 (setq idx (1+ idx))))
20247 (setq idx 0)
20248 (while (<= idx depth)
20249 (setq n (aref org-section-numbers idx))
20250 (setq string (concat string (if (not (string= string "")) "." "")
20251 (int-to-string n)))
20252 (setq idx (1+ idx)))
20253 (save-match-data
20254 (if (string-match "\\`\\([@0]\\.\\)+" string)
20255 (setq string (replace-match "" t nil string)))
20256 (if (string-match "\\(\\.0\\)+\\'" string)
20257 (setq string (replace-match "" t nil string))))
20258 string))
20260 ;;; ASCII export
20262 (defvar org-last-level nil) ; dynamically scoped variable
20263 (defvar org-levels-open nil) ; dynamically scoped parameter
20264 (defvar org-ascii-current-indentation nil) ; For communication
20266 (defun org-export-as-ascii (arg)
20267 "Export the outline as a pretty ASCII file.
20268 If there is an active region, export only the region.
20269 The prefix ARG specifies how many levels of the outline should become
20270 underlined headlines. The default is 3."
20271 (interactive "P")
20272 (setq-default org-todo-line-regexp org-todo-line-regexp)
20273 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
20274 (org-infile-export-plist)))
20275 (custom-times org-display-custom-times)
20276 (org-ascii-current-indentation '(0 . 0))
20277 (level 0) line txt
20278 (umax nil)
20279 (umax-toc nil)
20280 (case-fold-search nil)
20281 (filename (concat (file-name-as-directory
20282 (org-export-directory :ascii opt-plist))
20283 (file-name-sans-extension
20284 (file-name-nondirectory buffer-file-name))
20285 ".txt"))
20286 (buffer (find-file-noselect filename))
20287 (org-levels-open (make-vector org-level-max nil))
20288 (odd org-odd-levels-only)
20289 (date (format-time-string "%Y/%m/%d" (current-time)))
20290 (time (format-time-string "%X" (org-current-time)))
20291 (author (plist-get opt-plist :author))
20292 (title (or (plist-get opt-plist :title)
20293 (and (not
20294 (plist-get opt-plist :skip-before-1st-heading))
20295 (org-export-grab-title-from-buffer))
20296 (file-name-sans-extension
20297 (file-name-nondirectory buffer-file-name))))
20298 (email (plist-get opt-plist :email))
20299 (language (plist-get opt-plist :language))
20300 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
20301 ; (quote-re (concat "^\\(\\*+\\)\\([ \t]*" org-quote-string "\\>\\)"))
20302 (todo nil)
20303 (lang-words nil)
20304 (region
20305 (buffer-substring
20306 (if (org-region-active-p) (region-beginning) (point-min))
20307 (if (org-region-active-p) (region-end) (point-max))))
20308 (lines (org-skip-comments
20309 (org-split-string
20310 (org-cleaned-string-for-export
20311 region
20312 :skip-before-1st-heading
20313 (plist-get opt-plist :skip-before-1st-heading)
20314 :add-text (plist-get opt-plist :text))
20315 "[\r\n]"))) ;; FIXME: why \r here???/
20316 thetoc have-headings first-heading-pos
20317 table-open table-buffer)
20319 (let (buffer-read-only)
20320 (org-unmodified
20321 (remove-text-properties (point-min) (point-max)
20322 '(:org-license-to-kill t))))
20324 (setq org-last-level 1)
20325 (org-init-section-numbers)
20327 (find-file-noselect filename)
20329 (setq lang-words (or (assoc language org-export-language-setup)
20330 (assoc "en" org-export-language-setup)))
20331 (switch-to-buffer-other-window buffer)
20332 (erase-buffer)
20333 (fundamental-mode)
20334 ;; create local variables for all options, to make sure all called
20335 ;; functions get the correct information
20336 (mapcar (lambda (x)
20337 (set (make-local-variable (cdr x))
20338 (plist-get opt-plist (car x))))
20339 org-export-plist-vars)
20340 (org-set-local 'org-odd-levels-only odd)
20341 (setq umax (if arg (prefix-numeric-value arg)
20342 org-export-headline-levels))
20343 (setq umax-toc (if (integerp org-export-with-toc)
20344 (min org-export-with-toc umax)
20345 umax))
20347 ;; File header
20348 (if title (org-insert-centered title ?=))
20349 (insert "\n")
20350 (if (or author email)
20351 (insert (concat (nth 1 lang-words) ": " (or author "")
20352 (if email (concat " <" email ">") "")
20353 "\n")))
20354 (if (and date time)
20355 (insert (concat (nth 2 lang-words) ": " date " " time "\n")))
20357 (insert "\n\n")
20359 (if org-export-with-toc
20360 (progn
20361 (push (concat (nth 3 lang-words) "\n") thetoc)
20362 (push (concat (make-string (length (nth 3 lang-words)) ?=) "\n") thetoc)
20363 (mapcar '(lambda (line)
20364 (if (string-match org-todo-line-regexp
20365 line)
20366 ;; This is a headline
20367 (progn
20368 (setq have-headings t)
20369 (setq level (- (match-end 1) (match-beginning 1))
20370 level (org-tr-level level)
20371 txt (match-string 3 line)
20372 todo
20373 (or (and org-export-mark-todo-in-toc
20374 (match-beginning 2)
20375 (not (member (match-string 2 line)
20376 org-done-keywords)))
20377 ; TODO, not DONE
20378 (and org-export-mark-todo-in-toc
20379 (= level umax-toc)
20380 (org-search-todo-below
20381 line lines level))))
20382 (setq txt (org-html-expand-for-ascii txt))
20384 (if (and (memq org-export-with-tags '(not-in-toc nil))
20385 (string-match
20386 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
20387 txt))
20388 (setq txt (replace-match "" t t txt)))
20389 (if (string-match quote-re0 txt)
20390 (setq txt (replace-match "" t t txt)))
20392 (if org-export-with-section-numbers
20393 (setq txt (concat (org-section-number level)
20394 " " txt)))
20395 (if (<= level umax-toc)
20396 (progn
20397 (push
20398 (concat
20399 (make-string (* (1- level) 4) ?\ )
20400 (format (if todo "%s (*)\n" "%s\n") txt))
20401 thetoc)
20402 (setq org-last-level level))
20403 ))))
20404 lines)
20405 (setq thetoc (if have-headings (nreverse thetoc) nil))))
20407 (org-init-section-numbers)
20408 (while (setq line (pop lines))
20409 ;; Remove the quoted HTML tags.
20410 (setq line (org-html-expand-for-ascii line))
20411 ;; Remove targets
20412 (while (string-match "<<<?[^<>]*>>>?[ \t]*\n?" line)
20413 (setq line (replace-match "" t t line)))
20414 ;; Replace internal links
20415 (while (string-match org-bracket-link-regexp line)
20416 (setq line (replace-match
20417 (if (match-end 3) "[\\3]" "[\\1]")
20418 t nil line)))
20419 (when custom-times
20420 (setq line (org-translate-time line)))
20421 (cond
20422 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
20423 ;; a Headline
20424 (setq first-heading-pos (or first-heading-pos (point)))
20425 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
20426 txt (match-string 2 line))
20427 (org-ascii-level-start level txt umax lines))
20429 ((and org-export-with-tables
20430 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
20431 (if (not table-open)
20432 ;; New table starts
20433 (setq table-open t table-buffer nil))
20434 ;; Accumulate lines
20435 (setq table-buffer (cons line table-buffer))
20436 (when (or (not lines)
20437 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
20438 (car lines))))
20439 (setq table-open nil
20440 table-buffer (nreverse table-buffer))
20441 (insert (mapconcat
20442 (lambda (x)
20443 (org-fix-indentation x org-ascii-current-indentation))
20444 (org-format-table-ascii table-buffer)
20445 "\n") "\n")))
20447 (setq line (org-fix-indentation line org-ascii-current-indentation))
20448 (if (and org-export-with-fixed-width
20449 (string-match "^\\([ \t]*\\)\\(:\\)" line))
20450 (setq line (replace-match "\\1" nil nil line)))
20451 (insert line "\n"))))
20453 (normal-mode)
20455 ;; insert the table of contents
20456 (when thetoc
20457 (goto-char (point-min))
20458 (if (re-search-forward "^[ \t]*\\[TABLE-OF-CONTENTS\\][ \t]*$" nil t)
20459 (progn
20460 (goto-char (match-beginning 0))
20461 (replace-match ""))
20462 (goto-char first-heading-pos))
20463 (mapc 'insert thetoc)
20464 (or (looking-at "[ \t]*\n[ \t]*\n")
20465 (insert "\n\n")))
20467 (save-buffer)
20468 ;; remove display and invisible chars
20469 (let (beg end)
20470 (goto-char (point-min))
20471 (while (setq beg (next-single-property-change (point) 'display))
20472 (setq end (next-single-property-change beg 'display))
20473 (delete-region beg end)
20474 (goto-char beg)
20475 (insert "=>"))
20476 (goto-char (point-min))
20477 (while (setq beg (next-single-property-change (point) 'org-cwidth))
20478 (setq end (next-single-property-change beg 'org-cwidth))
20479 (delete-region beg end)
20480 (goto-char beg)))
20481 (goto-char (point-min))))
20483 (defun org-search-todo-below (line lines level)
20484 "Search the subtree below LINE for any TODO entries."
20485 (let ((rest (cdr (memq line lines)))
20486 (re org-todo-line-regexp)
20487 line lv todo)
20488 (catch 'exit
20489 (while (setq line (pop rest))
20490 (if (string-match re line)
20491 (progn
20492 (setq lv (- (match-end 1) (match-beginning 1))
20493 todo (and (match-beginning 2)
20494 (not (member (match-string 2 line)
20495 org-done-keywords))))
20496 ; TODO, not DONE
20497 (if (<= lv level) (throw 'exit nil))
20498 (if todo (throw 'exit t))))))))
20500 (defun org-html-expand-for-ascii (line)
20501 "Handle quoted HTML for ASCII export."
20502 (if org-export-html-expand
20503 (while (string-match "@<[^<>\n]*>" line)
20504 ;; We just remove the tags for now.
20505 (setq line (replace-match "" nil nil line))))
20506 line)
20508 (defun org-insert-centered (s &optional underline)
20509 "Insert the string S centered and underline it with character UNDERLINE."
20510 (let ((ind (max (/ (- 80 (string-width s)) 2) 0)))
20511 (insert (make-string ind ?\ ) s "\n")
20512 (if underline
20513 (insert (make-string ind ?\ )
20514 (make-string (string-width s) underline)
20515 "\n"))))
20517 (defun org-ascii-level-start (level title umax &optional lines)
20518 "Insert a new level in ASCII export."
20519 (let (char (n (- level umax 1)) (ind 0))
20520 (if (> level umax)
20521 (progn
20522 (insert (make-string (* 2 n) ?\ )
20523 (char-to-string (nth (% n (length org-export-ascii-bullets))
20524 org-export-ascii-bullets))
20525 " " title "\n")
20526 ;; find the indentation of the next non-empty line
20527 (catch 'stop
20528 (while lines
20529 (if (string-match "^\\* " (car lines)) (throw 'stop nil))
20530 (if (string-match "^\\([ \t]*\\)\\S-" (car lines))
20531 (throw 'stop (setq ind (org-get-indentation (car lines)))))
20532 (pop lines)))
20533 (setq org-ascii-current-indentation (cons (* 2 (1+ n)) ind)))
20534 (if (or (not (equal (char-before) ?\n))
20535 (not (equal (char-before (1- (point))) ?\n)))
20536 (insert "\n"))
20537 (setq char (nth (- umax level) (reverse org-export-ascii-underline)))
20538 (unless org-export-with-tags
20539 (if (string-match (org-re "[ \t]+\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
20540 (setq title (replace-match "" t t title))))
20541 (if org-export-with-section-numbers
20542 (setq title (concat (org-section-number level) " " title)))
20543 (insert title "\n" (make-string (string-width title) char) "\n")
20544 (setq org-ascii-current-indentation '(0 . 0)))))
20546 (defun org-export-visible (type arg)
20547 "Create a copy of the visible part of the current buffer, and export it.
20548 The copy is created in a temporary buffer and removed after use.
20549 TYPE is the final key (as a string) that also select the export command in
20550 the `C-c C-e' export dispatcher.
20551 As a special case, if the you type SPC at the prompt, the temporary
20552 org-mode file will not be removed but presented to you so that you can
20553 continue to use it. The prefix arg ARG is passed through to the exporting
20554 command."
20555 (interactive
20556 (list (progn
20557 (message "Export visible: [a]SCII [h]tml [b]rowse HTML [H/R]uffer with HTML [x]OXO [ ]keep buffer")
20558 (read-char-exclusive))
20559 current-prefix-arg))
20560 (if (not (member type '(?a ?\C-a ?b ?\C-b ?h ?x ?\ )))
20561 (error "Invalid export key"))
20562 (let* ((binding (cdr (assoc type
20563 '((?a . org-export-as-ascii)
20564 (?\C-a . org-export-as-ascii)
20565 (?b . org-export-as-html-and-open)
20566 (?\C-b . org-export-as-html-and-open)
20567 (?h . org-export-as-html)
20568 (?H . org-export-as-html-to-buffer)
20569 (?R . org-export-region-as-html)
20570 (?x . org-export-as-xoxo)))))
20571 (keepp (equal type ?\ ))
20572 (file buffer-file-name)
20573 (buffer (get-buffer-create "*Org Export Visible*"))
20574 s e)
20575 (with-current-buffer buffer (erase-buffer))
20576 (save-excursion
20577 (setq s (goto-char (point-min)))
20578 (while (not (= (point) (point-max)))
20579 (goto-char (org-find-invisible))
20580 (append-to-buffer buffer s (point))
20581 (setq s (goto-char (org-find-visible))))
20582 (goto-char (point-min))
20583 (unless keepp
20584 ;; Copy all comment lines to the end, to make sure #+ settings are
20585 ;; still available for the second export step. Kind of a hack, but
20586 ;; does do the trick.
20587 (if (looking-at "#[^\r\n]*")
20588 (append-to-buffer buffer (match-beginning 0) (1+ (match-end 0))))
20589 (while (re-search-forward "[\n\r]#[^\n\r]*" nil t)
20590 (append-to-buffer buffer (1+ (match-beginning 0))
20591 (min (point-max) (1+ (match-end 0))))))
20592 (set-buffer buffer)
20593 (let ((buffer-file-name file)
20594 (org-inhibit-startup t))
20595 (org-mode)
20596 (show-all)
20597 (unless keepp (funcall binding arg))))
20598 (if (not keepp)
20599 (kill-buffer buffer)
20600 (switch-to-buffer-other-window buffer)
20601 (goto-char (point-min)))))
20603 (defun org-find-visible ()
20604 (let ((s (point)))
20605 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
20606 (get-char-property s 'invisible)))
20608 (defun org-find-invisible ()
20609 (let ((s (point)))
20610 (while (and (not (= (point-max) (setq s (next-overlay-change s))))
20611 (not (get-char-property s 'invisible))))
20614 ;;; HTML export
20616 (defun org-get-current-options ()
20617 "Return a string with current options as keyword options.
20618 Does include HTML export options as well as TODO and CATEGORY stuff."
20619 (format
20620 "#+TITLE: %s
20621 #+AUTHOR: %s
20622 #+EMAIL: %s
20623 #+LANGUAGE: %s
20624 #+TEXT: Some descriptive text to be emitted. Several lines OK.
20625 #+OPTIONS: H:%d num:%s toc:%s \\n:%s @:%s ::%s |:%s ^:%s f:%s *:%s TeX:%s LaTeX:%s skip:%s p:%s
20626 #+CATEGORY: %s
20627 #+SEQ_TODO: %s
20628 #+TYP_TODO: %s
20629 #+PRIORITIES: %c %c %c
20630 #+STARTUP: %s %s %s %s %s
20631 #+TAGS: %s
20632 #+ARCHIVE: %s
20633 #+LINK: %s
20635 (buffer-name) (user-full-name) user-mail-address org-export-default-language
20636 org-export-headline-levels
20637 org-export-with-section-numbers
20638 org-export-with-toc
20639 org-export-preserve-breaks
20640 org-export-html-expand
20641 org-export-with-fixed-width
20642 org-export-with-tables
20643 org-export-with-sub-superscripts
20644 org-export-with-footnotes
20645 org-export-with-emphasize
20646 org-export-with-TeX-macros
20647 org-export-with-LaTeX-fragments
20648 org-export-skip-text-before-1st-heading
20649 org-export-with-property-drawer
20650 (file-name-nondirectory buffer-file-name)
20651 "TODO FEEDBACK VERIFY DONE"
20652 "Me Jason Marie DONE"
20653 org-highest-priority org-lowest-priority org-default-priority
20654 (cdr (assoc org-startup-folded
20655 '((nil . "showall") (t . "overview") (content . "content"))))
20656 (if org-odd-levels-only "odd" "oddeven")
20657 (if org-hide-leading-stars "hidestars" "showstars")
20658 (if org-startup-align-all-tables "align" "noalign")
20659 (cond ((eq t org-log-done) "logdone")
20660 ((not org-log-done) "nologging")
20661 ((listp org-log-done)
20662 (mapconcat (lambda (x) (concat "lognote" (symbol-name x)))
20663 org-log-done " ")))
20664 (or (mapconcat (lambda (x)
20665 (cond
20666 ((equal '(:startgroup) x) "{")
20667 ((equal '(:endgroup) x) "}")
20668 ((cdr x) (format "%s(%c)" (car x) (cdr x)))
20669 (t (car x))))
20670 (or org-tag-alist (org-get-buffer-tags)) " ") "")
20671 org-archive-location
20672 "org file:~/org/%s.org"
20675 (defun org-insert-export-options-template ()
20676 "Insert into the buffer a template with information for exporting."
20677 (interactive)
20678 (if (not (bolp)) (newline))
20679 (let ((s (org-get-current-options)))
20680 (and (string-match "#\\+CATEGORY" s)
20681 (setq s (substring s 0 (match-beginning 0))))
20682 (insert s)))
20684 (defun org-toggle-fixed-width-section (arg)
20685 "Toggle the fixed-width export.
20686 If there is no active region, the QUOTE keyword at the current headline is
20687 inserted or removed. When present, it causes the text between this headline
20688 and the next to be exported as fixed-width text, and unmodified.
20689 If there is an active region, this command adds or removes a colon as the
20690 first character of this line. If the first character of a line is a colon,
20691 this line is also exported in fixed-width font."
20692 (interactive "P")
20693 (let* ((cc 0)
20694 (regionp (org-region-active-p))
20695 (beg (if regionp (region-beginning) (point)))
20696 (end (if regionp (region-end)))
20697 (nlines (or arg (if (and beg end) (count-lines beg end) 1)))
20698 (re "[ \t]*\\(:\\)")
20699 off)
20700 (if regionp
20701 (save-excursion
20702 (goto-char beg)
20703 (setq cc (current-column))
20704 (beginning-of-line 1)
20705 (setq off (looking-at re))
20706 (while (> nlines 0)
20707 (setq nlines (1- nlines))
20708 (beginning-of-line 1)
20709 (cond
20710 (arg
20711 (move-to-column cc t)
20712 (insert ":\n")
20713 (forward-line -1))
20714 ((and off (looking-at re))
20715 (replace-match "" t t nil 1))
20716 ((not off) (move-to-column cc t) (insert ":")))
20717 (forward-line 1)))
20718 (save-excursion
20719 (org-back-to-heading)
20720 (if (looking-at (concat outline-regexp
20721 "\\( *\\<" org-quote-string "\\>\\)"))
20722 (replace-match "" t t nil 1)
20723 (if (looking-at outline-regexp)
20724 (progn
20725 (goto-char (match-end 0))
20726 (insert org-quote-string " "))))))))
20728 (defun org-export-as-html-and-open (arg)
20729 "Export the outline as HTML and immediately open it with a browser.
20730 If there is an active region, export only the region.
20731 The prefix ARG specifies how many levels of the outline should become
20732 headlines. The default is 3. Lower levels will become bulleted lists."
20733 (interactive "P")
20734 (org-export-as-html arg 'hidden)
20735 (org-open-file buffer-file-name))
20737 (defun org-export-as-html-batch ()
20738 "Call `org-export-as-html', may be used in batch processing as
20739 emacs --batch
20740 --load=$HOME/lib/emacs/org.el
20741 --eval \"(setq org-export-headline-levels 2)\"
20742 --visit=MyFile --funcall org-export-as-html-batch"
20743 (org-export-as-html org-export-headline-levels 'hidden))
20745 (defun org-export-as-html-to-buffer (arg)
20746 "Call `org-exort-as-html` with output to a temporary buffer.
20747 No file is created. The prefix ARG is passed through to `org-export-as-html'."
20748 (interactive "P")
20749 (org-export-as-html arg nil nil "*Org HTML Export*")
20750 (switch-to-buffer-other-window "*Org HTML Export*"))
20752 (defun org-replace-region-by-html (beg end)
20753 "Assume the current region has org-mode syntax, and convert it to HTML.
20754 This can be used in any buffer. For example, you could write an
20755 itemized list in org-mode syntax in an HTML buffer and then use this
20756 command to convert it."
20757 (interactive "r")
20758 (let (reg html buf)
20759 (if (org-mode-p)
20760 (setq html (org-export-region-as-html
20761 beg end t 'string))
20762 (setq reg (buffer-substring beg end)
20763 buf (get-buffer-create "*Org tmp*"))
20764 (save-excursion
20765 (set-buffer buf)
20766 (erase-buffer)
20767 (insert reg)
20768 (org-mode)
20769 (setq html (org-export-region-as-html
20770 (point-min) (point-max) t 'string)))
20771 (kill-buffer buf))
20772 (delete-region beg end)
20773 (insert html)))
20775 (defun org-export-region-as-html (beg end &optional body-only buffer)
20776 "Convert region from BEG to END in org-mode buffer to HTML.
20777 If prefix arg BODY-ONLY is set, omit file header, footer, and table of
20778 contents, and only produce the region of converted text, useful for
20779 cut-and-paste operations.
20780 If BUFFER is a buffer or a string, use/create that buffer as a target
20781 of the converted HTML. If BUFFER is the symbol `string', return the
20782 produced HTML as a string and leave not buffer behind. For example,
20783 a Lisp program could call this function in the following way:
20785 (setq html (org-export-region-as-html beg end t 'string))
20787 When called interactively, the output buffer is selected, and shown
20788 in a window. A non-interactive call will only retunr the buffer."
20789 (interactive "r\nP")
20790 (when (interactive-p)
20791 (setq buffer "*Org HTML EXPORT*"))
20792 (let ((transient-mark-mode t) (zmacs-regions t)
20793 rtn)
20794 (goto-char end)
20795 (set-mark (point)) ;; to activate the region
20796 (goto-char beg)
20797 (setq rtn (org-export-as-html
20798 nil nil nil
20799 buffer body-only))
20800 (if (fboundp 'deactivate-mark) (deactivate-mark))
20801 (if (and (interactive-p) (bufferp rtn))
20802 (switch-to-buffer-other-window rtn)
20803 rtn)))
20805 (defun org-export-as-html (arg &optional hidden ext-plist
20806 to-buffer body-only)
20807 "Export the outline as a pretty HTML file.
20808 If there is an active region, export only the region. The prefix
20809 ARG specifies how many levels of the outline should become
20810 headlines. The default is 3. Lower levels will become bulleted
20811 lists. When HIDDEN is non-nil, don't display the HTML buffer.
20812 EXT-PLIST is a property list with external parameters overriding
20813 org-mode's default settings, but still inferior to file-local
20814 settings. When TO-BUFFER is non-nil, create a buffer with that
20815 name and export to that buffer. If TO-BUFFER is the symbol `string',
20816 don't leave any buffer behind but just return the resulting HTML as
20817 a string. When BODY-ONLY is set, don't produce the file header and footer,
20818 simply return the content of <body>...</body>, without even
20819 the body tags themselves."
20820 (interactive "P")
20822 ;; Make sure we have a file name when we need it.
20823 (when (and (not (or to-buffer body-only))
20824 (not buffer-file-name))
20825 (if (buffer-base-buffer)
20826 (org-set-local 'buffer-file-name
20827 (with-current-buffer (buffer-base-buffer)
20828 buffer-file-name))
20829 (error "Need a file name to be able to export.")))
20831 (message "Exporting...")
20832 (setq-default org-todo-line-regexp org-todo-line-regexp)
20833 (setq-default org-deadline-line-regexp org-deadline-line-regexp)
20834 (setq-default org-done-keywords org-done-keywords)
20835 (setq-default org-maybe-keyword-time-regexp org-maybe-keyword-time-regexp)
20836 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
20837 ext-plist
20838 (org-infile-export-plist)))
20840 (style (plist-get opt-plist :style))
20841 (link-validate (plist-get opt-plist :link-validation-function))
20842 valid thetoc have-headings first-heading-pos
20843 (odd org-odd-levels-only)
20844 (region-p (org-region-active-p))
20845 ;; The following two are dynamically scoped into other
20846 ;; routines below.
20847 (org-current-export-dir (org-export-directory :html opt-plist))
20848 (org-current-export-file buffer-file-name)
20849 (level 0) (line "") (origline "") txt todo
20850 (umax nil)
20851 (umax-toc nil)
20852 (filename (if to-buffer nil
20853 (concat (file-name-as-directory
20854 (org-export-directory :html opt-plist))
20855 (file-name-sans-extension
20856 (file-name-nondirectory buffer-file-name))
20857 ".html")))
20858 (current-dir (if buffer-file-name
20859 (file-name-directory buffer-file-name)
20860 default-directory))
20861 (buffer (if to-buffer
20862 (cond
20863 ((eq to-buffer 'string) (get-buffer-create "*Org HTML Export*"))
20864 (t (get-buffer-create to-buffer)))
20865 (find-file-noselect filename)))
20866 (org-levels-open (make-vector org-level-max nil))
20867 (date (format-time-string "%Y/%m/%d" (current-time)))
20868 (time (format-time-string "%X" (org-current-time)))
20869 (author (plist-get opt-plist :author))
20870 (title (or (plist-get opt-plist :title)
20871 (and (not
20872 (plist-get opt-plist :skip-before-1st-heading))
20873 (org-export-grab-title-from-buffer))
20874 (and buffer-file-name
20875 (file-name-sans-extension
20876 (file-name-nondirectory buffer-file-name)))
20877 "UNTITLED"))
20878 (quote-re0 (concat "^[ \t]*" org-quote-string "\\>"))
20879 (quote-re (concat "^\\(\\*+\\)\\([ \t]+" org-quote-string "\\>\\)"))
20880 (inquote nil)
20881 (infixed nil)
20882 (in-local-list nil)
20883 (local-list-num nil)
20884 (local-list-indent nil)
20885 (llt org-plain-list-ordered-item-terminator)
20886 (email (plist-get opt-plist :email))
20887 (language (plist-get opt-plist :language))
20888 (lang-words nil)
20889 (target-alist nil) tg
20890 (head-count 0) cnt
20891 (start 0)
20892 (coding-system (and (boundp 'buffer-file-coding-system)
20893 buffer-file-coding-system))
20894 (coding-system-for-write (or org-export-html-coding-system
20895 coding-system))
20896 (save-buffer-coding-system (or org-export-html-coding-system
20897 coding-system))
20898 (charset (and coding-system-for-write
20899 (fboundp 'coding-system-get)
20900 (coding-system-get coding-system-for-write
20901 'mime-charset)))
20902 (region
20903 (buffer-substring
20904 (if region-p (region-beginning) (point-min))
20905 (if region-p (region-end) (point-max))))
20906 (lines
20907 (org-skip-comments (org-split-string
20908 (org-cleaned-string-for-export
20909 region
20910 :emph-multiline t
20911 :for-html t
20912 :skip-before-1st-heading
20913 (plist-get opt-plist :skip-before-1st-heading)
20914 :add-text
20915 (plist-get opt-plist :text)
20916 :LaTeX-fragments
20917 (plist-get opt-plist :LaTeX-fragments))
20918 "[\r\n]")))
20919 table-open type
20920 table-buffer table-orig-buffer
20921 ind start-is-num starter didclose
20922 rpl path desc descp desc1 desc2 link
20925 (let (buffer-read-only)
20926 (org-unmodified
20927 (remove-text-properties (point-min) (point-max)
20928 '(:org-license-to-kill t))))
20930 (message "Exporting...")
20932 (setq org-last-level 1)
20933 (org-init-section-numbers)
20935 ;; Get the language-dependent settings
20936 (setq lang-words (or (assoc language org-export-language-setup)
20937 (assoc "en" org-export-language-setup)))
20939 ;; Switch to the output buffer
20940 (set-buffer buffer)
20941 (erase-buffer)
20942 (fundamental-mode)
20943 (let ((case-fold-search nil)
20944 (org-odd-levels-only odd))
20945 ;; create local variables for all options, to make sure all called
20946 ;; functions get the correct information
20947 (mapcar (lambda (x)
20948 (set (make-local-variable (cdr x))
20949 (plist-get opt-plist (car x))))
20950 org-export-plist-vars)
20951 (setq umax (if arg (prefix-numeric-value arg)
20952 org-export-headline-levels))
20953 (setq umax-toc (if (integerp org-export-with-toc)
20954 (min org-export-with-toc umax)
20955 umax))
20956 (unless body-only
20957 ;; File header
20958 (insert (format
20959 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
20960 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
20961 <html xmlns=\"http://www.w3.org/1999/xhtml\"
20962 lang=\"%s\" xml:lang=\"%s\">
20963 <head>
20964 <title>%s</title>
20965 <meta http-equiv=\"Content-Type\" content=\"text/html;charset=%s\"/>
20966 <meta name=\"generator\" content=\"Org-mode\"/>
20967 <meta name=\"generated\" content=\"%s %s\"/>
20968 <meta name=\"author\" content=\"%s\"/>
20970 </head><body>
20972 language language (org-html-expand title)
20973 (or charset "iso-8859-1") date time author style))
20975 (insert (or (plist-get opt-plist :preamble) ""))
20977 (when (plist-get opt-plist :auto-preamble)
20978 (if title (insert (format org-export-html-title-format
20979 (org-html-expand title))))))
20981 (if (and org-export-with-toc (not body-only))
20982 (progn
20983 (push (format "<h%d>%s</h%d>\n"
20984 org-export-html-toplevel-hlevel
20985 (nth 3 lang-words)
20986 org-export-html-toplevel-hlevel)
20987 thetoc)
20988 (push "<ul>\n<li>" thetoc)
20989 (setq lines
20990 (mapcar '(lambda (line)
20991 (if (string-match org-todo-line-regexp line)
20992 ;; This is a headline
20993 (progn
20994 (setq have-headings t)
20995 (setq level (- (match-end 1) (match-beginning 1))
20996 level (org-tr-level level)
20997 txt (save-match-data
20998 (org-html-expand
20999 (org-export-cleanup-toc-line
21000 (match-string 3 line))))
21001 todo
21002 (or (and org-export-mark-todo-in-toc
21003 (match-beginning 2)
21004 (not (member (match-string 2 line)
21005 org-done-keywords)))
21006 ; TODO, not DONE
21007 (and org-export-mark-todo-in-toc
21008 (= level umax-toc)
21009 (org-search-todo-below
21010 line lines level))))
21011 (if (and (memq org-export-with-tags '(not-in-toc nil))
21012 (string-match
21013 (org-re "[ \t]+:[[:alnum:]_@:]+:[ \t]*$")
21014 txt))
21015 (setq txt (replace-match "" t t txt)))
21016 (if (string-match quote-re0 txt)
21017 (setq txt (replace-match "" t t txt)))
21018 (if org-export-with-section-numbers
21019 (setq txt (concat (org-section-number level)
21020 " " txt)))
21021 (if (<= level (max umax umax-toc))
21022 (setq head-count (+ head-count 1)))
21023 (if (<= level umax-toc)
21024 (progn
21025 (if (> level org-last-level)
21026 (progn
21027 (setq cnt (- level org-last-level))
21028 (while (>= (setq cnt (1- cnt)) 0)
21029 (push "\n<ul>\n<li>" thetoc))
21030 (push "\n" thetoc)))
21031 (if (< level org-last-level)
21032 (progn
21033 (setq cnt (- org-last-level level))
21034 (while (>= (setq cnt (1- cnt)) 0)
21035 (push "</li>\n</ul>" thetoc))
21036 (push "\n" thetoc)))
21037 ;; Check for targets
21038 (while (string-match org-target-regexp line)
21039 (setq tg (match-string 1 line)
21040 line (replace-match
21041 (concat "@<span class=\"target\">" tg "@</span> ")
21042 t t line))
21043 (push (cons (org-solidify-link-text tg)
21044 (format "sec-%d" head-count))
21045 target-alist))
21046 (while (string-match "&lt;\\(&lt;\\)+\\|&gt;\\(&gt;\\)+" txt)
21047 (setq txt (replace-match "" t t txt)))
21048 (push
21049 (format
21050 (if todo
21051 "</li>\n<li><a href=\"#sec-%d\"><span class=\"todo\">%s</span></a>"
21052 "</li>\n<li><a href=\"#sec-%d\">%s</a>")
21053 head-count txt) thetoc)
21055 (setq org-last-level level))
21057 line)
21058 lines))
21059 (while (> org-last-level 0)
21060 (setq org-last-level (1- org-last-level))
21061 (push "</li>\n</ul>\n" thetoc))
21062 (setq thetoc (if have-headings (nreverse thetoc) nil))))
21064 (setq head-count 0)
21065 (org-init-section-numbers)
21067 (while (setq line (pop lines) origline line)
21068 (catch 'nextline
21070 ;; end of quote section?
21071 (when (and inquote (string-match "^\\*+ " line))
21072 (insert "</pre>\n")
21073 (setq inquote nil))
21074 ;; inside a quote section?
21075 (when inquote
21076 (insert (org-html-protect line) "\n")
21077 (throw 'nextline nil))
21079 ;; verbatim lines
21080 (when (and org-export-with-fixed-width
21081 (string-match "^[ \t]*:\\(.*\\)" line))
21082 (when (not infixed)
21083 (setq infixed t)
21084 (insert "<pre>\n"))
21085 (insert (org-html-protect (match-string 1 line)) "\n")
21086 (when (and lines
21087 (not (string-match "^[ \t]*\\(:.*\\)"
21088 (car lines))))
21089 (setq infixed nil)
21090 (insert "</pre>\n"))
21091 (throw 'nextline nil))
21093 ;; Protected HTML
21094 (when (get-text-property 0 'org-protected line)
21095 (let (par)
21096 (when (re-search-backward
21097 "\\(<p>\\)\\([ \t\r\n]*\\)\\=" (- (point) 100) t)
21098 (setq par (match-string 1))
21099 (replace-match "\\2\n"))
21100 (insert line "\n")
21101 (while (and lines
21102 (get-text-property 0 'org-protected (car lines)))
21103 (insert (pop lines) "\n"))
21104 (and par (insert "<p>\n")))
21105 (throw 'nextline nil))
21107 ;; Horizontal line
21108 (when (string-match "^[ \t]*-\\{5,\\}[ \t]*$" line)
21109 (insert "\n<hr/>\n")
21110 (throw 'nextline nil))
21112 ;; make targets to anchors
21113 (while (string-match "<<<?\\([^<>]*\\)>>>?\\((INVISIBLE)\\)?[ \t]*\n?" line)
21114 (cond
21115 ((match-end 2)
21116 (setq line (replace-match
21117 (concat "@<a name=\""
21118 (org-solidify-link-text (match-string 1 line))
21119 "\">\\nbsp@</a>")
21120 t t line)))
21121 ((and org-export-with-toc (equal (string-to-char line) ?*))
21122 (setq line (replace-match
21123 (concat "@<span class=\"target\">" (match-string 1 line) "@</span> ")
21124 ; (concat "@<i>" (match-string 1 line) "@</i> ")
21125 t t line)))
21127 (setq line (replace-match
21128 (concat "@<a name=\""
21129 (org-solidify-link-text (match-string 1 line))
21130 "\" class=\"target\">" (match-string 1 line) "@</a> ")
21131 t t line)))))
21133 (setq line (org-html-handle-time-stamps line))
21135 ;; replace "&" by "&amp;", "<" and ">" by "&lt;" and "&gt;"
21136 ;; handle @<..> HTML tags (replace "@&gt;..&lt;" by "<..>")
21137 ;; Also handle sub_superscripts and checkboxes
21138 (setq line (org-html-expand line))
21140 ;; Format the links
21141 (setq start 0)
21142 (while (string-match org-bracket-link-analytic-regexp line start)
21143 (setq start (match-beginning 0))
21144 (setq type (if (match-end 2) (match-string 2 line) "internal"))
21145 (setq path (match-string 3 line))
21146 (setq desc1 (if (match-end 5) (match-string 5 line))
21147 desc2 (if (match-end 2) (concat type ":" path) path)
21148 descp (and desc1 (not (equal desc1 desc2)))
21149 desc (or desc1 desc2))
21150 ;; Make an image out of the description if that is so wanted
21151 (when (and descp (org-file-image-p desc))
21152 (save-match-data
21153 (if (string-match "^file:" desc)
21154 (setq desc (substring desc (match-end 0)))))
21155 (setq desc (concat "<img src=\"" desc "\"/>")))
21156 ;; FIXME: do we need to unescape here somewhere?
21157 (cond
21158 ((equal type "internal")
21159 (setq rpl
21160 (concat
21161 "<a href=\"#"
21162 (org-solidify-link-text
21163 (save-match-data (org-link-unescape path)) target-alist)
21164 "\">" desc "</a>")))
21165 ((member type '("http" "https")) ; FIXME: need to test this.
21166 ;; standard URL, just check if we need to inline an image
21167 (if (and (or (eq t org-export-html-inline-images)
21168 (and org-export-html-inline-images (not descp)))
21169 (org-file-image-p path))
21170 (setq rpl (concat "<img src=\"" type ":" path "\"/>"))
21171 (setq link (concat type ":" path))
21172 (setq rpl (concat "<a href=\"" link "\">" desc "</a>"))))
21173 ((member type '("ftp" "mailto" "news"))
21174 ;; standard URL
21175 (setq link (concat type ":" path))
21176 (setq rpl (concat "<a href=\"" link "\">" desc "</a>")))
21177 ((string= type "file")
21178 ;; FILE link
21179 (let* ((filename path)
21180 (abs-p (file-name-absolute-p filename))
21181 thefile file-is-image-p search)
21182 (save-match-data
21183 (if (string-match "::\\(.*\\)" filename)
21184 (setq search (match-string 1 filename)
21185 filename (replace-match "" t nil filename)))
21186 (setq valid
21187 (if (functionp link-validate)
21188 (funcall link-validate filename current-dir)
21190 (setq file-is-image-p (org-file-image-p filename))
21191 (setq thefile (if abs-p (expand-file-name filename) filename))
21192 (when (and org-export-html-link-org-files-as-html
21193 (string-match "\\.org$" thefile))
21194 (setq thefile (concat (substring thefile 0
21195 (match-beginning 0))
21196 ".html"))
21197 (if (and search
21198 ;; make sure this is can be used as target search
21199 (not (string-match "^[0-9]*$" search))
21200 (not (string-match "^\\*" search))
21201 (not (string-match "^/.*/$" search)))
21202 (setq thefile (concat thefile "#"
21203 (org-solidify-link-text
21204 (org-link-unescape search)))))
21205 (when (string-match "^file:" desc)
21206 (setq desc (replace-match "" t t desc))
21207 (if (string-match "\\.org$" desc)
21208 (setq desc (replace-match "" t t desc))))))
21209 (setq rpl (if (and file-is-image-p
21210 (or (eq t org-export-html-inline-images)
21211 (and org-export-html-inline-images
21212 (not descp))))
21213 (concat "<img src=\"" thefile "\"/>")
21214 (concat "<a href=\"" thefile "\">" desc "</a>")))
21215 (if (not valid) (setq rpl desc))))
21216 ((member type '("bbdb" "vm" "wl" "mhe" "rmail" "gnus" "shell" "info" "elisp"))
21217 (setq rpl (concat "<i>&lt;" type ":"
21218 (save-match-data (org-link-unescape path))
21219 "&gt;</i>"))))
21220 (setq line (replace-match rpl t t line)
21221 start (+ start (length rpl))))
21223 ;; TODO items
21224 (if (and (string-match org-todo-line-regexp line)
21225 (match-beginning 2))
21227 (setq line
21228 (concat (substring line 0 (match-beginning 2))
21229 "<span class=\""
21230 (if (member (match-string 2 line)
21231 org-done-keywords)
21232 "done" "todo")
21233 "\">" (match-string 2 line)
21234 "</span>" (substring line (match-end 2)))))
21236 ;; Does this contain a reference to a footnote?
21237 (when org-export-with-footnotes
21238 (while (string-match "\\([^* \t].*?\\)\\[\\([0-9]+\\)\\]" line)
21239 (let ((n (match-string 2 line)))
21240 (setq line
21241 (replace-match
21242 (format
21243 "%s<sup><a class=\"footref\" name=\"fnr.%s\" href=\"#fn.%s\">%s</a></sup>"
21244 (match-string 1 line) n n n)
21245 t t line)))))
21247 (cond
21248 ((string-match "^\\(\\*+\\)[ \t]+\\(.*\\)" line)
21249 ;; This is a headline
21250 (setq level (org-tr-level (- (match-end 1) (match-beginning 1)))
21251 txt (match-string 2 line))
21252 (if (string-match quote-re0 txt)
21253 (setq txt (replace-match "" t t txt)))
21254 (if (<= level (max umax umax-toc))
21255 (setq head-count (+ head-count 1)))
21256 (when in-local-list
21257 ;; Close any local lists before inserting a new header line
21258 (while local-list-num
21259 (org-close-li)
21260 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
21261 (pop local-list-num))
21262 (setq local-list-indent nil
21263 in-local-list nil))
21264 (setq first-heading-pos (or first-heading-pos (point)))
21265 (org-html-level-start level txt umax
21266 (and org-export-with-toc (<= level umax))
21267 head-count)
21268 ;; QUOTES
21269 (when (string-match quote-re line)
21270 (insert "<pre>")
21271 (setq inquote t)))
21273 ((and org-export-with-tables
21274 (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)" line))
21275 (if (not table-open)
21276 ;; New table starts
21277 (setq table-open t table-buffer nil table-orig-buffer nil))
21278 ;; Accumulate lines
21279 (setq table-buffer (cons line table-buffer)
21280 table-orig-buffer (cons origline table-orig-buffer))
21281 (when (or (not lines)
21282 (not (string-match "^\\([ \t]*\\)\\(|\\|\\+-+\\+\\)"
21283 (car lines))))
21284 (setq table-open nil
21285 table-buffer (nreverse table-buffer)
21286 table-orig-buffer (nreverse table-orig-buffer))
21287 (org-close-par-maybe)
21288 (insert (org-format-table-html table-buffer table-orig-buffer))))
21290 ;; Normal lines
21291 (when (string-match
21292 (cond
21293 ((eq llt t) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+[.)]\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
21294 ((= llt ?.) "^\\([ \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+\\.\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
21295 ((= llt ?\)) "^\\( \t]*\\)\\(\\([-+*] \\)\\|\\([0-9]+)\\) \\)?\\( *[^ \t\n\r]\\|[ \t]*$\\)")
21296 (t (error "Invalid value of `org-plain-list-ordered-item-terminator'")))
21297 line)
21298 (setq ind (org-get-string-indentation line)
21299 start-is-num (match-beginning 4)
21300 starter (if (match-beginning 2)
21301 (substring (match-string 2 line) 0 -1))
21302 line (substring line (match-beginning 5)))
21303 (unless (string-match "[^ \t]" line)
21304 ;; empty line. Pretend indentation is large.
21305 (setq ind (if org-empty-line-terminates-plain-lists
21307 (1+ (or (car local-list-indent) 1)))))
21308 (setq didclose nil)
21309 (while (and in-local-list
21310 (or (and (= ind (car local-list-indent))
21311 (not starter))
21312 (< ind (car local-list-indent))))
21313 (setq didclose t)
21314 (org-close-li)
21315 (insert (if (car local-list-num) "</ol>\n" "</ul>"))
21316 (pop local-list-num) (pop local-list-indent)
21317 (setq in-local-list local-list-indent))
21318 (cond
21319 ((and starter
21320 (or (not in-local-list)
21321 (> ind (car local-list-indent))))
21322 ;; Start new (level of) list
21323 (org-close-par-maybe)
21324 (insert (if start-is-num "<ol>\n<li>\n" "<ul>\n<li>\n"))
21325 (push start-is-num local-list-num)
21326 (push ind local-list-indent)
21327 (setq in-local-list t))
21328 (starter
21329 ;; continue current list
21330 (org-close-li)
21331 (insert "<li>\n"))
21332 (didclose
21333 ;; we did close a list, normal text follows: need <p>
21334 (org-open-par)))
21335 (if (string-match "^[ \t]*\\[\\([X ]\\)\\]" line)
21336 (setq line
21337 (replace-match
21338 (if (equal (match-string 1 line) "X")
21339 "<b>[X]</b>"
21340 "<b>[<span style=\"visibility:hidden;\">X</span>]</b>")
21341 t t line))))
21343 ;; Empty lines start a new paragraph. If hand-formatted lists
21344 ;; are not fully interpreted, lines starting with "-", "+", "*"
21345 ;; also start a new paragraph.
21346 (if (string-match "^ [-+*]-\\|^[ \t]*$" line) (org-open-par))
21348 ;; Is this the start of a footnote?
21349 (when org-export-with-footnotes
21350 (when (string-match "^[ \t]*\\[\\([0-9]+\\)\\]" line)
21351 (org-close-par-maybe)
21352 (let ((n (match-string 1 line)))
21353 (setq line (replace-match
21354 (format "<p class=\"footnote\"><sup><a class=\"footnum\" name=\"fn.%s\" href=\"#fnr.%s\">%s</a></sup>" n n n) t t line)))))
21356 ;; Check if the line break needs to be conserved
21357 (cond
21358 ((string-match "\\\\\\\\[ \t]*$" line)
21359 (setq line (replace-match "<br/>" t t line)))
21360 (org-export-preserve-breaks
21361 (setq line (concat line "<br/>"))))
21363 (insert line "\n")))))
21365 ;; Properly close all local lists and other lists
21366 (when inquote (insert "</pre>\n"))
21367 (when in-local-list
21368 ;; Close any local lists before inserting a new header line
21369 (while local-list-num
21370 (org-close-li)
21371 (insert (if (car local-list-num) "</ol>\n" "</ul>\n"))
21372 (pop local-list-num))
21373 (setq local-list-indent nil
21374 in-local-list nil))
21375 (org-html-level-start 1 nil umax
21376 (and org-export-with-toc (<= level umax))
21377 head-count)
21379 (unless body-only
21380 (when (plist-get opt-plist :auto-postamble)
21381 (when author
21382 (insert "<p class=\"author\"> "
21383 (nth 1 lang-words) ": " author "\n")
21384 (when email
21385 (insert "<a href=\"mailto:" email "\">&lt;"
21386 email "&gt;</a>\n"))
21387 (insert "</p>\n"))
21388 (when (and date time)
21389 (insert "<p class=\"date\"> "
21390 (nth 2 lang-words) ": "
21391 date " " time "</p>\n")))
21393 (if org-export-html-with-timestamp
21394 (insert org-export-html-html-helper-timestamp))
21395 (insert (or (plist-get opt-plist :postamble) ""))
21396 (insert "</body>\n</html>\n"))
21398 (normal-mode)
21399 (if (eq major-mode default-major-mode) (html-mode))
21401 ;; insert the table of contents
21402 (goto-char (point-min))
21403 (when thetoc
21404 (if (or (re-search-forward
21405 "<p>\\s-*\\[TABLE-OF-CONTENTS\\]\\s-*</p>" nil t)
21406 (re-search-forward
21407 "\\[TABLE-OF-CONTENTS\\]" nil t))
21408 (progn
21409 (goto-char (match-beginning 0))
21410 (replace-match ""))
21411 (goto-char first-heading-pos)
21412 (when (looking-at "\\s-*</p>")
21413 (goto-char (match-end 0))
21414 (insert "\n")))
21415 (mapc 'insert thetoc))
21416 ;; remove empty paragraphs and lists
21417 (goto-char (point-min))
21418 (while (re-search-forward "<p>[ \r\n\t]*</p>" nil t)
21419 (replace-match ""))
21420 (goto-char (point-min))
21421 (while (re-search-forward "<li>[ \r\n\t]*</li>\n?" nil t)
21422 (replace-match ""))
21423 (or to-buffer (save-buffer))
21424 (goto-char (point-min))
21425 (message "Exporting... done")
21426 (if (eq to-buffer 'string)
21427 (prog1 (buffer-substring (point-min) (point-max))
21428 (kill-buffer (current-buffer)))
21429 (current-buffer)))))
21431 (defvar org-table-colgroup-info nil) ;; FIXME: mode to a better place
21432 (defun org-format-table-ascii (lines)
21433 "Format a table for ascii export."
21434 (if (stringp lines)
21435 (setq lines (org-split-string lines "\n")))
21436 (if (not (string-match "^[ \t]*|" (car lines)))
21437 ;; Table made by table.el - test for spanning
21438 lines
21440 ;; A normal org table
21441 ;; Get rid of hlines at beginning and end
21442 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
21443 (setq lines (nreverse lines))
21444 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
21445 (setq lines (nreverse lines))
21446 (when org-export-table-remove-special-lines
21447 ;; Check if the table has a marking column. If yes remove the
21448 ;; column and the special lines
21449 (setq lines (org-table-clean-before-export lines)))
21450 ;; Get rid of the vertical lines except for grouping
21451 (let ((vl (org-colgroup-info-to-vline-list org-table-colgroup-info))
21452 rtn line vl1 start)
21453 (while (setq line (pop lines))
21454 (if (string-match org-table-hline-regexp line)
21455 (and (string-match "|\\(.*\\)|" line)
21456 (setq line (replace-match " \\1" t nil line)))
21457 (setq start 0 vl1 vl)
21458 (while (string-match "|" line start)
21459 (setq start (match-end 0))
21460 (or (pop vl1) (setq line (replace-match " " t t line)))))
21461 (push line rtn))
21462 (nreverse rtn))))
21464 (defun org-colgroup-info-to-vline-list (info)
21465 (let (vl new last)
21466 (while info
21467 (setq last new new (pop info))
21468 (if (or (memq last '(:end :startend))
21469 (memq new '(:start :startend)))
21470 (push t vl)
21471 (push nil vl)))
21472 (setq vl (cons nil (nreverse vl)))))
21475 (defun org-format-table-html (lines olines)
21476 "Find out which HTML converter to use and return the HTML code."
21477 (if (stringp lines)
21478 (setq lines (org-split-string lines "\n")))
21479 (if (string-match "^[ \t]*|" (car lines))
21480 ;; A normal org table
21481 (org-format-org-table-html lines)
21482 ;; Table made by table.el - test for spanning
21483 (let* ((hlines (delq nil (mapcar
21484 (lambda (x)
21485 (if (string-match "^[ \t]*\\+-" x) x
21486 nil))
21487 lines)))
21488 (first (car hlines))
21489 (ll (and (string-match "\\S-+" first)
21490 (match-string 0 first)))
21491 (re (concat "^[ \t]*" (regexp-quote ll)))
21492 (spanning (delq nil (mapcar (lambda (x) (not (string-match re x)))
21493 hlines))))
21494 (if (and (not spanning)
21495 (not org-export-prefer-native-exporter-for-tables))
21496 ;; We can use my own converter with HTML conversions
21497 (org-format-table-table-html lines)
21498 ;; Need to use the code generator in table.el, with the original text.
21499 (org-format-table-table-html-using-table-generate-source olines)))))
21501 (defun org-format-org-table-html (lines &optional splice)
21502 "Format a table into HTML."
21503 ;; Get rid of hlines at beginning and end
21504 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
21505 (setq lines (nreverse lines))
21506 (if (string-match "^[ \t]*|-" (car lines)) (setq lines (cdr lines)))
21507 (setq lines (nreverse lines))
21508 (when org-export-table-remove-special-lines
21509 ;; Check if the table has a marking column. If yes remove the
21510 ;; column and the special lines
21511 (setq lines (org-table-clean-before-export lines)))
21513 (let ((head (and org-export-highlight-first-table-line
21514 (delq nil (mapcar
21515 (lambda (x) (string-match "^[ \t]*|-" x))
21516 (cdr lines)))))
21517 (nlines 0) fnum i
21518 tbopen line fields html gr colgropen)
21519 (if splice (setq head nil))
21520 (unless splice (push (if head "<thead>" "<tbody>") html))
21521 (setq tbopen t)
21522 (while (setq line (pop lines))
21523 (catch 'next-line
21524 (if (string-match "^[ \t]*|-" line)
21525 (progn
21526 (unless splice
21527 (push (if head "</thead>" "</tbody>") html)
21528 (if lines (push "<tbody>" html) (setq tbopen nil)))
21529 (setq head nil) ;; head ends here, first time around
21530 ;; ignore this line
21531 (throw 'next-line t)))
21532 ;; Break the line into fields
21533 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
21534 (unless fnum (setq fnum (make-vector (length fields) 0)))
21535 (setq nlines (1+ nlines) i -1)
21536 (push (concat "<tr>"
21537 (mapconcat
21538 (lambda (x)
21539 (setq i (1+ i))
21540 (if (and (< i nlines)
21541 (string-match org-table-number-regexp x))
21542 (incf (aref fnum i)))
21543 (if head
21544 (concat (car org-export-table-header-tags) x
21545 (cdr org-export-table-header-tags))
21546 (concat (car org-export-table-data-tags) x
21547 (cdr org-export-table-data-tags))))
21548 fields "")
21549 "</tr>")
21550 html)))
21551 (unless splice (if tbopen (push "</tbody>" html)))
21552 (unless splice (push "</table>\n" html))
21553 (setq html (nreverse html))
21554 (unless splice
21555 ;; Put in COL tags with the alignment (unfortuntely often ignored...)
21556 (push (mapconcat
21557 (lambda (x)
21558 (setq gr (pop org-table-colgroup-info))
21559 (format "%s<COL align=\"%s\"></COL>%s"
21560 (if (memq gr '(:start :startend))
21561 (prog1
21562 (if colgropen "</colgroup>\n<colgroup>" "<colgroup>")
21563 (setq colgropen t))
21565 (if (> (/ (float x) nlines) org-table-number-fraction)
21566 "right" "left")
21567 (if (memq gr '(:end :startend))
21568 (progn (setq colgropen nil) "</colgroup>")
21569 "")))
21570 fnum "")
21571 html)
21572 (if colgropen (setq html (cons (car html) (cons "</colgroup>" (cdr html)))))
21573 (push org-export-html-table-tag html))
21574 (concat (mapconcat 'identity html "\n") "\n")))
21576 (defun org-table-clean-before-export (lines)
21577 "Check if the table has a marking column.
21578 If yes remove the column and the special lines."
21579 (setq org-table-colgroup-info nil)
21580 (if (memq nil
21581 (mapcar
21582 (lambda (x) (or (string-match "^[ \t]*|-" x)
21583 (string-match "^[ \t]*| *\\([#!$*_^ /]\\) *|" x)))
21584 lines))
21585 (progn
21586 (setq org-table-clean-did-remove-column nil)
21587 (delq nil
21588 (mapcar
21589 (lambda (x)
21590 (cond
21591 ((string-match "^[ \t]*| */ *|" x)
21592 (setq org-table-colgroup-info
21593 (mapcar (lambda (x)
21594 (cond ((member x '("<" "&lt;")) :start)
21595 ((member x '(">" "&gt;")) :end)
21596 ((member x '("<>" "&lt;&gt;")) :startend)
21597 (t nil)))
21598 (org-split-string x "[ \t]*|[ \t]*")))
21599 nil)
21600 (t x)))
21601 lines)))
21602 (setq org-table-clean-did-remove-column t)
21603 (delq nil
21604 (mapcar
21605 (lambda (x)
21606 (cond
21607 ((string-match "^[ \t]*| */ *|" x)
21608 (setq org-table-colgroup-info
21609 (mapcar (lambda (x)
21610 (cond ((member x '("<" "&lt;")) :start)
21611 ((member x '(">" "&gt;")) :end)
21612 ((member x '("<>" "&lt;&gt;")) :startend)
21613 (t nil)))
21614 (cdr (org-split-string x "[ \t]*|[ \t]*"))))
21615 nil)
21616 ((string-match "^[ \t]*| *[!_^/] *|" x)
21617 nil) ; ignore this line
21618 ((or (string-match "^\\([ \t]*\\)|-+\\+" x)
21619 (string-match "^\\([ \t]*\\)|[^|]*|" x))
21620 ;; remove the first column
21621 (replace-match "\\1|" t nil x))
21622 (t (error "This should not happen"))))
21623 lines))))
21625 (defun org-format-table-table-html (lines)
21626 "Format a table generated by table.el into HTML.
21627 This conversion does *not* use `table-generate-source' from table.el.
21628 This has the advantage that Org-mode's HTML conversions can be used.
21629 But it has the disadvantage, that no cell- or row-spanning is allowed."
21630 (let (line field-buffer
21631 (head org-export-highlight-first-table-line)
21632 fields html empty)
21633 (setq html (concat org-export-html-table-tag "\n"))
21634 (while (setq line (pop lines))
21635 (setq empty "&nbsp;")
21636 (catch 'next-line
21637 (if (string-match "^[ \t]*\\+-" line)
21638 (progn
21639 (if field-buffer
21640 (progn
21641 (setq
21642 html
21643 (concat
21644 html
21645 "<tr>"
21646 (mapconcat
21647 (lambda (x)
21648 (if (equal x "") (setq x empty))
21649 (if head
21650 (concat (car org-export-table-header-tags) x
21651 (cdr org-export-table-header-tags))
21652 (concat (car org-export-table-data-tags) x
21653 (cdr org-export-table-data-tags))))
21654 field-buffer "\n")
21655 "</tr>\n"))
21656 (setq head nil)
21657 (setq field-buffer nil)))
21658 ;; Ignore this line
21659 (throw 'next-line t)))
21660 ;; Break the line into fields and store the fields
21661 (setq fields (org-split-string line "[ \t]*|[ \t]*"))
21662 (if field-buffer
21663 (setq field-buffer (mapcar
21664 (lambda (x)
21665 (concat x "<br/>" (pop fields)))
21666 field-buffer))
21667 (setq field-buffer fields))))
21668 (setq html (concat html "</table>\n"))
21669 html))
21671 (defun org-format-table-table-html-using-table-generate-source (lines)
21672 "Format a table into html, using `table-generate-source' from table.el.
21673 This has the advantage that cell- or row-spanning is allowed.
21674 But it has the disadvantage, that Org-mode's HTML conversions cannot be used."
21675 (require 'table)
21676 (with-current-buffer (get-buffer-create " org-tmp1 ")
21677 (erase-buffer)
21678 (insert (mapconcat 'identity lines "\n"))
21679 (goto-char (point-min))
21680 (if (not (re-search-forward "|[^+]" nil t))
21681 (error "Error processing table"))
21682 (table-recognize-table)
21683 (with-current-buffer (get-buffer-create " org-tmp2 ") (erase-buffer))
21684 (table-generate-source 'html " org-tmp2 ")
21685 (set-buffer " org-tmp2 ")
21686 (buffer-substring (point-min) (point-max))))
21688 (defun org-html-handle-time-stamps (s)
21689 "Format time stamps in string S, or remove them."
21690 (catch 'exit
21691 (let (r b)
21692 (while (string-match org-maybe-keyword-time-regexp s)
21693 (if (and (match-end 1) (equal (match-string 1 s) org-clock-string))
21694 ;; never export CLOCK
21695 (throw 'exit ""))
21696 (or b (setq b (substring s 0 (match-beginning 0))))
21697 (if (not org-export-with-timestamps)
21698 (setq r (concat r (substring s 0 (match-beginning 0)))
21699 s (substring s (match-end 0)))
21700 (setq r (concat
21701 r (substring s 0 (match-beginning 0))
21702 (if (match-end 1)
21703 (format "@<span class=\"timestamp-kwd\">%s @</span>"
21704 (match-string 1 s)))
21705 (format " @<span class=\"timestamp\">%s@</span>"
21706 (substring
21707 (org-translate-time (match-string 3 s)) 1 -1)))
21708 s (substring s (match-end 0)))))
21709 ;; Line break if line started and ended with time stamp stuff
21710 (if (not r)
21712 (setq r (concat r s))
21713 (unless (string-match "\\S-" (concat b s))
21714 (setq r (concat r "@<br/>")))
21715 r))))
21717 (defun org-html-protect (s)
21718 ;; convert & to &amp;, < to &lt; and > to &gt;
21719 (let ((start 0))
21720 (while (string-match "&" s start)
21721 (setq s (replace-match "&amp;" t t s)
21722 start (1+ (match-beginning 0))))
21723 (while (string-match "<" s)
21724 (setq s (replace-match "&lt;" t t s)))
21725 (while (string-match ">" s)
21726 (setq s (replace-match "&gt;" t t s))))
21729 (defun org-export-cleanup-toc-line (s)
21730 "Remove tags and time staps from lines going into the toc."
21731 (if (string-match (org-re " +:[[:alnum:]_@:]+: *$") s)
21732 (setq s (replace-match "" t t s)))
21733 (when org-export-remove-timestamps-from-toc
21734 (while (string-match org-maybe-keyword-time-regexp s)
21735 (setq s (replace-match "" t t s))))
21736 (while (string-match org-bracket-link-regexp s)
21737 (setq s (replace-match (match-string (if (match-end 3) 3 1) s)
21738 t t s)))
21741 (defun org-html-expand (string)
21742 "Prepare STRING for HTML export. Applies all active conversions.
21743 If there are links in the string, don't modify these."
21744 (let* (m s l res)
21745 (while (setq m (string-match org-bracket-link-regexp string))
21746 (setq s (substring string 0 m)
21747 l (match-string 0 string)
21748 string (substring string (match-end 0)))
21749 (push (org-html-do-expand s) res)
21750 (push l res))
21751 (push (org-html-do-expand string) res)
21752 (apply 'concat (nreverse res))))
21754 (defun org-html-do-expand (s)
21755 "Apply all active conversions to translate special ASCII to HTML."
21756 (setq s (org-html-protect s))
21757 (if org-export-html-expand
21758 (while (string-match "@&lt;\\([^&]*\\)&gt;" s)
21759 (setq s (replace-match "<\\1>" t nil s))))
21760 (if org-export-with-emphasize
21761 (setq s (org-export-html-convert-emphasize s)))
21762 (if org-export-with-sub-superscripts
21763 (setq s (org-export-html-convert-sub-super s)))
21764 (if org-export-with-TeX-macros
21765 (let ((start 0) wd ass)
21766 (while (setq start (string-match "\\\\\\([a-zA-Z]+\\)" s start))
21767 (setq wd (match-string 1 s))
21768 (if (setq ass (assoc wd org-html-entities))
21769 (setq s (replace-match (or (cdr ass)
21770 (concat "&" (car ass) ";"))
21771 t t s))
21772 (setq start (+ start (length wd)))))))
21775 (defun org-create-multibrace-regexp (left right n)
21776 "Create a regular expression which will match a balanced sexp.
21777 Opening delimiter is LEFT, and closing delimiter is RIGHT, both given
21778 as single character strings.
21779 The regexp returned will match the entire expression including the
21780 delimiters. It will also define a single group which contains the
21781 match except for the outermost delimiters. The maximum depth of
21782 stacked delimiters is N. Escaping delimiters is not possible."
21783 (let* ((nothing (concat "[^" "\\" left "\\" right "]*?"))
21784 (or "\\|")
21785 (re nothing)
21786 (next (concat "\\(?:" nothing left nothing right "\\)+" nothing)))
21787 (while (> n 1)
21788 (setq n (1- n)
21789 re (concat re or next)
21790 next (concat "\\(?:" nothing left next right "\\)+" nothing)))
21791 (concat left "\\(" re "\\)" right)))
21793 (defvar org-match-substring-regexp
21794 (concat
21795 "\\([^\\]\\)\\([_^]\\)\\("
21796 "\\(" (org-create-multibrace-regexp "{" "}" org-match-sexp-depth) "\\)"
21797 "\\|"
21798 "\\(" (org-create-multibrace-regexp "(" ")" org-match-sexp-depth) "\\)"
21799 "\\|"
21800 "\\(\\(?:\\*\\|[-+]?[^-+*!@#$%^_ \t\r\n,:\"?<>~;./{}=()]+\\)\\)\\)")
21801 "The regular expression matching a sub- or superscript.")
21803 ;(let ((s "a\\_b"))
21804 ; (and (string-match org-match-substring-regexp s)
21805 ; (conca t (match-string 1 s) ":::" (match-string 2 s))))
21807 (defun org-export-html-convert-sub-super (string)
21808 "Convert sub- and superscripts in STRING to HTML."
21809 (let (key c (s 0) (requireb (eq org-export-with-sub-superscripts '{})))
21810 (while (string-match org-match-substring-regexp string s)
21811 (if (and requireb (match-end 8))
21812 (setq s (match-end 2))
21813 (setq s (match-end 1)
21814 key (if (string= (match-string 2 string) "_") "sub" "sup")
21815 c (or (match-string 8 string)
21816 (match-string 6 string)
21817 (match-string 5 string))
21818 string (replace-match
21819 (concat (match-string 1 string)
21820 "<" key ">" c "</" key ">")
21821 t t string))))
21822 (while (string-match "\\\\\\([_^]\\)" string)
21823 (setq string (replace-match (match-string 1 string) t t string)))
21824 string))
21826 (defun org-export-html-convert-emphasize (string)
21827 "Apply emphasis."
21828 (let ((s 0))
21829 (while (string-match org-emph-re string s)
21830 (if (not (equal
21831 (substring string (match-beginning 3) (1+ (match-beginning 3)))
21832 (substring string (match-beginning 4) (1+ (match-beginning 4)))))
21833 (setq string (replace-match
21834 (concat "\\1" (nth 2 (assoc (match-string 3 string) org-emphasis-alist))
21835 "\\4" (nth 3 (assoc (match-string 3 string) org-emphasis-alist))
21836 "\\5") t nil string))
21837 (setq s (1+ s))))
21838 string))
21840 (defvar org-par-open nil)
21841 (defun org-open-par ()
21842 "Insert <p>, but first close previous paragraph if any."
21843 (org-close-par-maybe)
21844 (insert "\n<p>")
21845 (setq org-par-open t))
21846 (defun org-close-par-maybe ()
21847 "Close paragraph if there is one open."
21848 (when org-par-open
21849 (insert "</p>")
21850 (setq org-par-open nil)))
21851 (defun org-close-li ()
21852 "Close <li> if necessary."
21853 (org-close-par-maybe)
21854 (insert "</li>\n"))
21856 (defvar body-only) ; dynamically scoped into this.
21857 (defun org-html-level-start (level title umax with-toc head-count)
21858 "Insert a new level in HTML export.
21859 When TITLE is nil, just close all open levels."
21860 (org-close-par-maybe)
21861 (let ((l (1+ (max level umax))))
21862 (while (<= l org-level-max)
21863 (if (aref org-levels-open (1- l))
21864 (progn
21865 (org-html-level-close l)
21866 (aset org-levels-open (1- l) nil)))
21867 (setq l (1+ l)))
21868 (when title
21869 ;; If title is nil, this means this function is called to close
21870 ;; all levels, so the rest is done only if title is given
21871 (when (string-match (org-re "\\(:[[:alnum:]_@:]+:\\)[ \t]*$") title)
21872 (setq title (replace-match
21873 (if org-export-with-tags
21874 (save-match-data
21875 (concat
21876 "&nbsp;&nbsp;&nbsp;<span class=\"tag\">"
21877 (mapconcat 'identity (org-split-string
21878 (match-string 1 title) ":")
21879 "&nbsp;")
21880 "</span>"))
21882 t t title)))
21883 (if (> level umax)
21884 (progn
21885 (if (aref org-levels-open (1- level))
21886 (progn
21887 (org-close-li)
21888 (insert "<li>" title "<br/>\n"))
21889 (aset org-levels-open (1- level) t)
21890 (org-close-par-maybe)
21891 (insert "<ul>\n<li>" title "<br/>\n")))
21892 (if (and org-export-with-section-numbers (not body-only))
21893 (setq title (concat (org-section-number level) " " title)))
21894 (setq level (+ level org-export-html-toplevel-hlevel -1))
21895 (if with-toc
21896 (insert (format "\n<h%d id=\"sec-%d\">%s</h%d>\n"
21897 level head-count title level))
21898 (insert (format "\n<h%d>%s</h%d>\n" level title level)))
21899 (org-open-par)))))
21901 (defun org-html-level-close (&rest args)
21902 "Terminate one level in HTML export."
21903 (org-close-li)
21904 (insert "</ul>\n"))
21906 ;;; iCalendar export
21908 ;;;###autoload
21909 (defun org-export-icalendar-this-file ()
21910 "Export current file as an iCalendar file.
21911 The iCalendar file will be located in the same directory as the Org-mode
21912 file, but with extension `.ics'."
21913 (interactive)
21914 (org-export-icalendar nil buffer-file-name))
21916 ;;;###autoload
21917 (defun org-export-icalendar-all-agenda-files ()
21918 "Export all files in `org-agenda-files' to iCalendar .ics files.
21919 Each iCalendar file will be located in the same directory as the Org-mode
21920 file, but with extension `.ics'."
21921 (interactive)
21922 (apply 'org-export-icalendar nil (org-agenda-files t)))
21924 ;;;###autoload
21925 (defun org-export-icalendar-combine-agenda-files ()
21926 "Export all files in `org-agenda-files' to a single combined iCalendar file.
21927 The file is stored under the name `org-combined-agenda-icalendar-file'."
21928 (interactive)
21929 (apply 'org-export-icalendar t (org-agenda-files t)))
21931 (defun org-export-icalendar (combine &rest files)
21932 "Create iCalendar files for all elements of FILES.
21933 If COMBINE is non-nil, combine all calendar entries into a single large
21934 file and store it under the name `org-combined-agenda-icalendar-file'."
21935 (save-excursion
21936 (org-prepare-agenda-buffers files)
21937 (let* ((dir (org-export-directory
21938 :ical (list :publishing-directory
21939 org-export-publishing-directory)))
21940 file ical-file ical-buffer category started org-agenda-new-buffers)
21942 (and (get-buffer "*ical-tmp*") (kill-buffer "*ical-tmp*"))
21943 (when combine
21944 (setq ical-file
21945 (if (file-name-absolute-p org-combined-agenda-icalendar-file)
21946 org-combined-agenda-icalendar-file
21947 (expand-file-name org-combined-agenda-icalendar-file dir))
21948 ical-buffer (org-get-agenda-file-buffer ical-file))
21949 (set-buffer ical-buffer) (erase-buffer))
21950 (while (setq file (pop files))
21951 (catch 'nextfile
21952 (org-check-agenda-file file)
21953 (set-buffer (org-get-agenda-file-buffer file))
21954 (unless combine
21955 (setq ical-file (concat (file-name-as-directory dir)
21956 (file-name-sans-extension
21957 (file-name-nondirectory buffer-file-name))
21958 ".ics"))
21959 (setq ical-buffer (org-get-agenda-file-buffer ical-file))
21960 (with-current-buffer ical-buffer (erase-buffer)))
21961 (setq category (or org-category
21962 (file-name-sans-extension
21963 (file-name-nondirectory buffer-file-name))))
21964 (if (symbolp category) (setq category (symbol-name category)))
21965 (let ((standard-output ical-buffer))
21966 (if combine
21967 (and (not started) (setq started t)
21968 (org-start-icalendar-file org-icalendar-combined-name))
21969 (org-start-icalendar-file category))
21970 (org-print-icalendar-entries combine)
21971 (when (or (and combine (not files)) (not combine))
21972 (org-finish-icalendar-file)
21973 (set-buffer ical-buffer)
21974 (save-buffer)
21975 (run-hooks 'org-after-save-iCalendar-file-hook)))))
21976 (org-release-buffers org-agenda-new-buffers))))
21978 (defvar org-after-save-iCalendar-file-hook nil
21979 "Hook run after an iCalendar file has been saved.
21980 The iCalendar buffer is still current when this hook is run.
21981 A good way to use this is to tell a desktop calenndar application to re-read
21982 the iCalendar file.")
21984 (defun org-print-icalendar-entries (&optional combine)
21985 "Print iCalendar entries for the current Org-mode file to `standard-output'.
21986 When COMBINE is non nil, add the category to each line."
21987 (let ((re1 (concat org-ts-regexp "\\|<%%([^>\n]+>"))
21988 (re2 (concat "--?-?\\(" org-ts-regexp "\\)"))
21989 (org-category-table (org-get-category-table))
21990 (dts (org-ical-ts-to-string
21991 (format-time-string (cdr org-time-stamp-formats) (current-time))
21992 "DTSTART"))
21993 hd ts ts2 state status (inc t) pos b sexp rrule
21994 scheduledp deadlinep tmp pri category
21995 (sexp-buffer (get-buffer-create "*ical-tmp*")))
21996 (save-excursion
21997 (goto-char (point-min))
21998 (while (re-search-forward re1 nil t)
21999 (catch :skip
22000 (org-agenda-skip)
22001 (setq pos (match-beginning 0)
22002 ts (match-string 0)
22003 inc t
22004 hd (org-get-heading)
22005 category (org-get-category))
22006 (if (looking-at re2)
22007 (progn
22008 (goto-char (match-end 0))
22009 (setq ts2 (match-string 1) inc nil))
22010 (setq tmp (buffer-substring (max (point-min)
22011 (- pos org-ds-keyword-length))
22012 pos)
22013 ts2 (if (string-match "[0-9]\\{1,2\\}:[0-9][0-9]-\\([0-9]\\{1,2\\}:[0-9][0-9]\\)" ts)
22014 (progn
22015 (setq inc nil)
22016 (replace-match "\\1" t nil ts))
22018 deadlinep (string-match org-deadline-regexp tmp)
22019 scheduledp (string-match org-scheduled-regexp tmp)
22020 ;; donep (org-entry-is-done-p)
22022 (if (or (string-match org-tr-regexp hd)
22023 (string-match org-ts-regexp hd))
22024 (setq hd (replace-match "" t t hd)))
22025 (if (string-match "\\+\\([0-9]+\\)\\([dwmy]\\)>" ts)
22026 (setq rrule
22027 (concat "\nRRULE:FREQ="
22028 (cdr (assoc
22029 (match-string 2 ts)
22030 '(("d" . "DAILY")("w" . "WEEKLY")
22031 ("m" . "MONTHLY")("y" . "YEARLY"))))
22032 ";INTERVAL=" (match-string 1 ts)))
22033 (setq rrule ""))
22034 (if (string-match org-bracket-link-regexp hd)
22035 (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
22036 (match-string 1 hd))
22037 t t hd)))
22038 (if deadlinep (setq hd (concat "DL: " hd)))
22039 (if scheduledp (setq hd (concat "S: " hd)))
22040 (if (string-match "\\`<%%" ts)
22041 (with-current-buffer sexp-buffer
22042 (insert (substring ts 1 -1) " " hd "\n"))
22043 (princ (format "BEGIN:VEVENT
22045 %s%s
22046 SUMMARY:%s
22047 CATEGORIES:%s
22048 END:VEVENT\n"
22049 (org-ical-ts-to-string ts "DTSTART")
22050 (org-ical-ts-to-string ts2 "DTEND" inc)
22051 rrule hd category)))))
22053 (when (and org-icalendar-include-sexps
22054 (condition-case nil (require 'icalendar) (error nil))
22055 (fboundp 'icalendar-export-region))
22056 ;; Get all the literal sexps
22057 (goto-char (point-min))
22058 (while (re-search-forward "^&?%%(" nil t)
22059 (catch :skip
22060 (org-agenda-skip)
22061 (setq b (match-beginning 0))
22062 (goto-char (1- (match-end 0)))
22063 (forward-sexp 1)
22064 (end-of-line 1)
22065 (setq sexp (buffer-substring b (point)))
22066 (with-current-buffer sexp-buffer
22067 (insert sexp "\n"))
22068 (princ (org-diary-to-ical-string sexp-buffer)))))
22070 (when org-icalendar-include-todo
22071 (goto-char (point-min))
22072 (while (re-search-forward org-todo-line-regexp nil t)
22073 (catch :skip
22074 (org-agenda-skip)
22075 (setq state (match-string 2))
22076 (setq status (if (member state org-done-keywords)
22077 "COMPLETED" "NEEDS-ACTION"))
22078 (when (and state
22079 (or (not (member state org-done-keywords))
22080 (eq org-icalendar-include-todo 'all))
22081 (not (member org-archive-tag (org-get-tags-at)))
22083 (setq hd (match-string 3))
22084 (if (string-match org-bracket-link-regexp hd)
22085 (setq hd (replace-match (if (match-end 3) (match-string 3 hd)
22086 (match-string 1 hd))
22087 t t hd)))
22088 (if (string-match org-priority-regexp hd)
22089 (setq pri (string-to-char (match-string 2 hd))
22090 hd (concat (substring hd 0 (match-beginning 1))
22091 (substring hd (match-end 1))))
22092 (setq pri org-default-priority))
22093 (setq pri (floor (1+ (* 8. (/ (float (- org-lowest-priority pri))
22094 (- org-lowest-priority org-highest-priority))))))
22096 (princ (format "BEGIN:VTODO
22098 SUMMARY:%s
22099 CATEGORIES:%s
22100 SEQUENCE:1
22101 PRIORITY:%d
22102 STATUS:%s
22103 END:VTODO\n"
22104 dts hd category pri status)))))))))
22106 (defun org-start-icalendar-file (name)
22107 "Start an iCalendar file by inserting the header."
22108 (let ((user user-full-name)
22109 (name (or name "unknown"))
22110 (timezone (cadr (current-time-zone))))
22111 (princ
22112 (format "BEGIN:VCALENDAR
22113 VERSION:2.0
22114 X-WR-CALNAME:%s
22115 PRODID:-//%s//Emacs with Org-mode//EN
22116 X-WR-TIMEZONE:%s
22117 CALSCALE:GREGORIAN\n" name user timezone))))
22119 (defun org-finish-icalendar-file ()
22120 "Finish an iCalendar file by inserting the END statement."
22121 (princ "END:VCALENDAR\n"))
22123 (defun org-ical-ts-to-string (s keyword &optional inc)
22124 "Take a time string S and convert it to iCalendar format.
22125 KEYWORD is added in front, to make a complete line like DTSTART....
22126 When INC is non-nil, increase the hour by two (if time string contains
22127 a time), or the day by one (if it does not contain a time)."
22128 (let ((t1 (org-parse-time-string s 'nodefault))
22129 t2 fmt have-time time)
22130 (if (and (car t1) (nth 1 t1) (nth 2 t1))
22131 (setq t2 t1 have-time t)
22132 (setq t2 (org-parse-time-string s)))
22133 (let ((s (car t2)) (mi (nth 1 t2)) (h (nth 2 t2))
22134 (d (nth 3 t2)) (m (nth 4 t2)) (y (nth 5 t2)))
22135 (when inc
22136 (if have-time (setq h (+ 2 h)) (setq d (1+ d))))
22137 (setq time (encode-time s mi h d m y)))
22138 (setq fmt (if have-time ":%Y%m%dT%H%M%S" ";VALUE=DATE:%Y%m%d"))
22139 (concat keyword (format-time-string fmt time))))
22141 ;;; XOXO export
22143 (defun org-export-as-xoxo-insert-into (buffer &rest output)
22144 (with-current-buffer buffer
22145 (apply 'insert output)))
22146 (put 'org-export-as-xoxo-insert-into 'lisp-indent-function 1)
22148 (defun org-export-as-xoxo (&optional buffer)
22149 "Export the org buffer as XOXO.
22150 The XOXO buffer is named *xoxo-<source buffer name>*"
22151 (interactive (list (current-buffer)))
22152 ;; A quickie abstraction
22154 ;; Output everything as XOXO
22155 (with-current-buffer (get-buffer buffer)
22156 (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed.
22157 (let* ((opt-plist (org-combine-plists (org-default-export-plist)
22158 (org-infile-export-plist)))
22159 (filename (concat (file-name-as-directory
22160 (org-export-directory :xoxo opt-plist))
22161 (file-name-sans-extension
22162 (file-name-nondirectory buffer-file-name))
22163 ".html"))
22164 (out (find-file-noselect filename))
22165 (last-level 1)
22166 (hanging-li nil))
22167 ;; Check the output buffer is empty.
22168 (with-current-buffer out (erase-buffer))
22169 ;; Kick off the output
22170 (org-export-as-xoxo-insert-into out "<ol class='xoxo'>\n")
22171 (while (re-search-forward "^\\(\\*+\\)[ \t]+\\(.+\\)" (point-max) 't)
22172 (let* ((hd (match-string-no-properties 1))
22173 (level (length hd))
22174 (text (concat
22175 (match-string-no-properties 2)
22176 (save-excursion
22177 (goto-char (match-end 0))
22178 (let ((str ""))
22179 (catch 'loop
22180 (while 't
22181 (forward-line)
22182 (if (looking-at "^[ \t]\\(.*\\)")
22183 (setq str (concat str (match-string-no-properties 1)))
22184 (throw 'loop str)))))))))
22186 ;; Handle level rendering
22187 (cond
22188 ((> level last-level)
22189 (org-export-as-xoxo-insert-into out "\n<ol>\n"))
22191 ((< level last-level)
22192 (dotimes (- (- last-level level) 1)
22193 (if hanging-li
22194 (org-export-as-xoxo-insert-into out "</li>\n"))
22195 (org-export-as-xoxo-insert-into out "</ol>\n"))
22196 (when hanging-li
22197 (org-export-as-xoxo-insert-into out "</li>\n")
22198 (setq hanging-li nil)))
22200 ((equal level last-level)
22201 (if hanging-li
22202 (org-export-as-xoxo-insert-into out "</li>\n")))
22205 (setq last-level level)
22207 ;; And output the new li
22208 (setq hanging-li 't)
22209 (if (equal ?+ (elt text 0))
22210 (org-export-as-xoxo-insert-into out "<li class='" (substring text 1) "'>")
22211 (org-export-as-xoxo-insert-into out "<li>" text))))
22213 ;; Finally finish off the ol
22214 (dotimes (- last-level 1)
22215 (if hanging-li
22216 (org-export-as-xoxo-insert-into out "</li>\n"))
22217 (org-export-as-xoxo-insert-into out "</ol>\n"))
22219 ;; Finish the buffer off and clean it up.
22220 (switch-to-buffer-other-window out)
22221 (indent-region (point-min) (point-max) nil)
22222 (save-buffer)
22223 (goto-char (point-min))
22227 ;;;; Key bindings
22229 ;; Make `C-c C-x' a prefix key
22230 (org-defkey org-mode-map "\C-c\C-x" (make-sparse-keymap))
22232 ;; TAB key with modifiers
22233 (org-defkey org-mode-map "\C-i" 'org-cycle)
22234 (org-defkey org-mode-map [(tab)] 'org-cycle)
22235 (org-defkey org-mode-map [(control tab)] 'org-force-cycle-archived)
22236 (org-defkey org-mode-map [(meta tab)] 'org-complete)
22237 (org-defkey org-mode-map "\M-\t" 'org-complete)
22238 (org-defkey org-mode-map "\M-\C-i" 'org-complete)
22239 ;; The following line is necessary under Suse GNU/Linux
22240 (unless (featurep 'xemacs)
22241 (org-defkey org-mode-map [S-iso-lefttab] 'org-shifttab))
22242 (org-defkey org-mode-map [(shift tab)] 'org-shifttab)
22243 (define-key org-mode-map (kbd "<backtab>") 'org-shifttab)
22245 (org-defkey org-mode-map [(shift return)] 'org-table-copy-down)
22246 (org-defkey org-mode-map [(meta shift return)] 'org-insert-todo-heading)
22247 (org-defkey org-mode-map [(meta return)] 'org-meta-return)
22249 ;; Cursor keys with modifiers
22250 (org-defkey org-mode-map [(meta left)] 'org-metaleft)
22251 (org-defkey org-mode-map [(meta right)] 'org-metaright)
22252 (org-defkey org-mode-map [(meta up)] 'org-metaup)
22253 (org-defkey org-mode-map [(meta down)] 'org-metadown)
22255 (org-defkey org-mode-map [(meta shift left)] 'org-shiftmetaleft)
22256 (org-defkey org-mode-map [(meta shift right)] 'org-shiftmetaright)
22257 (org-defkey org-mode-map [(meta shift up)] 'org-shiftmetaup)
22258 (org-defkey org-mode-map [(meta shift down)] 'org-shiftmetadown)
22260 (org-defkey org-mode-map [(shift up)] 'org-shiftup)
22261 (org-defkey org-mode-map [(shift down)] 'org-shiftdown)
22262 (org-defkey org-mode-map [(shift left)] 'org-shiftleft)
22263 (org-defkey org-mode-map [(shift right)] 'org-shiftright)
22265 (org-defkey org-mode-map [(control shift right)] 'org-shiftcontrolright)
22266 (org-defkey org-mode-map [(control shift left)] 'org-shiftcontrolleft)
22268 ;;; Extra keys for tty access.
22269 ;; We only set them when really needed because otherwise the
22270 ;; menus don't show the simple keys
22272 (when (or (featurep 'xemacs) ;; because XEmacs supports multi-device stuff
22273 (not window-system))
22274 (org-defkey org-mode-map "\C-c\C-xc" 'org-table-copy-down)
22275 (org-defkey org-mode-map "\C-c\C-xM" 'org-insert-todo-heading)
22276 (org-defkey org-mode-map "\C-c\C-xm" 'org-meta-return)
22277 (org-defkey org-mode-map [?\e (return)] 'org-meta-return)
22278 (org-defkey org-mode-map [?\e (left)] 'org-metaleft)
22279 (org-defkey org-mode-map "\C-c\C-xl" 'org-metaleft)
22280 (org-defkey org-mode-map [?\e (right)] 'org-metaright)
22281 (org-defkey org-mode-map "\C-c\C-xr" 'org-metaright)
22282 (org-defkey org-mode-map [?\e (up)] 'org-metaup)
22283 (org-defkey org-mode-map "\C-c\C-xu" 'org-metaup)
22284 (org-defkey org-mode-map [?\e (down)] 'org-metadown)
22285 (org-defkey org-mode-map "\C-c\C-xd" 'org-metadown)
22286 (org-defkey org-mode-map "\C-c\C-xL" 'org-shiftmetaleft)
22287 (org-defkey org-mode-map "\C-c\C-xR" 'org-shiftmetaright)
22288 (org-defkey org-mode-map "\C-c\C-xU" 'org-shiftmetaup)
22289 (org-defkey org-mode-map "\C-c\C-xD" 'org-shiftmetadown)
22290 (org-defkey org-mode-map [?\C-c (up)] 'org-shiftup)
22291 (org-defkey org-mode-map [?\C-c (down)] 'org-shiftdown)
22292 (org-defkey org-mode-map [?\C-c (left)] 'org-shiftleft)
22293 (org-defkey org-mode-map [?\C-c (right)] 'org-shiftright)
22294 (org-defkey org-mode-map [?\C-c ?\C-x (right)] 'org-shiftcontrolright)
22295 (org-defkey org-mode-map [?\C-c ?\C-x (left)] 'org-shiftcontrolleft))
22297 ;; All the other keys
22299 (org-defkey org-mode-map "\C-c\C-a" 'show-all) ; in case allout messed up.
22300 (org-defkey org-mode-map "\C-c\C-r" 'org-reveal)
22301 (org-defkey org-mode-map "\C-xns" 'org-narrow-to-subtree)
22302 (org-defkey org-mode-map "\C-c$" 'org-archive-subtree)
22303 (org-defkey org-mode-map "\C-c\C-x\C-s" 'org-advertized-archive-subtree)
22304 (org-defkey org-mode-map "\C-c\C-x\C-a" 'org-toggle-archive-tag)
22305 (org-defkey org-mode-map "\C-c\C-xb" 'org-tree-to-indirect-buffer)
22306 (org-defkey org-mode-map "\C-c\C-j" 'org-goto)
22307 (org-defkey org-mode-map "\C-c\C-t" 'org-todo)
22308 (org-defkey org-mode-map "\C-c\C-s" 'org-schedule)
22309 (org-defkey org-mode-map "\C-c\C-d" 'org-deadline)
22310 (org-defkey org-mode-map "\C-c;" 'org-toggle-comment)
22311 (org-defkey org-mode-map "\C-c\C-v" 'org-show-todo-tree)
22312 (org-defkey org-mode-map "\C-c\C-w" 'org-check-deadlines)
22313 (org-defkey org-mode-map "\C-c/" 'org-occur) ; Minor-mode reserved
22314 (org-defkey org-mode-map "\C-c\\" 'org-tags-sparse-tree) ; Minor-mode res.
22315 (org-defkey org-mode-map "\C-c\C-m" 'org-ctrl-c-ret)
22316 (org-defkey org-mode-map "\M-\C-m" 'org-insert-heading)
22317 (org-defkey org-mode-map "\C-c\C-x\C-n" 'org-next-link)
22318 (org-defkey org-mode-map "\C-c\C-x\C-p" 'org-previous-link)
22319 (org-defkey org-mode-map "\C-c\C-l" 'org-insert-link)
22320 (org-defkey org-mode-map "\C-c\C-o" 'org-open-at-point)
22321 (org-defkey org-mode-map "\C-c%" 'org-mark-ring-push)
22322 (org-defkey org-mode-map "\C-c&" 'org-mark-ring-goto)
22323 (org-defkey org-mode-map "\C-c\C-z" 'org-time-stamp) ; Alternative binding
22324 (org-defkey org-mode-map "\C-c." 'org-time-stamp) ; Minor-mode reserved
22325 (org-defkey org-mode-map "\C-c!" 'org-time-stamp-inactive) ; Minor-mode r.
22326 (org-defkey org-mode-map "\C-c," 'org-priority) ; Minor-mode reserved
22327 (org-defkey org-mode-map "\C-c\C-y" 'org-evaluate-time-range)
22328 (org-defkey org-mode-map "\C-c>" 'org-goto-calendar)
22329 (org-defkey org-mode-map "\C-c<" 'org-date-from-calendar)
22330 (org-defkey org-mode-map [(control ?,)] 'org-cycle-agenda-files)
22331 (org-defkey org-mode-map [(control ?\')] 'org-cycle-agenda-files)
22332 (org-defkey org-mode-map "\C-c[" 'org-agenda-file-to-front)
22333 (org-defkey org-mode-map "\C-c]" 'org-remove-file)
22334 (org-defkey org-mode-map "\C-c-" 'org-ctrl-c-minus)
22335 (org-defkey org-mode-map "\C-c^" 'org-sort)
22336 (org-defkey org-mode-map "\C-c\C-c" 'org-ctrl-c-ctrl-c)
22337 (org-defkey org-mode-map "\C-c#" 'org-update-checkbox-count)
22338 (org-defkey org-mode-map "\C-m" 'org-return)
22339 (org-defkey org-mode-map "\C-c?" 'org-table-field-info)
22340 (org-defkey org-mode-map "\C-c " 'org-table-blank-field)
22341 (org-defkey org-mode-map "\C-c+" 'org-table-sum)
22342 (org-defkey org-mode-map "\C-c=" 'org-table-eval-formula)
22343 (org-defkey org-mode-map "\C-c'" 'org-table-edit-formulas)
22344 (org-defkey org-mode-map "\C-c`" 'org-table-edit-field)
22345 (org-defkey org-mode-map "\C-c|" 'org-table-create-or-convert-from-region)
22346 (org-defkey org-mode-map "\C-c*" 'org-table-recalculate)
22347 (org-defkey org-mode-map [(control ?#)] 'org-table-rotate-recalc-marks)
22348 (org-defkey org-mode-map "\C-c~" 'org-table-create-with-table.el)
22349 (org-defkey org-mode-map "\C-c\C-q" 'org-table-wrap-region)
22350 (org-defkey org-mode-map "\C-c}" 'org-table-toggle-coordinate-overlays)
22351 (org-defkey org-mode-map "\C-c{" 'org-table-toggle-formula-debugger)
22352 (org-defkey org-mode-map "\C-c\C-e" 'org-export)
22353 (org-defkey org-mode-map "\C-c:" 'org-toggle-fixed-width-section)
22354 (org-defkey org-mode-map "\C-c\C-x\C-f" 'org-emphasize)
22356 (org-defkey org-mode-map "\C-c\C-x\C-k" 'org-cut-special)
22357 (org-defkey org-mode-map "\C-c\C-x\C-w" 'org-cut-special)
22358 (org-defkey org-mode-map "\C-c\C-x\M-w" 'org-copy-special)
22359 (org-defkey org-mode-map "\C-c\C-x\C-y" 'org-paste-special)
22361 (org-defkey org-mode-map "\C-c\C-x\C-t" 'org-toggle-time-stamp-overlays)
22362 (org-defkey org-mode-map "\C-c\C-x\C-i" 'org-clock-in)
22363 (org-defkey org-mode-map "\C-c\C-x\C-o" 'org-clock-out)
22364 (org-defkey org-mode-map "\C-c\C-x\C-x" 'org-clock-cancel)
22365 (org-defkey org-mode-map "\C-c\C-x\C-d" 'org-clock-display)
22366 (org-defkey org-mode-map "\C-c\C-x\C-r" 'org-clock-report)
22367 (org-defkey org-mode-map "\C-c\C-x\C-u" 'org-dblock-update)
22368 (org-defkey org-mode-map "\C-c\C-x\C-l" 'org-preview-latex-fragment)
22369 (org-defkey org-mode-map "\C-c\C-x\C-b" 'org-toggle-checkbox)
22371 (define-key org-mode-map "\C-c\C-x\C-c" 'org-columns)
22373 (when (featurep 'xemacs)
22374 (org-defkey org-mode-map 'button3 'popup-mode-menu))
22376 (defsubst org-table-p () (org-at-table-p))
22378 (defun org-self-insert-command (N)
22379 "Like `self-insert-command', use overwrite-mode for whitespace in tables.
22380 If the cursor is in a table looking at whitespace, the whitespace is
22381 overwritten, and the table is not marked as requiring realignment."
22382 (interactive "p")
22383 (if (and (org-table-p)
22384 (progn
22385 ;; check if we blank the field, and if that triggers align
22386 (and org-table-auto-blank-field
22387 (member last-command
22388 '(org-cycle org-return org-shifttab org-ctrl-c-ctrl-c))
22389 (if (or (equal (char-after) ?\ ) (looking-at "[^|\n]* |"))
22390 ;; got extra space, this field does not determine column width
22391 (let (org-table-may-need-update) (org-table-blank-field))
22392 ;; no extra space, this field may determine column width
22393 (org-table-blank-field)))
22395 (eq N 1)
22396 (looking-at "[^|\n]* |"))
22397 (let (org-table-may-need-update)
22398 (goto-char (1- (match-end 0)))
22399 (delete-backward-char 1)
22400 (goto-char (match-beginning 0))
22401 (self-insert-command N))
22402 (setq org-table-may-need-update t)
22403 (self-insert-command N)))
22405 (defun org-delete-backward-char (N)
22406 "Like `delete-backward-char', insert whitespace at field end in tables.
22407 When deleting backwards, in tables this function will insert whitespace in
22408 front of the next \"|\" separator, to keep the table aligned. The table will
22409 still be marked for re-alignment if the field did fill the entire column,
22410 because, in this case the deletion might narrow the column."
22411 (interactive "p")
22412 (if (and (org-table-p)
22413 (eq N 1)
22414 (string-match "|" (buffer-substring (point-at-bol) (point)))
22415 (looking-at ".*?|"))
22416 (let ((pos (point))
22417 (noalign (looking-at "[^|\n\r]* |"))
22418 (c org-table-may-need-update))
22419 (backward-delete-char N)
22420 (skip-chars-forward "^|")
22421 (insert " ")
22422 (goto-char (1- pos))
22423 ;; noalign: if there were two spaces at the end, this field
22424 ;; does not determine the width of the column.
22425 (if noalign (setq org-table-may-need-update c)))
22426 (backward-delete-char N)))
22428 (defun org-delete-char (N)
22429 "Like `delete-char', but insert whitespace at field end in tables.
22430 When deleting characters, in tables this function will insert whitespace in
22431 front of the next \"|\" separator, to keep the table aligned. The table will
22432 still be marked for re-alignment if the field did fill the entire column,
22433 because, in this case the deletion might narrow the column."
22434 (interactive "p")
22435 (if (and (org-table-p)
22436 (not (bolp))
22437 (not (= (char-after) ?|))
22438 (eq N 1))
22439 (if (looking-at ".*?|")
22440 (let ((pos (point))
22441 (noalign (looking-at "[^|\n\r]* |"))
22442 (c org-table-may-need-update))
22443 (replace-match (concat
22444 (substring (match-string 0) 1 -1)
22445 " |"))
22446 (goto-char pos)
22447 ;; noalign: if there were two spaces at the end, this field
22448 ;; does not determine the width of the column.
22449 (if noalign (setq org-table-may-need-update c)))
22450 (delete-char N))
22451 (delete-char N)))
22453 ;; Make `delete-selection-mode' work with org-mode and orgtbl-mode
22454 (put 'org-self-insert-command 'delete-selection t)
22455 (put 'orgtbl-self-insert-command 'delete-selection t)
22456 (put 'org-delete-char 'delete-selection 'supersede)
22457 (put 'org-delete-backward-char 'delete-selection 'supersede)
22459 ;; Make `flyspell-mode' delay after some commands
22460 (put 'org-self-insert-command 'flyspell-delayed t)
22461 (put 'orgtbl-self-insert-command 'flyspell-delayed t)
22462 (put 'org-delete-char 'flyspell-delayed t)
22463 (put 'org-delete-backward-char 'flyspell-delayed t)
22465 ;; How to do this: Measure non-white length of current string
22466 ;; If equal to column width, we should realign.
22468 (defun org-remap (map &rest commands)
22469 "In MAP, remap the functions given in COMMANDS.
22470 COMMANDS is a list of alternating OLDDEF NEWDEF command names."
22471 (let (new old)
22472 (while commands
22473 (setq old (pop commands) new (pop commands))
22474 (if (fboundp 'command-remapping)
22475 (org-defkey map (vector 'remap old) new)
22476 (substitute-key-definition old new map global-map)))))
22478 (when (eq org-enable-table-editor 'optimized)
22479 ;; If the user wants maximum table support, we need to hijack
22480 ;; some standard editing functions
22481 (org-remap org-mode-map
22482 'self-insert-command 'org-self-insert-command
22483 'delete-char 'org-delete-char
22484 'delete-backward-char 'org-delete-backward-char)
22485 (org-defkey org-mode-map "|" 'org-force-self-insert))
22487 (defun org-shiftcursor-error ()
22488 "Throw an error because Shift-Cursor command was applied in wrong context."
22489 (error "This command is active in special context like tables, headlines or timestamps"))
22491 (defun org-shifttab (&optional arg)
22492 "Global visibility cycling or move to previous table field.
22493 Calls `org-cycle' with argument t, or `org-table-previous-field', depending
22494 on context.
22495 See the individual commands for more information."
22496 (interactive "P")
22497 (cond
22498 ((org-at-table-p) (call-interactively 'org-table-previous-field))
22499 (arg (message "Content view to level: ")
22500 (org-content (prefix-numeric-value arg))
22501 (setq org-cycle-global-status 'overview))
22502 (t (call-interactively 'org-global-cycle))))
22504 (defun org-shiftmetaleft ()
22505 "Promote subtree or delete table column.
22506 Calls `org-promote-subtree', `org-outdent-item',
22507 or `org-table-delete-column', depending on context.
22508 See the individual commands for more information."
22509 (interactive)
22510 (cond
22511 ((org-at-table-p) (call-interactively 'org-table-delete-column))
22512 ((org-on-heading-p) (call-interactively 'org-promote-subtree))
22513 ((org-at-item-p) (call-interactively 'org-outdent-item))
22514 (t (org-shiftcursor-error))))
22516 (defun org-shiftmetaright ()
22517 "Demote subtree or insert table column.
22518 Calls `org-demote-subtree', `org-indent-item',
22519 or `org-table-insert-column', depending on context.
22520 See the individual commands for more information."
22521 (interactive)
22522 (cond
22523 ((org-at-table-p) (call-interactively 'org-table-insert-column))
22524 ((org-on-heading-p) (call-interactively 'org-demote-subtree))
22525 ((org-at-item-p) (call-interactively 'org-indent-item))
22526 (t (org-shiftcursor-error))))
22528 (defun org-shiftmetaup (&optional arg)
22529 "Move subtree up or kill table row.
22530 Calls `org-move-subtree-up' or `org-table-kill-row' or
22531 `org-move-item-up' depending on context. See the individual commands
22532 for more information."
22533 (interactive "P")
22534 (cond
22535 ((org-at-table-p) (call-interactively 'org-table-kill-row))
22536 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
22537 ((org-at-item-p) (call-interactively 'org-move-item-up))
22538 (t (org-shiftcursor-error))))
22539 (defun org-shiftmetadown (&optional arg)
22540 "Move subtree down or insert table row.
22541 Calls `org-move-subtree-down' or `org-table-insert-row' or
22542 `org-move-item-down', depending on context. See the individual
22543 commands for more information."
22544 (interactive "P")
22545 (cond
22546 ((org-at-table-p) (call-interactively 'org-table-insert-row))
22547 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
22548 ((org-at-item-p) (call-interactively 'org-move-item-down))
22549 (t (org-shiftcursor-error))))
22551 (defun org-metaleft (&optional arg)
22552 "Promote heading or move table column to left.
22553 Calls `org-do-promote' or `org-table-move-column', depending on context.
22554 With no specific context, calls the Emacs default `backward-word'.
22555 See the individual commands for more information."
22556 (interactive "P")
22557 (cond
22558 ((org-at-table-p) (org-call-with-arg 'org-table-move-column 'left))
22559 ((or (org-on-heading-p) (org-region-active-p))
22560 (call-interactively 'org-do-promote))
22561 ((org-at-item-p) (call-interactively 'org-outdent-item))
22562 (t (call-interactively 'backward-word))))
22564 (defun org-metaright (&optional arg)
22565 "Demote subtree or move table column to right.
22566 Calls `org-do-demote' or `org-table-move-column', depending on context.
22567 With no specific context, calls the Emacs default `forward-word'.
22568 See the individual commands for more information."
22569 (interactive "P")
22570 (cond
22571 ((org-at-table-p) (call-interactively 'org-table-move-column))
22572 ((or (org-on-heading-p) (org-region-active-p))
22573 (call-interactively 'org-do-demote))
22574 ((org-at-item-p) (call-interactively 'org-indent-item))
22575 (t (call-interactively 'forward-word))))
22577 (defun org-metaup (&optional arg)
22578 "Move subtree up or move table row up.
22579 Calls `org-move-subtree-up' or `org-table-move-row' or
22580 `org-move-item-up', depending on context. See the individual commands
22581 for more information."
22582 (interactive "P")
22583 (cond
22584 ((org-at-table-p) (org-call-with-arg 'org-table-move-row 'up))
22585 ((org-on-heading-p) (call-interactively 'org-move-subtree-up))
22586 ((org-at-item-p) (call-interactively 'org-move-item-up))
22587 (t (org-shiftcursor-error))))
22589 (defun org-metadown (&optional arg)
22590 "Move subtree down or move table row down.
22591 Calls `org-move-subtree-down' or `org-table-move-row' or
22592 `org-move-item-down', depending on context. See the individual
22593 commands for more information."
22594 (interactive "P")
22595 (cond
22596 ((org-at-table-p) (call-interactively 'org-table-move-row))
22597 ((org-on-heading-p) (call-interactively 'org-move-subtree-down))
22598 ((org-at-item-p) (call-interactively 'org-move-item-down))
22599 (t (org-shiftcursor-error))))
22601 (defun org-shiftup (&optional arg)
22602 "Increase item in timestamp or increase priority of current headline.
22603 Calls `org-timestamp-up' or `org-priority-up', or `org-previous-item',
22604 depending on context. See the individual commands for more information."
22605 (interactive "P")
22606 (cond
22607 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up))
22608 ((org-on-heading-p) (call-interactively 'org-priority-up))
22609 ((org-at-item-p) (call-interactively 'org-previous-item))
22610 (t (call-interactively 'org-beginning-of-item) (beginning-of-line 1))))
22612 (defun org-shiftdown (&optional arg)
22613 "Decrease item in timestamp or decrease priority of current headline.
22614 Calls `org-timestamp-down' or `org-priority-down', or `org-next-item'
22615 depending on context. See the individual commands for more information."
22616 (interactive "P")
22617 (cond
22618 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down))
22619 ((org-on-heading-p) (call-interactively 'org-priority-down))
22620 (t (call-interactively 'org-next-item))))
22622 (defun org-shiftright ()
22623 "Next TODO keyword or timestamp one day later, depending on context."
22624 (interactive)
22625 (cond
22626 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-up-day))
22627 ((org-on-heading-p) (org-call-with-arg 'org-todo 'right))
22628 ((org-at-property-p) (call-interactively 'org-property-next-allowed-value))
22629 (t (org-shiftcursor-error))))
22631 (defun org-shiftleft ()
22632 "Previous TODO keyword or timestamp one day earlier, depending on context."
22633 (interactive)
22634 (cond
22635 ((org-at-timestamp-p t) (call-interactively 'org-timestamp-down-day))
22636 ((org-on-heading-p) (org-call-with-arg 'org-todo 'left))
22637 ((org-at-property-p)
22638 (call-interactively 'org-property-previous-allowed-value))
22639 (t (org-shiftcursor-error))))
22641 (defun org-shiftcontrolright ()
22642 "Switch to next TODO set."
22643 (interactive)
22644 (cond
22645 ((org-on-heading-p) (org-call-with-arg 'org-todo 'nextset))
22646 (t (org-shiftcursor-error))))
22648 (defun org-shiftcontrolleft ()
22649 "Switch to previous TODO set."
22650 (interactive)
22651 (cond
22652 ((org-on-heading-p) (org-call-with-arg 'org-todo 'previousset))
22653 (t (org-shiftcursor-error))))
22655 (defun org-ctrl-c-ret ()
22656 "Call `org-table-hline-and-move' or `org-insert-heading' dep. on context."
22657 (interactive)
22658 (cond
22659 ((org-at-table-p) (call-interactively 'org-table-hline-and-move))
22660 (t (call-interactively 'org-insert-heading))))
22662 (defun org-copy-special ()
22663 "Copy region in table or copy current subtree.
22664 Calls `org-table-copy' or `org-copy-subtree', depending on context.
22665 See the individual commands for more information."
22666 (interactive)
22667 (call-interactively
22668 (if (org-at-table-p) 'org-table-copy-region 'org-copy-subtree)))
22670 (defun org-cut-special ()
22671 "Cut region in table or cut current subtree.
22672 Calls `org-table-copy' or `org-cut-subtree', depending on context.
22673 See the individual commands for more information."
22674 (interactive)
22675 (call-interactively
22676 (if (org-at-table-p) 'org-table-cut-region 'org-cut-subtree)))
22678 (defun org-paste-special (arg)
22679 "Paste rectangular region into table, or past subtree relative to level.
22680 Calls `org-table-paste-rectangle' or `org-paste-subtree', depending on context.
22681 See the individual commands for more information."
22682 (interactive "P")
22683 (if (org-at-table-p)
22684 (org-table-paste-rectangle)
22685 (org-paste-subtree arg)))
22687 (defun org-ctrl-c-ctrl-c (&optional arg)
22688 "Set tags in headline, or update according to changed information at point.
22690 This command does many different things, depending on context:
22692 - If the cursor is in a headline, prompt for tags and insert them
22693 into the current line, aligned to `org-tags-column'. When called
22694 with prefix arg, realign all tags in the current buffer.
22696 - If the cursor is in one of the special #+KEYWORD lines, this
22697 triggers scanning the buffer for these lines and updating the
22698 information.
22700 - If the cursor is inside a table, realign the table. This command
22701 works even if the automatic table editor has been turned off.
22703 - If the cursor is on a #+TBLFM line, re-apply the formulas to
22704 the entire table.
22706 - If the cursor is inside a table created by the table.el package,
22707 activate that table.
22709 - If the current buffer is a remember buffer, close note and file it.
22710 with a prefix argument, file it without further interaction to the default
22711 location.
22713 - If the cursor is on a <<<target>>>, update radio targets and corresponding
22714 links in this buffer.
22716 - If the cursor is on a numbered item in a plain list, renumber the
22717 ordered list."
22718 (interactive "P")
22719 (let ((org-enable-table-editor t))
22720 (cond
22721 ((or org-clock-overlays
22722 org-occur-highlights
22723 org-latex-fragment-image-overlays)
22724 (org-remove-clock-overlays)
22725 (org-remove-occur-highlights)
22726 (org-remove-latex-fragment-image-overlays)
22727 (message "Temporary highlights/overlays removed from current buffer"))
22728 ((and (local-variable-p 'org-finish-function (current-buffer))
22729 (fboundp org-finish-function))
22730 (funcall org-finish-function))
22731 ((org-at-property-p)
22732 (call-interactively 'org-property-action))
22733 ((org-on-target-p) (call-interactively 'org-update-radio-target-regexp))
22734 ((org-on-heading-p) (call-interactively 'org-set-tags))
22735 ((org-at-table.el-p)
22736 (require 'table)
22737 (beginning-of-line 1)
22738 (re-search-forward "|" (save-excursion (end-of-line 2) (point)))
22739 (call-interactively 'table-recognize-table))
22740 ((org-at-table-p)
22741 (org-table-maybe-eval-formula)
22742 (if arg
22743 (call-interactively 'org-table-recalculate)
22744 (org-table-maybe-recalculate-line))
22745 (call-interactively 'org-table-align))
22746 ((org-at-item-checkbox-p)
22747 (call-interactively 'org-toggle-checkbox))
22748 ((org-at-item-p)
22749 (call-interactively 'org-maybe-renumber-ordered-list))
22750 ((save-excursion (beginning-of-line 1) (looking-at "#\\+\\([A-Z]+\\)"))
22751 (cond
22752 ((equal (match-string 1) "TBLFM")
22753 ;; Recalculate the table before this line
22754 (save-excursion
22755 (beginning-of-line 1)
22756 (skip-chars-backward " \r\n\t")
22757 (if (org-at-table-p)
22758 (org-call-with-arg 'org-table-recalculate t))))
22760 (call-interactively 'org-mode-restart))))
22761 (t (error "C-c C-c can do nothing useful at this location.")))))
22763 (defun org-mode-restart ()
22764 "Restart Org-mode, to scan again for special lines.
22765 Also updates the keyword regular expressions."
22766 (interactive)
22767 (let ((org-inhibit-startup t)) (org-mode))
22768 (message "Org-mode restarted to refresh keyword and special line setup"))
22770 (defun org-return ()
22771 "Goto next table row or insert a newline.
22772 Calls `org-table-next-row' or `newline', depending on context.
22773 See the individual commands for more information."
22774 (interactive)
22775 (cond
22776 ((bobp) (newline))
22777 ((org-at-table-p)
22778 (org-table-justify-field-maybe)
22779 (call-interactively 'org-table-next-row))
22780 (t (newline))))
22782 (defun org-ctrl-c-minus ()
22783 "Insert separator line in table or modify bullet type in list.
22784 Calls `org-table-insert-hline' or `org-cycle-list-bullet',
22785 depending on context."
22786 (interactive)
22787 (cond
22788 ((org-at-table-p)
22789 (call-interactively 'org-table-insert-hline))
22790 ((org-in-item-p)
22791 (call-interactively 'org-cycle-list-bullet))
22792 (t (error "`C-c -' does have no function here."))))
22794 (defun org-meta-return (&optional arg)
22795 "Insert a new heading or wrap a region in a table.
22796 Calls `org-insert-heading' or `org-table-wrap-region', depending on context.
22797 See the individual commands for more information."
22798 (interactive "P")
22799 (cond
22800 ((org-at-table-p)
22801 (call-interactively 'org-table-wrap-region))
22802 (t (call-interactively 'org-insert-heading))))
22804 ;;; Menu entries
22806 ;; Define the Org-mode menus
22807 (easy-menu-define org-tbl-menu org-mode-map "Tbl menu"
22808 '("Tbl"
22809 ["Align" org-ctrl-c-ctrl-c (org-at-table-p)]
22810 ["Next Field" org-cycle (org-at-table-p)]
22811 ["Previous Field" org-shifttab (org-at-table-p)]
22812 ["Next Row" org-return (org-at-table-p)]
22813 "--"
22814 ["Blank Field" org-table-blank-field (org-at-table-p)]
22815 ["Edit Field" org-table-edit-field (org-at-table-p)]
22816 ["Copy Field from Above" org-table-copy-down (org-at-table-p)]
22817 "--"
22818 ("Column"
22819 ["Move Column Left" org-metaleft (org-at-table-p)]
22820 ["Move Column Right" org-metaright (org-at-table-p)]
22821 ["Delete Column" org-shiftmetaleft (org-at-table-p)]
22822 ["Insert Column" org-shiftmetaright (org-at-table-p)])
22823 ("Row"
22824 ["Move Row Up" org-metaup (org-at-table-p)]
22825 ["Move Row Down" org-metadown (org-at-table-p)]
22826 ["Delete Row" org-shiftmetaup (org-at-table-p)]
22827 ["Insert Row" org-shiftmetadown (org-at-table-p)]
22828 ["Sort lines in region" org-table-sort-lines (org-at-table-p)]
22829 "--"
22830 ["Insert Hline" org-ctrl-c-minus (org-at-table-p)])
22831 ("Rectangle"
22832 ["Copy Rectangle" org-copy-special (org-at-table-p)]
22833 ["Cut Rectangle" org-cut-special (org-at-table-p)]
22834 ["Paste Rectangle" org-paste-special (org-at-table-p)]
22835 ["Fill Rectangle" org-table-wrap-region (org-at-table-p)])
22836 "--"
22837 ("Calculate"
22838 ["Set Column Formula" org-table-eval-formula (org-at-table-p)]
22839 ["Set Field Formula" (org-table-eval-formula '(4)) :active (org-at-table-p) :keys "C-u C-c ="]
22840 ["Edit Formulas" org-table-edit-formulas (org-at-table-p)]
22841 "--"
22842 ["Recalculate line" org-table-recalculate (org-at-table-p)]
22843 ["Recalculate all" (lambda () (interactive) (org-table-recalculate '(4))) :active (org-at-table-p) :keys "C-u C-c *"]
22844 ["Iterate all" (lambda () (interactive) (org-table-recalculate '(16))) :active (org-at-table-p) :keys "C-u C-u C-c *"]
22845 "--"
22846 ["Toggle Recalculate Mark" org-table-rotate-recalc-marks (org-at-table-p)]
22847 "--"
22848 ["Sum Column/Rectangle" org-table-sum
22849 (or (org-at-table-p) (org-region-active-p))]
22850 ["Which Column?" org-table-current-column (org-at-table-p)])
22851 ["Debug Formulas"
22852 org-table-toggle-formula-debugger
22853 :style toggle :selected org-table-formula-debug]
22854 ["Show Col/Row Numbers"
22855 org-table-toggle-coordinate-overlays
22856 :style toggle :selected org-table-overlay-coordinates]
22857 "--"
22858 ["Create" org-table-create (and (not (org-at-table-p))
22859 org-enable-table-editor)]
22860 ["Convert Region" org-table-convert-region (not (org-at-table-p 'any))]
22861 ["Import from File" org-table-import (not (org-at-table-p))]
22862 ["Export to File" org-table-export (org-at-table-p)]
22863 "--"
22864 ["Create/Convert from/to table.el" org-table-create-with-table.el t]))
22866 (easy-menu-define org-org-menu org-mode-map "Org menu"
22867 '("Org"
22868 ("Show/Hide"
22869 ["Cycle Visibility" org-cycle (or (bobp) (outline-on-heading-p))]
22870 ["Cycle Global Visibility" org-shifttab (not (org-at-table-p))]
22871 ["Sparse Tree" org-occur t]
22872 ["Reveal Context" org-reveal t]
22873 ["Show All" show-all t]
22874 "--"
22875 ["Subtree to indirect buffer" org-tree-to-indirect-buffer t])
22876 "--"
22877 ["New Heading" org-insert-heading t]
22878 ("Navigate Headings"
22879 ["Up" outline-up-heading t]
22880 ["Next" outline-next-visible-heading t]
22881 ["Previous" outline-previous-visible-heading t]
22882 ["Next Same Level" outline-forward-same-level t]
22883 ["Previous Same Level" outline-backward-same-level t]
22884 "--"
22885 ["Jump" org-goto t]
22886 "--"
22887 ["C-a finds headline start"
22888 (setq org-special-ctrl-a (not org-special-ctrl-a))
22889 :style toggle :selected org-special-ctrl-a])
22890 ("Edit Structure"
22891 ["Move Subtree Up" org-shiftmetaup (not (org-at-table-p))]
22892 ["Move Subtree Down" org-shiftmetadown (not (org-at-table-p))]
22893 "--"
22894 ["Copy Subtree" org-copy-special (not (org-at-table-p))]
22895 ["Cut Subtree" org-cut-special (not (org-at-table-p))]
22896 ["Paste Subtree" org-paste-special (not (org-at-table-p))]
22897 "--"
22898 ["Promote Heading" org-metaleft (not (org-at-table-p))]
22899 ["Promote Subtree" org-shiftmetaleft (not (org-at-table-p))]
22900 ["Demote Heading" org-metaright (not (org-at-table-p))]
22901 ["Demote Subtree" org-shiftmetaright (not (org-at-table-p))]
22902 "--"
22903 ["Sort Region/Children" org-sort (not (org-at-table-p))]
22904 "--"
22905 ["Convert to odd levels" org-convert-to-odd-levels t]
22906 ["Convert to odd/even levels" org-convert-to-oddeven-levels t])
22907 ("Editing"
22908 ["Emphasis..." org-emphasize t])
22909 ("Archive"
22910 ["Toggle ARCHIVE tag" org-toggle-archive-tag t]
22911 ; ["Check and Tag Children" (org-toggle-archive-tag (4))
22912 ; :active t :keys "C-u C-c C-x C-a"]
22913 ["Sparse trees open ARCHIVE trees"
22914 (setq org-sparse-tree-open-archived-trees
22915 (not org-sparse-tree-open-archived-trees))
22916 :style toggle :selected org-sparse-tree-open-archived-trees]
22917 ["Cycling opens ARCHIVE trees"
22918 (setq org-cycle-open-archived-trees (not org-cycle-open-archived-trees))
22919 :style toggle :selected org-cycle-open-archived-trees]
22920 ["Agenda includes ARCHIVE trees"
22921 (setq org-agenda-skip-archived-trees (not org-agenda-skip-archived-trees))
22922 :style toggle :selected (not org-agenda-skip-archived-trees)]
22923 "--"
22924 ["Move Subtree to Archive" org-advertized-archive-subtree t]
22925 ; ["Check and Move Children" (org-archive-subtree '(4))
22926 ; :active t :keys "C-u C-c C-x C-s"]
22928 "--"
22929 ("TODO Lists"
22930 ["TODO/DONE/-" org-todo t]
22931 ("Select keyword"
22932 ["Next keyword" org-shiftright (org-on-heading-p)]
22933 ["Previous keyword" org-shiftleft (org-on-heading-p)]
22934 ["Complete Keyword" org-complete (assq :todo-keyword (org-context))]
22935 ["Next keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))]
22936 ["Previous keyword set" org-shiftcontrolright (and (> (length org-todo-sets) 1) (org-on-heading-p))])
22937 ["Show TODO Tree" org-show-todo-tree t]
22938 ["Global TODO list" org-todo-list t]
22939 "--"
22940 ["Set Priority" org-priority t]
22941 ["Priority Up" org-shiftup t]
22942 ["Priority Down" org-shiftdown t])
22943 ("TAGS and Properties"
22944 ["Set Tags" 'org-ctrl-c-ctrl-c (org-at-heading-p)]
22945 ["Column view of properties" org-columns t])
22946 ("Dates and Scheduling"
22947 ["Timestamp" org-time-stamp t]
22948 ["Timestamp (inactive)" org-time-stamp-inactive t]
22949 ("Change Date"
22950 ["1 Day Later" org-shiftright t]
22951 ["1 Day Earlier" org-shiftleft t]
22952 ["1 ... Later" org-shiftup t]
22953 ["1 ... Earlier" org-shiftdown t])
22954 ["Compute Time Range" org-evaluate-time-range t]
22955 ["Schedule Item" org-schedule t]
22956 ["Deadline" org-deadline t]
22957 "--"
22958 ["Custom time format" org-toggle-time-stamp-overlays
22959 :style radio :selected org-display-custom-times]
22960 "--"
22961 ["Goto Calendar" org-goto-calendar t]
22962 ["Date from Calendar" org-date-from-calendar t])
22963 ("Logging work"
22964 ["Clock in" org-clock-in t]
22965 ["Clock out" org-clock-out t]
22966 ["Clock cancel" org-clock-cancel t]
22967 ["Display times" org-clock-display t]
22968 ["Create clock table" org-clock-report t]
22969 "--"
22970 ["Record DONE time"
22971 (progn (setq org-log-done (not org-log-done))
22972 (message "Switching to %s will %s record a timestamp"
22973 (car org-done-keywords)
22974 (if org-log-done "automatically" "not")))
22975 :style toggle :selected org-log-done])
22976 "--"
22977 ["Agenda Command..." org-agenda t]
22978 ("File List for Agenda")
22979 ("Special views current file"
22980 ["TODO Tree" org-show-todo-tree t]
22981 ["Check Deadlines" org-check-deadlines t]
22982 ["Timeline" org-timeline t]
22983 ["Tags Tree" org-tags-sparse-tree t])
22984 "--"
22985 ("Hyperlinks"
22986 ["Store Link (Global)" org-store-link t]
22987 ["Insert Link" org-insert-link t]
22988 ["Follow Link" org-open-at-point t]
22989 "--"
22990 ["Next link" org-next-link t]
22991 ["Previous link" org-previous-link t]
22992 "--"
22993 ["Descriptive Links"
22994 (progn (org-add-to-invisibility-spec '(org-link)) (org-restart-font-lock))
22995 :style radio :selected (member '(org-link) buffer-invisibility-spec)]
22996 ["Literal Links"
22997 (progn
22998 (org-remove-from-invisibility-spec '(org-link)) (org-restart-font-lock))
22999 :style radio :selected (not (member '(org-link) buffer-invisibility-spec))])
23000 "--"
23001 ["Export/Publish..." org-export t]
23002 ("LaTeX"
23003 ["Org CDLaTeX mode" org-cdlatex-mode :style toggle
23004 :selected org-cdlatex-mode]
23005 ["Insert Environment" cdlatex-environment (fboundp 'cdlatex-environment)]
23006 ["Insert math symbol" cdlatex-math-symbol (fboundp 'cdlatex-math-symbol)]
23007 ["Modify math symbol" org-cdlatex-math-modify
23008 (org-inside-LaTeX-fragment-p)]
23009 ["Export LaTeX fragments as images"
23010 (setq org-export-with-LaTeX-fragments (not org-export-with-LaTeX-fragments))
23011 :style toggle :selected org-export-with-LaTeX-fragments])
23012 "--"
23013 ("Documentation"
23014 ["Show Version" org-version t]
23015 ["Info Documentation" org-info t])
23016 ("Customize"
23017 ["Browse Org Group" org-customize t]
23018 "--"
23019 ["Expand This Menu" org-create-customize-menu
23020 (fboundp 'customize-menu-create)])
23021 "--"
23022 ["Refresh setup" org-mode-restart t]
23025 (defun org-info (&optional node)
23026 "Read documentation for Org-mode in the info system.
23027 With optional NODE, go directly to that node."
23028 (interactive)
23029 (require 'info)
23030 (Info-goto-node (format "(org)%s" (or node ""))))
23032 (defun org-install-agenda-files-menu ()
23033 (let ((bl (buffer-list)))
23034 (save-excursion
23035 (while bl
23036 (set-buffer (pop bl))
23037 (if (org-mode-p) (setq bl nil)))
23038 (when (org-mode-p)
23039 (easy-menu-change
23040 '("Org") "File List for Agenda"
23041 (append
23042 (list
23043 ["Edit File List" (org-edit-agenda-file-list) t]
23044 ["Add/Move Current File to Front of List" org-agenda-file-to-front t]
23045 ["Remove Current File from List" org-remove-file t]
23046 ["Cycle through agenda files" org-cycle-agenda-files t]
23047 "--")
23048 (mapcar 'org-file-menu-entry (org-agenda-files t))))))))
23050 ;;;; Documentation
23052 (defun org-customize ()
23053 "Call the customize function with org as argument."
23054 (interactive)
23055 (customize-browse 'org))
23057 (defun org-create-customize-menu ()
23058 "Create a full customization menu for Org-mode, insert it into the menu."
23059 (interactive)
23060 (if (fboundp 'customize-menu-create)
23061 (progn
23062 (easy-menu-change
23063 '("Org") "Customize"
23064 `(["Browse Org group" org-customize t]
23065 "--"
23066 ,(customize-menu-create 'org)
23067 ["Set" Custom-set t]
23068 ["Save" Custom-save t]
23069 ["Reset to Current" Custom-reset-current t]
23070 ["Reset to Saved" Custom-reset-saved t]
23071 ["Reset to Standard Settings" Custom-reset-standard t]))
23072 (message "\"Org\"-menu now contains full customization menu"))
23073 (error "Cannot expand menu (outdated version of cus-edit.el)")))
23075 ;;;; Miscellaneous stuff
23078 ;;; Generally useful functions
23080 (defun org-context ()
23081 "Return a list of contexts of the current cursor position.
23082 If several contexts apply, all are returned.
23083 Each context entry is a list with a symbol naming the context, and
23084 two positions indicating start and end of the context. Possible
23085 contexts are:
23087 :headline anywhere in a headline
23088 :headline-stars on the leading stars in a headline
23089 :todo-keyword on a TODO keyword (including DONE) in a headline
23090 :tags on the TAGS in a headline
23091 :priority on the priority cookie in a headline
23092 :item on the first line of a plain list item
23093 :item-bullet on the bullet/number of a plain list item
23094 :checkbox on the checkbox in a plain list item
23095 :table in an org-mode table
23096 :table-special on a special filed in a table
23097 :table-table in a table.el table
23098 :link on a hyperlink
23099 :keyword on a keyword: SCHEDULED, DEADLINE, CLOSE,COMMENT, QUOTE.
23100 :target on a <<target>>
23101 :radio-target on a <<<radio-target>>>
23102 :latex-fragment on a LaTeX fragment
23103 :latex-preview on a LaTeX fragment with overlayed preview image
23105 This function expects the position to be visible because it uses font-lock
23106 faces as a help to recognize the following contexts: :table-special, :link,
23107 and :keyword."
23108 (let* ((f (get-text-property (point) 'face))
23109 (faces (if (listp f) f (list f)))
23110 (p (point)) clist o)
23111 ;; First the large context
23112 (cond
23113 ((org-on-heading-p t)
23114 (push (list :headline (point-at-bol) (point-at-eol)) clist)
23115 (when (progn
23116 (beginning-of-line 1)
23117 (looking-at org-todo-line-tags-regexp))
23118 (push (org-point-in-group p 1 :headline-stars) clist)
23119 (push (org-point-in-group p 2 :todo-keyword) clist)
23120 (push (org-point-in-group p 4 :tags) clist))
23121 (goto-char p)
23122 (skip-chars-backward "^[\n\r \t") (or (eobp) (backward-char 1))
23123 (if (looking-at "\\[#[A-Z0-9]\\]")
23124 (push (org-point-in-group p 0 :priority) clist)))
23126 ((org-at-item-p)
23127 (push (org-point-in-group p 2 :item-bullet) clist)
23128 (push (list :item (point-at-bol)
23129 (save-excursion (org-end-of-item) (point)))
23130 clist)
23131 (and (org-at-item-checkbox-p)
23132 (push (org-point-in-group p 0 :checkbox) clist)))
23134 ((org-at-table-p)
23135 (push (list :table (org-table-begin) (org-table-end)) clist)
23136 (if (memq 'org-formula faces)
23137 (push (list :table-special
23138 (previous-single-property-change p 'face)
23139 (next-single-property-change p 'face)) clist)))
23140 ((org-at-table-p 'any)
23141 (push (list :table-table) clist)))
23142 (goto-char p)
23144 ;; Now the small context
23145 (cond
23146 ((org-at-timestamp-p)
23147 (push (org-point-in-group p 0 :timestamp) clist))
23148 ((memq 'org-link faces)
23149 (push (list :link
23150 (previous-single-property-change p 'face)
23151 (next-single-property-change p 'face)) clist))
23152 ((memq 'org-special-keyword faces)
23153 (push (list :keyword
23154 (previous-single-property-change p 'face)
23155 (next-single-property-change p 'face)) clist))
23156 ((org-on-target-p)
23157 (push (org-point-in-group p 0 :target) clist)
23158 (goto-char (1- (match-beginning 0)))
23159 (if (looking-at org-radio-target-regexp)
23160 (push (org-point-in-group p 0 :radio-target) clist))
23161 (goto-char p))
23162 ((setq o (car (delq nil
23163 (mapcar
23164 (lambda (x)
23165 (if (memq x org-latex-fragment-image-overlays) x))
23166 (org-overlays-at (point))))))
23167 (push (list :latex-fragment
23168 (org-overlay-start o) (org-overlay-end o)) clist)
23169 (push (list :latex-preview
23170 (org-overlay-start o) (org-overlay-end o)) clist))
23171 ((org-inside-LaTeX-fragment-p)
23172 ;; FIXME: positions wrong.
23173 (push (list :latex-fragment (point) (point)) clist)))
23175 (setq clist (nreverse (delq nil clist)))
23176 clist))
23178 ;; FIXME Compare with at-regexp-p
23179 (defun org-in-regexp (re &optional nlines visually)
23180 "Check if point is inside a match of regexp.
23181 Normally only the current line is checked, but you can include NLINES extra
23182 lines both before and after point into the search.
23183 If VISUALLY is set, require that the cursor is not after the match but
23184 really on, so that the block visually is on the match."
23185 (catch 'exit
23186 (let ((pos (point))
23187 (eol (point-at-eol (+ 1 (or nlines 0))))
23188 (inc (if visually 1 0)))
23189 (save-excursion
23190 (beginning-of-line (- 1 (or nlines 0)))
23191 (while (re-search-forward re eol t)
23192 (if (and (<= (match-beginning 0) pos)
23193 (>= (+ inc (match-end 0)) pos))
23194 (throw 'exit (cons (match-beginning 0) (match-end 0)))))))))
23196 (defun org-at-regexp-p (regexp)
23197 "Is point inside a match of REGEXP in the current line?"
23198 (catch 'exit
23199 (save-excursion
23200 (let ((pos (point)) (end (point-at-eol)))
23201 (beginning-of-line 1)
23202 (while (re-search-forward regexp end t)
23203 (if (and (<= (match-beginning 0) pos)
23204 (>= (match-end 0) pos))
23205 (throw 'exit t)))
23206 nil))))
23208 (defun org-uniquify (list)
23209 "Remove duplicate elements from LIST."
23210 (let (res)
23211 (mapc (lambda (x) (add-to-list 'res x 'append)) list)
23212 res))
23214 (defun org-delete-all (elts list)
23215 "Remove all elements in ELTS from LIST."
23216 (while elts
23217 (setq list (delete (pop elts) list)))
23218 list)
23220 (defun org-point-in-group (point group &optional context)
23221 "Check if POINT is in match-group GROUP.
23222 If CONTEXT is non-nil, return a list with CONTEXT and the boundaries of the
23223 match. If the match group does ot exist or point is not inside it,
23224 return nil."
23225 (and (match-beginning group)
23226 (>= point (match-beginning group))
23227 (<= point (match-end group))
23228 (if context
23229 (list context (match-beginning group) (match-end group))
23230 t)))
23232 (defun org-combine-plists (&rest plists)
23233 "Create a single property list from all plists in PLISTS.
23234 The process starts by copying the first list, and then setting properties
23235 from the other lists. Settings in the last list are the most significant
23236 ones and overrule settings in the other lists."
23237 (let ((rtn (copy-sequence (pop plists)))
23238 p v ls)
23239 (while plists
23240 (setq ls (pop plists))
23241 (while ls
23242 (setq p (pop ls) v (pop ls))
23243 (setq rtn (plist-put rtn p v))))
23244 rtn))
23246 (defun org-move-line-down (arg)
23247 "Move the current line down. With prefix argument, move it past ARG lines."
23248 (interactive "p")
23249 (let ((col (current-column))
23250 beg end pos)
23251 (beginning-of-line 1) (setq beg (point))
23252 (beginning-of-line 2) (setq end (point))
23253 (beginning-of-line (+ 1 arg))
23254 (setq pos (move-marker (make-marker) (point)))
23255 (insert (delete-and-extract-region beg end))
23256 (goto-char pos)
23257 (move-to-column col)))
23259 (defun org-move-line-up (arg)
23260 "Move the current line up. With prefix argument, move it past ARG lines."
23261 (interactive "p")
23262 (let ((col (current-column))
23263 beg end pos)
23264 (beginning-of-line 1) (setq beg (point))
23265 (beginning-of-line 2) (setq end (point))
23266 (beginning-of-line (- arg))
23267 (setq pos (move-marker (make-marker) (point)))
23268 (insert (delete-and-extract-region beg end))
23269 (goto-char pos)
23270 (move-to-column col)))
23272 (defun org-replace-escapes (string table)
23273 "Replace %-escapes in STRING with values in TABLE.
23274 TABLE is an association list with keys line \"%a\" and string values.
23275 The sequences in STRING may contain normal field width and padding information,
23276 for example \"%-5s\". Replacements happen in the sequence given by TABLE,
23277 so values can contain further %-escapes if they are define later in TABLE."
23278 (let ((case-fold-search nil)
23279 e re rpl)
23280 (while (setq e (pop table))
23281 (setq re (concat "%-?[0-9.]*" (substring (car e) 1)))
23282 (while (string-match re string)
23283 (setq rpl (format (concat (substring (match-string 0 string) 0 -1) "s")
23284 (cdr e)))
23285 (setq string (replace-match rpl t t string))))
23286 string))
23289 (defun org-sublist (list start end)
23290 "Return a section of LIST, from START to END.
23291 Counting starts at 1."
23292 (let (rtn (c start))
23293 (setq list (nthcdr (1- start) list))
23294 (while (and list (<= c end))
23295 (push (pop list) rtn)
23296 (setq c (1+ c)))
23297 (nreverse rtn)))
23299 (defun org-find-base-buffer-visiting (file)
23300 "Like `find-buffer-visiting' but alway return the base buffer and
23301 not an indirect buffer"
23302 (let ((buf (find-buffer-visiting file)))
23303 (or (buffer-base-buffer buf) buf)))
23305 (defun org-image-file-name-regexp ()
23306 "Return regexp matching the file names of images."
23307 (if (fboundp 'image-file-name-regexp)
23308 (image-file-name-regexp)
23309 (let ((image-file-name-extensions
23310 '("png" "jpeg" "jpg" "gif" "tiff" "tif"
23311 "xbm" "xpm" "pbm" "pgm" "ppm")))
23312 (concat "\\."
23313 (regexp-opt (nconc (mapcar 'upcase
23314 image-file-name-extensions)
23315 image-file-name-extensions)
23317 "\\'"))))
23319 (defun org-file-image-p (file)
23320 "Return non-nil if FILE is an image."
23321 (save-match-data
23322 (string-match (org-image-file-name-regexp) file)))
23324 ;;; Paragraph filling stuff.
23325 ;; We want this to be just right, so use the full arsenal.
23327 (defun org-indent-line-function ()
23328 "Indent line like previous, but further if previous was headline or item."
23329 (interactive)
23330 (let* ((pos (point))
23331 (itemp (org-at-item-p))
23332 column bpos bcol tpos tcol bullet btype bullet-type)
23333 ;; Find the previous relevant line
23334 (beginning-of-line 1)
23335 (cond
23336 ((looking-at "#") (setq column 0))
23337 ((looking-at "\\*+ ") (setq column 0))
23339 (beginning-of-line 0)
23340 (while (and (not (bobp)) (looking-at "[ \t]*[\n:#|]"))
23341 (beginning-of-line 0))
23342 (cond
23343 ((looking-at "\\*+[ \t]+")
23344 (goto-char (match-end 0))
23345 (setq column (current-column)))
23346 ((org-in-item-p)
23347 (org-beginning-of-item)
23348 (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
23349 (setq bpos (match-beginning 1) tpos (match-end 0)
23350 bcol (progn (goto-char bpos) (current-column))
23351 tcol (progn (goto-char tpos) (current-column))
23352 bullet (match-string 1)
23353 bullet-type (if (string-match "[0-9]" bullet) "n" bullet))
23354 (if (not itemp)
23355 (setq column tcol)
23356 (goto-char pos)
23357 (beginning-of-line 1)
23358 (looking-at "[ \t]*\\(\\S-+\\)[ \t]*")
23359 (setq bullet (match-string 1)
23360 btype (if (string-match "[0-9]" bullet) "n" bullet))
23361 (setq column (if (equal btype bullet-type) bcol tcol))))
23362 (t (setq column (org-get-indentation))))))
23363 (goto-char pos)
23364 (if (<= (current-column) (current-indentation))
23365 (indent-line-to column)
23366 (save-excursion (indent-line-to column)))
23367 (setq column (current-column))
23368 (beginning-of-line 1)
23369 (if (looking-at
23370 "\\([ \t]+\\)\\(:[0-9a-zA-Z]+:\\)[ \t]*\\(\\S-.*\\(\\S-\\|$\\)\\)")
23371 (replace-match (concat "\\1" (format org-property-format
23372 (match-string 2) (match-string 3)))
23373 t nil))
23374 (move-to-column column)))
23376 (defun org-set-autofill-regexps ()
23377 (interactive)
23378 ;; In the paragraph separator we include headlines, because filling
23379 ;; text in a line directly attached to a headline would otherwise
23380 ;; fill the headline as well.
23381 (org-set-local 'comment-start-skip "^#+[ \t]*")
23382 (org-set-local 'paragraph-separate "\f\\|\\*+ \\|[ ]*$\\|[ \t]*[:|]")
23383 ;; FIXME!!!!!!! (org-set-local 'paragraph-separate "\f\\|[ ]*$")
23384 ;; The paragraph starter includes hand-formatted lists.
23385 (org-set-local 'paragraph-start
23386 "\f\\|[ ]*$\\|\\*+ \\|\f\\|[ \t]*\\([-+*][ \t]+\\|[0-9]+[.)][ \t]+\\)\\|[ \t]*[:|]")
23387 ;; Inhibit auto-fill for headers, tables and fixed-width lines.
23388 ;; But only if the user has not turned off tables or fixed-width regions
23389 (org-set-local
23390 'auto-fill-inhibit-regexp
23391 (concat "\\*+ \\|#\\+"
23392 "\\|[ \t]*" org-keyword-time-regexp
23393 (if (or org-enable-table-editor org-enable-fixed-width-editor)
23394 (concat
23395 "\\|[ \t]*["
23396 (if org-enable-table-editor "|" "")
23397 (if org-enable-fixed-width-editor ":" "")
23398 "]"))))
23399 ;; We use our own fill-paragraph function, to make sure that tables
23400 ;; and fixed-width regions are not wrapped. That function will pass
23401 ;; through to `fill-paragraph' when appropriate.
23402 (org-set-local 'fill-paragraph-function 'org-fill-paragraph)
23403 ; Adaptive filling: To get full control, first make sure that
23404 ;; `adaptive-fill-regexp' never matches. Then install our own matcher.
23405 (org-set-local 'adaptive-fill-regexp "\000")
23406 (org-set-local 'adaptive-fill-function
23407 'org-adaptive-fill-function))
23409 (defun org-fill-paragraph (&optional justify)
23410 "Re-align a table, pass through to fill-paragraph if no table."
23411 (let ((table-p (org-at-table-p))
23412 (table.el-p (org-at-table.el-p)))
23413 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
23414 (table.el-p t) ; skip table.el tables
23415 (table-p (org-table-align) t) ; align org-mode tables
23416 (t nil)))) ; call paragraph-fill
23418 ;; For reference, this is the default value of adaptive-fill-regexp
23419 ;; "[ \t]*\\([-|#;>*]+[ \t]*\\|(?[0-9]+[.)][ \t]*\\)*"
23421 (defun org-adaptive-fill-function ()
23422 "Return a fill prefix for org-mode files.
23423 In particular, this makes sure hanging paragraphs for hand-formatted lists
23424 work correctly."
23425 (cond ((looking-at "#[ \t]+")
23426 (match-string 0))
23427 ((looking-at "[ \t]*\\([-*+] \\|[0-9]+[.)] \\)?")
23428 (save-excursion
23429 (goto-char (match-end 0))
23430 (make-string (current-column) ?\ )))
23431 (t nil)))
23433 ;;;; Functions extending outline functionality
23435 ;; C-a should go to the beginning of a *visible* line, also in the
23436 ;; new outline.el. I guess this should be patched into Emacs?
23437 (defun org-beginning-of-line ()
23438 "Go to the beginning of the current line. If that is invisible, continue
23439 to a visible line beginning. This makes the function of C-a more intuitive."
23440 (interactive)
23441 (let ((pos (point)))
23442 (beginning-of-line 1)
23443 (if (bobp)
23445 (backward-char 1)
23446 (if (org-invisible-p)
23447 (while (and (not (bobp)) (org-invisible-p))
23448 (backward-char 1)
23449 (beginning-of-line 1))
23450 (forward-char 1)))
23451 (when (and org-special-ctrl-a (looking-at org-todo-line-regexp)
23452 (= (char-after (match-end 1)) ?\ ))
23453 (goto-char
23454 (cond ((> pos (match-beginning 3)) (match-beginning 3))
23455 ((= pos (point)) (match-beginning 3))
23456 (t (point)))))))
23458 (define-key org-mode-map "\C-a" 'org-beginning-of-line)
23460 (defun org-invisible-p ()
23461 "Check if point is at a character currently not visible."
23462 ;; Early versions of noutline don't have `outline-invisible-p'.
23463 (if (fboundp 'outline-invisible-p)
23464 (outline-invisible-p)
23465 (get-char-property (point) 'invisible)))
23467 (defun org-invisible-p2 ()
23468 "Check if point is at a character currently not visible."
23469 (save-excursion
23470 (if (and (eolp) (not (bobp))) (backward-char 1))
23471 ;; Early versions of noutline don't have `outline-invisible-p'.
23472 (if (fboundp 'outline-invisible-p)
23473 (outline-invisible-p)
23474 (get-char-property (point) 'invisible))))
23476 (defalias 'org-back-to-heading 'outline-back-to-heading)
23477 (defalias 'org-on-heading-p 'outline-on-heading-p)
23478 (defalias 'org-at-heading-p 'outline-on-heading-p)
23479 (defun org-at-heading-or-item-p ()
23480 (or (org-on-heading-p) (org-at-item-p)))
23482 (defun org-on-target-p ()
23483 (or (org-in-regexp org-radio-target-regexp)
23484 (org-in-regexp org-target-regexp)))
23486 (defun org-up-heading-all (arg)
23487 "Move to the heading line of which the present line is a subheading.
23488 This function considers both visible and invisible heading lines.
23489 With argument, move up ARG levels."
23490 (if (fboundp 'outline-up-heading-all)
23491 (outline-up-heading-all arg) ; emacs 21 version of outline.el
23492 (outline-up-heading arg t))) ; emacs 22 version of outline.el
23494 (defun org-goto-sibling (&optional previous)
23495 "Goto the next sibling, even if it is invisible.
23496 When PREVIOUS is set, go to the previous sibling instead. Returns t
23497 when a sibling was found. When none is found, return nil and don't
23498 move point."
23499 (let ((fun (if previous 're-search-backward 're-search-forward))
23500 (pos (point))
23501 (re (concat "^" outline-regexp))
23502 level l)
23503 (when (condition-case nil (org-back-to-heading t) (error nil))
23504 (setq level (funcall outline-level))
23505 (catch 'exit
23506 (or previous (forward-char 1))
23507 (while (funcall fun re nil t)
23508 (setq l (funcall outline-level))
23509 (when (< l level) (goto-char pos) (throw 'exit nil))
23510 (when (= l level) (goto-char (match-beginning 0)) (throw 'exit t)))
23511 (goto-char pos)
23512 nil))))
23514 (defun org-show-siblings ()
23515 "Show all siblings of the current headline."
23516 (save-excursion
23517 (while (org-goto-sibling) (org-flag-heading nil)))
23518 (save-excursion
23519 (while (org-goto-sibling 'previous)
23520 (org-flag-heading nil))))
23522 (defun org-show-hidden-entry ()
23523 "Show an entry where even the heading is hidden."
23524 (save-excursion
23525 (org-show-entry)))
23527 (defun org-flag-heading (flag &optional entry)
23528 "Flag the current heading. FLAG non-nil means make invisible.
23529 When ENTRY is non-nil, show the entire entry."
23530 (save-excursion
23531 (org-back-to-heading t)
23532 ;; Check if we should show the entire entry
23533 (if entry
23534 (progn
23535 (org-show-entry)
23536 (save-excursion
23537 (and (outline-next-heading)
23538 (org-flag-heading nil))))
23539 (outline-flag-region (max 1 (1- (point)))
23540 (save-excursion (outline-end-of-heading) (point))
23541 flag))))
23543 (defun org-end-of-subtree (&optional invisible-OK to-heading)
23544 ;; This is an exact copy of the original function, but it uses
23545 ;; `org-back-to-heading', to make it work also in invisible
23546 ;; trees. And is uses an invisible-OK argument.
23547 ;; Under Emacs this is not needed, but the old outline.el needs this fix.
23548 (org-back-to-heading invisible-OK)
23549 (let ((first t)
23550 (level (funcall outline-level)))
23551 (while (and (not (eobp))
23552 (or first (> (funcall outline-level) level)))
23553 (setq first nil)
23554 (outline-next-heading))
23555 (unless to-heading
23556 (if (memq (preceding-char) '(?\n ?\^M))
23557 (progn
23558 ;; Go to end of line before heading
23559 (forward-char -1)
23560 (if (memq (preceding-char) '(?\n ?\^M))
23561 ;; leave blank line before heading
23562 (forward-char -1))))))
23563 (point))
23565 (defun org-show-subtree ()
23566 "Show everything after this heading at deeper levels."
23567 (outline-flag-region
23568 (point)
23569 (save-excursion
23570 (outline-end-of-subtree) (outline-next-heading) (point))
23571 nil))
23573 (defun org-show-entry ()
23574 "Show the body directly following this heading.
23575 Show the heading too, if it is currently invisible."
23576 (interactive)
23577 (save-excursion
23578 (org-back-to-heading t)
23579 (outline-flag-region
23580 (max 1 (1- (point)))
23581 (save-excursion
23582 (re-search-forward (concat "[\r\n]\\(" outline-regexp "\\)") nil 'move)
23583 (or (match-beginning 1) (point-max)))
23584 nil)))
23586 (defun org-make-options-regexp (kwds)
23587 "Make a regular expression for keyword lines."
23588 (concat
23590 "#?[ \t]*\\+\\("
23591 (mapconcat 'regexp-quote kwds "\\|")
23592 "\\):[ \t]*"
23593 "\\(.+\\)"))
23595 ;; Make isearch reveal the necessary context
23596 (defun org-isearch-end ()
23597 "Reveal context after isearch exits."
23598 (when isearch-success ; only if search was successful
23599 (if (featurep 'xemacs)
23600 ;; Under XEmacs, the hook is run in the correct place,
23601 ;; we directly show the context.
23602 (org-show-context 'isearch)
23603 ;; In Emacs the hook runs *before* restoring the overlays.
23604 ;; So we have to use a one-time post-command-hook to do this.
23605 ;; (Emacs 22 has a special variable, see function `org-mode')
23606 (unless (and (boundp 'isearch-mode-end-hook-quit)
23607 isearch-mode-end-hook-quit)
23608 ;; Only when the isearch was not quitted.
23609 (org-add-hook 'post-command-hook 'org-isearch-post-command
23610 'append 'local)))))
23612 (defun org-isearch-post-command ()
23613 "Remove self from hook, and show context."
23614 (remove-hook 'post-command-hook 'org-isearch-post-command 'local)
23615 (org-show-context 'isearch))
23618 ;;;; Address problems with some other packages
23620 ;; Make flyspell not check words in links, to not mess up our keymap
23621 (defun org-mode-flyspell-verify ()
23622 "Don't let flyspell put overlays at active buttons."
23623 (not (get-text-property (point) 'keymap)))
23625 ;; Make `bookmark-jump' show the jump location if it was hidden.
23626 (eval-after-load "bookmark"
23627 '(if (boundp 'bookmark-after-jump-hook)
23628 ;; We can use the hook
23629 (add-hook 'bookmark-after-jump-hook 'org-bookmark-jump-unhide)
23630 ;; Hook not available, use advice
23631 (defadvice bookmark-jump (after org-make-visible activate)
23632 "Make the position visible."
23633 (org-bookmark-jump-unhide))))
23635 (defun org-bookmark-jump-unhide ()
23636 "Unhide the current position, to show the bookmark location."
23637 (and (org-mode-p)
23638 (or (org-invisible-p)
23639 (save-excursion (goto-char (max (point-min) (1- (point))))
23640 (org-invisible-p)))
23641 (org-show-context 'bookmark-jump)))
23643 ;; Make session.el ignore our circular variable
23644 (eval-after-load "session"
23645 '(add-to-list 'session-globals-exclude 'org-mark-ring))
23647 ;;;; Experimental code
23649 (defun org-closed-in-range ()
23650 "Sparse tree of items closed in a certain time range.
23651 Still experimental, may disappear in the furture."
23652 (interactive)
23653 ;; Get the time interval from the user.
23654 (let* ((time1 (time-to-seconds
23655 (org-read-date nil 'to-time nil "Starting date: ")))
23656 (time2 (time-to-seconds
23657 (org-read-date nil 'to-time nil "End date:")))
23658 ;; callback function
23659 (callback (lambda ()
23660 (let ((time
23661 (time-to-seconds
23662 (apply 'encode-time
23663 (org-parse-time-string
23664 (match-string 1))))))
23665 ;; check if time in interval
23666 (and (>= time time1) (<= time time2))))))
23667 ;; make tree, check each match with the callback
23668 (org-occur "CLOSED: +\\[\\(.*?\\)\\]" nil callback)))
23670 (defun org-fill-paragraph-experimental (&optional justify)
23671 "Re-align a table, pass through to fill-paragraph if no table."
23672 (let ((table-p (org-at-table-p))
23673 (table.el-p (org-at-table.el-p)))
23674 (cond ((equal (char-after (point-at-bol)) ?*) t) ; skip headlines
23675 (table.el-p t) ; skip table.el tables
23676 (table-p (org-table-align) t) ; align org-mode tables
23677 ((save-excursion
23678 (let ((pos (1+ (point-at-eol))))
23679 (backward-paragraph 1)
23680 (re-search-forward "\\\\\\\\[ \t]*$" pos t)))
23681 (save-excursion
23682 (save-restriction
23683 (narrow-to-region (1+ (match-end 0)) (point-max))
23684 (fill-paragraph nil)
23685 t)))
23686 (t nil)))) ; call paragraph-fill
23688 (defun org-property-previous-allowed-value (&optional previous)
23689 "Switch to the next allowed value for this property."
23690 (interactive)
23691 (org-property-next-allowed-value t))
23693 (defun org-property-next-allowed-value (&optional previous)
23694 "Switch to the next allowed value for this property."
23695 (interactive)
23696 (unless (org-at-property-p)
23697 (error "Not at a property"))
23698 (let* ((key (match-string 2))
23699 (value (match-string 3))
23700 (allowed (or (org-property-get-allowed-values (point) key)
23701 (and (member value '("[ ]" "[-]" "[X]"))
23702 '("[ ]" "[X]"))))
23703 nval)
23704 (unless allowed
23705 (error "Allowed values for this property have not been defined"))
23706 (if previous (setq allowed (reverse allowed)))
23707 (if (member value allowed)
23708 (setq nval (car (cdr (member value allowed)))))
23709 (setq nval (or nval (car allowed)))
23710 (if (equal nval value)
23711 (error "Only one allowed value for this property"))
23712 (org-at-property-p)
23713 (replace-match (concat " :" key ": " nval))
23714 (org-indent-line-function)
23715 (beginning-of-line 1)
23716 (skip-chars-forward " \t")))
23718 ;;;; Finish up
23720 (provide 'org)
23722 (run-hooks 'org-load-hook)
23724 ;; arch-tag: e77da1a7-acc7-4336-b19e-efa25af3f9fd
23725 ;;; org.el ends here